Ejemplo n.º 1
0
        private void WriteMonitorSettings(Ini configIni)
        {
            if (configIni == null)
                return;

            // First read and delete all Monitor tasks - start with a clean slate (incase there were previous delete monitor tasks without writing)
            string[] searchRecords = configIni.ReadString("Engine", "SearchRecords", "").Split(',');
            foreach (string searchRecord in searchRecords)
            {
                if (String.IsNullOrEmpty(searchRecord))
                    continue;

                configIni.DeleteSection(searchRecord);
            }

            // Write the Monitor Tasks Settings
            foreach (MonitorJobOptions monitorTask in mceBuddyConfSettings.monitorTasks)
            {
                string section = monitorTask.taskName;

                configIni.Write(section, "SearchPath", monitorTask.searchPath);
                monitorTask.searchPattern = monitorTask.searchPattern.Replace(GlobalDefs.DEFAULT_VIDEO_STRING, GlobalDefs.DEFAULT_VIDEO_FILE_TYPES);
                configIni.Write(section, "SearchPattern", monitorTask.searchPattern);
                configIni.Write(section, "MonitorSubdirectories", monitorTask.monitorSubdirectories);
                configIni.Write(section, "MonitorConvertedFiles", monitorTask.monitorConvertedFiles);
                configIni.Write(section, "ReMonitorRecordedFiles", monitorTask.reMonitorRecordedFiles);

                configIni.Write(section, "DomainName", monitorTask.domainName);
                configIni.Write(section, "UserName", monitorTask.userName);
                if (!String.IsNullOrEmpty(monitorTask.password))
                    configIni.Write(section, "Password", Crypto.Encrypt(monitorTask.password)); // Password is written as encrypted
            }

            WriteMonitorTasksList(configIni); // this list goes in the Engine section
        }
