Example #1
0
        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);
        }
Example #2
0
        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);
        }
Example #3
0
        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;
        }
Example #5
0
        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
        }
Example #6
0
        /// <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));
        }
Example #7
0
        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);
            }
        }
Example #8
0
        /// <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));
        }