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
14 using System.Text.RegularExpressions;
\r
15 using System.Threading;
\r
16 using System.Windows.Forms;
\r
17 using System.Xml.Serialization;
\r
19 using HandBrake.ApplicationServices.Model;
\r
20 using HandBrake.ApplicationServices.Parsing;
\r
21 using HandBrake.ApplicationServices.Services.Interfaces;
\r
26 /// Useful functions which various screens can use.
\r
28 public static class Main
\r
31 /// The XML Serializer
\r
33 private static readonly XmlSerializer Ser = new XmlSerializer(typeof(List<Job>));
\r
36 /// Calculate the duration of the selected title and chapters
\r
38 /// <param name="chapterStart">
\r
39 /// The chapter Start.
\r
41 /// <param name="chapterEnd">
\r
42 /// The chapter End.
\r
44 /// <param name="selectedTitle">
\r
45 /// The selected Title.
\r
48 /// The calculated duration.
\r
50 public static TimeSpan CalculateDuration(int chapterStart, int chapterEnd, Title selectedTitle)
\r
52 TimeSpan duration = TimeSpan.FromSeconds(0.0);
\r
55 if (chapterStart != 0 && chapterEnd != 0 && chapterEnd <= selectedTitle.Chapters.Count)
\r
57 for (int i = chapterStart; i <= chapterEnd; i++)
\r
58 duration += selectedTitle.Chapters[i - 1].Duration;
\r
65 /// Set's up the DataGridView on the Chapters tab (frmMain)
\r
67 /// <param name="dataChpt">
\r
68 /// The DataGridView Control
\r
70 /// <param name="chapterEnd">
\r
71 /// The chapter End.
\r
74 /// The chapter naming.
\r
76 public static DataGridView ChapterNaming(DataGridView dataChpt, string chapterEnd)
\r
78 int i = 0, finish = 0;
\r
80 if (chapterEnd != "Auto")
\r
81 int.TryParse(chapterEnd, out finish);
\r
85 int n = dataChpt.Rows.Add();
\r
86 dataChpt.Rows[n].Cells[0].Value = i + 1;
\r
87 dataChpt.Rows[n].Cells[1].Value = "Chapter " + (i + 1);
\r
88 dataChpt.Rows[n].Cells[0].ValueType = typeof(int);
\r
89 dataChpt.Rows[n].Cells[1].ValueType = typeof(string);
\r
97 /// Import a CSV file which contains Chapter Names
\r
99 /// <param name="dataChpt">
\r
100 /// The DataGridView Control
\r
102 /// <param name="filename">
\r
103 /// The filepath and name
\r
105 /// <returns>A Populated DataGridView</returns>
\r
106 public static DataGridView ImportChapterNames(DataGridView dataChpt, string filename)
\r
108 IDictionary<int, string> chapterMap = new Dictionary<int, string>();
\r
111 StreamReader sr = new StreamReader(filename);
\r
112 string csv = sr.ReadLine();
\r
113 while (csv != null)
\r
115 if (csv.Trim() != string.Empty)
\r
117 csv = csv.Replace("\\,", "<!comma!>");
\r
118 string[] contents = csv.Split(',');
\r
120 int.TryParse(contents[0], out chapter);
\r
121 chapterMap.Add(chapter, contents[1].Replace("<!comma!>", ","));
\r
123 csv = sr.ReadLine();
\r
131 foreach (DataGridViewRow item in dataChpt.Rows)
\r
134 chapterMap.TryGetValue((int)item.Cells[0].Value, out name);
\r
135 item.Cells[1].Value = name ?? "Chapter " + item.Cells[0].Value;
\r
142 /// Create a CSV file with the data from the Main Window Chapters tab
\r
144 /// <param name="mainWindow">Main Window</param>
\r
145 /// <param name="filePathName">Path to save the csv file</param>
\r
146 /// <returns>True if successful </returns>
\r
147 public static bool SaveChapterMarkersToCsv(frmMain mainWindow, string filePathName)
\r
151 string csv = string.Empty;
\r
153 foreach (DataGridViewRow row in mainWindow.data_chpt.Rows)
\r
155 csv += row.Cells[0].Value.ToString();
\r
157 csv += row.Cells[1].Value.ToString().Replace(",", "\\,");
\r
158 csv += Environment.NewLine;
\r
160 StreamWriter file = new StreamWriter(filePathName);
\r
166 catch (Exception exc)
\r
168 frmExceptionWindow exceptionWindow = new frmExceptionWindow();
\r
169 exceptionWindow.Setup("Unable to save Chapter Makrers file! \nChapter marker names will NOT be saved in your encode", exc.ToString());
\r
170 exceptionWindow.ShowDialog();
\r
176 /// Function which generates the filename and path automatically based on
\r
177 /// the Source Name, DVD title and DVD Chapters
\r
179 /// <param name="mainWindow">
\r
180 /// The main Window.
\r
183 /// The Generated FileName
\r
185 public static string AutoName(frmMain mainWindow)
\r
187 string autoNamePath = string.Empty;
\r
188 if (mainWindow.drp_dvdtitle.Text != "Automatic")
\r
190 // Get the Source Name
\r
191 string sourceName = mainWindow.SourceName;
\r
193 // Remove any illeagal characters from the source name
\r
194 foreach (char character in Path.GetInvalidFileNameChars())
\r
196 if (autoNamePath != null)
\r
198 sourceName = sourceName.Replace(character.ToString(), string.Empty);
\r
202 if (Properties.Settings.Default.AutoNameRemoveUnderscore)
\r
203 sourceName = sourceName.Replace("_", " ");
\r
205 if (Properties.Settings.Default.AutoNameTitleCase)
\r
206 sourceName = TitleCase(sourceName);
\r
208 // Get the Selected Title Number
\r
209 string[] titlesplit = mainWindow.drp_dvdtitle.Text.Split(' ');
\r
210 string dvdTitle = titlesplit[0].Replace("Automatic", string.Empty);
\r
212 // Get the Chapter Start and Chapter End Numbers
\r
213 string chapterStart = mainWindow.drop_chapterStart.Text.Replace("Auto", string.Empty);
\r
214 string chapterFinish = mainWindow.drop_chapterFinish.Text.Replace("Auto", string.Empty);
\r
215 string combinedChapterTag = chapterStart;
\r
216 if (chapterFinish != chapterStart && chapterFinish != string.Empty)
\r
217 combinedChapterTag = chapterStart + "-" + chapterFinish;
\r
219 // Get the destination filename.
\r
220 string destinationFilename;
\r
221 if (Properties.Settings.Default.autoNameFormat != string.Empty)
\r
223 destinationFilename = Properties.Settings.Default.autoNameFormat;
\r
224 destinationFilename =
\r
225 destinationFilename.Replace("{source}", sourceName).Replace("{title}", dvdTitle).Replace(
\r
226 "{chapters}", combinedChapterTag);
\r
229 destinationFilename = sourceName + "_T" + dvdTitle + "_C" + combinedChapterTag;
\r
231 // Add the appropriate file extension
\r
232 if (mainWindow.drop_format.SelectedIndex == 0)
\r
234 if (Properties.Settings.Default.useM4v || mainWindow.Check_ChapterMarkers.Checked ||
\r
235 mainWindow.AudioSettings.RequiresM4V() || mainWindow.Subtitles.RequiresM4V())
\r
236 destinationFilename += ".m4v";
\r
238 destinationFilename += ".mp4";
\r
240 else if (mainWindow.drop_format.SelectedIndex == 1)
\r
241 destinationFilename += ".mkv";
\r
243 // Now work out the path where the file will be stored.
\r
244 // First case: If the destination box doesn't already contain a path, make one.
\r
245 if (!mainWindow.text_destination.Text.Contains(Path.DirectorySeparatorChar.ToString()))
\r
247 // If there is an auto name path, use it...
\r
248 if (Properties.Settings.Default.autoNamePath.Trim() != string.Empty &&
\r
249 Properties.Settings.Default.autoNamePath.Trim() != "Click 'Browse' to set the default location")
\r
250 autoNamePath = Path.Combine(Properties.Settings.Default.autoNamePath, destinationFilename);
\r
251 else // ...otherwise, output to the source directory
\r
252 autoNamePath = null;
\r
254 else // Otherwise, use the path that is already there.
\r
256 // Use the path and change the file extension to match the previous destination
\r
257 autoNamePath = Path.Combine(Path.GetDirectoryName(mainWindow.text_destination.Text),
\r
258 destinationFilename);
\r
260 if (Path.HasExtension(mainWindow.text_destination.Text))
\r
261 autoNamePath = Path.ChangeExtension(autoNamePath,
\r
262 Path.GetExtension(mainWindow.text_destination.Text));
\r
266 return autoNamePath;
\r
270 /// Get's HandBrakes version data from the CLI.
\r
272 public static void SetCliVersionData()
\r
276 // 0 = SVN Build / Version
\r
278 DateTime lastModified = File.GetLastWriteTime("HandBrakeCLI.exe");
\r
280 if (Properties.Settings.Default.cliLastModified == lastModified && Properties.Settings.Default.hb_build != 0)
\r
283 Properties.Settings.Default.cliLastModified = lastModified;
\r
285 Process cliProcess = new Process();
\r
286 ProcessStartInfo handBrakeCli = new ProcessStartInfo("HandBrakeCLI.exe", " -u -v0")
\r
288 UseShellExecute = false,
\r
289 RedirectStandardError = true,
\r
290 RedirectStandardOutput = true,
\r
291 CreateNoWindow = true
\r
293 cliProcess.StartInfo = handBrakeCli;
\r
297 cliProcess.Start();
\r
299 // Retrieve standard output and report back to parent thread until the process is complete
\r
300 TextReader stdOutput = cliProcess.StandardError;
\r
302 while (!cliProcess.HasExited)
\r
304 line = stdOutput.ReadLine() ?? string.Empty;
\r
305 Match m = Regex.Match(line, @"HandBrake ([svnM0-9.]*) \([0-9]*\)");
\r
306 Match platform = Regex.Match(line, @"- ([A-Za-z0-9\s ]*) -");
\r
310 string data = line.Replace("(", string.Empty).Replace(")", string.Empty).Replace("HandBrake ", string.Empty);
\r
311 string[] arr = data.Split(' ');
\r
313 Properties.Settings.Default.hb_build = int.Parse(arr[1]);
\r
314 Properties.Settings.Default.hb_version = arr[0];
\r
317 if (platform.Success)
\r
319 Properties.Settings.Default.hb_platform = platform.Value.Replace("-", string.Empty).Trim();
\r
322 if (cliProcess.TotalProcessorTime.Seconds > 10) // Don't wait longer than 10 seconds.
\r
324 Process cli = Process.GetProcessById(cliProcess.Id);
\r
325 if (!cli.HasExited)
\r
332 Properties.Settings.Default.Save();
\r
334 catch (Exception e)
\r
336 frmExceptionWindow exceptionWindow = new frmExceptionWindow();
\r
337 exceptionWindow.Setup("Unable to retrieve version information from the CLI.", e.ToString());
\r
338 exceptionWindow.ShowDialog();
\r
343 /// Check to make sure that the user has an up to date version of the CLI installed.
\r
345 public static void CheckForValidCliVersion()
\r
347 // Make sure we have a recent version for svn builds
\r
348 string version = Properties.Settings.Default.hb_version;
\r
349 if (version.Contains("svn"))
\r
351 version = version.Replace("svn", string.Empty).Trim();
\r
353 int.TryParse(version, out build);
\r
354 if (build < Properties.Settings.Default.hb_min_cli)
\r
357 "It appears you are trying to use a CLI executable that is too old for this version of the HandBrake GUI.\n" +
\r
358 "Please update the HandBrakeCLI.exe to a newer build.\n\n" +
\r
359 "HandBrake build Detected: " + Properties.Settings.Default.hb_version,
\r
361 MessageBoxButtons.OK,
\r
362 MessageBoxIcon.Error);
\r
369 /// Check if the queue recovery file contains records.
\r
370 /// If it does, it means the last queue did not complete before HandBrake closed.
\r
371 /// So, return a boolean if true.
\r
374 /// True if there is a queue to recover.
\r
376 public static List<string> CheckQueueRecovery()
\r
380 string tempPath = Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.ApplicationData), @"HandBrake\");
\r
381 List<string> queueFiles = new List<string>();
\r
383 DirectoryInfo info = new DirectoryInfo(tempPath);
\r
384 FileInfo[] logFiles = info.GetFiles("*.xml");
\r
385 foreach (FileInfo file in logFiles)
\r
387 if (!file.Name.Contains("hb_queue_recovery"))
\r
390 using (FileStream strm = new FileStream(Path.Combine(file.DirectoryName, file.Name), FileMode.Open, FileAccess.Read))
\r
392 List<Job> list = Ser.Deserialize(strm) as List<Job>;
\r
395 if (list.Count != 0)
\r
397 queueFiles.Add(file.Name);
\r
407 return new List<string>(); // Keep quiet about the error.
\r
412 /// Recover a queue from file.
\r
414 /// <param name="encodeQueue">
\r
415 /// The encode Queue.
\r
417 public static void RecoverQueue(IQueue encodeQueue)
\r
419 DialogResult result = DialogResult.None;
\r
420 List<string> queueFiles = CheckQueueRecovery();
\r
421 if (queueFiles.Count == 1)
\r
423 result = MessageBox.Show(
\r
424 "HandBrake has detected unfinished items on the queue from the last time the application was launched. Would you like to recover these?",
\r
425 "Queue Recovery Possible", MessageBoxButtons.YesNo, MessageBoxIcon.Question);
\r
427 else if (queueFiles.Count > 1)
\r
429 result = MessageBox.Show(
\r
430 "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
431 "Queue Recovery Possible", MessageBoxButtons.YesNo, MessageBoxIcon.Question);
\r
434 if (result == DialogResult.Yes)
\r
436 foreach (string file in queueFiles)
\r
438 encodeQueue.LoadQueueFromFile(file); // Start Recovery
\r
443 if (IsMultiInstance) return; // Don't tamper with the files if we are multi instance
\r
445 string tempPath = Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.ApplicationData), @"HandBrake\");
\r
446 foreach (string file in queueFiles)
\r
448 if (File.Exists(Path.Combine(tempPath, file)))
\r
449 File.Delete(Path.Combine(tempPath, file));
\r
455 /// Gets a value indicating whether HandBrake is running in multi instance mode
\r
457 /// <returns>True if the UI has another instance running</returns>
\r
458 public static bool IsMultiInstance
\r
462 return Process.GetProcessesByName("HandBrake").Length > 0 ? true : false;
\r
467 /// Clear all the encode log files.
\r
469 public static void ClearLogs()
\r
471 string logDir = Environment.GetFolderPath(Environment.SpecialFolder.ApplicationData) + "\\HandBrake\\logs";
\r
472 if (Directory.Exists(logDir))
\r
474 DirectoryInfo info = new DirectoryInfo(logDir);
\r
475 FileInfo[] logFiles = info.GetFiles("*.txt");
\r
476 foreach (FileInfo file in logFiles)
\r
478 if (!file.Name.Contains("last_scan_log") && !file.Name.Contains("last_encode_log"))
\r
479 File.Delete(file.FullName);
\r
485 /// Clear old log files x days in the past
\r
487 public static void ClearOldLogs()
\r
489 string logDir = Environment.GetFolderPath(Environment.SpecialFolder.ApplicationData) + "\\HandBrake\\logs";
\r
490 if (Directory.Exists(logDir))
\r
492 DirectoryInfo info = new DirectoryInfo(logDir);
\r
493 FileInfo[] logFiles = info.GetFiles("*.txt");
\r
495 foreach (FileInfo file in logFiles)
\r
497 if (file.LastWriteTime < DateTime.Now.AddDays(-30))
\r
499 if (!file.Name.Contains("last_scan_log.txt") && !file.Name.Contains("last_encode_log.txt"))
\r
500 File.Delete(file.FullName);
\r
507 /// Begins checking for an update to HandBrake.
\r
509 /// <param name="callback">The method that will be called when the check is finished.</param>
\r
510 /// <param name="debug">Whether or not to execute this in debug mode.</param>
\r
511 public static void BeginCheckForUpdates(AsyncCallback callback, bool debug)
\r
513 ThreadPool.QueueUserWorkItem(new WaitCallback(delegate
\r
517 // Is this a stable or unstable build?
\r
519 Properties.Settings.Default.hb_build.ToString()
\r
521 ? Properties.Settings.Default.
\r
523 : Properties.Settings.Default.appcast;
\r
525 // Initialize variables
\r
526 WebRequest request = WebRequest.Create(url);
\r
527 WebResponse response = request.GetResponse();
\r
528 AppcastReader reader = new AppcastReader();
\r
530 // Get the data, convert it to a string, and parse it into the AppcastReader
\r
532 new StreamReader(response.GetResponseStream())
\r
535 // Further parse the information
\r
536 string build = reader.Build;
\r
538 int latest = int.Parse(build);
\r
539 int current = Properties.Settings.Default.hb_build;
\r
540 int skip = Properties.Settings.Default.skipversion;
\r
542 // If the user wanted to skip this version, don't report the update
\r
543 if (latest == skip)
\r
545 UpdateCheckInformation info =
\r
546 new UpdateCheckInformation
\r
548 NewVersionAvailable = false,
\r
549 BuildInformation = null
\r
551 callback(new UpdateCheckResult(debug, info));
\r
555 // Set when the last update was
\r
556 Properties.Settings.Default.lastUpdateCheckDate =
\r
558 Properties.Settings.Default.Save();
\r
560 UpdateCheckInformation info2 =
\r
561 new UpdateCheckInformation
\r
563 NewVersionAvailable = latest > current,
\r
564 BuildInformation = reader
\r
566 callback(new UpdateCheckResult(debug, info2));
\r
568 catch (Exception exc)
\r
570 callback(new UpdateCheckResult(debug, new UpdateCheckInformation { Error = exc }));
\r
576 /// End Check for Updates
\r
578 /// <param name="result">
\r
582 /// Update Check information
\r
584 public static UpdateCheckInformation EndCheckForUpdates(IAsyncResult result)
\r
586 UpdateCheckResult checkResult = (UpdateCheckResult)result;
\r
587 return checkResult.Result;
\r
591 /// Map languages and their iso639_2 value into a IDictionary
\r
593 /// <returns>A Dictionary containing the language and iso code</returns>
\r
594 public static IDictionary<string, string> MapLanguages()
\r
596 IDictionary<string, string> languageMap = new Dictionary<string, string>
\r
600 {"Abkhazian", "abk"},
\r
601 {"Afrikaans", "afr"},
\r
603 {"Albanian", "sqi"},
\r
604 {"Amharic", "amh"},
\r
605 {"Arabic", "ara"},
\r
606 {"Aragonese", "arg"},
\r
607 {"Armenian", "hye"},
\r
608 {"Assamese", "asm"},
\r
609 {"Avaric", "ava"},
\r
610 {"Avestan", "ave"},
\r
611 {"Aymara", "aym"},
\r
612 {"Azerbaijani", "aze"},
\r
613 {"Bashkir", "bak"},
\r
614 {"Bambara", "bam"},
\r
615 {"Basque", "eus"},
\r
616 {"Belarusian", "bel"},
\r
617 {"Bengali", "ben"},
\r
618 {"Bihari", "bih"},
\r
619 {"Bislama", "bis"},
\r
620 {"Bosnian", "bos"},
\r
621 {"Breton", "bre"},
\r
622 {"Bulgarian", "bul"},
\r
623 {"Burmese", "mya"},
\r
624 {"Catalan", "cat"},
\r
625 {"Chamorro", "cha"},
\r
626 {"Chechen", "che"},
\r
627 {"Chinese", "zho"},
\r
628 {"Church Slavic", "chu"},
\r
629 {"Chuvash", "chv"},
\r
630 {"Cornish", "cor"},
\r
631 {"Corsican", "cos"},
\r
635 {"Divehi", "div"},
\r
636 {"Nederlands", "nld"},
\r
637 {"Dzongkha", "dzo"},
\r
638 {"English", "eng"},
\r
639 {"Esperanto", "epo"},
\r
640 {"Estonian", "est"},
\r
642 {"Faroese", "fao"},
\r
643 {"Fijian", "fij"},
\r
645 {"Francais", "fra"},
\r
646 {"Western Frisian", "fry"},
\r
648 {"Georgian", "kat"},
\r
649 {"Deutsch", "deu"},
\r
650 {"Gaelic (Scots)", "gla"},
\r
652 {"Galician", "glg"},
\r
654 {"Greek Modern", "ell"},
\r
655 {"Guarani", "grn"},
\r
656 {"Gujarati", "guj"},
\r
657 {"Haitian", "hat"},
\r
659 {"Hebrew", "heb"},
\r
660 {"Herero", "her"},
\r
662 {"Hiri Motu", "hmo"},
\r
663 {"Magyar", "hun"},
\r
665 {"Islenska", "isl"},
\r
667 {"Sichuan Yi", "iii"},
\r
668 {"Inuktitut", "iku"},
\r
669 {"Interlingue", "ile"},
\r
670 {"Interlingua", "ina"},
\r
671 {"Indonesian", "ind"},
\r
672 {"Inupiaq", "ipk"},
\r
673 {"Italiano", "ita"},
\r
674 {"Javanese", "jav"},
\r
675 {"Japanese", "jpn"},
\r
676 {"Kalaallisut", "kal"},
\r
677 {"Kannada", "kan"},
\r
678 {"Kashmiri", "kas"},
\r
679 {"Kanuri", "kau"},
\r
680 {"Kazakh", "kaz"},
\r
681 {"Central Khmer", "khm"},
\r
682 {"Kikuyu", "kik"},
\r
683 {"Kinyarwanda", "kin"},
\r
684 {"Kirghiz", "kir"},
\r
687 {"Korean", "kor"},
\r
688 {"Kuanyama", "kua"},
\r
689 {"Kurdish", "kur"},
\r
692 {"Latvian", "lav"},
\r
693 {"Limburgan", "lim"},
\r
694 {"Lingala", "lin"},
\r
695 {"Lithuanian", "lit"},
\r
696 {"Luxembourgish", "ltz"},
\r
697 {"Luba-Katanga", "lub"},
\r
699 {"Macedonian", "mkd"},
\r
700 {"Marshallese", "mah"},
\r
701 {"Malayalam", "mal"},
\r
703 {"Marathi", "mar"},
\r
705 {"Malagasy", "mlg"},
\r
706 {"Maltese", "mlt"},
\r
707 {"Moldavian", "mol"},
\r
708 {"Mongolian", "mon"},
\r
710 {"Navajo", "nav"},
\r
711 {"Ndebele, South", "nbl"},
\r
712 {"Ndebele, North", "nde"},
\r
713 {"Ndonga", "ndo"},
\r
714 {"Nepali", "nep"},
\r
715 {"Norwegian Nynorsk", "nno"},
\r
716 {"Norwegian Bokmål", "nob"},
\r
718 {"Chichewa; Nyanja", "nya"},
\r
719 {"Occitan", "oci"},
\r
720 {"Ojibwa", "oji"},
\r
723 {"Ossetian", "oss"},
\r
724 {"Panjabi", "pan"},
\r
725 {"Persian", "fas"},
\r
727 {"Polish", "pol"},
\r
728 {"Portugues", "por"},
\r
729 {"Pushto", "pus"},
\r
730 {"Quechua", "que"},
\r
731 {"Romansh", "roh"},
\r
732 {"Romanian", "ron"},
\r
734 {"Russian", "rus"},
\r
736 {"Sanskrit", "san"},
\r
737 {"Serbian", "srp"},
\r
738 {"Hrvatski", "hrv"},
\r
739 {"Sinhala", "sin"},
\r
740 {"Slovak", "slk"},
\r
741 {"Slovenian", "slv"},
\r
742 {"Northern Sami", "sme"},
\r
743 {"Samoan", "smo"},
\r
745 {"Sindhi", "snd"},
\r
746 {"Somali", "som"},
\r
747 {"Sotho Southern", "sot"},
\r
748 {"Espanol", "spa"},
\r
749 {"Sardinian", "srd"},
\r
751 {"Sundanese", "sun"},
\r
752 {"Swahili", "swa"},
\r
753 {"Svenska", "swe"},
\r
754 {"Tahitian", "tah"},
\r
757 {"Telugu", "tel"},
\r
759 {"Tagalog", "tgl"},
\r
761 {"Tibetan", "bod"},
\r
762 {"Tigrinya", "tir"},
\r
764 {"Tswana", "tsn"},
\r
765 {"Tsonga", "tso"},
\r
766 {"Turkmen", "tuk"},
\r
767 {"Turkish", "tur"},
\r
769 {"Uighur", "uig"},
\r
770 {"Ukrainian", "ukr"},
\r
774 {"Vietnamese", "vie"},
\r
775 {"Volapük", "vol"},
\r
777 {"Walloon", "wln"},
\r
780 {"Yiddish", "yid"},
\r
781 {"Yoruba", "yor"},
\r
782 {"Zhuang", "zha"},
\r
785 return languageMap;
\r
789 /// Get a list of available DVD drives which are ready and contain DVD content.
\r
791 /// <returns>A List of Drives with their details</returns>
\r
792 public static List<DriveInformation> GetDrives()
\r
794 List<DriveInformation> drives = new List<DriveInformation>();
\r
795 DriveInfo[] theCollectionOfDrives = DriveInfo.GetDrives();
\r
797 foreach (DriveInfo curDrive in theCollectionOfDrives)
\r
799 if (curDrive.DriveType == DriveType.CDRom && curDrive.IsReady &&
\r
800 File.Exists(curDrive.RootDirectory + "VIDEO_TS\\VIDEO_TS.IFO"))
\r
802 drives.Add(new DriveInformation
\r
805 VolumeLabel = curDrive.VolumeLabel,
\r
806 RootDirectory = curDrive.RootDirectory + "VIDEO_TS"
\r
815 /// Change a string to Title Case/
\r
817 /// <param name="input">
\r
821 /// A string in title case.
\r
823 public static string TitleCase(string input)
\r
825 string[] tokens = input.Split(' ');
\r
826 StringBuilder sb = new StringBuilder(input.Length);
\r
827 foreach (string s in tokens)
\r
829 sb.Append(s[0].ToString().ToUpper());
\r
830 sb.Append(s.Substring(1).ToLower());
\r
834 return sb.ToString().Trim();
\r
838 /// Show the Exception Window
\r
840 /// <param name="shortError">
\r
841 /// The short error.
\r
843 /// <param name="longError">
\r
844 /// The long error.
\r
846 public static void ShowExceptiowWindow(string shortError, string longError)
\r
848 frmExceptionWindow exceptionWindow = new frmExceptionWindow();
\r
849 exceptionWindow.Setup(shortError, longError);
\r
850 exceptionWindow.Show();
\r
854 /// Get The Source from the CLI Query
\r
856 /// <param name="query">Full CLI Query</param>
\r
857 /// <returns>The Source Path</returns>
\r
858 public static string GetSourceFromQuery(string query)
\r
860 int startIndex = query.IndexOf("-i \"");
\r
861 if (startIndex != -1)
\r
863 string input = query.Substring(startIndex).Replace("-i \"", string.Empty).Trim();
\r
865 int closeIndex = input.IndexOf('"');
\r
867 return closeIndex == -1 ? "Unknown" : input.Substring(0, closeIndex);
\r
874 /// Get the Destination from the CLI Query
\r
876 /// <param name="query">Full CLI Query</param>
\r
877 /// <returns>The Destination path</returns>
\r
878 public static string GetDestinationFromQuery(string query)
\r
880 int startIndex = query.IndexOf("-o \"");
\r
881 if (startIndex != -1)
\r
883 string output = query.Substring(startIndex).Replace("-o \"", string.Empty).Trim();
\r
885 int closeIndex = output.IndexOf('"');
\r
887 return closeIndex == -1 ? "Unknown" : output.Substring(0, closeIndex);
\r