Ejemplo n.º 2
0
        /// <summary>
        /// Scans the Monitored directories and Manual Queue for new files to process
        /// Applies the filter tests
        /// Processes conversion task jobs for the files and adds them to the queue
        /// This function takes a lock on the Queue while modifying the queue and is thread safe
        /// </summary>
        public void ScanForFiles()
        {
            // Search the specific directories
            foreach (MonitorJobOptions monitorTask in MCEBuddyConf.GlobalMCEConfig.AllMonitorTasks)
            {
                IEnumerable<string> foundFiles = null;
                try
                {
                    // Directory.EnumerateFiles throws an exception if it comes across a protected/unaccesible directory and the ENTIRE list is empty
                    // Instead we need to handle exceptions, skip the protected file/directory and continue walking down the rest
                    foundFiles = FilePaths.GetDirectoryFiles(monitorTask.searchPath, "*", (monitorTask.monitorSubdirectories ? SearchOption.AllDirectories : SearchOption.TopDirectoryOnly)).OrderBy(File.GetLastWriteTime); // We sort the files by last modified time when scanning and adding (oldest to newest)

                    if (foundFiles != null && foundFiles.Count() > 0) // Check for no files (could be due to security access/protection errors
                    {
                        foreach (string foundFile in foundFiles)
                        {
                            if (GlobalDefs.Shutdown) // Check for a shutdown command, this can be an intensive loop
                                return; // Exit - we're done here

                            Monitor.Enter(_monitorTaskFilterMismatchFiles); // Make this thread safe
                            if (_monitorTaskFilterMismatchFiles.ContainsKey(foundFile)) // Check if this file has been processed by this monitor task and doesn't have a filter match, if so skip it (the filters do not change until the engine is stopped, settings changed, engine restarted which will create a new queue)
                            {
                                if (_monitorTaskFilterMismatchFiles[foundFile].Contains(monitorTask.taskName))
                                {
                                    Monitor.Exit(_monitorTaskFilterMismatchFiles);
                                    continue;
                                }
                            }
                            Monitor.Exit(_monitorTaskFilterMismatchFiles);

                            Monitor.Enter(_archivedFiles);
                            if (_archivedFiles.Contains(foundFile)) // Check if the file has been marked as an archive file if so skip it
                            {
                                Monitor.Exit(_archivedFiles);
                                continue;
                            }
                            Monitor.Exit(_archivedFiles);

                            // First check if this file is in the MCEBuddyArchive directory (which contains converted files, if so skip them)
                            if (Path.GetDirectoryName(foundFile).ToLower().Contains((string.IsNullOrEmpty(MCEBuddyConf.GlobalMCEConfig.GeneralOptions.archivePath) ? GlobalDefs.MCEBUDDY_ARCHIVE.ToLower() : MCEBuddyConf.GlobalMCEConfig.GeneralOptions.archivePath.ToLower())))
                            {
                                Monitor.Enter(_archivedFiles);
                                _archivedFiles.Add(foundFile); // add to the list
                                Monitor.Exit(_archivedFiles);
                                Log.AppLog.WriteEntry(this, "File " + foundFile + " has been converted and archived, skipping", Log.LogEntryType.Debug);
                                continue;
                            }

                            // 1st Level Pattern Check - Found a file, filename pattern match from monitor task
                            if (Util.Text.WildcardRegexPatternMatch(Path.GetFileName(foundFile), monitorTask.searchPattern)) // Check pattern match for Monitor Locations filter
                            {
                                // Take a lock here for EACH file before processing and modifying queue
                                // This is done per file and not for all files so that we don't lock up the engine interfaces which need the same lock to respond to GUI queries
                                // CheckAndAddFile is very intensive time consuming process for each file as it extracts metadata and compares filters
                                // Also EnumerateFiles is a very intensive process for very large nested and remote directories which will lock up the thread if the lock is taken
                                Monitor.Enter(Queue); // Take a lock on the queue before modifying the queue
                                CheckAndAddFile(foundFile, monitorTask, false); // Check history, monitor and conversion task filters and creates conversion job for file
                                Monitor.Exit(Queue); // Release the lock on the queue after modifying the queue
                            }
                            else // File type mismatch, log and keep track of them for each monitor task processed
                            {
                                Monitor.Enter(_monitorTaskFilterMismatchFiles); // Make it thread safe
                                if (!_monitorTaskFilterMismatchFiles.ContainsKey(foundFile)) /// Check if this file does not have a key, then create one
                                    _monitorTaskFilterMismatchFiles.Add(foundFile, new List<string>()); // Make a new key for the file
                                _monitorTaskFilterMismatchFiles[foundFile].Add(monitorTask.taskName); // Add this task for the file as a filter mismatch
                                Monitor.Exit(_monitorTaskFilterMismatchFiles);

                                Log.AppLog.WriteEntry(this, "File " + Path.GetFileName(foundFile) + " did not match wildcard" + " " + monitorTask.searchPattern + " for monitor task " + monitorTask.taskName, Log.LogEntryType.Debug);
                            }
                        }
                    }
                    else
                        Log.AppLog.WriteEntry("No accessible files founds in location " + monitorTask.searchPath + " for monitor task " + monitorTask.taskName, Log.LogEntryType.Information);
                }
                catch (Exception ex)
                {
                    Log.AppLog.WriteEntry("Unable to search for files in location " + monitorTask.searchPath + " for monitor task " + monitorTask.taskName + "\r\nERROR : " + ex.Message, Log.LogEntryType.Warning);
                    foundFiles = null;

                    try { Monitor.Exit(Queue); } // Release queue lock
                    catch { }

                    try { Monitor.Exit(_monitorTaskFilterMismatchFiles); } // Release monitor mismatch list lock
                    catch { }

                    try { Monitor.Exit(_archivedFiles); } // Release archived list lock
                    catch { }
                }
            }

            // Read the manual queue - manual selections are always first
            Ini iniQueue = new Ini(GlobalDefs.ManualQueueFile);
            SortedList<string, string> manualQueue = iniQueue.GetSectionKeyValuePairs("ManualQueue");
            foreach (KeyValuePair<string, string> manualFile in manualQueue)
            {
                string filePath = manualFile.Value; // Due to INI restriction only the Value can hold special characters like ];= which maybe contained in the filename, hence the Value is used to capture the "TRUE" filename (Key and Section have restrictions)

                if (GlobalDefs.Shutdown) // Check for a shutdown command, this can be an intensive loop
                    return; // Exit - we're done here

                // Check for valid entry
                if (String.IsNullOrWhiteSpace(filePath))
                    continue;

                string destinationPath = Path.GetDirectoryName(filePath);
                if (String.IsNullOrWhiteSpace(destinationPath)) // check for a null directory name here (happens with some root level network paths)
                {
                    iniQueue.DeleteSection(filePath); // Remove the key from the manual file
                    continue;
                }

                // Connect network drives if needed for each manual entry
                GeneralOptions go = MCEBuddyConf.GlobalMCEConfig.GeneralOptions;
                if (Util.Net.IsUNCPath(destinationPath))
                {
                    if (!String.IsNullOrWhiteSpace(go.userName))
                    {
                        ConnectNet(destinationPath, go.domainName, go.userName, go.password);
                    }
                    else
                    {
                        Log.AppLog.WriteEntry("No network authentication username found, defaulting to Guest authentication", Log.LogEntryType.Warning);
                        ConnectNet(destinationPath, "", GlobalDefs.DEFAULT_NETWORK_USERNAME, "");
                    }
                }

                if (Directory.Exists(filePath)) // After we are connected, check if the target is a directory (accidentally happens), we don't process it
                {
                    Log.AppLog.WriteEntry("Manually selected file " + filePath + " is a directory, skipping", Log.LogEntryType.Warning);
                    iniQueue.DeleteSection(filePath); // Remove the key from the manual file
                    continue;
                }

                if (!File.Exists(filePath)) // After we are connected, check if the file actually exists
                {
                    Log.AppLog.WriteEntry("Manually selected file " + filePath + " does not exist, skipping", Log.LogEntryType.Warning);
                    iniQueue.DeleteSection(filePath); // Remove the key from the manual file
                    continue;
                }

                Log.AppLog.WriteEntry("Manually selected file " + filePath + " added to queue", Log.LogEntryType.Debug);
                // Take a lock here for EACH file before processing and modifying queue
                // This is done per file and not for all files so that we don't lock up the engine interfaces which need the same lock to respond to GUI queries
                // CheckAndAddFile is very intensive time consuming process for each file as it extracts metadata and compares filters
                try
                {
                    Monitor.Enter(Queue); // Take a lock on the queue before modifying the queue
                    CheckAndAddFile(filePath, null, true);
                    Monitor.Exit(Queue); // Release the lock on the queue after modifying the queue
                }
                catch (Exception ex)
                {
                    Log.AppLog.WriteEntry("Add manual files terminated.\r\nERROR : " + ex.Message, Log.LogEntryType.Warning);

                    try { Monitor.Exit(Queue); } // Release queue lock
                    catch { }
                }
            }
        }
