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
8 namespace Handbrake.Functions
\r
11 using System.Collections.Generic;
\r
12 using System.Diagnostics;
\r
15 using System.Reflection;
\r
17 using System.Text.RegularExpressions;
\r
18 using System.Threading;
\r
19 using System.Windows.Forms;
\r
20 using System.Xml.Serialization;
\r
22 using HandBrake.ApplicationServices.Model;
\r
23 using HandBrake.ApplicationServices.Parsing;
\r
24 using HandBrake.ApplicationServices.Services.Interfaces;
\r
29 /// Useful functions which various screens can use.
\r
31 public static class Main
\r
34 /// The XML Serializer
\r
36 private static readonly XmlSerializer Ser = new XmlSerializer(typeof(List<Job>));
\r
39 /// Calculate the duration of the selected title and chapters
\r
41 /// <param name="chapterStart">
\r
42 /// The chapter Start.
\r
44 /// <param name="chapterEnd">
\r
45 /// The chapter End.
\r
47 /// <param name="selectedTitle">
\r
48 /// The selected Title.
\r
51 /// The calculated duration.
\r
53 public static TimeSpan CalculateDuration(int chapterStart, int chapterEnd, Title selectedTitle)
\r
55 TimeSpan duration = TimeSpan.FromSeconds(0.0);
\r
58 if (chapterStart != 0 && chapterEnd != 0 && chapterEnd <= selectedTitle.Chapters.Count)
\r
60 for (int i = chapterStart; i <= chapterEnd; i++)
\r
61 duration += selectedTitle.Chapters[i - 1].Duration;
\r
68 /// Set's up the DataGridView on the Chapters tab (frmMain)
\r
70 /// <param name="dataChpt">
\r
71 /// The DataGridView Control
\r
73 /// <param name="chapterEnd">
\r
74 /// The chapter End.
\r
77 /// The chapter naming.
\r
79 public static DataGridView ChapterNaming(DataGridView dataChpt, string chapterEnd)
\r
81 int i = 0, finish = 0;
\r
83 if (chapterEnd != "Auto")
\r
84 int.TryParse(chapterEnd, out finish);
\r
88 int n = dataChpt.Rows.Add();
\r
89 dataChpt.Rows[n].Cells[0].Value = i + 1;
\r
90 dataChpt.Rows[n].Cells[1].Value = "Chapter " + (i + 1);
\r
91 dataChpt.Rows[n].Cells[0].ValueType = typeof(int);
\r
92 dataChpt.Rows[n].Cells[1].ValueType = typeof(string);
\r
100 /// Import a CSV file which contains Chapter Names
\r
102 /// <param name="dataChpt">
\r
103 /// The DataGridView Control
\r
105 /// <param name="filename">
\r
106 /// The filepath and name
\r
108 /// <returns>A Populated DataGridView</returns>
\r
109 public static DataGridView ImportChapterNames(DataGridView dataChpt, string filename)
\r
111 IDictionary<int, string> chapterMap = new Dictionary<int, string>();
\r
114 StreamReader sr = new StreamReader(filename);
\r
115 string csv = sr.ReadLine();
\r
116 while (csv != null)
\r
118 if (csv.Trim() != string.Empty)
\r
120 csv = csv.Replace("\\,", "<!comma!>");
\r
121 string[] contents = csv.Split(',');
\r
123 int.TryParse(contents[0], out chapter);
\r
124 chapterMap.Add(chapter, contents[1].Replace("<!comma!>", ","));
\r
126 csv = sr.ReadLine();
\r
134 foreach (DataGridViewRow item in dataChpt.Rows)
\r
137 chapterMap.TryGetValue((int)item.Cells[0].Value, out name);
\r
138 item.Cells[1].Value = name ?? "Chapter " + item.Cells[0].Value;
\r
145 /// Create a CSV file with the data from the Main Window Chapters tab
\r
147 /// <param name="mainWindow">Main Window</param>
\r
148 /// <param name="filePathName">Path to save the csv file</param>
\r
149 /// <returns>True if successful </returns>
\r
150 public static bool SaveChapterMarkersToCsv(frmMain mainWindow, string filePathName)
\r
154 string csv = string.Empty;
\r
156 foreach (DataGridViewRow row in mainWindow.data_chpt.Rows)
\r
158 csv += row.Cells[0].Value.ToString();
\r
160 csv += row.Cells[1].Value.ToString().Replace(",", "\\,");
\r
161 csv += Environment.NewLine;
\r
163 StreamWriter file = new StreamWriter(filePathName);
\r
169 catch (Exception exc)
\r
171 frmExceptionWindow exceptionWindow = new frmExceptionWindow();
\r
172 exceptionWindow.Setup("Unable to save Chapter Makrers file! \nChapter marker names will NOT be saved in your encode", exc.ToString());
\r
173 exceptionWindow.ShowDialog();
\r
179 /// Function which generates the filename and path automatically based on
\r
180 /// the Source Name, DVD title and DVD Chapters
\r
182 /// <param name="mainWindow">
\r
183 /// The main Window.
\r
186 /// The Generated FileName
\r
188 public static string AutoName(frmMain mainWindow)
\r
190 string autoNamePath = string.Empty;
\r
191 if (mainWindow.drp_dvdtitle.Text != "Automatic")
\r
193 // Get the Source Name and remove any invalid characters
\r
194 string sourceName = Path.GetInvalidFileNameChars().Aggregate(mainWindow.SourceName, (current, character) => current.Replace(character.ToString(), string.Empty));
\r
196 if (Properties.Settings.Default.AutoNameRemoveUnderscore)
\r
197 sourceName = sourceName.Replace("_", " ");
\r
199 if (Properties.Settings.Default.AutoNameTitleCase)
\r
200 sourceName = TitleCase(sourceName);
\r
202 // Get the Selected Title Number
\r
203 string[] titlesplit = mainWindow.drp_dvdtitle.Text.Split(' ');
\r
204 string dvdTitle = titlesplit[0].Replace("Automatic", string.Empty);
\r
206 // Get the Chapter Start and Chapter End Numbers
\r
207 string chapterStart = mainWindow.drop_chapterStart.Text.Replace("Auto", string.Empty);
\r
208 string chapterFinish = mainWindow.drop_chapterFinish.Text.Replace("Auto", string.Empty);
\r
209 string combinedChapterTag = chapterStart;
\r
210 if (chapterFinish != chapterStart && chapterFinish != string.Empty)
\r
211 combinedChapterTag = chapterStart + "-" + chapterFinish;
\r
213 // Get the destination filename.
\r
214 string destinationFilename;
\r
215 if (Properties.Settings.Default.autoNameFormat != string.Empty)
\r
217 destinationFilename = Properties.Settings.Default.autoNameFormat;
\r
218 destinationFilename = destinationFilename.Replace("{source}", sourceName)
\r
219 .Replace("{title}", dvdTitle)
\r
220 .Replace("{chapters}", combinedChapterTag);
\r
223 destinationFilename = sourceName + "_T" + dvdTitle + "_C" + combinedChapterTag;
\r
225 // Add the appropriate file extension
\r
226 if (mainWindow.drop_format.SelectedIndex == 0)
\r
228 destinationFilename += Properties.Settings.Default.useM4v || mainWindow.Check_ChapterMarkers.Checked ||
\r
229 mainWindow.AudioSettings.RequiresM4V() || mainWindow.Subtitles.RequiresM4V()
\r
233 else if (mainWindow.drop_format.SelectedIndex == 1)
\r
234 destinationFilename += ".mkv";
\r
236 // Now work out the path where the file will be stored.
\r
237 // First case: If the destination box doesn't already contain a path, make one.
\r
238 if (!mainWindow.text_destination.Text.Contains(Path.DirectorySeparatorChar.ToString()))
\r
240 // If there is an auto name path, use it...
\r
241 if (Properties.Settings.Default.autoNamePath.Trim() == "{source}" && !string.IsNullOrEmpty(mainWindow.sourcePath))
\r
243 autoNamePath = Path.Combine(Path.GetDirectoryName(mainWindow.sourcePath), destinationFilename);
\r
244 if (autoNamePath == mainWindow.sourcePath)
\r
246 // Append out_ to files that already exist or is the source file
\r
247 autoNamePath = Path.Combine(Path.GetDirectoryName(mainWindow.sourcePath), "output_" + destinationFilename);
\r
250 else if (Properties.Settings.Default.autoNamePath.Trim() != string.Empty && Properties.Settings.Default.autoNamePath.Trim() != "Click 'Browse' to set the default location")
\r
252 autoNamePath = Path.Combine(Properties.Settings.Default.autoNamePath, destinationFilename);
\r
254 else // ...otherwise, output to the source directory
\r
255 autoNamePath = null;
\r
257 else // Otherwise, use the path that is already there.
\r
259 // Use the path and change the file extension to match the previous destination
\r
260 autoNamePath = Path.Combine(Path.GetDirectoryName(mainWindow.text_destination.Text), destinationFilename);
\r
262 if (Path.HasExtension(mainWindow.text_destination.Text))
\r
263 autoNamePath = Path.ChangeExtension(autoNamePath,
\r
264 Path.GetExtension(mainWindow.text_destination.Text));
\r
268 return autoNamePath;
\r
272 /// Get's HandBrakes version data from the CLI.
\r
274 public static void SetCliVersionData()
\r
278 // 0 = SVN Build / Version
\r
280 DateTime lastModified = File.GetLastWriteTime("HandBrakeCLI.exe");
\r
282 if (Properties.Settings.Default.hb_build != 0 && Properties.Settings.Default.cliLastModified == lastModified)
\r
287 Properties.Settings.Default.cliLastModified = lastModified;
\r
289 Process cliProcess = new Process();
\r
290 ProcessStartInfo handBrakeCli = new ProcessStartInfo("HandBrakeCLI.exe", " -u -v0")
\r
292 UseShellExecute = false,
\r
293 RedirectStandardError = true,
\r
294 RedirectStandardOutput = true,
\r
295 CreateNoWindow = true
\r
297 cliProcess.StartInfo = handBrakeCli;
\r
301 cliProcess.Start();
\r
303 // Retrieve standard output and report back to parent thread until the process is complete
\r
304 TextReader stdOutput = cliProcess.StandardError;
\r
306 while (!cliProcess.HasExited)
\r
308 line = stdOutput.ReadLine() ?? string.Empty;
\r
309 Match m = Regex.Match(line, @"HandBrake ([svnM0-9.]*) \(([0-9]*)\)");
\r
310 Match platform = Regex.Match(line, @"- ([A-Za-z0-9\s ]*) -");
\r
314 string version = m.Groups[1].Success ? m.Groups[1].Value : string.Empty;
\r
315 string build = m.Groups[2].Success ? m.Groups[2].Value : string.Empty;
\r
318 int.TryParse(build, out buildValue);
\r
320 Properties.Settings.Default.hb_build = buildValue;
\r
321 Properties.Settings.Default.hb_version = version;
\r
324 if (platform.Success)
\r
326 Properties.Settings.Default.hb_platform = platform.Value.Replace("-", string.Empty).Trim();
\r
329 if (cliProcess.TotalProcessorTime.Seconds > 10) // Don't wait longer than 10 seconds.
\r
331 Process cli = Process.GetProcessById(cliProcess.Id);
\r
332 if (!cli.HasExited)
\r
339 Properties.Settings.Default.Save();
\r
341 catch (Exception e)
\r
343 Properties.Settings.Default.hb_build = 0;
\r
344 Properties.Settings.Default.Save();
\r
346 frmExceptionWindow exceptionWindow = new frmExceptionWindow();
\r
347 exceptionWindow.Setup("Unable to retrieve version information from the CLI.", e.ToString());
\r
348 exceptionWindow.ShowDialog();
\r
353 /// Check if the queue recovery file contains records.
\r
354 /// If it does, it means the last queue did not complete before HandBrake closed.
\r
355 /// So, return a boolean if true.
\r
358 /// True if there is a queue to recover.
\r
360 public static List<string> CheckQueueRecovery()
\r
364 string tempPath = Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.ApplicationData), @"HandBrake\");
\r
365 List<string> queueFiles = new List<string>();
\r
367 DirectoryInfo info = new DirectoryInfo(tempPath);
\r
368 FileInfo[] logFiles = info.GetFiles("*.xml");
\r
369 foreach (FileInfo file in logFiles)
\r
371 if (!file.Name.Contains("hb_queue_recovery"))
\r
374 using (FileStream strm = new FileStream(Path.Combine(file.DirectoryName, file.Name), FileMode.Open, FileAccess.Read))
\r
376 List<Job> list = Ser.Deserialize(strm) as List<Job>;
\r
379 if (list.Count != 0)
\r
381 queueFiles.Add(file.Name);
\r
391 return new List<string>(); // Keep quiet about the error.
\r
396 /// Recover a queue from file.
\r
398 /// <param name="encodeQueue">
\r
399 /// The encode Queue.
\r
401 public static void RecoverQueue(IQueue encodeQueue)
\r
403 DialogResult result = DialogResult.None;
\r
404 List<string> queueFiles = CheckQueueRecovery();
\r
405 if (queueFiles.Count == 1)
\r
407 result = MessageBox.Show(
\r
408 "HandBrake has detected unfinished items on the queue from the last time the application was launched. Would you like to recover these?",
\r
409 "Queue Recovery Possible", MessageBoxButtons.YesNo, MessageBoxIcon.Question);
\r
411 else if (queueFiles.Count > 1)
\r
413 result = MessageBox.Show(
\r
414 "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
415 "Queue Recovery Possible", MessageBoxButtons.YesNo, MessageBoxIcon.Question);
\r
418 if (result == DialogResult.Yes)
\r
420 foreach (string file in queueFiles)
\r
422 encodeQueue.LoadQueueFromFile(file); // Start Recovery
\r
427 if (IsMultiInstance) return; // Don't tamper with the files if we are multi instance
\r
429 string tempPath = Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.ApplicationData), @"HandBrake\");
\r
430 foreach (string file in queueFiles)
\r
432 if (File.Exists(Path.Combine(tempPath, file)))
\r
433 File.Delete(Path.Combine(tempPath, file));
\r
439 /// Gets a value indicating whether HandBrake is running in multi instance mode
\r
441 /// <returns>True if the UI has another instance running</returns>
\r
442 public static bool IsMultiInstance
\r
446 return Process.GetProcessesByName("HandBrake").Length > 0 ? true : false;
\r
451 /// Clear all the encode log files.
\r
453 public static void ClearLogs()
\r
455 string logDir = Environment.GetFolderPath(Environment.SpecialFolder.ApplicationData) + "\\HandBrake\\logs";
\r
456 if (Directory.Exists(logDir))
\r
458 DirectoryInfo info = new DirectoryInfo(logDir);
\r
459 FileInfo[] logFiles = info.GetFiles("*.txt");
\r
460 foreach (FileInfo file in logFiles)
\r
462 if (!file.Name.Contains("last_scan_log") && !file.Name.Contains("last_encode_log"))
\r
463 File.Delete(file.FullName);
\r
469 /// Clear old log files x days in the past
\r
471 public static void ClearOldLogs()
\r
473 string logDir = Environment.GetFolderPath(Environment.SpecialFolder.ApplicationData) + "\\HandBrake\\logs";
\r
474 if (Directory.Exists(logDir))
\r
476 DirectoryInfo info = new DirectoryInfo(logDir);
\r
477 FileInfo[] logFiles = info.GetFiles("*.txt");
\r
479 foreach (FileInfo file in logFiles)
\r
481 if (file.LastWriteTime < DateTime.Now.AddDays(-30))
\r
483 if (!file.Name.Contains("last_scan_log.txt") && !file.Name.Contains("last_encode_log.txt"))
\r
484 File.Delete(file.FullName);
\r
491 /// Begins checking for an update to HandBrake.
\r
493 /// <param name="callback">The method that will be called when the check is finished.</param>
\r
494 /// <param name="debug">Whether or not to execute this in debug mode.</param>
\r
495 public static void BeginCheckForUpdates(AsyncCallback callback, bool debug)
\r
497 ThreadPool.QueueUserWorkItem(new WaitCallback(delegate
\r
501 // Is this a stable or unstable build?
\r
503 Properties.Settings.Default.hb_build.ToString()
\r
505 ? Properties.Settings.Default.
\r
507 : Properties.Settings.Default.appcast;
\r
509 // Initialize variables
\r
510 WebRequest request = WebRequest.Create(url);
\r
511 WebResponse response = request.GetResponse();
\r
512 AppcastReader reader = new AppcastReader();
\r
514 // Get the data, convert it to a string, and parse it into the AppcastReader
\r
516 new StreamReader(response.GetResponseStream())
\r
519 // Further parse the information
\r
520 string build = reader.Build;
\r
522 int latest = int.Parse(build);
\r
523 int current = Properties.Settings.Default.hb_build;
\r
524 int skip = Properties.Settings.Default.skipversion;
\r
526 // If the user wanted to skip this version, don't report the update
\r
527 if (latest == skip)
\r
529 UpdateCheckInformation info =
\r
530 new UpdateCheckInformation
\r
532 NewVersionAvailable = false,
\r
533 BuildInformation = null
\r
535 callback(new UpdateCheckResult(debug, info));
\r
539 // Set when the last update was
\r
540 Properties.Settings.Default.lastUpdateCheckDate =
\r
542 Properties.Settings.Default.Save();
\r
544 UpdateCheckInformation info2 =
\r
545 new UpdateCheckInformation
\r
547 NewVersionAvailable = latest > current,
\r
548 BuildInformation = reader
\r
550 callback(new UpdateCheckResult(debug, info2));
\r
552 catch (Exception exc)
\r
554 callback(new UpdateCheckResult(debug, new UpdateCheckInformation { Error = exc }));
\r
560 /// End Check for Updates
\r
562 /// <param name="result">
\r
566 /// Update Check information
\r
568 public static UpdateCheckInformation EndCheckForUpdates(IAsyncResult result)
\r
570 UpdateCheckResult checkResult = (UpdateCheckResult)result;
\r
571 return checkResult.Result;
\r
575 /// Map languages and their iso639_2 value into a IDictionary
\r
577 /// <returns>A Dictionary containing the language and iso code</returns>
\r
578 public static IDictionary<string, string> MapLanguages()
\r
580 IDictionary<string, string> languageMap = new Dictionary<string, string>
\r
584 {"Abkhazian", "abk"},
\r
585 {"Afrikaans", "afr"},
\r
587 {"Albanian", "sqi"},
\r
588 {"Amharic", "amh"},
\r
589 {"Arabic", "ara"},
\r
590 {"Aragonese", "arg"},
\r
591 {"Armenian", "hye"},
\r
592 {"Assamese", "asm"},
\r
593 {"Avaric", "ava"},
\r
594 {"Avestan", "ave"},
\r
595 {"Aymara", "aym"},
\r
596 {"Azerbaijani", "aze"},
\r
597 {"Bashkir", "bak"},
\r
598 {"Bambara", "bam"},
\r
599 {"Basque", "eus"},
\r
600 {"Belarusian", "bel"},
\r
601 {"Bengali", "ben"},
\r
602 {"Bihari", "bih"},
\r
603 {"Bislama", "bis"},
\r
604 {"Bosnian", "bos"},
\r
605 {"Breton", "bre"},
\r
606 {"Bulgarian", "bul"},
\r
607 {"Burmese", "mya"},
\r
608 {"Catalan", "cat"},
\r
609 {"Chamorro", "cha"},
\r
610 {"Chechen", "che"},
\r
611 {"Chinese", "zho"},
\r
612 {"Church Slavic", "chu"},
\r
613 {"Chuvash", "chv"},
\r
614 {"Cornish", "cor"},
\r
615 {"Corsican", "cos"},
\r
619 {"Divehi", "div"},
\r
620 {"Nederlands", "nld"},
\r
621 {"Dzongkha", "dzo"},
\r
622 {"English", "eng"},
\r
623 {"Esperanto", "epo"},
\r
624 {"Estonian", "est"},
\r
626 {"Faroese", "fao"},
\r
627 {"Fijian", "fij"},
\r
629 {"Francais", "fra"},
\r
630 {"Western Frisian", "fry"},
\r
632 {"Georgian", "kat"},
\r
633 {"Deutsch", "deu"},
\r
634 {"Gaelic (Scots)", "gla"},
\r
636 {"Galician", "glg"},
\r
638 {"Greek Modern", "ell"},
\r
639 {"Guarani", "grn"},
\r
640 {"Gujarati", "guj"},
\r
641 {"Haitian", "hat"},
\r
643 {"Hebrew", "heb"},
\r
644 {"Herero", "her"},
\r
646 {"Hiri Motu", "hmo"},
\r
647 {"Magyar", "hun"},
\r
649 {"Islenska", "isl"},
\r
651 {"Sichuan Yi", "iii"},
\r
652 {"Inuktitut", "iku"},
\r
653 {"Interlingue", "ile"},
\r
654 {"Interlingua", "ina"},
\r
655 {"Indonesian", "ind"},
\r
656 {"Inupiaq", "ipk"},
\r
657 {"Italiano", "ita"},
\r
658 {"Javanese", "jav"},
\r
659 {"Japanese", "jpn"},
\r
660 {"Kalaallisut", "kal"},
\r
661 {"Kannada", "kan"},
\r
662 {"Kashmiri", "kas"},
\r
663 {"Kanuri", "kau"},
\r
664 {"Kazakh", "kaz"},
\r
665 {"Central Khmer", "khm"},
\r
666 {"Kikuyu", "kik"},
\r
667 {"Kinyarwanda", "kin"},
\r
668 {"Kirghiz", "kir"},
\r
671 {"Korean", "kor"},
\r
672 {"Kuanyama", "kua"},
\r
673 {"Kurdish", "kur"},
\r
676 {"Latvian", "lav"},
\r
677 {"Limburgan", "lim"},
\r
678 {"Lingala", "lin"},
\r
679 {"Lithuanian", "lit"},
\r
680 {"Luxembourgish", "ltz"},
\r
681 {"Luba-Katanga", "lub"},
\r
683 {"Macedonian", "mkd"},
\r
684 {"Marshallese", "mah"},
\r
685 {"Malayalam", "mal"},
\r
687 {"Marathi", "mar"},
\r
689 {"Malagasy", "mlg"},
\r
690 {"Maltese", "mlt"},
\r
691 {"Moldavian", "mol"},
\r
692 {"Mongolian", "mon"},
\r
694 {"Navajo", "nav"},
\r
695 {"Ndebele, South", "nbl"},
\r
696 {"Ndebele, North", "nde"},
\r
697 {"Ndonga", "ndo"},
\r
698 {"Nepali", "nep"},
\r
699 {"Norwegian Nynorsk", "nno"},
\r
700 {"Norwegian Bokmål", "nob"},
\r
702 {"Chichewa; Nyanja", "nya"},
\r
703 {"Occitan", "oci"},
\r
704 {"Ojibwa", "oji"},
\r
707 {"Ossetian", "oss"},
\r
708 {"Panjabi", "pan"},
\r
709 {"Persian", "fas"},
\r
711 {"Polish", "pol"},
\r
712 {"Portugues", "por"},
\r
713 {"Pushto", "pus"},
\r
714 {"Quechua", "que"},
\r
715 {"Romansh", "roh"},
\r
716 {"Romanian", "ron"},
\r
718 {"Russian", "rus"},
\r
720 {"Sanskrit", "san"},
\r
721 {"Serbian", "srp"},
\r
722 {"Hrvatski", "hrv"},
\r
723 {"Sinhala", "sin"},
\r
724 {"Slovak", "slk"},
\r
725 {"Slovenian", "slv"},
\r
726 {"Northern Sami", "sme"},
\r
727 {"Samoan", "smo"},
\r
729 {"Sindhi", "snd"},
\r
730 {"Somali", "som"},
\r
731 {"Sotho Southern", "sot"},
\r
732 {"Espanol", "spa"},
\r
733 {"Sardinian", "srd"},
\r
735 {"Sundanese", "sun"},
\r
736 {"Swahili", "swa"},
\r
737 {"Svenska", "swe"},
\r
738 {"Tahitian", "tah"},
\r
741 {"Telugu", "tel"},
\r
743 {"Tagalog", "tgl"},
\r
745 {"Tibetan", "bod"},
\r
746 {"Tigrinya", "tir"},
\r
748 {"Tswana", "tsn"},
\r
749 {"Tsonga", "tso"},
\r
750 {"Turkmen", "tuk"},
\r
751 {"Turkish", "tur"},
\r
753 {"Uighur", "uig"},
\r
754 {"Ukrainian", "ukr"},
\r
758 {"Vietnamese", "vie"},
\r
759 {"Volapük", "vol"},
\r
761 {"Walloon", "wln"},
\r
764 {"Yiddish", "yid"},
\r
765 {"Yoruba", "yor"},
\r
766 {"Zhuang", "zha"},
\r
769 return languageMap;
\r
773 /// Get a list of available DVD drives which are ready and contain DVD content.
\r
775 /// <returns>A List of Drives with their details</returns>
\r
776 public static List<DriveInformation> GetDrives()
\r
778 List<DriveInformation> drives = new List<DriveInformation>();
\r
779 DriveInfo[] theCollectionOfDrives = DriveInfo.GetDrives();
\r
781 foreach (DriveInfo curDrive in theCollectionOfDrives)
\r
783 if (curDrive.DriveType == DriveType.CDRom && curDrive.IsReady &&
\r
784 File.Exists(curDrive.RootDirectory + "VIDEO_TS\\VIDEO_TS.IFO"))
\r
786 drives.Add(new DriveInformation
\r
789 VolumeLabel = curDrive.VolumeLabel,
\r
790 RootDirectory = curDrive.RootDirectory + "VIDEO_TS"
\r
799 /// Change a string to Title Case/
\r
801 /// <param name="input">
\r
805 /// A string in title case.
\r
807 public static string TitleCase(string input)
\r
809 string[] tokens = input.Split(' ');
\r
810 StringBuilder sb = new StringBuilder(input.Length);
\r
811 foreach (string s in tokens)
\r
813 sb.Append(s[0].ToString().ToUpper());
\r
814 sb.Append(s.Substring(1).ToLower());
\r
818 return sb.ToString().Trim();
\r
822 /// Show the Exception Window
\r
824 /// <param name="shortError">
\r
825 /// The short error.
\r
827 /// <param name="longError">
\r
828 /// The long error.
\r
830 public static void ShowExceptiowWindow(string shortError, string longError)
\r
832 frmExceptionWindow exceptionWindow = new frmExceptionWindow();
\r
833 exceptionWindow.Setup(shortError, longError);
\r
834 exceptionWindow.Show();
\r
838 /// Get The Source from the CLI Query
\r
840 /// <param name="query">Full CLI Query</param>
\r
841 /// <returns>The Source Path</returns>
\r
842 public static string GetSourceFromQuery(string query)
\r
844 int startIndex = query.IndexOf("-i \"");
\r
845 if (startIndex != -1)
\r
847 string input = query.Substring(startIndex).Replace("-i \"", string.Empty).Trim();
\r
849 int closeIndex = input.IndexOf('"');
\r
851 return closeIndex == -1 ? "Unknown" : input.Substring(0, closeIndex);
\r
858 /// Get the Destination from the CLI Query
\r
860 /// <param name="query">Full CLI Query</param>
\r
861 /// <returns>The Destination path</returns>
\r
862 public static string GetDestinationFromQuery(string query)
\r
864 int startIndex = query.IndexOf("-o \"");
\r
865 if (startIndex != -1)
\r
867 string output = query.Substring(startIndex).Replace("-o \"", string.Empty).Trim();
\r
869 int closeIndex = output.IndexOf('"');
\r
871 return closeIndex == -1 ? "Unknown" : output.Substring(0, closeIndex);
\r