/// <summary> /// syncs the watched state locally from trakt.tv /// </summary> public static void SyncTraktWatchedState() { if (string.IsNullOrEmpty(TraktAPI.Username) || string.IsNullOrEmpty(TraktAPI.Password)) { return; } // Get all local unwatched episodes SQLCondition conditions = new SQLCondition(new DBOnlineEpisode(), DBOnlineEpisode.cWatched, false, SQLConditionType.Equal); List <DBEpisode> episodes = DBEpisode.Get(conditions, false); var watchedItems = TraktAPI.GetUserWatched(TraktAPI.Username); MPTVSeriesLog.Write("Trakt: Syncronizing Watched/Seen from trakt.tv"); // go through all unwatched episodes and check if watched online foreach (DBEpisode episode in episodes) { // if the episode exists on server response // then we mark as watched locally if (HasEpisode(watchedItems, episode)) { MPTVSeriesLog.Write("Trakt: Marking '{0}' as watched", episode.ToString()); episode[DBOnlineEpisode.cWatched] = true; episode[DBOnlineEpisode.cTraktSeen] = true; episode.Commit(); } } MPTVSeriesLog.Write("Finished Syncronizing Watched/Seen state from trakt.tv"); }
/// <summary> /// Create PlayListItem from TvSeries episode id /// </summary> /// <param name="compositeId">Composite id of episode</param> /// <returns>PlayListItem item</returns> internal static MediaPortal.Playlists.PlayListItem CreatePlaylistItemFromEpisode(String compositeId) { var episodes = DBEpisode.Get(new SQLCondition(new DBTable("online_episodes"), "CompositeID", new DBValue(compositeId), SQLConditionType.Equal)); var episode = episodes.FirstOrDefault(e => !string.IsNullOrEmpty(e[DBEpisode.cFilename])); return(CreatePlaylistItemFromEpisode(episode)); }
public List <DBEpisode> getEpisodeItems(int stepIndex, string[] currentStepSelection) { MPTVSeriesLog.Write("View: Get Episodes", MPTVSeriesLog.LogLevel.Debug); SQLCondition conditions = null; if (stepIndex >= m_steps.Count) { return(null); // wrong index specified!! } addHierarchyConditions(ref stepIndex, ref currentStepSelection, ref conditions); MPTVSeriesLog.Write("View: Get Episodes: Executing SQL", MPTVSeriesLog.LogLevel.Debug); List <DBEpisode> eps = DBEpisode.Get(conditions); // WARNING: this naturally only works if the ordering is by season/episodeOrder // inline the special episodes to there relevant positions (Season == 0 by airsbefore_episode) MPTVSeriesLog.Write("View: Sorting Episodes", MPTVSeriesLog.LogLevel.Debug); if (m_steps[stepIndex].inLineSpecials && currentStepSelection[currentStepSelection.Length - 1] != "0") { if (m_steps[stepIndex].inLineSpecialsAsc) { eps = Helper.inverseList <DBEpisode>(eps); } eps.Sort(); } return(eps); }
void MarkEpisodeAsWatched(DBEpisode episode) { // Could be a double episode, so mark both as watched SQLCondition condition = new SQLCondition(); condition.Add(new DBEpisode(), DBEpisode.cFilename, episode[DBEpisode.cFilename], SQLConditionType.Equal); List <DBEpisode> episodes = DBEpisode.Get(condition, false); foreach (DBEpisode ep in episodes) { string date = DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss"); ep[DBOnlineEpisode.cWatched] = 1; ep[DBOnlineEpisode.cPlayCount] = ep[DBOnlineEpisode.cPlayCount] + 1; ep[DBEpisode.cDateWatched] = date; ep[DBOnlineEpisode.cLastWatchedDate] = date; if (string.IsNullOrEmpty(ep[DBOnlineEpisode.cFirstWatchedDate])) { ep[DBOnlineEpisode.cFirstWatchedDate] = date; } ep.Commit(); } // Update Episode Counts DBSeries series = Helper.getCorrespondingSeries(m_currentEpisode[DBEpisode.cSeriesID]); DBSeason season = Helper.getCorrespondingSeason(episode[DBEpisode.cSeriesID], episode[DBEpisode.cSeasonIndex]); DBSeason.UpdateEpisodeCounts(series, season); }
/// <summary> /// Playback the first unwatched episode for a series using TVSeries internal Video Handler /// If no Unwatched episodes exists, play the Most Recently Aired /// /// Taken from Trakt-for-MediaPortal: /// https://github.com/Technicolour/Trakt-for-Mediaportal/blob/master/TraktPlugin/TraktHandlers/TVSeries.cs /// </summary> /// <param name="seriesid">series id of episode</param> /// <param name="resume">Resume from last stop?</param> public static void PlayFirstUnwatchedEpisode(int seriesid, bool resume) { var episodes = DBEpisode.Get(seriesid); if (episodes == null || episodes.Count == 0) { return; } // filter out anything we can't play episodes.RemoveAll(e => string.IsNullOrEmpty(e[DBEpisode.cFilename])); if (episodes.Count == 0) { return; } // sort episodes using DBEpisode sort comparer // this takes into consideration Aired/DVD order and Specials in-line sorting episodes.Sort(); // get first episode unwatched, otherwise get most recently aired var episode = episodes.Where(e => e[DBOnlineEpisode.cWatched] == 0).FirstOrDefault(); if (episode == null) { WifiRemote.LogMessage("No Unwatched episodes found, Playing most recent episode", WifiRemote.LogType.Info); episode = episodes.LastOrDefault(); } if (episode != null) { PlayEpisode(episode, resume); } }
/// <summary> /// Play an episode of a specific series and season /// /// Thanks to Trakt-for-MediaPortal: /// https://github.com/Technicolour/Trakt-for-Mediaportal/blob/master/TraktPlugin/TraktHandlers/TVSeries.cs /// </summary> /// <param name="compositeId">Composite id of the episode</param> /// <paraparam name="resume">Resume from last stop?</paraparam> /// <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> public static void PlayEpisode(String compositeId, bool resume, int startPosition) { var episodes = DBEpisode.Get(new SQLCondition(new DBTable("online_episodes"), "CompositeID", new DBValue(compositeId), SQLConditionType.Equal)); var episode = episodes.FirstOrDefault(e => !string.IsNullOrEmpty(e[DBEpisode.cFilename])); if (episode == null) { return; } PlayEpisode(episode, resume, startPosition);; }
/// <summary> /// Play an episode of a specific series and season /// /// Thanks to Trakt-for-MediaPortal: /// https://github.com/Technicolour/Trakt-for-Mediaportal/blob/master/TraktPlugin/TraktHandlers/TVSeries.cs /// </summary> /// <param name="seriesId">ID of the series</param> /// <param name="seasonNumber">Number of the season</param> /// <param name="episodeNumber">Number of the episode</param> /// <paraparam name="resume">Resume from last stop?</paraparam> /// <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> public static void Play(int seriesId, int seasonNumer, int episodeNumber, bool resume, int startPosition = 0) { var episodes = DBEpisode.Get(seriesId, seasonNumer); var episode = episodes.FirstOrDefault(e => (e[DBEpisode.cEpisodeIndex] == episodeNumber || e[DBEpisode.cEpisodeIndex2] == episodeNumber) && !string.IsNullOrEmpty(e[DBEpisode.cFilename])); if (episode == null) { return; } PlayEpisode(episode, resume, startPosition); }
/// <summary> /// Create PlayListItem from TvSeries show /// </summary> /// <param name="seriesId">Id of show</param> /// <returns>PlayListItem item</returns> internal static List <MediaPortal.Playlists.PlayListItem> CreatePlaylistItemsFromShow(int seriesId) { List <MediaPortal.Playlists.PlayListItem> returnList = new List <MediaPortal.Playlists.PlayListItem>(); var episodes = DBEpisode.Get(seriesId); foreach (DBEpisode e in episodes) { returnList.Add(CreatePlaylistItemFromEpisode(e)); } return(returnList); }
private bool AddItem(string episodeID) { SQLCondition condition = new SQLCondition(); condition.Add(new DBOnlineEpisode(), DBOnlineEpisode.cID, episodeID, SQLConditionType.Equal); List <DBEpisode> ep = DBEpisode.Get(condition, false); if (ep.Count > 0) { PlayListItem newItem = new PlayListItem(ep[0]); playlist.Add(newItem); } return(true); }
/// <summary> /// Constructor. /// </summary> /// <param name="filename">Filename of the currently played episode</param> public NowPlayingSeries(string filename) { try { SQLCondition query = new SQLCondition(new DBEpisode(), DBEpisode.cFilename, filename, SQLConditionType.Equal); List <DBEpisode> episodes = DBEpisode.Get(query); if (episodes.Count > 0) { episodeFound = true; SeriesId = episodes[0].onlineEpisode[DBOnlineEpisode.cSeriesID]; SeasonId = episodes[0].onlineEpisode[DBOnlineEpisode.cSeasonID]; EpisodeId = episodes[0].onlineEpisode[DBOnlineEpisode.cID]; CompositeId = episodes[0].fullItem[DBEpisode.cCompositeID]; Episode = episodes[0].onlineEpisode[DBOnlineEpisode.cEpisodeIndex]; Season = episodes[0].onlineEpisode[DBOnlineEpisode.cSeasonIndex]; Plot = episodes[0].onlineEpisode[DBOnlineEpisode.cEpisodeSummary]; Title = episodes[0].onlineEpisode[DBOnlineEpisode.cEpisodeName]; Director = episodes[0].onlineEpisode[DBOnlineEpisode.cDirector]; Writer = episodes[0].onlineEpisode[DBOnlineEpisode.cWriter]; Rating = episodes[0].onlineEpisode[DBOnlineEpisode.cRating]; MyRating = episodes[0].onlineEpisode[DBOnlineEpisode.cMyRating]; RatingCount = episodes[0].onlineEpisode[DBOnlineEpisode.cRatingCount]; AirDate = episodes[0].onlineEpisode[DBOnlineEpisode.cFirstAired]; DBSeries s = Helper.getCorrespondingSeries(episodes[0].onlineEpisode[DBOnlineEpisode.cSeriesID]); Series = s[DBOnlineSeries.cPrettyName]; Status = s[DBOnlineSeries.cStatus]; Genre = s[DBOnlineSeries.cGenre]; // Get season poster path DBSeason season = DBSeason.getRaw(SeriesId, episodes[0].onlineEpisode[DBOnlineEpisode.cSeasonIndex]); ImageName = ImageAllocator.GetSeasonBannerAsFilename(season); // Fall back to series poster if no season poster is available if (String.IsNullOrEmpty(ImageName)) { ImageName = ImageAllocator.GetSeriesPosterAsFilename(s); } } } catch (Exception e) { WifiRemote.LogMessage("Error getting now playing tvseries: " + e.Message, WifiRemote.LogType.Error); } }
public static LatestMediaHandler.MQTTItem CheckDB(string SearchFile) { LatestMediaHandler.MQTTItem item = new LatestMediaHandler.MQTTItem(); if (MQTTPlugin.DebugMode) { Logger.Debug("Check to see if video is in MP-TVSeries database."); } if (Utils.IsAssemblyAvailable("MP-TVSeries", new Version(2, 6, 3, 1242))) { if (MQTTPlugin.DebugMode) { Logger.Debug("MP-TVSeries found, searching Database for: " + SearchFile); } try { SQLCondition query = new SQLCondition(new DBEpisode(), DBEpisode.cFilename, SearchFile, SQLConditionType.Equal); List <DBEpisode> episodes = DBEpisode.Get(query); if (MQTTPlugin.DebugMode) { Logger.Debug("Found: " + episodes.Count.ToString() + " episodes."); } if (episodes.Count > 0) { DBSeries s = Helper.getCorrespondingSeries(episodes[0].onlineEpisode[DBOnlineEpisode.cSeriesID]); if (MQTTPlugin.DebugMode) { Logger.Debug("Video is in MP-TVSeries database."); } item.Id = episodes[0][DBEpisode.cSeriesID]; item.Title = s.ToString() + " - " + episodes[0][DBEpisode.cEpisodeName]; item.Filename = SearchFile; item.Genres = s[DBOnlineSeries.cGenre]; item.GetArtwork("tv"); } } catch (Exception e) { Logger.Error("Error getting info from TVSeries Database: " + e.Message); } } return(item); }
public static List <DBEpisode> GetEpisodesToSync(DBSeries series, TraktSyncModes mode) { List <DBEpisode> episodes = new List <DBEpisode>(); SQLCondition conditions = new SQLCondition(); if (series == null) { // Get episodes for every series conditions.Add(new DBOnlineEpisode(), DBOnlineEpisode.cSeriesID, 0, SQLConditionType.GreaterThan); } else { // Get episodes for a single series conditions.Add(new DBOnlineEpisode(), DBOnlineEpisode.cSeriesID, series[DBSeries.cID], SQLConditionType.Equal); } switch (mode) { case TraktSyncModes.library: conditions.Add(new DBOnlineEpisode(), DBOnlineEpisode.cTraktLibrary, 0, SQLConditionType.Equal); conditions.Add(new DBOnlineEpisode(), DBOnlineEpisode.cHidden, 0, SQLConditionType.Equal); conditions.Add(new DBEpisode(), DBEpisode.cFilename, string.Empty, SQLConditionType.NotEqual); episodes = DBEpisode.Get(conditions, false); break; case TraktSyncModes.seen: conditions.Add(new DBOnlineEpisode(), DBOnlineEpisode.cHidden, 0, SQLConditionType.Equal); conditions.Add(new DBOnlineEpisode(), DBOnlineEpisode.cWatched, 1, SQLConditionType.Equal); conditions.Add(new DBOnlineEpisode(), DBOnlineEpisode.cTraktSeen, 0, SQLConditionType.Equal); episodes = DBEpisode.Get(conditions, false); break; case TraktSyncModes.unseen: conditions.Add(new DBOnlineEpisode(), DBOnlineEpisode.cHidden, 0, SQLConditionType.Equal); conditions.Add(new DBOnlineEpisode(), DBOnlineEpisode.cTraktSeen, 2, SQLConditionType.Equal); episodes = DBEpisode.Get(conditions, false); break; } return(episodes); }
public void HideSeason(bool hide) { MPTVSeriesLog.Write(string.Format("{0} series {1}, season {2} from view", (hide ? "Hiding" : "UnHiding"), Helper.getCorrespondingSeries(this[DBSeason.cSeriesID]), this[DBSeason.cIndex])); // respect 'Show Local Files Only' setting List <DBEpisode> episodes = DBEpisode.Get(int.Parse(this[DBSeason.cSeriesID]), int.Parse((this[DBSeason.cIndex]))); if (episodes != null) { foreach (DBEpisode episode in episodes) { // Hide Episodes episode.HideEpisode(hide); } } // Hide Season this[DBSeason.cHidden] = hide; this.Commit(); }
/// <summary> /// Play a random episode of a series /// </summary> /// <param name="seriesId">ID of a series</param> /// <param name="resume">Resume from last stop?</param> public static void PlayRandomEpisode(int seriesId, bool resume) { List <DBEpisode> episodes = DBEpisode.Get(seriesId); if (episodes == null || episodes.Count == 0) { return; } // filter out anything we can't play episodes.RemoveAll(e => string.IsNullOrEmpty(e[DBEpisode.cFilename])); if (episodes.Count == 0) { return; } DBEpisode episode = episodes.GetRandomElement <DBEpisode>(); if (episode != null) { PlayEpisode(episode, resume); } }
public List <string> deleteSeason(TVSeriesPlugin.DeleteMenuItems type) { List <string> resultMsg = new List <string>(); // Always delete from Local episode table if deleting from disk or database SQLCondition condition = new SQLCondition(); condition.Add(new DBEpisode(), DBEpisode.cSeriesID, this[DBSeason.cSeriesID], SQLConditionType.Equal); condition.Add(new DBEpisode(), DBEpisode.cSeasonIndex, this[DBSeason.cIndex], SQLConditionType.Equal); /* TODO will include hidden episodes as hidden attribute is only in onlineepisodes. maybe we should include it in localepisodes also.. * if hidden episodes are excluded then the if (resultMsg.Count is wrong and should do another select to get proper count * if (!DBOption.GetOptions(DBOption.cShowHiddenItems)) * { * //don't include hidden seasons unless the ShowHiddenItems option is set * condition.Add(new DBEpisode(), idden, 0, SQLConditionType.Equal); * } */ List <DBEpisode> episodes = DBEpisode.Get(condition, false); if (episodes != null) { bool hasLocalEpisodesToDelete = episodes.Exists(e => !string.IsNullOrEmpty(e[DBEpisode.cFilename])); hasLocalEpisodesToDelete &= (type == TVSeriesPlugin.DeleteMenuItems.disk || type == TVSeriesPlugin.DeleteMenuItems.diskdatabase); DBSeries series = Helper.getCorrespondingSeries(this[DBSeason.cSeriesID]); string seriesName = series == null ? this[DBSeason.cSeriesID].ToString() : series.ToString(); // show progress dialog as this can be a long process esp for network drives // will show new progress for each season if deleting from the series level GUIDialogProgress progressDialog = null; if (!Settings.isConfig) { progressDialog = (GUIDialogProgress)GUIWindowManager.GetWindow((int)GUIWindow.Window.WINDOW_DIALOG_PROGRESS); progressDialog.Reset(); progressDialog.DisplayProgressBar = true; progressDialog.ShowWaitCursor = false; progressDialog.DisableCancel(true); progressDialog.SetHeading(Translation.Delete); progressDialog.Percentage = 0; progressDialog.SetLine(1, string.Format("{0} {1} {2}", seriesName, Translation.Season, this[DBSeason.cIndex])); progressDialog.SetLine(2, string.Empty); // only show progress dialog if we have local files in season if (hasLocalEpisodesToDelete) { progressDialog.StartModal(GUIWindowManager.ActiveWindow); } } int counter = 0; foreach (DBEpisode episode in episodes) { string episodeName = string.Format("{0}x{1} - {2}", episode[DBOnlineEpisode.cSeasonIndex], episode[DBOnlineEpisode.cEpisodeIndex], episode[DBOnlineEpisode.cEpisodeName]); if (!Settings.isConfig) { progressDialog.SetLine(2, episodeName); } if (!Settings.isConfig) { GUIWindowManager.Process(); } resultMsg.AddRange(episode.deleteEpisode(type, true)); if (!Settings.isConfig) { progressDialog.Percentage = Convert.ToInt32(((double)++counter / (double)episodes.Count) * 100.0); } if (!Settings.isConfig) { GUIWindowManager.Process(); } } // close progress dialog if (!Settings.isConfig) { progressDialog.Close(); } // if we have removed all episodes in season without error, cleanup the online table if (resultMsg.Count == 0 && type != TVSeriesPlugin.DeleteMenuItems.disk) { condition = new SQLCondition(); condition.Add(new DBOnlineEpisode(), DBOnlineEpisode.cSeriesID, this[DBSeason.cSeriesID], SQLConditionType.Equal); condition.Add(new DBOnlineEpisode(), DBOnlineEpisode.cSeasonIndex, this[DBSeason.cIndex], SQLConditionType.Equal); DBOnlineEpisode.Clear(condition); } } #region Facade Remote Color // if we were successful at deleting all episodes of season from disk, set HasLocalFiles to false // note: we only do this if the database entries still exist if (resultMsg.Count == 0 && type == TVSeriesPlugin.DeleteMenuItems.disk) { this[cHasLocalFiles] = false; this.Commit(); } // if we were successful at deleting all episodes of season from disk, // also check if any local episodes exist on disk for series and set HasLocalFiles to false if (resultMsg.Count == 0 && type != TVSeriesPlugin.DeleteMenuItems.database) { // Check Series for Local Files SQLCondition episodeConditions = new SQLCondition(); episodeConditions.Add(new DBEpisode(), DBEpisode.cSeriesID, this[DBSeason.cSeriesID], SQLConditionType.Equal); List <DBEpisode> localEpisodes = DBEpisode.Get(episodeConditions); if (localEpisodes.Count == 0 && !DBSeries.IsSeriesRemoved) { DBSeries series = DBSeries.Get(this[DBSeason.cSeriesID]); if (series != null) { series[DBOnlineSeries.cHasLocalFiles] = false; series.Commit(); } } } #endregion #region Cleanup // if there are no error messages and if we need to delete from db if (resultMsg.Count == 0 && type != TVSeriesPlugin.DeleteMenuItems.disk) { condition = new SQLCondition(); condition.Add(new DBSeason(), DBSeason.cSeriesID, this[DBSeason.cSeriesID], SQLConditionType.Equal); condition.Add(new DBSeason(), DBSeason.cIndex, this[DBSeason.cIndex], SQLConditionType.Equal); DBSeason.Clear(condition); } DBSeries.IsSeriesRemoved = false; if (type != TVSeriesPlugin.DeleteMenuItems.disk) { // If local/online episode count is zero then delete the series and all seasons condition = new SQLCondition(); condition.Add(new DBOnlineEpisode(), DBOnlineEpisode.cSeriesID, this[DBSeason.cSeriesID], SQLConditionType.Equal); episodes = DBEpisode.Get(condition, false); if (episodes.Count == 0) { // Delete Seasons condition = new SQLCondition(); condition.Add(new DBSeason(), DBSeason.cSeriesID, this[DBSeason.cSeriesID], SQLConditionType.Equal); DBSeason.Clear(condition); // Delete Local Series condition = new SQLCondition(); condition.Add(new DBSeries(), DBSeries.cID, this[DBSeason.cSeriesID], SQLConditionType.Equal); DBSeries.Clear(condition); // Delete Online Series condition = new SQLCondition(); condition.Add(new DBOnlineSeries(), DBOnlineSeries.cID, this[DBSeason.cSeriesID], SQLConditionType.Equal); DBOnlineSeries.Clear(condition); DBSeries.IsSeriesRemoved = true; } } #endregion return(resultMsg); }
public bool ResumeOrPlay(DBEpisode episode) { try { MPTVSeriesLog.Write("Attempting to play: ", episode[DBEpisode.cFilename].ToString(), MPTVSeriesLog.LogLevel.Debug); // don't have this file ! if (episode[DBEpisode.cFilename].ToString().Length == 0) { return(false); } // check that we are not playing an episode out of episode if unwatched // ignore specials as they can be pretty out of wack! #region PlayBack Order // check sort order so our check is accurate var series = Helper.getCorrespondingSeries(episode[DBOnlineEpisode.cSeriesID]); bool dvdSortOrder = series[DBOnlineSeries.cEpisodeSortOrder] == "DVD"; string seasonField = dvdSortOrder ? DBOnlineEpisode.cCombinedSeason : DBOnlineEpisode.cSeasonIndex; string episodeField = dvdSortOrder ? DBOnlineEpisode.cCombinedEpisodeNumber : DBOnlineEpisode.cEpisodeIndex; if (DBOption.GetOptions(DBOption.cCheckPlayOutOfOrder) && !episode[DBOnlineEpisode.cWatched] && episode[seasonField] > 0 && episode[episodeField] > 1) { // first get the next unwatched episode from previously played // we are only interested in current season (could be multi-user watching multiple seasons) // API for GetNextUnwatched is not desirable as that works from Date Watched, we only care about watched here var conditions = new SQLCondition(); conditions.Add(new DBOnlineEpisode(), DBOnlineEpisode.cSeriesID, episode[DBOnlineSeries.cSeriesID], SQLConditionType.Equal); conditions.Add(new DBOnlineEpisode(), seasonField, episode[seasonField], SQLConditionType.Equal); conditions.Add(new DBOnlineEpisode(), episodeField, episode[episodeField], SQLConditionType.LessThan); conditions.Add(new DBOnlineEpisode(), episodeField, 0, SQLConditionType.GreaterThan); var episodes = DBEpisode.Get(conditions, false); if (episodes != null && episodes.Count > 0) { // set logical playback order based on sort order episodes.Sort(); // if the previous found episode is not watched then we are playing out of order // if we have a gap in episode collection then assume it has not been watched (this check is needed when user does not download all episode info) if (!episodes.Last()[DBOnlineEpisode.cWatched] || (episode[episodeField] - episodes.Last()[episodeField]) > 1) { GUIDialogYesNo dlgYesNo = (GUIDialogYesNo)GUIWindowManager.GetWindow((int)GUIWindow.Window.WINDOW_DIALOG_YES_NO); dlgYesNo.SetHeading(Translation.Warning); dlgYesNo.SetLine(1, Translation.PlaybackOutOfOrderLine1); dlgYesNo.SetLine(2, string.Format("{0} - {1}x{2}", series.ToString(), episode[seasonField], episode[episodeField] - 1)); dlgYesNo.SetLine(3, Translation.PlaybackOutOfOrderLine2); dlgYesNo.DoModal(GUIWindowManager.ActiveWindow); if (!dlgYesNo.IsConfirmed) { return(false); } } } } #endregion m_previousEpisode = m_currentEpisode; m_currentEpisode = episode; int timeMovieStopped = m_currentEpisode[DBEpisode.cStopTime]; // Check if file is an Image e.g. ISO string filename = m_currentEpisode[DBEpisode.cFilename]; m_bIsImageFile = Helper.IsImageFile(filename); #region Invoke Before Playback // see if we have an invokeOption set up string invoke = (string)DBOption.GetOptions(DBOption.cInvokeExtBeforePlayback); if (!string.IsNullOrEmpty(invoke)) { string invokeArgs = (string)DBOption.GetOptions(DBOption.cInvokeExtBeforePlaybackArgs); try { // replace any placeholders in the arguments for the script if any have been supplied. if (!string.IsNullOrEmpty(invokeArgs)) { invokeArgs = FieldGetter.resolveDynString(invokeArgs, m_currentEpisode, true); } invoke = FieldGetter.resolveDynString(invoke, m_currentEpisode, true); // use ProcessStartInfo instead of Process.Start(string) as latter produces a "cannot find file" // error if you pass in command line arguments. // also allows us to run the script hidden, preventing, for example, a command prompt popping up. ProcessStartInfo psi = new ProcessStartInfo(invoke, invokeArgs); psi.WindowStyle = ProcessWindowStyle.Hidden; Process proc = System.Diagnostics.Process.Start(psi); MPTVSeriesLog.Write(string.Format("Sucessfully Invoked BeforeFilePlay Command: '{0}' '{1}'", invoke, invokeArgs)); // if not present in database this evaluates to false. If present and not a valid bool then // it evaluates to true bool waitForExit = (bool)DBOption.GetOptions(DBOption.cInvokeExtBeforePlaybackWaitForExit); // if true this thread will wait for the external user script to complete before continuing. if (waitForExit) { proc.WaitForExit(); } } catch (Exception e) { MPTVSeriesLog.Write(string.Format("Unable to Invoke BeforeFilePlay Command: '{0}' '{1}'", invoke, invokeArgs)); MPTVSeriesLog.Write(e.Message); } } #endregion #region Removable Media Handling if (!File.Exists(m_currentEpisode[DBEpisode.cFilename])) { string episodeVolumeLabel = m_currentEpisode[DBEpisode.cVolumeLabel].ToString(); if (string.IsNullOrEmpty(episodeVolumeLabel)) { episodeVolumeLabel = LocalParse.getImportPath(m_currentEpisode[DBEpisode.cFilename]); } // ask the user to input cd/dvd, usb disk or confirm network drive is connected GUIDialogOK dlgOK = (GUIDialogOK)GUIWindowManager.GetWindow((int)GUIWindow.Window.WINDOW_DIALOG_OK); if (null == dlgOK) { return(false); } dlgOK.SetHeading(Translation.insertDisk); dlgOK.SetLine(1, Translation.InsertDiskMessage1); dlgOK.SetLine(2, Translation.InsertDiskMessage2); dlgOK.SetLine(3, Translation.InsertDiskMessage3); dlgOK.SetLine(4, string.Format(Translation.InsertDiskMessage4, episodeVolumeLabel)); dlgOK.DoModal(GUIWindowManager.ActiveWindow); if (!File.Exists(m_currentEpisode[DBEpisode.cFilename])) { return(false); // still not found, return to list } } #endregion #region Ask user to Resume // skip this if we are using an External Player bool bExternalPlayer = m_bIsImageFile ? m_bIsExternalDVDPlayer : m_bIsExternalPlayer; if (timeMovieStopped > 0 && !bExternalPlayer) { MPTVSeriesLog.Write("Asking user to resume episode from: " + Utils.SecondsToHMSString(timeMovieStopped)); GUIDialogYesNo dlgYesNo = (GUIDialogYesNo)GUIWindowManager.GetWindow((int)GUIWindow.Window.WINDOW_DIALOG_YES_NO); if (null != dlgYesNo) { dlgYesNo.SetHeading(Translation.ResumeEpisode); dlgYesNo.SetLine(1, m_currentEpisode.onlineEpisode.CompleteTitle); dlgYesNo.SetLine(2, GUILocalizeStrings.Get(936) + " " + Utils.SecondsToHMSString(timeMovieStopped)); dlgYesNo.SetDefaultToYes(true); dlgYesNo.DoModal(GUIWindowManager.ActiveWindow); // reset resume data in DB if (!dlgYesNo.IsConfirmed) { timeMovieStopped = 0; m_currentEpisode[DBEpisode.cStopTime] = timeMovieStopped; m_currentEpisode.Commit(); MPTVSeriesLog.Write("User selected to start episode from beginning", MPTVSeriesLog.LogLevel.Debug); } else { MPTVSeriesLog.Write("User selected to resume episode", MPTVSeriesLog.LogLevel.Debug); // dont scrobble first of double episode if resuming past halfway double duration = m_currentEpisode[DBEpisode.cLocalPlaytime]; } } } #endregion Play(timeMovieStopped); return(true); } catch (Exception e) { MPTVSeriesLog.Write("TVSeriesPlugin.VideoHandler.ResumeOrPlay()\r\n" + e.ToString()); return(false); } }
/// <summary> /// Play all episodes of a series /// </summary> /// <param name="seriesId">ID of a series</param> /// <param name="onlyUnwatched">Play only unwatched episodes</param> /// <param name="autostart">If yes, automatically starts playback with the first episode</param> /// <param name="startIndex">Index of the item with which playback should start</param> /// <param name="switchToPlaylistView">If yes the playlistview will be shown</param> public static void PlaySeries(int seriesId, bool autostart, int startIndex, bool onlyUnwatched, bool switchToPlaylistView) { if (GUIGraphicsContext.form.InvokeRequired) { PlaySeriesAsyncDelegate d = new PlaySeriesAsyncDelegate(PlaySeries); GUIGraphicsContext.form.Invoke(d, new object[] { seriesId, autostart, startIndex, onlyUnwatched, switchToPlaylistView }); return; } List <DBEpisode> episodes = DBEpisode.Get(seriesId); if (episodes == null || episodes.Count == 0) { return; } // filter out anything we can't play episodes.RemoveAll(e => string.IsNullOrEmpty(e[DBEpisode.cFilename])); // filter out watched episodes if (onlyUnwatched) { episodes.RemoveAll(e => e[DBOnlineEpisode.cWatched] != 0); } if (episodes.Count == 0) { return; } // Sort episodes and add them to the MP-TVSeries playlist player // Setup playlist player if (playlistPlayer == null) { playlistPlayer = PlayListPlayer.SingletonPlayer; playlistPlayer.PlaylistAutoPlay = true; playlistPlayer.RepeatPlaylist = DBOption.GetOptions(DBOption.cRepeatPlaylist); } playlistPlayer.GetPlaylist(PlayListType.PLAYLIST_TVSERIES).Clear(); episodes.Sort(); foreach (DBEpisode episode in episodes) { PlayListItem playlistItem = new PlayListItem(episode); playlistPlayer.GetPlaylist(PlayListType.PLAYLIST_TVSERIES).Add(playlistItem); } //automatically start playing the playlist if (autostart) { // and activate the playlist window if its not activated yet if (switchToPlaylistView) { GUIWindowManager.ActivateWindow(GUITVSeriesPlayList.GetWindowID); } playlistPlayer.CurrentPlaylistType = PlayListType.PLAYLIST_TVSERIES; playlistPlayer.Reset(); playlistPlayer.Play(0); } }
public GetUpdates(OnlineAPI.UpdateType type) { if (type != OnlineAPI.UpdateType.all) { MPTVSeriesLog.Write(string.Format("Downloading updates from the last {0}", type.ToString())); } else { MPTVSeriesLog.Write("Downloading all updates"); } XmlNode updates = OnlineAPI.Updates(type); series = new Dictionary <DBValue, long>(); episodes = new Dictionary <DBValue, long>(); banners = new Dictionary <DBValue, long>(); fanart = new Dictionary <DBValue, long>(); // if updates via zip fails, try xml if (updates == null) { MPTVSeriesLog.Write("Failed to get updates from 'zip' file, trying 'xml'..."); updates = OnlineAPI.Updates(type, OnlineAPI.Format.Xml); // if we're still failing to get updates... if (updates == null) { // manually define what series need updating basis whether the series is continuing and has local episodes SQLCondition condition = new SQLCondition(); condition.Add(new DBOnlineSeries(), DBOnlineSeries.cID, 0, SQLConditionType.GreaterThan); condition.Add(new DBOnlineSeries(), DBOnlineSeries.cHasLocalFiles, 1, SQLConditionType.Equal); condition.Add(new DBOnlineSeries(), DBOnlineSeries.cStatus, "Ended", SQLConditionType.NotEqual); condition.Add(new DBSeries(), DBSeries.cScanIgnore, 0, SQLConditionType.Equal); condition.Add(new DBSeries(), DBSeries.cDuplicateLocalName, 0, SQLConditionType.Equal); var lContinuingSeries = DBSeries.Get(condition, false, false); MPTVSeriesLog.Write($"Failed to get updates from online, manually defining series and images for updates. Database contains '{lContinuingSeries.Count}' continuing series with local files"); // force our local download cache to expire after a 12hrs timestamp = DateTime.UtcNow.Subtract(new TimeSpan(0, 12, 0, 0)).ToEpoch(); foreach (var lSeries in lContinuingSeries) { string lSeriesId = lSeries[DBOnlineSeries.cID]; series.Add(lSeriesId, timestamp); banners.Add(lSeriesId, timestamp); fanart.Add(lSeriesId, timestamp); // get the most recent season as that is the one that is most likely recently updated // NB: specials could also be recently updated var lSeasons = DBSeason.Get(int.Parse(lSeriesId)); if (lSeasons != null && lSeasons.Count > 0) { int lSeasonIndex = lSeasons.Max(s => ( int )s[DBSeason.cIndex]); var lEpisodes = DBEpisode.Get(int.Parse(lSeriesId), lSeasonIndex); lEpisodes.AddRange(DBEpisode.Get(int.Parse(lSeriesId), 0)); foreach (var episode in lEpisodes) { episodes.Add(episode[DBOnlineEpisode.cID], timestamp); } } } } else { long.TryParse(updates.Attributes["time"].Value, out timestamp); // get all available series in database, there is not point processing updates from online if not needed var lAvailableSeriesInDb = DBSeries.Get(new SQLCondition()).Select(field => (string)field[DBOnlineSeries.cID]).ToList(); // NB: updates from xml only includes series (no episodes or artwork!) foreach (XmlNode node in updates.SelectNodes("/Data/Series")) { long.TryParse(node.SelectSingleNode("time").InnerText, out long lTime); string lSeriesId = node.SelectSingleNode("id").InnerText; // check if we're interested in this series if (!lAvailableSeriesInDb.Contains(lSeriesId)) { continue; } series.Add(lSeriesId, lTime); banners.Add(lSeriesId, lTime); fanart.Add(lSeriesId, lTime); // get the most recent season as that is the one that is most likely recently updated // NB: specials could also be recently updated if (Helper.getCorrespondingSeries(int.Parse(lSeriesId)) != null) { var lSeasons = DBSeason.Get(int.Parse(lSeriesId)); if (lSeasons != null && lSeasons.Count > 0) { int lSeasonIndex = lSeasons.Max(s => ( int )s[DBSeason.cIndex]); var lEpisodes = DBEpisode.Get(int.Parse(lSeriesId), lSeasonIndex); lEpisodes.AddRange(DBEpisode.Get(int.Parse(lSeriesId), 0)); foreach (var episode in lEpisodes) { episodes.Add(episode[DBOnlineEpisode.cID], lTime); } } } } } return; } // process zip file update... long.TryParse(updates.Attributes["time"].Value, out this.timestamp); // get all the series ids foreach (XmlNode node in updates.SelectNodes("/Data/Series")) { long time; long.TryParse(node.SelectSingleNode("time").InnerText, out time); this.series.Add(node.SelectSingleNode("id").InnerText, time); } // get all the episode ids foreach (XmlNode node in updates.SelectNodes("/Data/Episode")) { long time; long.TryParse(node.SelectSingleNode("time").InnerText, out time); this.episodes.Add(node.SelectSingleNode("id").InnerText, time); } // get all the season banners string id = string.Empty; long value; foreach (XmlNode node in updates.SelectNodes("/Data/Banner[type='season']")) { long time; long.TryParse(node.SelectSingleNode("time").InnerText, out time); id = node.SelectSingleNode("Series").InnerText; if (!this.banners.TryGetValue(id, out value)) { this.banners.Add(id, time); } } //get all the series banners foreach (XmlNode node in updates.SelectNodes("/Data/Banner[type='series']")) { long time; long.TryParse(node.SelectSingleNode("time").InnerText, out time); id = node.SelectSingleNode("Series").InnerText; if (!this.banners.TryGetValue(id, out value)) { this.banners.Add(id, time); } } //get all the poster banners foreach (XmlNode node in updates.SelectNodes("/Data/Banner[type='poster']")) { long time; long.TryParse(node.SelectSingleNode("time").InnerText, out time); id = node.SelectSingleNode("Series").InnerText; if (!this.banners.TryGetValue(id, out value)) { this.banners.Add(id, time); } } //get all the fanart banners id = string.Empty; foreach (XmlNode node in updates.SelectNodes("/Data/Banner[type='fanart']")) { long time; long.TryParse(node.SelectSingleNode("time").InnerText, out time); id = node.SelectSingleNode("Series").InnerText; if (!this.fanart.TryGetValue(id, out value)) { this.fanart.Add(id, time); } } }
void watcher_Changed(object sender, FileSystemEventArgs e) { MPTVSeriesLog.Write("File Watcher: Changed event: " + e.FullPath); List <PathPair> filesChanged = new List <PathPair>(); bool isDirectoryChange = false; if (Directory.Exists(e.FullPath)) { isDirectoryChange = true; List <string> folder = new List <string>(); folder.Add(e.FullPath); filesChanged = Filelister.GetFiles(folder); } // a file has changed! created, not created, whatever. Just add it to our list. // we only process this list once in a while lock (m_modifiedFilesList) { if (e.ChangeType == WatcherChangeTypes.Deleted) { removeFromModifiedFilesList(e.FullPath, WatcherItemType.Added, true); SQLCondition condition = new SQLCondition(new DBEpisode(), DBEpisode.cFilename, e.FullPath + "\\%", SQLConditionType.Like); List <DBEpisode> dbepisodes = DBEpisode.Get(condition, false); if (dbepisodes != null && dbepisodes.Count > 0) { foreach (DBEpisode dbepisode in dbepisodes) { m_modifiedFilesList.Add(new WatcherItem(new PathPair(dbepisode[DBEpisode.cFilename].ToString().Substring(e.FullPath.Length).TrimStart('\\'), dbepisode[DBEpisode.cFilename]), WatcherItemType.Deleted)); } } } if (isDirectoryChange) { foreach (PathPair pathPair in filesChanged) { removeFromModifiedFilesList(pathPair.m_sFull_FileName, WatcherItemType.Deleted, false); m_modifiedFilesList.Add(new WatcherItem(pathPair, WatcherItemType.Added)); } } else { /* duplicates are removed later * foreach (WatcherItem item in m_modifiedFilesList) * { * if (item.m_sFullPathFileName == e.FullPath) * return; * } */ String sExtention = System.IO.Path.GetExtension(e.FullPath); if (MediaPortal.Util.Utils.VideoExtensions.IndexOf(sExtention) != -1) { if (e.ChangeType == WatcherChangeTypes.Deleted) { removeFromModifiedFilesList(e.FullPath, WatcherItemType.Added, false); } else { removeFromModifiedFilesList(e.FullPath, WatcherItemType.Deleted, false); } m_modifiedFilesList.Add(new WatcherItem(sender as FileSystemWatcher, e)); } } } }
public void GetSeries() { Log.Instance().Print("Pulling series list from MP-TVSeries started"); List <DBOnlineSeries> myseries = DBOnlineSeries.getAllSeries(); foreach (DBOnlineSeries tvshow in myseries) { DBSeries mytv = Helper.getCorrespondingSeries(tvshow[DBOnlineSeries.cID]); if (mytv != null) { string ishidden = mytv[DBSeries.cHidden]; if (ishidden != "1") { Series s = new Series(); s.ID = (tvshow[DBOnlineSeries.cID]); s.Name = tvshow[DBOnlineSeries.cPrettyName]; s.OriginalName = tvshow[DBOnlineSeries.cOriginalName]; s.Description = tvshow[DBOnlineSeries.cSummary]; s.Rating = tvshow[DBOnlineSeries.cRating]; s.Genres = tvshow[DBOnlineSeries.cGenre]; s.Poster = Config.GetFolder(Config.Dir.Thumbs) + @"\" + "MPTVSeriesBanners" + @"\" + tvshow[DBOnlineSeries.cCurrentBannerFileName].ToString().Replace("/", @"\"); DBEpisode lastlocal = null; DBEpisode firstunlocal = null; DBSeries series = Helper.getCorrespondingSeries(tvshow[DBOnlineSeries.cID]); //DownList.Add(todownload); // get all episodes for the series var conditions = new SQLCondition(); conditions.Add(new DBOnlineEpisode(), DBOnlineEpisode.cSeriesID, tvshow[DBOnlineSeries.cID], SQLConditionType.Equal); var episodes = DBEpisode.Get(conditions, false); episodes.Sort(); //first option - get all unlocal episodes var unLocalEpisodes = episodes.Where(e => !e.IsAvailableLocally).ToList(); StringBuilder sb = new StringBuilder(); foreach (DBEpisode e in unLocalEpisodes) { s.AllUnlocal += "S" + ((int)e[DBEpisode.cSeasonIndex]).ToString("00") + "E" + ((int)e[DBEpisode.cEpisodeIndex]).ToString("00") + "|"; } // //second option - get first unlocal episode var localepisodes = episodes.Where(e => e.IsAvailableLocally); try { lastlocal = localepisodes.Last(); } catch { lastlocal = null; } int firstunlocalid = episodes.IndexOf(lastlocal) + 1; try { firstunlocal = episodes[firstunlocalid]; s.FirstUnlocal = "S" + ((int)firstunlocal[DBEpisode.cSeasonIndex]).ToString("00") + "E" + ((int)firstunlocal[DBEpisode.cEpisodeIndex]).ToString("00"); } catch (Exception e) { firstunlocal = null; s.FirstUnlocal = ""; } allseries.Add(s); } } } Log.Instance().Print("Pulling series list from MP-TVSeries finished"); }