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 public static void RecoverQueue(IQueue encodeQueue)
\r
416 DialogResult result = DialogResult.None;
\r
417 List<string> queueFiles = CheckQueueRecovery();
\r
418 if (queueFiles.Count == 1)
\r
420 result = MessageBox.Show(
\r
421 "HandBrake has detected unfinished items on the queue from the last time the application was launched. Would you like to recover these?",
\r
422 "Queue Recovery Possible", MessageBoxButtons.YesNo, MessageBoxIcon.Question);
\r
424 else if (queueFiles.Count > 1)
\r
426 result = MessageBox.Show(
\r
427 "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
428 "Queue Recovery Possible", MessageBoxButtons.YesNo, MessageBoxIcon.Question);
\r
431 if (result == DialogResult.Yes)
\r
433 foreach (string file in queueFiles)
\r
435 encodeQueue.LoadQueueFromFile(file); // Start Recovery
\r
440 if (IsMultiInstance) return; // Don't tamper with the files if we are multi instance
\r
442 string tempPath = Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.ApplicationData), @"HandBrake\");
\r
443 foreach (string file in queueFiles)
\r
445 if (File.Exists(Path.Combine(tempPath, file)))
\r
446 File.Delete(Path.Combine(tempPath, file));
\r
452 /// Checks if this HandBrake is running multiple instances
\r
454 /// <returns>True if the UI has another instance running</returns>
\r
455 public static bool IsMultiInstance
\r
459 return Process.GetProcessesByName("HandBrake").Length > 0 ? true : false;
\r
464 /// Clear all the encode log files.
\r
466 public static void ClearLogs()
\r
468 string logDir = Environment.GetFolderPath(Environment.SpecialFolder.ApplicationData) + "\\HandBrake\\logs";
\r
469 if (Directory.Exists(logDir))
\r
471 DirectoryInfo info = new DirectoryInfo(logDir);
\r
472 FileInfo[] logFiles = info.GetFiles("*.txt");
\r
473 foreach (FileInfo file in logFiles)
\r
475 if (!file.Name.Contains("last_scan_log") && !file.Name.Contains("last_encode_log"))
\r
476 File.Delete(file.FullName);
\r
482 /// Clear old log files x days in the past
\r
484 public static void ClearOldLogs()
\r
486 string logDir = Environment.GetFolderPath(Environment.SpecialFolder.ApplicationData) + "\\HandBrake\\logs";
\r
487 if (Directory.Exists(logDir))
\r
489 DirectoryInfo info = new DirectoryInfo(logDir);
\r
490 FileInfo[] logFiles = info.GetFiles("*.txt");
\r
492 foreach (FileInfo file in logFiles)
\r
494 if (file.LastWriteTime < DateTime.Now.AddDays(-30))
\r
496 if (!file.Name.Contains("last_scan_log.txt") && !file.Name.Contains("last_encode_log.txt"))
\r
497 File.Delete(file.FullName);
\r
504 /// Begins checking for an update to HandBrake.
\r
506 /// <param name="callback">The method that will be called when the check is finished.</param>
\r
507 /// <param name="debug">Whether or not to execute this in debug mode.</param>
\r
508 public static void BeginCheckForUpdates(AsyncCallback callback, bool debug)
\r
510 ThreadPool.QueueUserWorkItem(new WaitCallback(delegate
\r
514 // Is this a stable or unstable build?
\r
516 Properties.Settings.Default.hb_build.ToString()
\r
518 ? Properties.Settings.Default.
\r
520 : Properties.Settings.Default.appcast;
\r
522 // Initialize variables
\r
523 WebRequest request = WebRequest.Create(url);
\r
524 WebResponse response = request.GetResponse();
\r
525 AppcastReader reader = new AppcastReader();
\r
527 // Get the data, convert it to a string, and parse it into the AppcastReader
\r
529 new StreamReader(response.GetResponseStream())
\r
532 // Further parse the information
\r
533 string build = reader.Build;
\r
535 int latest = int.Parse(build);
\r
536 int current = Properties.Settings.Default.hb_build;
\r
537 int skip = Properties.Settings.Default.skipversion;
\r
539 // If the user wanted to skip this version, don't report the update
\r
540 if (latest == skip)
\r
542 UpdateCheckInformation info =
\r
543 new UpdateCheckInformation
\r
545 NewVersionAvailable = false,
\r
546 BuildInformation = null
\r
548 callback(new UpdateCheckResult(debug, info));
\r
552 // Set when the last update was
\r
553 Properties.Settings.Default.lastUpdateCheckDate =
\r
555 Properties.Settings.Default.Save();
\r
557 UpdateCheckInformation info2 =
\r
558 new UpdateCheckInformation
\r
560 NewVersionAvailable = latest > current,
\r
561 BuildInformation = reader
\r
563 callback(new UpdateCheckResult(debug, info2));
\r
565 catch (Exception exc)
\r
567 callback(new UpdateCheckResult(debug, new UpdateCheckInformation { Error = exc }));
\r
573 /// End Check for Updates
\r
575 /// <param name="result">
\r
579 /// Update Check information
\r
581 public static UpdateCheckInformation EndCheckForUpdates(IAsyncResult result)
\r
583 UpdateCheckResult checkResult = (UpdateCheckResult)result;
\r
584 return checkResult.Result;
\r
588 /// Map languages and their iso639_2 value into a IDictionary
\r
590 /// <returns>A Dictionary containing the language and iso code</returns>
\r
591 public static IDictionary<string, string> MapLanguages()
\r
593 IDictionary<string, string> languageMap = new Dictionary<string, string>
\r
597 {"Abkhazian", "abk"},
\r
598 {"Afrikaans", "afr"},
\r
600 {"Albanian", "sqi"},
\r
601 {"Amharic", "amh"},
\r
602 {"Arabic", "ara"},
\r
603 {"Aragonese", "arg"},
\r
604 {"Armenian", "hye"},
\r
605 {"Assamese", "asm"},
\r
606 {"Avaric", "ava"},
\r
607 {"Avestan", "ave"},
\r
608 {"Aymara", "aym"},
\r
609 {"Azerbaijani", "aze"},
\r
610 {"Bashkir", "bak"},
\r
611 {"Bambara", "bam"},
\r
612 {"Basque", "eus"},
\r
613 {"Belarusian", "bel"},
\r
614 {"Bengali", "ben"},
\r
615 {"Bihari", "bih"},
\r
616 {"Bislama", "bis"},
\r
617 {"Bosnian", "bos"},
\r
618 {"Breton", "bre"},
\r
619 {"Bulgarian", "bul"},
\r
620 {"Burmese", "mya"},
\r
621 {"Catalan", "cat"},
\r
622 {"Chamorro", "cha"},
\r
623 {"Chechen", "che"},
\r
624 {"Chinese", "zho"},
\r
625 {"Church Slavic", "chu"},
\r
626 {"Chuvash", "chv"},
\r
627 {"Cornish", "cor"},
\r
628 {"Corsican", "cos"},
\r
632 {"Divehi", "div"},
\r
633 {"Nederlands", "nld"},
\r
634 {"Dzongkha", "dzo"},
\r
635 {"English", "eng"},
\r
636 {"Esperanto", "epo"},
\r
637 {"Estonian", "est"},
\r
639 {"Faroese", "fao"},
\r
640 {"Fijian", "fij"},
\r
642 {"Francais", "fra"},
\r
643 {"Western Frisian", "fry"},
\r
645 {"Georgian", "kat"},
\r
646 {"Deutsch", "deu"},
\r
647 {"Gaelic (Scots)", "gla"},
\r
649 {"Galician", "glg"},
\r
651 {"Greek Modern", "ell"},
\r
652 {"Guarani", "grn"},
\r
653 {"Gujarati", "guj"},
\r
654 {"Haitian", "hat"},
\r
656 {"Hebrew", "heb"},
\r
657 {"Herero", "her"},
\r
659 {"Hiri Motu", "hmo"},
\r
660 {"Magyar", "hun"},
\r
662 {"Islenska", "isl"},
\r
664 {"Sichuan Yi", "iii"},
\r
665 {"Inuktitut", "iku"},
\r
666 {"Interlingue", "ile"},
\r
667 {"Interlingua", "ina"},
\r
668 {"Indonesian", "ind"},
\r
669 {"Inupiaq", "ipk"},
\r
670 {"Italiano", "ita"},
\r
671 {"Javanese", "jav"},
\r
672 {"Japanese", "jpn"},
\r
673 {"Kalaallisut", "kal"},
\r
674 {"Kannada", "kan"},
\r
675 {"Kashmiri", "kas"},
\r
676 {"Kanuri", "kau"},
\r
677 {"Kazakh", "kaz"},
\r
678 {"Central Khmer", "khm"},
\r
679 {"Kikuyu", "kik"},
\r
680 {"Kinyarwanda", "kin"},
\r
681 {"Kirghiz", "kir"},
\r
684 {"Korean", "kor"},
\r
685 {"Kuanyama", "kua"},
\r
686 {"Kurdish", "kur"},
\r
689 {"Latvian", "lav"},
\r
690 {"Limburgan", "lim"},
\r
691 {"Lingala", "lin"},
\r
692 {"Lithuanian", "lit"},
\r
693 {"Luxembourgish", "ltz"},
\r
694 {"Luba-Katanga", "lub"},
\r
696 {"Macedonian", "mkd"},
\r
697 {"Marshallese", "mah"},
\r
698 {"Malayalam", "mal"},
\r
700 {"Marathi", "mar"},
\r
702 {"Malagasy", "mlg"},
\r
703 {"Maltese", "mlt"},
\r
704 {"Moldavian", "mol"},
\r
705 {"Mongolian", "mon"},
\r
707 {"Navajo", "nav"},
\r
708 {"Ndebele, South", "nbl"},
\r
709 {"Ndebele, North", "nde"},
\r
710 {"Ndonga", "ndo"},
\r
711 {"Nepali", "nep"},
\r
712 {"Norwegian Nynorsk", "nno"},
\r
713 {"Norwegian Bokmål", "nob"},
\r
715 {"Chichewa; Nyanja", "nya"},
\r
716 {"Occitan", "oci"},
\r
717 {"Ojibwa", "oji"},
\r
720 {"Ossetian", "oss"},
\r
721 {"Panjabi", "pan"},
\r
722 {"Persian", "fas"},
\r
724 {"Polish", "pol"},
\r
725 {"Portugues", "por"},
\r
726 {"Pushto", "pus"},
\r
727 {"Quechua", "que"},
\r
728 {"Romansh", "roh"},
\r
729 {"Romanian", "ron"},
\r
731 {"Russian", "rus"},
\r
733 {"Sanskrit", "san"},
\r
734 {"Serbian", "srp"},
\r
735 {"Hrvatski", "hrv"},
\r
736 {"Sinhala", "sin"},
\r
737 {"Slovak", "slk"},
\r
738 {"Slovenian", "slv"},
\r
739 {"Northern Sami", "sme"},
\r
740 {"Samoan", "smo"},
\r
742 {"Sindhi", "snd"},
\r
743 {"Somali", "som"},
\r
744 {"Sotho Southern", "sot"},
\r
745 {"Espanol", "spa"},
\r
746 {"Sardinian", "srd"},
\r
748 {"Sundanese", "sun"},
\r
749 {"Swahili", "swa"},
\r
750 {"Svenska", "swe"},
\r
751 {"Tahitian", "tah"},
\r
754 {"Telugu", "tel"},
\r
756 {"Tagalog", "tgl"},
\r
758 {"Tibetan", "bod"},
\r
759 {"Tigrinya", "tir"},
\r
761 {"Tswana", "tsn"},
\r
762 {"Tsonga", "tso"},
\r
763 {"Turkmen", "tuk"},
\r
764 {"Turkish", "tur"},
\r
766 {"Uighur", "uig"},
\r
767 {"Ukrainian", "ukr"},
\r
771 {"Vietnamese", "vie"},
\r
772 {"Volapük", "vol"},
\r
774 {"Walloon", "wln"},
\r
777 {"Yiddish", "yid"},
\r
778 {"Yoruba", "yor"},
\r
779 {"Zhuang", "zha"},
\r
782 return languageMap;
\r
786 /// Get a list of available DVD drives which are ready and contain DVD content.
\r
788 /// <returns>A List of Drives with their details</returns>
\r
789 public static List<DriveInformation> GetDrives()
\r
791 List<DriveInformation> drives = new List<DriveInformation>();
\r
792 DriveInfo[] theCollectionOfDrives = DriveInfo.GetDrives();
\r
794 foreach (DriveInfo curDrive in theCollectionOfDrives)
\r
796 if (curDrive.DriveType == DriveType.CDRom && curDrive.IsReady &&
\r
797 File.Exists(curDrive.RootDirectory + "VIDEO_TS\\VIDEO_TS.IFO"))
\r
799 drives.Add(new DriveInformation
\r
802 VolumeLabel = curDrive.VolumeLabel,
\r
803 RootDirectory = curDrive.RootDirectory + "VIDEO_TS"
\r
812 /// Change a string to Title Case/
\r
814 /// <param name="input">
\r
818 /// A string in title case.
\r
820 public static string TitleCase(string input)
\r
822 string[] tokens = input.Split(' ');
\r
823 StringBuilder sb = new StringBuilder(input.Length);
\r
824 foreach (string s in tokens)
\r
826 sb.Append(s[0].ToString().ToUpper());
\r
827 sb.Append(s.Substring(1).ToLower());
\r
831 return sb.ToString().Trim();
\r
835 /// Show the Exception Window
\r
837 /// <param name="shortError">
\r
838 /// The short error.
\r
840 /// <param name="longError">
\r
841 /// The long error.
\r
843 public static void ShowExceptiowWindow(string shortError, string longError)
\r
845 frmExceptionWindow exceptionWindow = new frmExceptionWindow();
\r
846 exceptionWindow.Setup(shortError, longError);
\r
847 exceptionWindow.Show();
\r
851 /// Get The Source from the CLI Query
\r
853 /// <param name="query">Full CLI Query</param>
\r
854 /// <returns>The Source Path</returns>
\r
855 public static string GetSourceFromQuery(string query)
\r
857 int startIndex = query.IndexOf("-i \"");
\r
858 if (startIndex != -1)
\r
860 string input = query.Substring(startIndex).Replace("-i \"", string.Empty).Trim();
\r
862 int closeIndex = input.IndexOf('"');
\r
864 return closeIndex == -1 ? "Unknown" : input.Substring(0, closeIndex);
\r
871 /// Get the Destination from the CLI Query
\r
873 /// <param name="query">Full CLI Query</param>
\r
874 /// <returns>The Destination path</returns>
\r
875 public static string GetDestinationFromQuery(string query)
\r
877 int startIndex = query.IndexOf("-o \"");
\r
878 if (startIndex != -1)
\r
880 string output = query.Substring(startIndex).Replace("-o \"", string.Empty).Trim();
\r
882 int closeIndex = output.IndexOf('"');
\r
884 return closeIndex == -1 ? "Unknown" : output.Substring(0, closeIndex);
\r