/// <summary>
        /// Search through all sub-folders and attempt to assign each one to content.
        /// </summary>
        /// <param name="fastUpdate">Whether update is fast, skips detailed updating(e.g. episodes for shows)</param>
        /// <param name="idsToUpdate">List of dtabase IDs that need updating</param>
        /// <param name="cancel">Cancelation flag</param>
        /// <param name="serverTime">Time on online database server</param>
        /// <returns>Whether update was completed without cancelation</returns>
        public bool UpdateContent(bool fastUpdate, ref bool cancel)
        {
            updateCancelled = false;

            // Update progress
            string progressMsg = "Update of '" + this.FullPath + "' started - Building threads";

            OnUpdateProgressChange(this, false, 0, progressMsg);

            // Initialize processing - First pass
            OrgProcessing firstPass = new OrgProcessing(UpdateProcess);

            updateNumber = firstPass.ProcessNumber;

            // Run 1st pass (build of sub-dirs is recursive, so all child root folder sub-dirs will be included)
            firstPass.Run(BuildSubDirectories(this.ContentType), ref cancel, true, Settings.General.NumProcessingThreads);
            updateCancelled = cancel;

            // Initialize processing - Second pass
            OrgProcessing secondPass = new OrgProcessing(UpdateProcess);

            updateNumber = secondPass.ProcessNumber;

            // Run 2nd pass (build of sub-dirs is recursive, so all child root folder sub-dirs will be included)
            secondPass.Run(BuildSubDirectories(this.ContentType), ref cancel, false, Settings.General.NumProcessingThreads);
            updateCancelled = cancel;

            // Get content collection to add content to
            ContentCollection content = GetContentCollection();

            // Remove shows that no longer exists
            if (!cancel)
            {
                content.RemoveMissing();
            }

            // Save changes
            //content.Sort();
            content.Save();

            // Set progress to completed
            progressMsg = "Update of '" + this.FullPath + "' complete!";
            OnUpdateProgressChange(this, false, 100, progressMsg);
            OnUpdateProgressComplete(this);

            // Return whether update was completed without cancelation
            return(!cancel);
        }
        /// <summary>
        /// Builds a list of content matching filter that is contained within a root folder
        /// </summary>
        /// <param name="genre">Filter for genre type - use "All" to disable filter</param>
        /// <param name="contents">List to add content to</param>
        /// <param name="yearFilter">Enables year filtering</param>
        /// <param name="minYear">Minimum for year filter</param>
        /// <param name="maxYear">Maximum for year filter</param>
        /// <param name="nameFilter">String that must be contained in content name - empty string disables filter</param>
        public void GetContent(bool recursive, bool genreEnable, GenreCollection genre, List <Content> contents, bool yearFilter, int minYear, int maxYear, string nameFilter)
        {
            // Go through all movies
            ContentCollection contentCollection = GetContentCollection();

            lock (contentCollection.ContentLock)
            {
                //Console.WriteLine(contentCollection.ToString() + " lock get");
                foreach (Content content in contentCollection)
                {
                    // Apply genre filter
                    bool genreMatch = false;
                    if (content.DatabaseGenres != null && !genreMatch)
                    {
                        foreach (string contentGenre in content.DatabaseGenres)
                        {
                            if (genre.Contains(contentGenre))
                            {
                                genreMatch = true;
                                break;
                            }
                        }
                    }

                    // Apply year filter
                    bool yearMatch = !yearFilter || (content.DatabaseYear >= minYear && content.DatabaseYear <= maxYear);

                    // Apply text filter
                    bool nameMatch = string.IsNullOrEmpty(nameFilter) || content.DatabaseName.ToLower().Contains(nameFilter.ToLower());

                    // Check if movie is in the folder
                    if (ContainsContent(content, recursive) && ApplyContentFilter(content, genreEnable, genre, yearFilter, minYear, maxYear, nameFilter))
                    {
                        contents.Add(content);
                    }
                }
            }
            //Console.WriteLine(contentCollection.ToString() + " release get");
        }