Ejemplo n.º 3
0
        private void WriteConversionSettings(Ini configIni)
        {
            if (configIni == null)
                return;

            // First read and delete all Conversion tasks - start with a clean slate (incase there were previous delete conversion tasks without writing)
            string[] conversionRecords = configIni.ReadString("Engine", "Tasks", "").Split(',');
            foreach (string conversionRecord in conversionRecords)
            {
                if (String.IsNullOrEmpty(conversionRecord))
                    continue;

                configIni.DeleteSection(conversionRecord);
            }

            // Write the Converstion Task Settings
            foreach (ConversionJobOptions conversionTask in mceBuddyConfSettings.conversionTasks)
            {
                string section = conversionTask.taskName;

                configIni.Write(section, "Profile", conversionTask.profile);
                configIni.Write(section, "DestinationPath", conversionTask.destinationPath);
                configIni.Write(section, "WorkingPath", conversionTask.workingPath);
                configIni.Write(section, "FallbackDestination", conversionTask.fallbackToSourcePath);
                configIni.Write(section, "CheckReprocessingHistory", conversionTask.checkReprocessingHistory);
                configIni.Write(section, "AddToiTunesLibrary", conversionTask.addToiTunes);
                configIni.Write(section, "AddToWMPLibrary", conversionTask.addToWMP);
                configIni.Write(section, "AutoIncrementFilename", conversionTask.autoIncrementFilename);
                configIni.Write(section, "SkipReprocessing", conversionTask.skipReprocessing);
                configIni.Write(section, "MaxWidth", conversionTask.maxWidth);
                configIni.Write(section, "FPS", conversionTask.FPS);
                configIni.Write(section, "VolumeMultiplier", conversionTask.volumeMultiplier.ToString(CultureInfo.InvariantCulture));
                configIni.Write(section, "QualityMultiplier", conversionTask.qualityMultiplier.ToString(CultureInfo.InvariantCulture));
                configIni.Write(section, "RenameBySeries", conversionTask.renameBySeries);
                configIni.Write(section, "AltRenameBySeries", conversionTask.altRenameBySeries);
                configIni.Write(section, "CustomRenameBySeries", conversionTask.customRenameBySeries);
                configIni.Write(section, "RenameOnly", conversionTask.renameOnly);
                configIni.Write(section, "DownloadSeriesDetails", conversionTask.downloadSeriesDetails);
                configIni.Write(section, "DownloadBanner", conversionTask.downloadBanner); 
                configIni.Write(section, "FileSelection", conversionTask.fileSelection);
                configIni.Write(section, "MetaSelection", conversionTask.metaShowSelection);
                configIni.Write(section, "MetaChannelSelection", conversionTask.metaNetworkSelection);
                configIni.Write(section, "MonitorTaskNames", (conversionTask.monitorTaskNames == null ? "" : String.Join(",", conversionTask.monitorTaskNames)));
                configIni.Write(section, "DRC", conversionTask.drc);
                configIni.Write(section, "AudioLanguage", conversionTask.audioLanguage);
                configIni.Write(section, "AudioOffset", conversionTask.audioOffset.ToString(CultureInfo.InvariantCulture));
                configIni.Write(section, "InsertQueueTop", conversionTask.insertQueueTop);
                configIni.Write(section, "ExtractXML", conversionTask.extractXML);
                configIni.Write(section, "WriteMetadata", conversionTask.writeMetadata);
                configIni.Write(section, "AutoDeInterlace", conversionTask.autoDeInterlace);
                configIni.Write(section, "PreferHardwareEncoding", conversionTask.preferHardwareEncoding);
                configIni.Write(section, "StereoAudio", conversionTask.stereoAudio);
                configIni.Write(section, "EncoderSelectBestAudioTrack", conversionTask.encoderSelectBestAudioTrack);
                configIni.Write(section, "DisableCropping", conversionTask.disableCropping);
                configIni.Write(section, "StartTrim", conversionTask.startTrim);
                configIni.Write(section, "EndTrim", conversionTask.endTrim);
                configIni.Write(section, "ExtractCC", conversionTask.extractCC);
                configIni.Write(section, "CCOffset", conversionTask.ccOffset.ToString(CultureInfo.InvariantCulture));
                configIni.Write(section, "EmbedSubtitlesChapters", conversionTask.embedSubtitlesChapters);
                configIni.Write(section, "PrioritizeOriginalBroadcastDateMatch", conversionTask.prioritizeOriginalBroadcastDateMatch);
                configIni.Write(section, "TaskCommercialSkipCut", conversionTask.commercialSkipCut);
                configIni.Write(section, "SkipCopyBackup", conversionTask.skipCopyBackup);
                configIni.Write(section, "SkipRemux", conversionTask.skipRemuxing);
                configIni.Write(section, "IgnoreCopyProtection", conversionTask.ignoreCopyProtection);
                configIni.Write(section, "TiVOMAKKey", conversionTask.tivoMAKKey);
                configIni.Write(section, "Enabled", conversionTask.enabled);
                configIni.Write(section, "ForceShowType", conversionTask.forceShowType.ToString());
                configIni.Write(section, "MetaShowTypeSelection", conversionTask.metaShowTypeSelection.ToString());
                configIni.Write(section, "MetaDRMTypeSelection", conversionTask.metaDRMSelection.ToString());
                configIni.Write(section, "CommercialRemoval", conversionTask.commercialRemoval.ToString());
                configIni.Write(section, "ComskipINI", conversionTask.comskipIni);
                configIni.Write(section, "DomainName", conversionTask.domainName);
                configIni.Write(section, "UserName", conversionTask.userName);
                if (!String.IsNullOrEmpty(conversionTask.password))
                    configIni.Write(section, "Password", Crypto.Encrypt(conversionTask.password)); // Password is written as encrypted

                // First wipe the MetaCorrectionEntries section clean, to remove old/redundant data and then start afresh since we don't know how many entries may exist
                configIni.DeleteSection(section + "-MetaCorrectionEntries");

                if (conversionTask.metadataCorrections == null)
                    configIni.Write(section, "MetaCorrectionsCount", 0);
                else
                {
                    configIni.Write(section, "MetaCorrectionsCount", conversionTask.metadataCorrections.Length);

                    for (int i = 0; i < conversionTask.metadataCorrections.Length; i++) // the Enteries are kept in their own section
                    {
                        configIni.Write(section + "-MetaCorrectionEntries", "OriginalTitle" + i.ToString(), conversionTask.metadataCorrections[i].originalTitle);
                        configIni.Write(section + "-MetaCorrectionEntries", "CorrectedTitle" + i.ToString(), conversionTask.metadataCorrections[i].correctedTitle);
                        configIni.Write(section + "-MetaCorrectionEntries", "TVDBSeriesId" + i.ToString(), conversionTask.metadataCorrections[i].tvdbSeriesId);
                        configIni.Write(section + "-MetaCorrectionEntries", "IMDBSeriesId" + i.ToString(), conversionTask.metadataCorrections[i].imdbSeriesId);
                    }
                }
            }

            WriteConversionTasksList(configIni); // this list goes in the Engine section
        }
Ejemplo n.º 4
0
        public void DeleteHistoryItem(string sourceFileName)
        {
            if (String.IsNullOrWhiteSpace(sourceFileName))
            {
                Log.AppLog.WriteEntry(this, "No filename to delete from History", Log.LogEntryType.Error, true);
                return;
            }

            Ini historyFile = new Ini(GlobalDefs.HistoryFile);
            historyFile.DeleteSection(sourceFileName);
        }