2 This file is part of the HandBrake source code.
\r
3 Homepage: <http://handbrake.fr>.
\r
4 It may be used under the terms of the GNU General Public License. */
\r
6 namespace Handbrake.Functions
\r
9 using System.Collections.Generic;
\r
10 using System.Diagnostics;
\r
13 using System.Reflection;
\r
15 using System.Text.RegularExpressions;
\r
16 using System.Threading;
\r
17 using System.Windows.Forms;
\r
18 using System.Xml.Serialization;
\r
20 using HandBrake.ApplicationServices.Model;
\r
21 using HandBrake.ApplicationServices.Parsing;
\r
22 using HandBrake.ApplicationServices.Services.Interfaces;
\r
27 /// Useful functions which various screens can use.
\r
29 public static class Main
\r
32 /// The XML Serializer
\r
34 private static readonly XmlSerializer Ser = new XmlSerializer(typeof(List<Job>));
\r
37 /// Calculate the duration of the selected title and chapters
\r
39 /// <param name="chapterStart">
\r
40 /// The chapter Start.
\r
42 /// <param name="chapterEnd">
\r
43 /// The chapter End.
\r
45 /// <param name="selectedTitle">
\r
46 /// The selected Title.
\r
49 /// The calculated duration.
\r
51 public static TimeSpan CalculateDuration(int chapterStart, int chapterEnd, Title selectedTitle)
\r
53 TimeSpan duration = TimeSpan.FromSeconds(0.0);
\r
56 if (chapterStart != 0 && chapterEnd != 0 && chapterEnd <= selectedTitle.Chapters.Count)
\r
58 for (int i = chapterStart; i <= chapterEnd; i++)
\r
59 duration += selectedTitle.Chapters[i - 1].Duration;
\r
66 /// Set's up the DataGridView on the Chapters tab (frmMain)
\r
68 /// <param name="dataChpt">
\r
69 /// The DataGridView Control
\r
71 /// <param name="chapterEnd">
\r
72 /// The chapter End.
\r
75 /// The chapter naming.
\r
77 public static DataGridView ChapterNaming(DataGridView dataChpt, string chapterEnd)
\r
79 int i = 0, finish = 0;
\r
81 if (chapterEnd != "Auto")
\r
82 int.TryParse(chapterEnd, out finish);
\r
86 int n = dataChpt.Rows.Add();
\r
87 dataChpt.Rows[n].Cells[0].Value = i + 1;
\r
88 dataChpt.Rows[n].Cells[1].Value = "Chapter " + (i + 1);
\r
89 dataChpt.Rows[n].Cells[0].ValueType = typeof(int);
\r
90 dataChpt.Rows[n].Cells[1].ValueType = typeof(string);
\r
98 /// Import a CSV file which contains Chapter Names
\r
100 /// <param name="dataChpt">
\r
101 /// The DataGridView Control
\r
103 /// <param name="filename">
\r
104 /// The filepath and name
\r
106 /// <returns>A Populated DataGridView</returns>
\r
107 public static DataGridView ImportChapterNames(DataGridView dataChpt, string filename)
\r
109 IDictionary<int, string> chapterMap = new Dictionary<int, string>();
\r
112 StreamReader sr = new StreamReader(filename);
\r
113 string csv = sr.ReadLine();
\r
114 while (csv != null)
\r
116 if (csv.Trim() != string.Empty)
\r
118 csv = csv.Replace("\\,", "<!comma!>");
\r
119 string[] contents = csv.Split(',');
\r
121 int.TryParse(contents[0], out chapter);
\r
122 chapterMap.Add(chapter, contents[1].Replace("<!comma!>", ","));
\r
124 csv = sr.ReadLine();
\r
132 foreach (DataGridViewRow item in dataChpt.Rows)
\r
135 chapterMap.TryGetValue((int)item.Cells[0].Value, out name);
\r
136 item.Cells[1].Value = name ?? "Chapter " + item.Cells[0].Value;
\r
143 /// Create a CSV file with the data from the Main Window Chapters tab
\r
145 /// <param name="mainWindow">Main Window</param>
\r
146 /// <param name="filePathName">Path to save the csv file</param>
\r
147 /// <returns>True if successful </returns>
\r
148 public static bool SaveChapterMarkersToCsv(frmMain mainWindow, string filePathName)
\r
152 string csv = string.Empty;
\r
154 foreach (DataGridViewRow row in mainWindow.data_chpt.Rows)
\r
156 csv += row.Cells[0].Value.ToString();
\r
158 csv += row.Cells[1].Value.ToString().Replace(",", "\\,");
\r
159 csv += Environment.NewLine;
\r
161 StreamWriter file = new StreamWriter(filePathName);
\r
167 catch (Exception exc)
\r
169 frmExceptionWindow exceptionWindow = new frmExceptionWindow();
\r
170 exceptionWindow.Setup("Unable to save Chapter Makrers file! \nChapter marker names will NOT be saved in your encode", exc.ToString());
\r
171 exceptionWindow.ShowDialog();
\r
177 /// Function which generates the filename and path automatically based on
\r
178 /// the Source Name, DVD title and DVD Chapters
\r
180 /// <param name="mainWindow">
\r
181 /// The main Window.
\r
184 /// The Generated FileName
\r
186 public static string AutoName(frmMain mainWindow)
\r
188 string autoNamePath = string.Empty;
\r
189 if (mainWindow.drp_dvdtitle.Text != "Automatic")
\r
191 // Get the Source Name
\r
192 string sourceName = mainWindow.SourceName;
\r
194 // Remove any illeagal characters from the source name
\r
195 foreach (char character in Path.GetInvalidFileNameChars())
\r
197 if (autoNamePath != null)
\r
199 sourceName = sourceName.Replace(character.ToString(), string.Empty);
\r
203 if (Properties.Settings.Default.AutoNameRemoveUnderscore)
\r
204 sourceName = sourceName.Replace("_", " ");
\r
206 if (Properties.Settings.Default.AutoNameTitleCase)
\r
207 sourceName = TitleCase(sourceName);
\r
209 // Get the Selected Title Number
\r
210 string[] titlesplit = mainWindow.drp_dvdtitle.Text.Split(' ');
\r
211 string dvdTitle = titlesplit[0].Replace("Automatic", string.Empty);
\r
213 // Get the Chapter Start and Chapter End Numbers
\r
214 string chapterStart = mainWindow.drop_chapterStart.Text.Replace("Auto", string.Empty);
\r
215 string chapterFinish = mainWindow.drop_chapterFinish.Text.Replace("Auto", string.Empty);
\r
216 string combinedChapterTag = chapterStart;
\r
217 if (chapterFinish != chapterStart && chapterFinish != string.Empty)
\r
218 combinedChapterTag = chapterStart + "-" + chapterFinish;
\r
220 // Get the destination filename.
\r
221 string destinationFilename;
\r
222 if (Properties.Settings.Default.autoNameFormat != string.Empty)
\r
224 destinationFilename = Properties.Settings.Default.autoNameFormat;
\r
225 destinationFilename =
\r
226 destinationFilename.Replace("{source}", sourceName).Replace("{title}", dvdTitle).Replace(
\r
227 "{chapters}", combinedChapterTag);
\r
230 destinationFilename = sourceName + "_T" + dvdTitle + "_C" + combinedChapterTag;
\r
232 // Add the appropriate file extension
\r
233 if (mainWindow.drop_format.SelectedIndex == 0)
\r
235 if (Properties.Settings.Default.useM4v || mainWindow.Check_ChapterMarkers.Checked ||
\r
236 mainWindow.AudioSettings.RequiresM4V() || mainWindow.Subtitles.RequiresM4V())
\r
237 destinationFilename += ".m4v";
\r
239 destinationFilename += ".mp4";
\r
241 else if (mainWindow.drop_format.SelectedIndex == 1)
\r
242 destinationFilename += ".mkv";
\r
244 // Now work out the path where the file will be stored.
\r
245 // First case: If the destination box doesn't already contain a path, make one.
\r
246 if (!mainWindow.text_destination.Text.Contains(Path.DirectorySeparatorChar.ToString()))
\r
248 // If there is an auto name path, use it...
\r
249 if (Properties.Settings.Default.autoNamePath.Trim() != string.Empty &&
\r
250 Properties.Settings.Default.autoNamePath.Trim() != "Click 'Browse' to set the default location")
\r
251 autoNamePath = Path.Combine(Properties.Settings.Default.autoNamePath, destinationFilename);
\r
252 else // ...otherwise, output to the source directory
\r
253 autoNamePath = null;
\r
255 else // Otherwise, use the path that is already there.
\r
257 // Use the path and change the file extension to match the previous destination
\r
258 autoNamePath = Path.Combine(Path.GetDirectoryName(mainWindow.text_destination.Text),
\r
259 destinationFilename);
\r
261 if (Path.HasExtension(mainWindow.text_destination.Text))
\r
262 autoNamePath = Path.ChangeExtension(autoNamePath,
\r
263 Path.GetExtension(mainWindow.text_destination.Text));
\r
267 return autoNamePath;
\r
271 /// Get's HandBrakes version data from the CLI.
\r
273 public static void SetCliVersionData()
\r
277 // 0 = SVN Build / Version
\r
279 DateTime lastModified = File.GetLastWriteTime("HandBrakeCLI.exe");
\r
281 if (Properties.Settings.Default.hb_build != 0 && Properties.Settings.Default.cliLastModified == lastModified)
\r
286 Properties.Settings.Default.cliLastModified = lastModified;
\r
288 Process cliProcess = new Process();
\r
289 ProcessStartInfo handBrakeCli = new ProcessStartInfo("HandBrakeCLI.exe", " -u -v0")
\r
291 UseShellExecute = false,
\r
292 RedirectStandardError = true,
\r
293 RedirectStandardOutput = true,
\r
294 CreateNoWindow = true
\r
296 cliProcess.StartInfo = handBrakeCli;
\r
300 cliProcess.Start();
\r
302 // Retrieve standard output and report back to parent thread until the process is complete
\r
303 TextReader stdOutput = cliProcess.StandardError;
\r
305 while (!cliProcess.HasExited)
\r
307 line = stdOutput.ReadLine() ?? string.Empty;
\r
308 Match m = Regex.Match(line, @"HandBrake ([svnM0-9.]*) \(([0-9]*)\)");
\r
309 Match platform = Regex.Match(line, @"- ([A-Za-z0-9\s ]*) -");
\r
313 string version = m.Groups[1].Success ? m.Groups[1].Value : string.Empty;
\r
314 string build = m.Groups[2].Success ? m.Groups[2].Value : string.Empty;
\r
317 int.TryParse(build, out buildValue);
\r
319 Properties.Settings.Default.hb_build = buildValue;
\r
320 Properties.Settings.Default.hb_version = version;
\r
323 if (platform.Success)
\r
325 Properties.Settings.Default.hb_platform = platform.Value.Replace("-", string.Empty).Trim();
\r
328 if (cliProcess.TotalProcessorTime.Seconds > 10) // Don't wait longer than 10 seconds.
\r
330 Process cli = Process.GetProcessById(cliProcess.Id);
\r
331 if (!cli.HasExited)
\r
338 Properties.Settings.Default.Save();
\r
340 catch (Exception e)
\r
342 Properties.Settings.Default.hb_build = 0;
\r
343 Properties.Settings.Default.Save();
\r
345 frmExceptionWindow exceptionWindow = new frmExceptionWindow();
\r
346 exceptionWindow.Setup("Unable to retrieve version information from the CLI.", e.ToString());
\r
347 exceptionWindow.ShowDialog();
\r
352 /// Check if the queue recovery file contains records.
\r
353 /// If it does, it means the last queue did not complete before HandBrake closed.
\r
354 /// So, return a boolean if true.
\r
357 /// True if there is a queue to recover.
\r
359 public static List<string> CheckQueueRecovery()
\r
363 string tempPath = Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.ApplicationData), @"HandBrake\");
\r
364 List<string> queueFiles = new List<string>();
\r
366 DirectoryInfo info = new DirectoryInfo(tempPath);
\r
367 FileInfo[] logFiles = info.GetFiles("*.xml");
\r
368 foreach (FileInfo file in logFiles)
\r
370 if (!file.Name.Contains("hb_queue_recovery"))
\r
373 using (FileStream strm = new FileStream(Path.Combine(file.DirectoryName, file.Name), FileMode.Open, FileAccess.Read))
\r
375 List<Job> list = Ser.Deserialize(strm) as List<Job>;
\r
378 if (list.Count != 0)
\r
380 queueFiles.Add(file.Name);
\r
390 return new List<string>(); // Keep quiet about the error.
\r
395 /// Recover a queue from file.
\r
397 /// <param name="encodeQueue">
\r
398 /// The encode Queue.
\r
400 public static void RecoverQueue(IQueue encodeQueue)
\r
402 DialogResult result = DialogResult.None;
\r
403 List<string> queueFiles = CheckQueueRecovery();
\r
404 if (queueFiles.Count == 1)
\r
406 result = MessageBox.Show(
\r
407 "HandBrake has detected unfinished items on the queue from the last time the application was launched. Would you like to recover these?",
\r
408 "Queue Recovery Possible", MessageBoxButtons.YesNo, MessageBoxIcon.Question);
\r
410 else if (queueFiles.Count > 1)
\r
412 result = MessageBox.Show(
\r
413 "HandBrake has detected multiple unfinished queue files. These will be from multiple instances of HandBrake running. Would you like to recover all unfinished jobs?",
\r
414 "Queue Recovery Possible", MessageBoxButtons.YesNo, MessageBoxIcon.Question);
\r
417 if (result == DialogResult.Yes)
\r
419 foreach (string file in queueFiles)
\r
421 encodeQueue.LoadQueueFromFile(file); // Start Recovery
\r
426 if (IsMultiInstance) return; // Don't tamper with the files if we are multi instance
\r
428 string tempPath = Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.ApplicationData), @"HandBrake\");
\r
429 foreach (string file in queueFiles)
\r
431 if (File.Exists(Path.Combine(tempPath, file)))
\r
432 File.Delete(Path.Combine(tempPath, file));
\r
438 /// Gets a value indicating whether HandBrake is running in multi instance mode
\r
440 /// <returns>True if the UI has another instance running</returns>
\r
441 public static bool IsMultiInstance
\r
445 return Process.GetProcessesByName("HandBrake").Length > 0 ? true : false;
\r
450 /// Clear all the encode log files.
\r
452 public static void ClearLogs()
\r
454 string logDir = Environment.GetFolderPath(Environment.SpecialFolder.ApplicationData) + "\\HandBrake\\logs";
\r
455 if (Directory.Exists(logDir))
\r
457 DirectoryInfo info = new DirectoryInfo(logDir);
\r
458 FileInfo[] logFiles = info.GetFiles("*.txt");
\r
459 foreach (FileInfo file in logFiles)
\r
461 if (!file.Name.Contains("last_scan_log") && !file.Name.Contains("last_encode_log"))
\r
462 File.Delete(file.FullName);
\r
468 /// Clear old log files x days in the past
\r
470 public static void ClearOldLogs()
\r
472 string logDir = Environment.GetFolderPath(Environment.SpecialFolder.ApplicationData) + "\\HandBrake\\logs";
\r
473 if (Directory.Exists(logDir))
\r
475 DirectoryInfo info = new DirectoryInfo(logDir);
\r
476 FileInfo[] logFiles = info.GetFiles("*.txt");
\r
478 foreach (FileInfo file in logFiles)
\r
480 if (file.LastWriteTime < DateTime.Now.AddDays(-30))
\r
482 if (!file.Name.Contains("last_scan_log.txt") && !file.Name.Contains("last_encode_log.txt"))
\r
483 File.Delete(file.FullName);
\r
490 /// Begins checking for an update to HandBrake.
\r
492 /// <param name="callback">The method that will be called when the check is finished.</param>
\r
493 /// <param name="debug">Whether or not to execute this in debug mode.</param>
\r
494 public static void BeginCheckForUpdates(AsyncCallback callback, bool debug)
\r
496 ThreadPool.QueueUserWorkItem(new WaitCallback(delegate
\r
500 // Is this a stable or unstable build?
\r
502 Properties.Settings.Default.hb_build.ToString()
\r
504 ? Properties.Settings.Default.
\r
506 : Properties.Settings.Default.appcast;
\r
508 // Initialize variables
\r
509 WebRequest request = WebRequest.Create(url);
\r
510 WebResponse response = request.GetResponse();
\r
511 AppcastReader reader = new AppcastReader();
\r
513 // Get the data, convert it to a string, and parse it into the AppcastReader
\r
515 new StreamReader(response.GetResponseStream())
\r
518 // Further parse the information
\r
519 string build = reader.Build;
\r
521 int latest = int.Parse(build);
\r
522 int current = Properties.Settings.Default.hb_build;
\r
523 int skip = Properties.Settings.Default.skipversion;
\r
525 // If the user wanted to skip this version, don't report the update
\r
526 if (latest == skip)
\r
528 UpdateCheckInformation info =
\r
529 new UpdateCheckInformation
\r
531 NewVersionAvailable = false,
\r
532 BuildInformation = null
\r
534 callback(new UpdateCheckResult(debug, info));
\r
538 // Set when the last update was
\r
539 Properties.Settings.Default.lastUpdateCheckDate =
\r
541 Properties.Settings.Default.Save();
\r
543 UpdateCheckInformation info2 =
\r
544 new UpdateCheckInformation
\r
546 NewVersionAvailable = latest > current,
\r
547 BuildInformation = reader
\r
549 callback(new UpdateCheckResult(debug, info2));
\r
551 catch (Exception exc)
\r
553 callback(new UpdateCheckResult(debug, new UpdateCheckInformation { Error = exc }));
\r
559 /// End Check for Updates
\r
561 /// <param name="result">
\r
565 /// Update Check information
\r
567 public static UpdateCheckInformation EndCheckForUpdates(IAsyncResult result)
\r
569 UpdateCheckResult checkResult = (UpdateCheckResult)result;
\r
570 return checkResult.Result;
\r
574 /// Map languages and their iso639_2 value into a IDictionary
\r
576 /// <returns>A Dictionary containing the language and iso code</returns>
\r
577 public static IDictionary<string, string> MapLanguages()
\r
579 IDictionary<string, string> languageMap = new Dictionary<string, string>
\r
583 {"Abkhazian", "abk"},
\r
584 {"Afrikaans", "afr"},
\r
586 {"Albanian", "sqi"},
\r
587 {"Amharic", "amh"},
\r
588 {"Arabic", "ara"},
\r
589 {"Aragonese", "arg"},
\r
590 {"Armenian", "hye"},
\r
591 {"Assamese", "asm"},
\r
592 {"Avaric", "ava"},
\r
593 {"Avestan", "ave"},
\r
594 {"Aymara", "aym"},
\r
595 {"Azerbaijani", "aze"},
\r
596 {"Bashkir", "bak"},
\r
597 {"Bambara", "bam"},
\r
598 {"Basque", "eus"},
\r
599 {"Belarusian", "bel"},
\r
600 {"Bengali", "ben"},
\r
601 {"Bihari", "bih"},
\r
602 {"Bislama", "bis"},
\r
603 {"Bosnian", "bos"},
\r
604 {"Breton", "bre"},
\r
605 {"Bulgarian", "bul"},
\r
606 {"Burmese", "mya"},
\r
607 {"Catalan", "cat"},
\r
608 {"Chamorro", "cha"},
\r
609 {"Chechen", "che"},
\r
610 {"Chinese", "zho"},
\r
611 {"Church Slavic", "chu"},
\r
612 {"Chuvash", "chv"},
\r
613 {"Cornish", "cor"},
\r
614 {"Corsican", "cos"},
\r
618 {"Divehi", "div"},
\r
619 {"Nederlands", "nld"},
\r
620 {"Dzongkha", "dzo"},
\r
621 {"English", "eng"},
\r
622 {"Esperanto", "epo"},
\r
623 {"Estonian", "est"},
\r
625 {"Faroese", "fao"},
\r
626 {"Fijian", "fij"},
\r
628 {"Francais", "fra"},
\r
629 {"Western Frisian", "fry"},
\r
631 {"Georgian", "kat"},
\r
632 {"Deutsch", "deu"},
\r
633 {"Gaelic (Scots)", "gla"},
\r
635 {"Galician", "glg"},
\r
637 {"Greek Modern", "ell"},
\r
638 {"Guarani", "grn"},
\r
639 {"Gujarati", "guj"},
\r
640 {"Haitian", "hat"},
\r
642 {"Hebrew", "heb"},
\r
643 {"Herero", "her"},
\r
645 {"Hiri Motu", "hmo"},
\r
646 {"Magyar", "hun"},
\r
648 {"Islenska", "isl"},
\r
650 {"Sichuan Yi", "iii"},
\r
651 {"Inuktitut", "iku"},
\r
652 {"Interlingue", "ile"},
\r
653 {"Interlingua", "ina"},
\r
654 {"Indonesian", "ind"},
\r
655 {"Inupiaq", "ipk"},
\r
656 {"Italiano", "ita"},
\r
657 {"Javanese", "jav"},
\r
658 {"Japanese", "jpn"},
\r
659 {"Kalaallisut", "kal"},
\r
660 {"Kannada", "kan"},
\r
661 {"Kashmiri", "kas"},
\r
662 {"Kanuri", "kau"},
\r
663 {"Kazakh", "kaz"},
\r
664 {"Central Khmer", "khm"},
\r
665 {"Kikuyu", "kik"},
\r
666 {"Kinyarwanda", "kin"},
\r
667 {"Kirghiz", "kir"},
\r
670 {"Korean", "kor"},
\r
671 {"Kuanyama", "kua"},
\r
672 {"Kurdish", "kur"},
\r
675 {"Latvian", "lav"},
\r
676 {"Limburgan", "lim"},
\r
677 {"Lingala", "lin"},
\r
678 {"Lithuanian", "lit"},
\r
679 {"Luxembourgish", "ltz"},
\r
680 {"Luba-Katanga", "lub"},
\r
682 {"Macedonian", "mkd"},
\r
683 {"Marshallese", "mah"},
\r
684 {"Malayalam", "mal"},
\r
686 {"Marathi", "mar"},
\r
688 {"Malagasy", "mlg"},
\r
689 {"Maltese", "mlt"},
\r
690 {"Moldavian", "mol"},
\r
691 {"Mongolian", "mon"},
\r
693 {"Navajo", "nav"},
\r
694 {"Ndebele, South", "nbl"},
\r
695 {"Ndebele, North", "nde"},
\r
696 {"Ndonga", "ndo"},
\r
697 {"Nepali", "nep"},
\r
698 {"Norwegian Nynorsk", "nno"},
\r
699 {"Norwegian Bokmål", "nob"},
\r
701 {"Chichewa; Nyanja", "nya"},
\r
702 {"Occitan", "oci"},
\r
703 {"Ojibwa", "oji"},
\r
706 {"Ossetian", "oss"},
\r
707 {"Panjabi", "pan"},
\r
708 {"Persian", "fas"},
\r
710 {"Polish", "pol"},
\r
711 {"Portugues", "por"},
\r
712 {"Pushto", "pus"},
\r
713 {"Quechua", "que"},
\r
714 {"Romansh", "roh"},
\r
715 {"Romanian", "ron"},
\r
717 {"Russian", "rus"},
\r
719 {"Sanskrit", "san"},
\r
720 {"Serbian", "srp"},
\r
721 {"Hrvatski", "hrv"},
\r
722 {"Sinhala", "sin"},
\r
723 {"Slovak", "slk"},
\r
724 {"Slovenian", "slv"},
\r
725 {"Northern Sami", "sme"},
\r
726 {"Samoan", "smo"},
\r
728 {"Sindhi", "snd"},
\r
729 {"Somali", "som"},
\r
730 {"Sotho Southern", "sot"},
\r
731 {"Espanol", "spa"},
\r
732 {"Sardinian", "srd"},
\r
734 {"Sundanese", "sun"},
\r
735 {"Swahili", "swa"},
\r
736 {"Svenska", "swe"},
\r
737 {"Tahitian", "tah"},
\r
740 {"Telugu", "tel"},
\r
742 {"Tagalog", "tgl"},
\r
744 {"Tibetan", "bod"},
\r
745 {"Tigrinya", "tir"},
\r
747 {"Tswana", "tsn"},
\r
748 {"Tsonga", "tso"},
\r
749 {"Turkmen", "tuk"},
\r
750 {"Turkish", "tur"},
\r
752 {"Uighur", "uig"},
\r
753 {"Ukrainian", "ukr"},
\r
757 {"Vietnamese", "vie"},
\r
758 {"Volapük", "vol"},
\r
760 {"Walloon", "wln"},
\r
763 {"Yiddish", "yid"},
\r
764 {"Yoruba", "yor"},
\r
765 {"Zhuang", "zha"},
\r
768 return languageMap;
\r
772 /// Get a list of available DVD drives which are ready and contain DVD content.
\r
774 /// <returns>A List of Drives with their details</returns>
\r
775 public static List<DriveInformation> GetDrives()
\r
777 List<DriveInformation> drives = new List<DriveInformation>();
\r
778 DriveInfo[] theCollectionOfDrives = DriveInfo.GetDrives();
\r
780 foreach (DriveInfo curDrive in theCollectionOfDrives)
\r
782 if (curDrive.DriveType == DriveType.CDRom && curDrive.IsReady &&
\r
783 File.Exists(curDrive.RootDirectory + "VIDEO_TS\\VIDEO_TS.IFO"))
\r
785 drives.Add(new DriveInformation
\r
788 VolumeLabel = curDrive.VolumeLabel,
\r
789 RootDirectory = curDrive.RootDirectory + "VIDEO_TS"
\r
798 /// Change a string to Title Case/
\r
800 /// <param name="input">
\r
804 /// A string in title case.
\r
806 public static string TitleCase(string input)
\r
808 string[] tokens = input.Split(' ');
\r
809 StringBuilder sb = new StringBuilder(input.Length);
\r
810 foreach (string s in tokens)
\r
812 sb.Append(s[0].ToString().ToUpper());
\r
813 sb.Append(s.Substring(1).ToLower());
\r
817 return sb.ToString().Trim();
\r
821 /// Show the Exception Window
\r
823 /// <param name="shortError">
\r
824 /// The short error.
\r
826 /// <param name="longError">
\r
827 /// The long error.
\r
829 public static void ShowExceptiowWindow(string shortError, string longError)
\r
831 frmExceptionWindow exceptionWindow = new frmExceptionWindow();
\r
832 exceptionWindow.Setup(shortError, longError);
\r
833 exceptionWindow.Show();
\r
837 /// Get The Source from the CLI Query
\r
839 /// <param name="query">Full CLI Query</param>
\r
840 /// <returns>The Source Path</returns>
\r
841 public static string GetSourceFromQuery(string query)
\r
843 int startIndex = query.IndexOf("-i \"");
\r
844 if (startIndex != -1)
\r
846 string input = query.Substring(startIndex).Replace("-i \"", string.Empty).Trim();
\r
848 int closeIndex = input.IndexOf('"');
\r
850 return closeIndex == -1 ? "Unknown" : input.Substring(0, closeIndex);
\r
857 /// Get the Destination from the CLI Query
\r
859 /// <param name="query">Full CLI Query</param>
\r
860 /// <returns>The Destination path</returns>
\r
861 public static string GetDestinationFromQuery(string query)
\r
863 int startIndex = query.IndexOf("-o \"");
\r
864 if (startIndex != -1)
\r
866 string output = query.Substring(startIndex).Replace("-o \"", string.Empty).Trim();
\r
868 int closeIndex = output.IndexOf('"');
\r
870 return closeIndex == -1 ? "Unknown" : output.Substring(0, closeIndex);
\r