Exemple #3
0
        /// <summary>
        /// Load collection from saved XML file
        /// </summary>
        public void Load(bool doUpdating)
        {
            XmlTextReader reader = null;
            XmlDocument   xmlDoc = new XmlDocument();

            try
            {
                string path = Path.Combine(Organization.GetBasePath(false), XML_ROOT + ".xml");

                if (File.Exists(path))
                {
                    // Use dummy collection to load into so that loading doesn't hog use of object
                    ContentCollection loadContent = new ContentCollection(this.ContentType, "Loading Shows");
                    lock (XmlLock)
                    {
                        // Load XML
                        reader = new XmlTextReader(path);
                        xmlDoc.Load(reader);

                        // Extract data
                        XmlNodeList contentNodes = xmlDoc.DocumentElement.ChildNodes;
                        for (int i = 0; i < contentNodes.Count; i++)
                        {
                            // Update loading progress
                            OnLoadProgressChange((int)(((double)i / contentNodes.Count) * 100));

                            // All elements will be content items or last update time
                            if (contentNodes[i].Name == "LastUpdate")
                            {
                                loadContent.LastUpdate = contentNodes[i].InnerText;
                            }
                            else
                            {
                                // Load content from element based on type
                                switch (this.ContentType)
                                {
                                case ContentType.TvShow:
                                    TvShow show = new TvShow();
                                    if (show.Load(contentNodes[i]))
                                    {
                                        bool rootFolderExists = false;
                                        foreach (ContentRootFolder folder in Settings.GetAllRootFolders(this.ContentType, true))
                                        {
                                            if (folder.FullPath == show.RootFolder)
                                            {
                                                rootFolderExists = true;
                                            }
                                        }

                                        if (!rootFolderExists || !Directory.Exists(show.Path))
                                        {
                                            continue;
                                        }

                                        loadContent.Add(show);
                                        if (doUpdating)
                                        {
                                            show.UpdateMissing();
                                        }
                                    }
                                    break;

                                case ContentType.Movie:
                                    Movie movie = new Movie();
                                    if (movie.Load(contentNodes[i]))
                                    {
                                        loadContent.Add(movie);
                                    }
                                    break;

                                default:
                                    throw new Exception("Unknown content type");
                                }
                            }
                        }
                    }
                    // Update progress
                    OnLoadProgressChange(100);

                    this.LastUpdate = loadContent.LastUpdate;
                    this.Clear();
                    AddMultiple(loadContent);
                }
            }
            catch (Exception e)
            {
                MessageBox.Show(e.ToString(), "Error loading " + this.ContentType + "s from saved data!");
            }
            finally
            {
                if (reader != null)
                {
                    reader.Close();
                }
            }

            // Start updating of TV episode in scan dirs.
            if (this.ContentType == ContentType.TvShow && doUpdating)
            {
                TvItemInScanDirHelper.DoUpdate(false);
                TvItemInScanDirHelper.StartUpdateTimer();
            }

            // Trigger load complete event
            OnLoadComplete();
        }
        /// <summary>
        /// Update processing method (thread) for single content folder in root.
        /// </summary>
        /// <param name="orgPath">Organization path instance to be processed</param>
        /// <param name="pathNum">The path's number out of total being processed</param>
        /// <param name="totalPaths">Total number of paths being processed</param>
        /// <param name="processNumber">The identifier for the OrgProcessing instance</param>
        /// <param name="numItemsProcessed">Number of paths that have been processed - used for progress updates</param>
        /// <param name="numItemsStarted">Number of paths that have had been added to thread pool for processing</param>
        /// <param name="processSpecificArgs">Arguments specific to this process</param>
        private void UpdateProcess(OrgPath orgPath, int pathNum, int totalPaths, int processNumber, ref int numItemsProcessed, ref int numItemsStarted, object processSpecificArgs)
        {
            // Check for cancellation - this method is called from thread pool, so cancellation could have occured by the time this is run
            if (updateCancelled || this.updateNumber != processNumber)
            {
                return;
            }

            // First pass run does quick folder update by skipping online database searching
            bool   firstPass  = (bool)processSpecificArgs;
            string passString = firstPass ? " (First Pass)" : " (Second Pass)";

            // Set processing messge
            string progressMsg = "Updating of '" + orgPath.RootFolder.FullPath + "'" + passString + " - '" + Path.GetFileName(orgPath.Path) + "' started";

            OnUpdateProgressChange(this, false, CalcProgress(numItemsProcessed, numItemsStarted, totalPaths), progressMsg);

            // Get content collection to add content to
            ContentCollection content = GetContentCollection();

            // Check if folder already has a match to existing content
            bool    contentExists   = false;
            bool    contentComplete = false;
            Content newContent      = null;
            int     index           = 0;

            for (int j = 0; j < content.Count; j++)
            {
                if (Path.Equals(orgPath.Path, content[j].Path))
                {
                    contentExists    = true;
                    content[j].Found = true;
                    if (!string.IsNullOrEmpty(content[j].DatabaseName))
                    {
                        contentComplete = true;
                    }
                    newContent = content[j];
                    index      = j;
                    break;
                }
            }

            // Set completed progess message
            progressMsg = "Updating of '" + orgPath.RootFolder.FullPath + "'" + passString + " - '" + Path.GetFileName(orgPath.Path) + "' complete";

            // Check if content found
            if (contentExists && contentComplete)
            {
                // Check if content needs updating
                if ((DateTime.Now - newContent.LastUpdated).TotalDays > 7 && this.ContentType == ContentType.TvShow)
                {
                    newContent.UpdateInfoFromDatabase();
                }

                // Update progress
                if (this.updateNumber == processNumber)
                {
                    OnUpdateProgressChange(this, false, CalcProgress(numItemsProcessed, numItemsStarted, totalPaths), progressMsg);
                }

                return;
            }

            // Folder wasn't matched to an existing content instance, try tmatch folder to content from online database
            Content match;
            bool    matchSucess;

            switch (this.ContentType)
            {
            case ContentType.TvShow:
                TvShow showMatch;
                matchSucess = SearchHelper.TvShowSearch.PathMatch(orgPath.RootFolder.FullPath, orgPath.Path, firstPass, true, out showMatch);
                match       = showMatch;
                break;

            case ContentType.Movie:
                Movie movieMatch;
                matchSucess = SearchHelper.MovieSearch.PathMatch(orgPath.RootFolder.FullPath, orgPath.Path, firstPass, true, out movieMatch);
                match       = movieMatch;
                break;

            default:
                throw new Exception("unknown content type");
            }


            // Check that current process hasn't been replaced - search can be slow, so update may have been cancelled by the time it gets here
            if (updateCancelled || this.updateNumber != processNumber)
            {
                return;
            }

            // Folder already existed, but wasn't previously match to valid content
            if (contentExists && matchSucess)
            {
                switch (this.ContentType)
                {
                case ContentType.TvShow:
                    ((TvShow)newContent).CloneAndHandlePath((TvShow)match, true);
                    ((TvShow)newContent).UpdateMissing();
                    break;

                case ContentType.Movie:
                    ((Movie)newContent).CloneAndHandlePath((Movie)match, true);
                    break;

                default:
                    throw new Exception("unknown content type");
                }
                newContent.LastUpdated = DateTime.Now;
            }
            else if (matchSucess)
            {
                newContent = match;
            }
            else
            {
                switch (this.ContentType)
                {
                case ContentType.TvShow:
                    newContent = new TvShow(string.Empty, 0, 0, orgPath.Path, orgPath.RootFolder.FullPath);
                    break;

                case ContentType.Movie:
                    newContent = new Movie(string.Empty, 0, 0, orgPath.Path, orgPath.RootFolder.FullPath);
                    break;

                default:
                    throw new Exception("unknown content type");
                }
            }

            // Set found flag
            newContent.Found = true;

            // Add content to list if new
            if (!contentExists)
            {
                content.Add(newContent);
            }

            // Update progress
            OnUpdateProgressChange(this, true, CalcProgress(numItemsProcessed, numItemsStarted, totalPaths), progressMsg);
        }