void OnPlaybackChanged(g_Player.MediaType type, int timeMovieStopped, string filename) { if (PlayBackOpWasOfConcern(g_Player.IsVideo? g_Player.MediaType.Video : g_Player.MediaType.Unknown, g_Player.CurrentFile)) { if (PlayPropertyUpdater.IsBusy) { PlayPropertyUpdater.CancelAsync(); } LogPlayBackOp("changed", g_Player.CurrentFile); try { #region Set Resume Point or Watched double watchedAfter = DBOption.GetOptions(DBOption.cWatchedAfter); if (!m_previousEpisode[DBOnlineEpisode.cWatched] && (timeMovieStopped / playlistPlayer.g_Player.Duration) > watchedAfter / 100) { m_previousEpisode[DBEpisode.cStopTime] = 0; m_previousEpisode.Commit(); MPTVSeriesLog.Write("This episode counts as watched"); MarkEpisodeAsWatched(m_previousEpisode); SetGUIProperties(true); } else { m_previousEpisode[DBEpisode.cStopTime] = timeMovieStopped; m_previousEpisode.Commit(); SetGUIProperties(true); } #endregion m_previousEpisode = null; } catch (Exception e) { MPTVSeriesLog.Write("TVSeriesPlugin.VideoHandler.OnPlaybackChanged()\r\n" + e.ToString()); } } }
void OnPlayBackStopped(g_Player.MediaType type, int timeMovieStopped, string filename) { if (PlayBackOpIsOfConcern(type, filename)) { if (PlayPropertyUpdater.IsBusy) { PlayPropertyUpdater.CancelAsync(); } LogPlayBackOp("stopped", filename); try { #region Set Resume Point or Watched double watchedAfter = DBOption.GetOptions(DBOption.cWatchedAfter); if ((timeMovieStopped / playlistPlayer.g_Player.Duration) > watchedAfter / 100) { m_currentEpisode[DBEpisode.cStopTime] = 0; m_currentEpisode.Commit(); PlaybackOperationEnded(true); } else { m_currentEpisode[DBEpisode.cStopTime] = timeMovieStopped; m_currentEpisode.Commit(); PlaybackOperationEnded(false); } #endregion m_currentEpisode = null; m_previousEpisode = null; } catch (Exception e) { MPTVSeriesLog.Write("TVSeriesPlugin.VideoHandler.OnPlayBackStopped()\r\n" + e.ToString()); } } }
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); } }
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; } }