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.cliLastModified == lastModified && Properties.Settings.Default.hb_build != 0)
\r
284 Properties.Settings.Default.cliLastModified = lastModified;
\r
286 Process cliProcess = new Process();
\r
287 ProcessStartInfo handBrakeCli = new ProcessStartInfo("HandBrakeCLI.exe", " -u -v0")
\r
289 UseShellExecute = false,
\r
290 RedirectStandardError = true,
\r
291 RedirectStandardOutput = true,
\r
292 CreateNoWindow = true
\r
294 cliProcess.StartInfo = handBrakeCli;
\r
298 cliProcess.Start();
\r
300 // Retrieve standard output and report back to parent thread until the process is complete
\r
301 TextReader stdOutput = cliProcess.StandardError;
\r
303 while (!cliProcess.HasExited)
\r
305 line = stdOutput.ReadLine() ?? string.Empty;
\r
306 Match m = Regex.Match(line, @"HandBrake ([svnM0-9.]*) \([0-9]*\)");
\r
307 Match platform = Regex.Match(line, @"- ([A-Za-z0-9\s ]*) -");
\r
311 string data = line.Replace("(", string.Empty).Replace(")", string.Empty).Replace("HandBrake ", string.Empty);
\r
312 string[] arr = data.Split(' ');
\r
314 Properties.Settings.Default.hb_build = int.Parse(arr[1]);
\r
315 Properties.Settings.Default.hb_version = arr[0];
\r
318 if (platform.Success)
\r
320 Properties.Settings.Default.hb_platform = platform.Value.Replace("-", string.Empty).Trim();
\r
323 if (cliProcess.TotalProcessorTime.Seconds > 10) // Don't wait longer than 10 seconds.
\r
325 Process cli = Process.GetProcessById(cliProcess.Id);
\r
326 if (!cli.HasExited)
\r
333 Properties.Settings.Default.Save();
\r
335 catch (Exception e)
\r
337 frmExceptionWindow exceptionWindow = new frmExceptionWindow();
\r
338 exceptionWindow.Setup("Unable to retrieve version information from the CLI.", e.ToString());
\r
339 exceptionWindow.ShowDialog();
\r
344 /// Check to make sure that the user has an up to date version of the CLI installed.
\r
346 public static void CheckForValidCliVersion()
\r
348 // Make sure we have a recent version for svn builds
\r
349 string cli_version = Properties.Settings.Default.hb_version;
\r
350 Version gui_version = Assembly.GetExecutingAssembly().GetName().Version;
\r
352 if (cli_version.Contains("svn") || gui_version.Revision > 0)
\r
354 int gui_build, cli_build;
\r
355 int.TryParse(gui_version.Revision.ToString(), out gui_build);
\r
356 int.TryParse(Properties.Settings.Default.hb_version.Replace("svn", string.Empty), out cli_build);
\r
358 if (gui_build > cli_build)
\r
361 "It appears you are trying to use a CLI executable that is too old for this version of the HandBrake GUI.\n" +
\r
362 "Please update the HandBrakeCLI.exe to a newer build.\n\n" +
\r
363 "HandBrake build Detected: " + cli_build,
\r
365 MessageBoxButtons.OK,
\r
366 MessageBoxIcon.Error);
\r
373 /// Check if the queue recovery file contains records.
\r
374 /// If it does, it means the last queue did not complete before HandBrake closed.
\r
375 /// So, return a boolean if true.
\r
378 /// True if there is a queue to recover.
\r
380 public static List<string> CheckQueueRecovery()
\r
384 string tempPath = Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.ApplicationData), @"HandBrake\");
\r
385 List<string> queueFiles = new List<string>();
\r
387 DirectoryInfo info = new DirectoryInfo(tempPath);
\r
388 FileInfo[] logFiles = info.GetFiles("*.xml");
\r
389 foreach (FileInfo file in logFiles)
\r
391 if (!file.Name.Contains("hb_queue_recovery"))
\r
394 using (FileStream strm = new FileStream(Path.Combine(file.DirectoryName, file.Name), FileMode.Open, FileAccess.Read))
\r
396 List<Job> list = Ser.Deserialize(strm) as List<Job>;
\r
399 if (list.Count != 0)
\r
401 queueFiles.Add(file.Name);
\r
411 return new List<string>(); // Keep quiet about the error.
\r
416 /// Recover a queue from file.
\r
418 /// <param name="encodeQueue">
\r
419 /// The encode Queue.
\r
421 public static void RecoverQueue(IQueue encodeQueue)
\r
423 DialogResult result = DialogResult.None;
\r
424 List<string> queueFiles = CheckQueueRecovery();
\r
425 if (queueFiles.Count == 1)
\r
427 result = MessageBox.Show(
\r
428 "HandBrake has detected unfinished items on the queue from the last time the application was launched. Would you like to recover these?",
\r
429 "Queue Recovery Possible", MessageBoxButtons.YesNo, MessageBoxIcon.Question);
\r
431 else if (queueFiles.Count > 1)
\r
433 result = MessageBox.Show(
\r
434 "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
435 "Queue Recovery Possible", MessageBoxButtons.YesNo, MessageBoxIcon.Question);
\r
438 if (result == DialogResult.Yes)
\r
440 foreach (string file in queueFiles)
\r
442 encodeQueue.LoadQueueFromFile(file); // Start Recovery
\r
447 if (IsMultiInstance) return; // Don't tamper with the files if we are multi instance
\r
449 string tempPath = Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.ApplicationData), @"HandBrake\");
\r
450 foreach (string file in queueFiles)
\r
452 if (File.Exists(Path.Combine(tempPath, file)))
\r
453 File.Delete(Path.Combine(tempPath, file));
\r
459 /// Gets a value indicating whether HandBrake is running in multi instance mode
\r
461 /// <returns>True if the UI has another instance running</returns>
\r
462 public static bool IsMultiInstance
\r
466 return Process.GetProcessesByName("HandBrake").Length > 0 ? true : false;
\r
471 /// Clear all the encode log files.
\r
473 public static void ClearLogs()
\r
475 string logDir = Environment.GetFolderPath(Environment.SpecialFolder.ApplicationData) + "\\HandBrake\\logs";
\r
476 if (Directory.Exists(logDir))
\r
478 DirectoryInfo info = new DirectoryInfo(logDir);
\r
479 FileInfo[] logFiles = info.GetFiles("*.txt");
\r
480 foreach (FileInfo file in logFiles)
\r
482 if (!file.Name.Contains("last_scan_log") && !file.Name.Contains("last_encode_log"))
\r
483 File.Delete(file.FullName);
\r
489 /// Clear old log files x days in the past
\r
491 public static void ClearOldLogs()
\r
493 string logDir = Environment.GetFolderPath(Environment.SpecialFolder.ApplicationData) + "\\HandBrake\\logs";
\r
494 if (Directory.Exists(logDir))
\r
496 DirectoryInfo info = new DirectoryInfo(logDir);
\r
497 FileInfo[] logFiles = info.GetFiles("*.txt");
\r
499 foreach (FileInfo file in logFiles)
\r
501 if (file.LastWriteTime < DateTime.Now.AddDays(-30))
\r
503 if (!file.Name.Contains("last_scan_log.txt") && !file.Name.Contains("last_encode_log.txt"))
\r
504 File.Delete(file.FullName);
\r
511 /// Begins checking for an update to HandBrake.
\r
513 /// <param name="callback">The method that will be called when the check is finished.</param>
\r
514 /// <param name="debug">Whether or not to execute this in debug mode.</param>
\r
515 public static void BeginCheckForUpdates(AsyncCallback callback, bool debug)
\r
517 ThreadPool.QueueUserWorkItem(new WaitCallback(delegate
\r
521 // Is this a stable or unstable build?
\r
523 Properties.Settings.Default.hb_build.ToString()
\r
525 ? Properties.Settings.Default.
\r
527 : Properties.Settings.Default.appcast;
\r
529 // Initialize variables
\r
530 WebRequest request = WebRequest.Create(url);
\r
531 WebResponse response = request.GetResponse();
\r
532 AppcastReader reader = new AppcastReader();
\r
534 // Get the data, convert it to a string, and parse it into the AppcastReader
\r
536 new StreamReader(response.GetResponseStream())
\r
539 // Further parse the information
\r
540 string build = reader.Build;
\r
542 int latest = int.Parse(build);
\r
543 int current = Properties.Settings.Default.hb_build;
\r
544 int skip = Properties.Settings.Default.skipversion;
\r
546 // If the user wanted to skip this version, don't report the update
\r
547 if (latest == skip)
\r
549 UpdateCheckInformation info =
\r
550 new UpdateCheckInformation
\r
552 NewVersionAvailable = false,
\r
553 BuildInformation = null
\r
555 callback(new UpdateCheckResult(debug, info));
\r
559 // Set when the last update was
\r
560 Properties.Settings.Default.lastUpdateCheckDate =
\r
562 Properties.Settings.Default.Save();
\r
564 UpdateCheckInformation info2 =
\r
565 new UpdateCheckInformation
\r
567 NewVersionAvailable = latest > current,
\r
568 BuildInformation = reader
\r
570 callback(new UpdateCheckResult(debug, info2));
\r
572 catch (Exception exc)
\r
574 callback(new UpdateCheckResult(debug, new UpdateCheckInformation { Error = exc }));
\r
580 /// End Check for Updates
\r
582 /// <param name="result">
\r
586 /// Update Check information
\r
588 public static UpdateCheckInformation EndCheckForUpdates(IAsyncResult result)
\r
590 UpdateCheckResult checkResult = (UpdateCheckResult)result;
\r
591 return checkResult.Result;
\r
595 /// Map languages and their iso639_2 value into a IDictionary
\r
597 /// <returns>A Dictionary containing the language and iso code</returns>
\r
598 public static IDictionary<string, string> MapLanguages()
\r
600 IDictionary<string, string> languageMap = new Dictionary<string, string>
\r
604 {"Abkhazian", "abk"},
\r
605 {"Afrikaans", "afr"},
\r
607 {"Albanian", "sqi"},
\r
608 {"Amharic", "amh"},
\r
609 {"Arabic", "ara"},
\r
610 {"Aragonese", "arg"},
\r
611 {"Armenian", "hye"},
\r
612 {"Assamese", "asm"},
\r
613 {"Avaric", "ava"},
\r
614 {"Avestan", "ave"},
\r
615 {"Aymara", "aym"},
\r
616 {"Azerbaijani", "aze"},
\r
617 {"Bashkir", "bak"},
\r
618 {"Bambara", "bam"},
\r
619 {"Basque", "eus"},
\r
620 {"Belarusian", "bel"},
\r
621 {"Bengali", "ben"},
\r
622 {"Bihari", "bih"},
\r
623 {"Bislama", "bis"},
\r
624 {"Bosnian", "bos"},
\r
625 {"Breton", "bre"},
\r
626 {"Bulgarian", "bul"},
\r
627 {"Burmese", "mya"},
\r
628 {"Catalan", "cat"},
\r
629 {"Chamorro", "cha"},
\r
630 {"Chechen", "che"},
\r
631 {"Chinese", "zho"},
\r
632 {"Church Slavic", "chu"},
\r
633 {"Chuvash", "chv"},
\r
634 {"Cornish", "cor"},
\r
635 {"Corsican", "cos"},
\r
639 {"Divehi", "div"},
\r
640 {"Nederlands", "nld"},
\r
641 {"Dzongkha", "dzo"},
\r
642 {"English", "eng"},
\r
643 {"Esperanto", "epo"},
\r
644 {"Estonian", "est"},
\r
646 {"Faroese", "fao"},
\r
647 {"Fijian", "fij"},
\r
649 {"Francais", "fra"},
\r
650 {"Western Frisian", "fry"},
\r
652 {"Georgian", "kat"},
\r
653 {"Deutsch", "deu"},
\r
654 {"Gaelic (Scots)", "gla"},
\r
656 {"Galician", "glg"},
\r
658 {"Greek Modern", "ell"},
\r
659 {"Guarani", "grn"},
\r
660 {"Gujarati", "guj"},
\r
661 {"Haitian", "hat"},
\r
663 {"Hebrew", "heb"},
\r
664 {"Herero", "her"},
\r
666 {"Hiri Motu", "hmo"},
\r
667 {"Magyar", "hun"},
\r
669 {"Islenska", "isl"},
\r
671 {"Sichuan Yi", "iii"},
\r
672 {"Inuktitut", "iku"},
\r
673 {"Interlingue", "ile"},
\r
674 {"Interlingua", "ina"},
\r
675 {"Indonesian", "ind"},
\r
676 {"Inupiaq", "ipk"},
\r
677 {"Italiano", "ita"},
\r
678 {"Javanese", "jav"},
\r
679 {"Japanese", "jpn"},
\r
680 {"Kalaallisut", "kal"},
\r
681 {"Kannada", "kan"},
\r
682 {"Kashmiri", "kas"},
\r
683 {"Kanuri", "kau"},
\r
684 {"Kazakh", "kaz"},
\r
685 {"Central Khmer", "khm"},
\r
686 {"Kikuyu", "kik"},
\r
687 {"Kinyarwanda", "kin"},
\r
688 {"Kirghiz", "kir"},
\r
691 {"Korean", "kor"},
\r
692 {"Kuanyama", "kua"},
\r
693 {"Kurdish", "kur"},
\r
696 {"Latvian", "lav"},
\r
697 {"Limburgan", "lim"},
\r
698 {"Lingala", "lin"},
\r
699 {"Lithuanian", "lit"},
\r
700 {"Luxembourgish", "ltz"},
\r
701 {"Luba-Katanga", "lub"},
\r
703 {"Macedonian", "mkd"},
\r
704 {"Marshallese", "mah"},
\r
705 {"Malayalam", "mal"},
\r
707 {"Marathi", "mar"},
\r
709 {"Malagasy", "mlg"},
\r
710 {"Maltese", "mlt"},
\r
711 {"Moldavian", "mol"},
\r
712 {"Mongolian", "mon"},
\r
714 {"Navajo", "nav"},
\r
715 {"Ndebele, South", "nbl"},
\r
716 {"Ndebele, North", "nde"},
\r
717 {"Ndonga", "ndo"},
\r
718 {"Nepali", "nep"},
\r
719 {"Norwegian Nynorsk", "nno"},
\r
720 {"Norwegian Bokmål", "nob"},
\r
722 {"Chichewa; Nyanja", "nya"},
\r
723 {"Occitan", "oci"},
\r
724 {"Ojibwa", "oji"},
\r
727 {"Ossetian", "oss"},
\r
728 {"Panjabi", "pan"},
\r
729 {"Persian", "fas"},
\r
731 {"Polish", "pol"},
\r
732 {"Portugues", "por"},
\r
733 {"Pushto", "pus"},
\r
734 {"Quechua", "que"},
\r
735 {"Romansh", "roh"},
\r
736 {"Romanian", "ron"},
\r
738 {"Russian", "rus"},
\r
740 {"Sanskrit", "san"},
\r
741 {"Serbian", "srp"},
\r
742 {"Hrvatski", "hrv"},
\r
743 {"Sinhala", "sin"},
\r
744 {"Slovak", "slk"},
\r
745 {"Slovenian", "slv"},
\r
746 {"Northern Sami", "sme"},
\r
747 {"Samoan", "smo"},
\r
749 {"Sindhi", "snd"},
\r
750 {"Somali", "som"},
\r
751 {"Sotho Southern", "sot"},
\r
752 {"Espanol", "spa"},
\r
753 {"Sardinian", "srd"},
\r
755 {"Sundanese", "sun"},
\r
756 {"Swahili", "swa"},
\r
757 {"Svenska", "swe"},
\r
758 {"Tahitian", "tah"},
\r
761 {"Telugu", "tel"},
\r
763 {"Tagalog", "tgl"},
\r
765 {"Tibetan", "bod"},
\r
766 {"Tigrinya", "tir"},
\r
768 {"Tswana", "tsn"},
\r
769 {"Tsonga", "tso"},
\r
770 {"Turkmen", "tuk"},
\r
771 {"Turkish", "tur"},
\r
773 {"Uighur", "uig"},
\r
774 {"Ukrainian", "ukr"},
\r
778 {"Vietnamese", "vie"},
\r
779 {"Volapük", "vol"},
\r
781 {"Walloon", "wln"},
\r
784 {"Yiddish", "yid"},
\r
785 {"Yoruba", "yor"},
\r
786 {"Zhuang", "zha"},
\r
789 return languageMap;
\r
793 /// Get a list of available DVD drives which are ready and contain DVD content.
\r
795 /// <returns>A List of Drives with their details</returns>
\r
796 public static List<DriveInformation> GetDrives()
\r
798 List<DriveInformation> drives = new List<DriveInformation>();
\r
799 DriveInfo[] theCollectionOfDrives = DriveInfo.GetDrives();
\r
801 foreach (DriveInfo curDrive in theCollectionOfDrives)
\r
803 if (curDrive.DriveType == DriveType.CDRom && curDrive.IsReady &&
\r
804 File.Exists(curDrive.RootDirectory + "VIDEO_TS\\VIDEO_TS.IFO"))
\r
806 drives.Add(new DriveInformation
\r
809 VolumeLabel = curDrive.VolumeLabel,
\r
810 RootDirectory = curDrive.RootDirectory + "VIDEO_TS"
\r
819 /// Change a string to Title Case/
\r
821 /// <param name="input">
\r
825 /// A string in title case.
\r
827 public static string TitleCase(string input)
\r
829 string[] tokens = input.Split(' ');
\r
830 StringBuilder sb = new StringBuilder(input.Length);
\r
831 foreach (string s in tokens)
\r
833 sb.Append(s[0].ToString().ToUpper());
\r
834 sb.Append(s.Substring(1).ToLower());
\r
838 return sb.ToString().Trim();
\r
842 /// Show the Exception Window
\r
844 /// <param name="shortError">
\r
845 /// The short error.
\r
847 /// <param name="longError">
\r
848 /// The long error.
\r
850 public static void ShowExceptiowWindow(string shortError, string longError)
\r
852 frmExceptionWindow exceptionWindow = new frmExceptionWindow();
\r
853 exceptionWindow.Setup(shortError, longError);
\r
854 exceptionWindow.Show();
\r
858 /// Get The Source from the CLI Query
\r
860 /// <param name="query">Full CLI Query</param>
\r
861 /// <returns>The Source Path</returns>
\r
862 public static string GetSourceFromQuery(string query)
\r
864 int startIndex = query.IndexOf("-i \"");
\r
865 if (startIndex != -1)
\r
867 string input = query.Substring(startIndex).Replace("-i \"", string.Empty).Trim();
\r
869 int closeIndex = input.IndexOf('"');
\r
871 return closeIndex == -1 ? "Unknown" : input.Substring(0, closeIndex);
\r
878 /// Get the Destination from the CLI Query
\r
880 /// <param name="query">Full CLI Query</param>
\r
881 /// <returns>The Destination path</returns>
\r
882 public static string GetDestinationFromQuery(string query)
\r
884 int startIndex = query.IndexOf("-o \"");
\r
885 if (startIndex != -1)
\r
887 string output = query.Substring(startIndex).Replace("-o \"", string.Empty).Trim();
\r
889 int closeIndex = output.IndexOf('"');
\r
891 return closeIndex == -1 ? "Unknown" : output.Substring(0, closeIndex);
\r