static bool getFieldValues(string what, out string value, Level level) { value = string.Empty; if (what.Trim().Length == 0) { return(true); // just skip it } if (level == Level.Group) { value = groupedSelection.ToString(); // the only thing we can do } else { DBTable item = null; switch (level) { case Level.Episode: item = tmpEp; break; case Level.Season: item = tmpSeason; break; case Level.Series: item = tmpSeries; break; } value = FieldGetter.resolveDynString(what, item, false); } return(true); }
string replaceDynamicFields(string value) { string result = value; Regex matchRegEx = new Regex(@"\<[a-zA-Z\.]+\>"); foreach (Match m in matchRegEx.Matches(value)) { string resolvedValue = FieldGetter.resolveDynString(m.Value, m_currentEpisode, false); result = result.Replace(m.Value, resolvedValue); } return(result); }
private string replaceDynamicFields(string value, DBTable item) { string result = value; Regex matchRegEx = new Regex(@"\<[a-zA-Z\.]+\>"); foreach (Match m in matchRegEx.Matches(value)) { string resolvedValue = FieldGetter.resolveDynString(m.Value, item, false); result = result.Replace(m.Value, resolvedValue); } return(result); }
private void onFacadeItemSelected(GUIListItem item, GUIControl parent) { // if this is not a message from the facade, exit if (parent != m_Facade && parent != m_Facade.FilmstripLayout && parent != m_Facade.ThumbnailLayout && parent != m_Facade.ListLayout && parent != m_Facade.PlayListLayout) { return; } if (item == null || item.TVTag == null) { return; } DBEpisode episode = item.TVTag as DBEpisode; if (episode == null || prevSelectedEpisode == episode) { return; } if (item.IsPlayed) { episode[DBOnlineEpisode.cWatched] = true; } // Push properties to skin TVSeriesPlugin.setGUIProperty(guiProperty.Title.ToString(), FieldGetter.resolveDynString(m_sFormatEpisodeTitle, episode)); TVSeriesPlugin.setGUIProperty(guiProperty.Subtitle.ToString(), FieldGetter.resolveDynString(m_sFormatEpisodeSubtitle, episode)); TVSeriesPlugin.setGUIProperty(guiProperty.Description.ToString(), FieldGetter.resolveDynString(m_sFormatEpisodeMain, episode)); TVSeriesPlugin.setGUIProperty(guiProperty.Logos.ToString(), localLogos.getLogos(ref episode, TVSeriesPlugin.logosHeight, TVSeriesPlugin.logosWidth)); TVSeriesPlugin.setGUIProperty(guiProperty.EpisodeImage.ToString(), ImageAllocator.GetEpisodeImage(episode)); GUIPropertyManager.SetProperty("#selectedthumb", ImageAllocator.GetEpisodeImage(episode)); TVSeriesPlugin.pushFieldsToSkin(episode, "Episode"); // Some strange issues with logos when using mouse and hovering over current item // Dont push properties next time if the same episode is selected prevSelectedEpisode = episode; }
void PlaybackOperationEnded(bool countAsWatched) { // notify listeners if (!countAsWatched && EpisodeStopped != null) { EpisodeStopped(m_currentEpisode); } if (countAsWatched || m_currentEpisode[DBOnlineEpisode.cWatched]) { MPTVSeriesLog.Write("This episode counts as watched"); if (countAsWatched) { MarkEpisodeAsWatched(m_currentEpisode); // notify listeners if (EpisodeWatched != null) { EpisodeWatched(m_currentEpisode); } } // if the ep wasn't rated before, and the option to ask is set, bring up the ratings menu if ((String.IsNullOrEmpty(m_currentEpisode[DBOnlineEpisode.cMyRating]) || m_currentEpisode[DBOnlineEpisode.cMyRating] == 0) && DBOption.GetOptions(DBOption.cAskToRate)) { MPTVSeriesLog.Write("Episode not rated yet"); if (RateRequestOccured != null) { RateRequestOccured.Invoke(m_currentEpisode); } } else { MPTVSeriesLog.Write("Episode has already been rated or option not set"); } } SetGUIProperties(true); // clear GUI Properties #region Invoke After Playback string invoke = (string)DBOption.GetOptions(DBOption.cInvokeExtAfterPlayback); if (countAsWatched && !string.IsNullOrEmpty(invoke)) { string invokeArgs = (string)DBOption.GetOptions(DBOption.cInvokeExtAfterPlaybackArgs); 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 AfterFilePlay 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.cInvokeExtAfterPlaybackWaitForExit); // 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 ExtAfterPlayback Command: '{0}' '{1}'", invoke, invokeArgs)); MPTVSeriesLog.Write(e.Message); } } #endregion }
/// <summary> /// Sets the following Properties: /// "#Play.Current.Title" /// "#Play.Current.Plot" /// "#Play.Current.Thumb" /// "#Play.Current.Year" /// </summary> /// <param name="clear">Clears the properties instead of filling them if True</param> void SetGUIProperties(bool clear) { if (m_currentEpisode == null) { return; } DBSeries series = null; if (!clear) { series = Helper.getCorrespondingSeries(m_currentEpisode[DBEpisode.cSeriesID]); } DBSeason season = null; if (!clear) { season = Helper.getCorrespondingSeason(m_currentEpisode[DBEpisode.cSeriesID], m_currentEpisode[DBEpisode.cSeasonIndex]); } // Show Plot in OSD or Hide Spoilers (note: FieldGetter takes care of that) GUIPropertyManager.SetProperty("#Play.Current.Plot", clear ? " " : FieldGetter.resolveDynString(TVSeriesPlugin.m_sFormatEpisodeMain, m_currentEpisode)); // Show Episode Thumbnail or Series Poster if Hide Spoilers is enabled string osdImage = string.Empty; if (!clear) { foreach (KeyValuePair <string, string> kvp in SkinSettings.VideoOSDImages) { switch (kvp.Key) { case "episode": osdImage = ImageAllocator.GetEpisodeImage(m_currentEpisode); break; case "season": osdImage = season.Banner; break; case "series": osdImage = series.Poster; break; case "custom": string value = replaceDynamicFields(kvp.Value); string file = Helper.getCleanAbsolutePath(value); if (System.IO.File.Exists(file)) { osdImage = file; } break; } osdImage = osdImage.Trim(); if (string.IsNullOrEmpty(osdImage)) { continue; } else { break; } } } GUIPropertyManager.SetProperty("#Play.Current.Thumb", clear ? " " : osdImage); // double check, i don't want play images to be cleared on ended or stopped... if (PlayPropertyUpdater.CancellationPending) { return; } foreach (KeyValuePair <string, string> kvp in SkinSettings.VideoPlayImages) { if (!clear) { string value = replaceDynamicFields(kvp.Value); string file = Helper.getCleanAbsolutePath(value); if (System.IO.File.Exists(file)) { MPTVSeriesLog.Write(string.Format("Setting play image {0} for property {1}", file, kvp.Key), MPTVSeriesLog.LogLevel.Debug); GUIPropertyManager.SetProperty(kvp.Key, clear ? " " : file); } } else { MPTVSeriesLog.Write(string.Format("Clearing play image for property {0}", kvp.Key), MPTVSeriesLog.LogLevel.Debug); GUIPropertyManager.SetProperty(kvp.Key, " "); } } GUIPropertyManager.SetProperty("#Play.Current.Title", clear ? " " : m_currentEpisode.onlineEpisode.CompleteTitle); GUIPropertyManager.SetProperty("#Play.Current.Year", clear ? " " : FieldGetter.resolveDynString("<" + DBEpisode.cOutName + "." + DBOnlineEpisode.cFirstAired + ">", m_currentEpisode, false)); GUIPropertyManager.SetProperty("#Play.Current.Genre", clear ? " " : FieldGetter.resolveDynString(TVSeriesPlugin.m_sFormatEpisodeSubtitle, m_currentEpisode)); }
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> /// Updates the movie metadata on the playback screen (for when the user clicks info). /// The delay is neccesary because Player tries to use metadata from the MyVideos database. /// We want to update this after that happens so the correct info is there. /// </summary> /// <param name="item">Playlist item</param> /// <param name="clear">Clears the properties instead of filling them if True</param> private void SetProperties(PlayListItem item, bool clear) { if (item == null) { return; } string title = string.Empty; DBSeries series = null; DBSeason season = null; if (!clear) { title = string.Format("{0} - {1}x{2} - {3}", item.SeriesName, item.SeasonIndex, item.EpisodeIndex, item.EpisodeName); series = Helper.getCorrespondingSeries(item.Episode[DBEpisode.cSeriesID]); season = Helper.getCorrespondingSeason(item.Episode[DBEpisode.cSeriesID], int.Parse(item.SeasonIndex)); } // Show Plot in OSD or Hide Spoilers (note: FieldGetter takes care of that) GUIPropertyManager.SetProperty("#Play.Current.Plot", clear ? " " : FieldGetter.resolveDynString(TVSeriesPlugin.m_sFormatEpisodeMain, item.Episode)); // Show Episode Thumbnail or Series Poster if Hide Spoilers is enabled string osdImage = string.Empty; if (!clear) { foreach (KeyValuePair <string, string> kvp in SkinSettings.VideoOSDImages) { switch (kvp.Key) { case "episode": osdImage = ImageAllocator.GetEpisodeImage(item.Episode); break; case "season": osdImage = season.Banner; break; case "series": osdImage = series.Poster; break; case "custom": string value = replaceDynamicFields(kvp.Value, item.Episode); string file = Helper.getCleanAbsolutePath(value); if (System.IO.File.Exists(file)) { osdImage = file; } break; } osdImage = osdImage.Trim(); if (string.IsNullOrEmpty(osdImage)) { continue; } else { break; } } } GUIPropertyManager.SetProperty("#Play.Current.Thumb", clear ? " " : osdImage); foreach (KeyValuePair <string, string> kvp in SkinSettings.VideoPlayImages) { if (!clear) { string value = replaceDynamicFields(kvp.Value, item.Episode); string file = Helper.getCleanAbsolutePath(value); if (System.IO.File.Exists(file)) { MPTVSeriesLog.Write(string.Format("Setting play image {0} for property {1}", file, kvp.Key), MPTVSeriesLog.LogLevel.Debug); GUIPropertyManager.SetProperty(kvp.Key, clear ? " " : file); } } else { MPTVSeriesLog.Write(string.Format("Clearing play image for property {0}", kvp.Key), MPTVSeriesLog.LogLevel.Debug); GUIPropertyManager.SetProperty(kvp.Key, " "); } } GUIPropertyManager.SetProperty("#Play.Current.Title", clear ? "" : title); GUIPropertyManager.SetProperty("#Play.Current.Year", clear ? "" : FieldGetter.resolveDynString("<" + DBEpisode.cOutName + "." + DBOnlineEpisode.cFirstAired + ">", item.Episode, false)); GUIPropertyManager.SetProperty("#Play.Current.Genre", clear ? "" : FieldGetter.resolveDynString(TVSeriesPlugin.m_sFormatEpisodeSubtitle, item.Episode)); }