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
9 using System.Collections.Generic;
\r
10 using System.ComponentModel;
\r
11 using System.Diagnostics;
\r
12 using System.Drawing;
\r
13 using System.Globalization;
\r
15 using System.Reflection;
\r
16 using System.Threading;
\r
17 using System.Windows.Forms;
\r
20 using HandBrake.ApplicationServices.Functions;
\r
21 using HandBrake.ApplicationServices.Model;
\r
22 using HandBrake.ApplicationServices.Parsing;
\r
23 using HandBrake.ApplicationServices.Services;
\r
24 using HandBrake.ApplicationServices.Services.Interfaces;
\r
30 using Main = Handbrake.Functions.Main;
\r
35 public partial class frmMain : Form
\r
37 // Objects which may be used by one or more other objects *************
\r
38 private IQueue encodeQueue = new Queue();
\r
39 private PresetsHandler presetHandler = new PresetsHandler();
\r
41 // Windows ************************************************************
\r
42 private frmQueue queueWindow;
\r
43 private frmPreview qtpreview;
\r
44 private frmActivityWindow activityWindow;
\r
46 // Globals: Mainly used for tracking. *********************************
\r
47 public Title selectedTitle;
\r
48 public string sourcePath;
\r
49 private SourceType selectedSourceType;
\r
50 private string dvdDrivePath;
\r
51 private string dvdDriveLabel;
\r
52 private Preset currentlySelectedPreset;
\r
53 private DVD currentSource;
\r
54 private IScan SourceScan = new ScanService();
\r
55 private List<DriveInformation> drives;
\r
57 // Delegates **********************************************************
\r
58 private delegate void UpdateWindowHandler();
\r
60 // Applicaiton Startup ************************************************
\r
65 /// Gets SourceName.
\r
67 public string SourceName
\r
71 if (this.selectedSourceType == SourceType.DvdDrive)
\r
73 return this.dvdDriveLabel;
\r
76 if (Path.GetFileNameWithoutExtension(this.sourcePath) != "VIDEO_TS")
\r
77 return Path.GetFileNameWithoutExtension(this.sourcePath);
\r
79 return Path.GetFileNameWithoutExtension(Path.GetDirectoryName(this.sourcePath));
\r
85 #region Application Startup
\r
88 /// Initializes a new instance of the <see cref="frmMain"/> class.
\r
90 /// <param name="args">
\r
91 /// The arguments passed in on application startup.
\r
93 public frmMain(string[] args)
\r
95 InitializeComponent();
\r
97 // Update the users config file with the CLI version data.
\r
98 Main.SetCliVersionData();
\r
99 Main.CheckForValidCliVersion();
\r
101 if (Settings.Default.hb_version.Contains("svn"))
\r
103 Version v = Assembly.GetExecutingAssembly().GetName().Version;
\r
104 this.Text += " " + v.ToString(4);
\r
107 // Check for new versions, if update checking is enabled
\r
108 if (Settings.Default.updateStatus)
\r
110 if (DateTime.Now.Subtract(Settings.Default.lastUpdateCheckDate).TotalDays > Properties.Settings.Default.daysBetweenUpdateCheck)
\r
112 Main.BeginCheckForUpdates(new AsyncCallback(UpdateCheckDone), false);
\r
116 // Clear the log files in the background
\r
117 if (Settings.Default.clearOldLogs)
\r
119 Thread clearLog = new Thread(Main.ClearOldLogs);
\r
123 // Setup the GUI components
\r
124 LoadPresetPanel(); // Load the Preset Panel
\r
125 treeView_presets.ExpandAll();
\r
126 lbl_encode.Text = string.Empty;
\r
127 drop_mode.SelectedIndex = 0;
\r
128 queueWindow = new frmQueue(encodeQueue, this); // Prepare the Queue
\r
129 if (!Settings.Default.QueryEditorTab)
\r
130 tabs_panel.TabPages.RemoveAt(7); // Remove the query editor tab if the user does not want it enabled.
\r
131 if (Settings.Default.tooltipEnable)
\r
132 ToolTip.Active = true;
\r
134 // Load the user's default settings or Normal Preset
\r
135 if (Settings.Default.defaultPreset != string.Empty && presetHandler.GetPreset(Properties.Settings.Default.defaultPreset) != null)
\r
137 string query = presetHandler.GetPreset(Settings.Default.defaultPreset).Query;
\r
140 x264Panel.Reset2Defaults();
\r
142 QueryParser presetQuery = QueryParser.Parse(query);
\r
143 PresetLoader.LoadPreset(this, presetQuery, Settings.Default.defaultPreset);
\r
145 x264Panel.StandardizeOptString();
\r
146 x264Panel.SetCurrentSettingsInPanel();
\r
150 loadNormalPreset();
\r
152 // Register with Growl (if not using Growl for the encoding completion action, this wont hurt anything)
\r
153 GrowlCommunicator.Register();
\r
155 // Event Handlers and Queue Recovery
\r
157 Main.RecoverQueue(encodeQueue);
\r
159 // If have a file passed in via command arguemtents, check it's a file and try scanning it.
\r
160 if (args.Length >= 1 && (File.Exists(args[0]) || Directory.Exists(args[0])))
\r
162 this.StartScan(args[0], 0);
\r
167 /// When the update check is done, process the results.
\r
169 /// <param name="result">IAsyncResult result</param>
\r
170 private void UpdateCheckDone(IAsyncResult result)
\r
172 if (InvokeRequired)
\r
174 Invoke(new MethodInvoker(() => UpdateCheckDone(result)));
\r
178 UpdateCheckInformation info;
\r
182 info = Main.EndCheckForUpdates(result);
\r
184 if (info.NewVersionAvailable)
\r
186 frmUpdater updateWindow = new frmUpdater(info.BuildInformation);
\r
187 updateWindow.ShowDialog();
\r
190 catch (Exception ex)
\r
192 if ((bool)result.AsyncState)
\r
193 Main.ShowExceptiowWindow("Unable to check for updates, Please try again later.", ex.ToString());
\r
201 // Encoding Events for setting up the GUI
\r
202 private void events()
\r
204 // Handle Widget changes when preset is selected.
\r
205 RegisterPresetEventHandler();
\r
207 // Handle Window Resize
\r
208 if (Properties.Settings.Default.MainWindowMinimize)
\r
209 this.Resize += new EventHandler(frmMain_Resize);
\r
211 // Handle Encode Start / Finish / Pause
\r
212 encodeQueue.EncodeStarted += new EventHandler(encodeStarted);
\r
213 encodeQueue.EncodeEnded += new EventHandler(encodeEnded);
\r
215 // Handle a file being draged onto the GUI.
\r
216 this.DragEnter += new DragEventHandler(frmMain_DragEnter);
\r
217 this.DragDrop += new DragEventHandler(frmMain_DragDrop);
\r
220 // Change the preset label to custom when a user changes a setting. Don't want to give the impression that users can change settings and still be using a preset
\r
221 private void RegisterPresetEventHandler()
\r
224 drop_format.SelectedIndexChanged += new EventHandler(changePresetLabel);
\r
225 check_largeFile.CheckedChanged += new EventHandler(changePresetLabel);
\r
226 check_iPodAtom.CheckedChanged += new EventHandler(changePresetLabel);
\r
227 check_optimiseMP4.CheckedChanged += new EventHandler(changePresetLabel);
\r
229 // Picture Settings
\r
230 PictureSettings.PictureSettingsChanged += new EventHandler(changePresetLabel);
\r
233 Filters.FilterSettingsChanged += new EventHandler(changePresetLabel);
\r
236 drp_videoEncoder.SelectedIndexChanged += new EventHandler(changePresetLabel);
\r
237 check_2PassEncode.CheckedChanged += new EventHandler(changePresetLabel);
\r
238 check_turbo.CheckedChanged += new EventHandler(changePresetLabel);
\r
239 text_filesize.TextChanged += new EventHandler(changePresetLabel);
\r
240 text_bitrate.TextChanged += new EventHandler(changePresetLabel);
\r
241 slider_videoQuality.ValueChanged += new EventHandler(changePresetLabel);
\r
244 AudioSettings.AudioListChanged += new EventHandler(changePresetLabel);
\r
247 x264Panel.rtf_x264Query.TextChanged += new EventHandler(changePresetLabel);
\r
250 private void UnRegisterPresetEventHandler()
\r
252 // Output Settings
\r
253 drop_format.SelectedIndexChanged -= new EventHandler(changePresetLabel);
\r
254 check_largeFile.CheckedChanged -= new EventHandler(changePresetLabel);
\r
255 check_iPodAtom.CheckedChanged -= new EventHandler(changePresetLabel);
\r
256 check_optimiseMP4.CheckedChanged -= new EventHandler(changePresetLabel);
\r
258 // Picture Settings
\r
259 PictureSettings.PictureSettingsChanged -= new EventHandler(changePresetLabel);
\r
262 Filters.FilterSettingsChanged -= new EventHandler(changePresetLabel);
\r
265 drp_videoEncoder.SelectedIndexChanged -= new EventHandler(changePresetLabel);
\r
266 check_2PassEncode.CheckedChanged -= new EventHandler(changePresetLabel);
\r
267 check_turbo.CheckedChanged -= new EventHandler(changePresetLabel);
\r
268 text_filesize.TextChanged -= new EventHandler(changePresetLabel);
\r
269 text_bitrate.TextChanged -= new EventHandler(changePresetLabel);
\r
270 slider_videoQuality.ValueChanged -= new EventHandler(changePresetLabel);
\r
273 AudioSettings.AudioListChanged -= new EventHandler(changePresetLabel);
\r
276 x264Panel.rtf_x264Query.TextChanged -= new EventHandler(changePresetLabel);
\r
279 private void changePresetLabel(object sender, EventArgs e)
\r
281 labelPreset.Text = "Output Settings (Preset: Custom)";
\r
282 this.currentlySelectedPreset = null;
\r
285 private static void frmMain_DragEnter(object sender, DragEventArgs e)
\r
287 if (e.Data.GetDataPresent(DataFormats.FileDrop, false))
\r
288 e.Effect = DragDropEffects.All;
\r
291 private void frmMain_DragDrop(object sender, DragEventArgs e)
\r
293 string[] fileList = e.Data.GetData(DataFormats.FileDrop) as string[];
\r
294 sourcePath = string.Empty;
\r
296 if (fileList != null)
\r
298 if (!string.IsNullOrEmpty(fileList[0]))
\r
300 this.selectedSourceType = SourceType.VideoFile;
\r
301 StartScan(fileList[0], 0);
\r
304 UpdateSourceLabel();
\r
307 UpdateSourceLabel();
\r
310 private void encodeStarted(object sender, EventArgs e)
\r
312 SetEncodeStarted();
\r
313 encodeQueue.EncodeStatusChanged += EncodeQueue_EncodeStatusChanged;
\r
316 private void encodeEnded(object sender, EventArgs e)
\r
318 encodeQueue.EncodeStatusChanged -= EncodeQueue_EncodeStatusChanged;
\r
319 SetEncodeFinished();
\r
323 // User Interface Menus / Tool Strips *********************************
\r
328 /// Kill The scan menu Item
\r
330 /// <param name="sender">
\r
333 /// <param name="e">
\r
336 private void mnu_killCLI_Click(object sender, EventArgs e)
\r
342 /// Exit the Application Menu Item
\r
344 /// <param name="sender">
\r
347 /// <param name="e">
\r
350 private void mnu_exit_Click(object sender, EventArgs e)
\r
352 Application.Exit();
\r
360 /// Menu - Start Button
\r
362 /// <param name="sender">
\r
365 /// <param name="e">
\r
368 private void mnu_encode_Click(object sender, EventArgs e)
\r
370 queueWindow.Show();
\r
374 /// Menu - Display the Log Window
\r
376 /// <param name="sender">
\r
379 /// <param name="e">
\r
382 private void mnu_encodeLog_Click(object sender, EventArgs e)
\r
384 this.btn_ActivityWindow_Click(this, null);
\r
388 /// Menu - Display the Options Window
\r
390 /// <param name="sender">
\r
393 /// <param name="e">
\r
396 private void mnu_options_Click(object sender, EventArgs e)
\r
398 Form options = new frmOptions(this);
\r
399 options.ShowDialog();
\r
404 #region Presets Menu
\r
407 /// Reset the Built in Presets
\r
409 /// <param name="sender">
\r
412 /// <param name="e">
\r
415 private void mnu_presetReset_Click(object sender, EventArgs e)
\r
417 presetHandler.UpdateBuiltInPresets();
\r
419 if (treeView_presets.Nodes.Count == 0)
\r
421 "Unable to load the presets.xml file. Please select \"Update Built-in Presets\" from the Presets Menu. \nMake sure you are running the program in Admin mode if running on Vista. See Windows FAQ for details!",
\r
422 "Error", MessageBoxButtons.OK, MessageBoxIcon.Error);
\r
424 MessageBox.Show("Presets have been updated!", "Alert", MessageBoxButtons.OK, MessageBoxIcon.Information);
\r
426 treeView_presets.ExpandAll();
\r
430 /// Delete the selected preset
\r
432 /// <param name="sender">
\r
435 /// <param name="e">
\r
438 private void mnu_delete_preset_Click(object sender, EventArgs e)
\r
440 presetHandler.RemoveBuiltInPresets();
\r
441 LoadPresetPanel(); // Reload the preset panel
\r
445 /// Select the Normal preset
\r
447 /// <param name="sender">
\r
450 /// <param name="e">
\r
453 private void mnu_SelectDefault_Click(object sender, EventArgs e)
\r
455 loadNormalPreset();
\r
459 /// Import a plist Preset
\r
461 /// <param name="sender">
\r
464 /// <param name="e">
\r
467 private void mnu_importMacPreset_Click(object sender, EventArgs e)
\r
473 /// Export a Plist Preset
\r
475 /// <param name="sender">
\r
478 /// <param name="e">
\r
481 private void mnu_exportMacPreset_Click(object sender, EventArgs e)
\r
487 /// Create a new Preset
\r
489 /// <param name="sender">
\r
492 /// <param name="e">
\r
495 private void btn_new_preset_Click(object sender, EventArgs e)
\r
497 Form preset = new frmAddPreset(this, presetHandler);
\r
498 if (preset.ShowDialog() == DialogResult.OK)
\r
500 TreeNode presetTreeview = new TreeNode(presetHandler.LastPresetAdded.Name) { ForeColor = Color.Black };
\r
501 treeView_presets.Nodes.Add(presetTreeview);
\r
502 presetHandler.LastPresetAdded = null;
\r
511 /// Menu - Display the User Guide Web Page
\r
513 /// <param name="sender">
\r
516 /// <param name="e">
\r
519 private void mnu_user_guide_Click(object sender, EventArgs e)
\r
521 Process.Start("http://trac.handbrake.fr/wiki/HandBrakeGuide");
\r
525 /// Menu - Check for Updates
\r
527 /// <param name="sender">
\r
530 /// <param name="e">
\r
533 private void mnu_UpdateCheck_Click(object sender, EventArgs e)
\r
535 lbl_updateCheck.Visible = true;
\r
536 Main.BeginCheckForUpdates(new AsyncCallback(this.UpdateCheckDoneMenu), false);
\r
540 /// Menu - Display the About Window
\r
542 /// <param name="sender">
\r
545 /// <param name="e">
\r
548 private void mnu_about_Click(object sender, EventArgs e)
\r
550 using (frmAbout About = new frmAbout())
\r
552 About.ShowDialog();
\r
561 /// RMenu - Expand All
\r
563 /// <param name="sender">
\r
566 /// <param name="e">
\r
569 private void pmnu_expandAll_Click(object sender, EventArgs e)
\r
571 treeView_presets.ExpandAll();
\r
575 /// RMenu - Collaspe All
\r
577 /// <param name="sender">
\r
580 /// <param name="e">
\r
583 private void pmnu_collapse_Click(object sender, EventArgs e)
\r
585 treeView_presets.CollapseAll();
\r
589 /// Menu - Import Preset
\r
591 /// <param name="sender">
\r
594 /// <param name="e">
\r
597 private void pmnu_import_Click(object sender, EventArgs e)
\r
603 /// RMenu - Save Changes to Preset
\r
605 /// <param name="sender">
\r
608 /// <param name="e">
\r
611 private void pmnu_saveChanges_Click(object sender, EventArgs e)
\r
613 // TODO this requires a re-think since the Query Editor has changed.
\r
614 DialogResult result =
\r
616 "Do you wish to include picture settings when updating the preset: " +
\r
617 treeView_presets.SelectedNode.Text, "Update Preset", MessageBoxButtons.YesNoCancel,
\r
618 MessageBoxIcon.Question);
\r
619 if (result == DialogResult.Yes)
\r
620 presetHandler.Update(treeView_presets.SelectedNode.Text,
\r
621 QueryGenerator.GenerateQueryForPreset(this, QueryPictureSettingsMode.SourceMaximum, true, 0, 0), true);
\r
622 else if (result == DialogResult.No)
\r
623 presetHandler.Update(treeView_presets.SelectedNode.Text,
\r
624 QueryGenerator.GenerateQueryForPreset(this, QueryPictureSettingsMode.SourceMaximum, true, 0, 0), false);
\r
628 /// RMenu - Delete Preset
\r
630 /// <param name="sender">
\r
633 /// <param name="e">
\r
636 private void pmnu_delete_click(object sender, EventArgs e)
\r
638 if (treeView_presets.SelectedNode != null)
\r
640 presetHandler.Remove(treeView_presets.SelectedNode.Text);
\r
641 treeView_presets.Nodes.Remove(treeView_presets.SelectedNode);
\r
643 treeView_presets.Select();
\r
647 /// Preset Menu Is Opening. Setup the Menu
\r
649 /// <param name="sender">
\r
652 /// <param name="e">
\r
655 private void presets_menu_Opening(object sender, CancelEventArgs e)
\r
657 // Make sure that the save menu is always disabled by default
\r
658 pmnu_saveChanges.Enabled = false;
\r
660 // Now enable the save menu if the selected preset is a user preset
\r
661 if (treeView_presets.SelectedNode != null)
\r
662 if (presetHandler.CheckIfUserPresetExists(treeView_presets.SelectedNode.Text))
\r
663 pmnu_saveChanges.Enabled = true;
\r
665 treeView_presets.Select();
\r
668 // Presets Management
\r
671 /// Button - Add a preset
\r
673 /// <param name="sender">
\r
676 /// <param name="e">
\r
679 private void btn_addPreset_Click(object sender, EventArgs e)
\r
681 Form preset = new frmAddPreset(this, presetHandler);
\r
682 if (preset.ShowDialog() == DialogResult.OK)
\r
684 TreeNode presetTreeview = new TreeNode(presetHandler.LastPresetAdded.Name) { ForeColor = Color.Black };
\r
685 treeView_presets.Nodes.Add(presetTreeview);
\r
686 presetHandler.LastPresetAdded = null;
\r
691 /// Button - remove a Preset
\r
693 /// <param name="sender">
\r
696 /// <param name="e">
\r
699 private void btn_removePreset_Click(object sender, EventArgs e)
\r
701 DialogResult result = MessageBox.Show("Are you sure you wish to delete the selected preset?", "Preset",
\r
702 MessageBoxButtons.YesNo, MessageBoxIcon.Question);
\r
703 if (result == DialogResult.Yes)
\r
705 if (treeView_presets.SelectedNode != null)
\r
707 presetHandler.Remove(treeView_presets.SelectedNode.Text);
\r
708 treeView_presets.Nodes.Remove(treeView_presets.SelectedNode);
\r
711 treeView_presets.Select();
\r
715 /// Button - Set the selected preset as the default
\r
717 /// <param name="sender">
\r
720 /// <param name="e">
\r
723 private void btn_setDefault_Click(object sender, EventArgs e)
\r
725 if (treeView_presets.SelectedNode != null)
\r
727 DialogResult result = MessageBox.Show("Are you sure you wish to set this preset as the default?",
\r
728 "Preset", MessageBoxButtons.YesNo, MessageBoxIcon.Question);
\r
729 if (result == DialogResult.Yes)
\r
731 Properties.Settings.Default.defaultPreset = treeView_presets.SelectedNode.Text;
\r
732 Properties.Settings.Default.Save();
\r
733 MessageBox.Show("New default preset set.", "Alert", MessageBoxButtons.OK, MessageBoxIcon.Information);
\r
737 MessageBox.Show("Please select a preset first.", "Warning", MessageBoxButtons.OK, MessageBoxIcon.Warning);
\r
741 /// PresetBar Mouse Down event
\r
743 /// <param name="sender">
\r
746 /// <param name="e">
\r
749 private void treeview_presets_mouseUp(object sender, MouseEventArgs e)
\r
751 if (e.Button == MouseButtons.Right)
\r
752 treeView_presets.SelectedNode = treeView_presets.GetNodeAt(e.Location);
\r
753 else if (e.Button == MouseButtons.Left)
\r
755 if (treeView_presets.GetNodeAt(e.Location) != null)
\r
757 if (labelPreset.Text.Contains(treeView_presets.GetNodeAt(e.Location).Text))
\r
762 treeView_presets.Select();
\r
766 /// Preset Bar after selecting the preset
\r
768 /// <param name="sender">
\r
771 /// <param name="e">
\r
774 private void treeView_presets_AfterSelect(object sender, TreeViewEventArgs e)
\r
780 /// Preset Bar - Handle the Delete Key
\r
782 /// <param name="sender">
\r
785 /// <param name="e">
\r
788 private void treeView_presets_deleteKey(object sender, KeyEventArgs e)
\r
790 if (e.KeyCode == Keys.Delete)
\r
792 DialogResult result = MessageBox.Show("Are you sure you wish to delete the selected preset?", "Preset",
\r
793 MessageBoxButtons.YesNo, MessageBoxIcon.Question);
\r
794 if (result == DialogResult.Yes)
\r
796 if (treeView_presets.SelectedNode != null)
\r
797 presetHandler.Remove(treeView_presets.SelectedNode.Text);
\r
799 // Remember each nodes expanded status so we can reload it
\r
800 List<bool> nodeStatus = new List<bool>();
\r
801 foreach (TreeNode node in treeView_presets.Nodes)
\r
802 nodeStatus.Add(node.IsExpanded);
\r
804 // Now reload the preset panel
\r
807 // And finally, re-expand any of the nodes if required
\r
809 foreach (TreeNode node in treeView_presets.Nodes)
\r
821 /// Select the selected preset and setup the GUI
\r
823 private void selectPreset()
\r
825 if (treeView_presets.SelectedNode != null)
\r
827 // Ok, so, we've selected a preset. Now we want to load it.
\r
828 string presetName = treeView_presets.SelectedNode.Text;
\r
829 Preset preset = presetHandler.GetPreset(presetName);
\r
830 if (preset != null)
\r
832 string query = presetHandler.GetPreset(presetName).Query;
\r
836 // Ok, Reset all the H264 widgets before changing the preset
\r
837 x264Panel.Reset2Defaults();
\r
839 // Send the query from the file to the Query Parser class
\r
840 QueryParser presetQuery = QueryParser.Parse(query);
\r
842 // Now load the preset
\r
843 PresetLoader.LoadPreset(this, presetQuery, presetName);
\r
845 // The x264 widgets will need updated, so do this now:
\r
846 x264Panel.StandardizeOptString();
\r
847 x264Panel.SetCurrentSettingsInPanel();
\r
849 // Finally, let this window have a copy of the preset settings.
\r
850 this.currentlySelectedPreset = preset;
\r
851 PictureSettings.SetPresetCropWarningLabel(preset);
\r
858 /// Load the Normal Preset
\r
860 private void loadNormalPreset()
\r
862 foreach (TreeNode treenode in treeView_presets.Nodes)
\r
864 foreach (TreeNode node in treenode.Nodes)
\r
866 if (node.Text.Equals("Normal"))
\r
867 treeView_presets.SelectedNode = treeView_presets.Nodes[treenode.Index].Nodes[0];
\r
873 /// Import a plist preset
\r
875 private void ImportPreset()
\r
877 if (openPreset.ShowDialog() == DialogResult.OK)
\r
879 QueryParser parsed = PlistPresetHandler.Import(openPreset.FileName);
\r
880 if (presetHandler.CheckIfUserPresetExists(parsed.PresetName + " (Imported)"))
\r
882 DialogResult result =
\r
883 MessageBox.Show("This preset appears to already exist. Would you like to overwrite it?",
\r
884 "Overwrite preset?",
\r
885 MessageBoxButtons.YesNo, MessageBoxIcon.Warning);
\r
886 if (result == DialogResult.Yes)
\r
888 PresetLoader.LoadPreset(this, parsed, parsed.PresetName);
\r
889 presetHandler.Update(parsed.PresetName + " (Imported)",
\r
890 QueryGenerator.GenerateFullQuery(this),
\r
891 parsed.UsesPictureSettings);
\r
896 PresetLoader.LoadPreset(this, parsed, parsed.PresetName);
\r
897 if (presetHandler.Add(parsed.PresetName + " (Imported)",
\r
898 QueryGenerator.GenerateFullQuery(this),
\r
899 parsed.UsesPictureSettings))
\r
901 TreeNode preset_treeview = new TreeNode(parsed.PresetName + " (Imported)")
\r
903 ForeColor = Color.Black
\r
905 treeView_presets.Nodes.Add(preset_treeview);
\r
912 /// Export a plist Preset
\r
914 private void ExportPreset()
\r
916 MessageBox.Show("This feature has not been implimented yet.", "Not Implimented", MessageBoxButtons.OK, MessageBoxIcon.Warning);
\r
919 /*SaveFileDialog savefiledialog = new SaveFileDialog();
\r
920 savefiledialog.Filter = "plist|*.plist";
\r
922 if (treeView_presets.SelectedNode != null)
\r
925 if (savefiledialog.ShowDialog() == DialogResult.OK)
\r
927 Preset preset = presetHandler.GetPreset(treeView_presets.SelectedNode.Text);
\r
928 PlistPresetHandler.Export(savefiledialog.FileName, preset);
\r
938 /// Toolbar - When the Source button is clicked, Clear any DVD drives and add any available DVD drives that can be used as a source.
\r
940 /// <param name="sender">
\r
943 /// <param name="e">
\r
946 private void btn_source_Click(object sender, EventArgs e)
\r
948 // Remove old Drive Menu Items.
\r
949 List<ToolStripMenuItem> itemsToRemove = new List<ToolStripMenuItem>();
\r
950 foreach (var item in btn_source.DropDownItems)
\r
952 if (item.GetType() == typeof(ToolStripMenuItem))
\r
954 ToolStripMenuItem menuItem = (ToolStripMenuItem)item;
\r
955 if (menuItem.Name.StartsWith("Drive"))
\r
957 itemsToRemove.Add(menuItem);
\r
962 foreach (ToolStripMenuItem item in itemsToRemove)
\r
963 btn_source.DropDownItems.Remove(item);
\r
965 Thread driveInfoThread = new Thread(SetDriveSelectionMenuItem);
\r
966 driveInfoThread.Start();
\r
970 /// Toolbar - Start The Encode
\r
972 /// <param name="sender">
\r
975 /// <param name="e">
\r
978 private void btn_start_Click(object sender, EventArgs e)
\r
980 if (btn_start.Text == "Stop")
\r
982 DialogResult result = !Properties.Settings.Default.showCliForInGuiEncodeStatus
\r
984 "Are you sure you wish to cancel the encode?\n\nPlease note: Stopping this encode will render the file unplayable. ",
\r
986 MessageBoxButtons.YesNo,
\r
987 MessageBoxIcon.Question)
\r
989 "Are you sure you wish to cancel the encode?",
\r
991 MessageBoxButtons.YesNo,
\r
992 MessageBoxIcon.Question);
\r
994 if (result == DialogResult.Yes)
\r
997 encodeQueue.Pause();
\r
999 if (Settings.Default.showCliForInGuiEncodeStatus)
\r
1000 encodeQueue.SafelyClose();
\r
1002 encodeQueue.Stop();
\r
1007 // If we have a custom query, then we'll want to figure out what the new source and destination is, otherwise we'll just use the gui components.
\r
1008 string jobSourcePath = !string.IsNullOrEmpty(rtf_query.Text) ? Main.GetSourceFromQuery(rtf_query.Text) : sourcePath;
\r
1009 string jobDestination = !string.IsNullOrEmpty(rtf_query.Text) ? Main.GetDestinationFromQuery(rtf_query.Text) : text_destination.Text;
\r
1011 if (encodeQueue.Count != 0 || (!string.IsNullOrEmpty(jobSourcePath) && !string.IsNullOrEmpty(jobDestination)))
\r
1013 string generatedQuery = QueryGenerator.GenerateFullQuery(this);
\r
1014 string specifiedQuery = rtf_query.Text != string.Empty
\r
1016 : QueryGenerator.GenerateFullQuery(this);
\r
1017 string query = string.Empty;
\r
1019 // Check to make sure the generated query matches the GUI settings
\r
1020 if (Properties.Settings.Default.PromptOnUnmatchingQueries && !string.IsNullOrEmpty(specifiedQuery) &&
\r
1021 generatedQuery != specifiedQuery)
\r
1023 DialogResult result = MessageBox.Show("The query under the \"Query Editor\" tab " +
\r
1024 "does not match the current GUI settings.\n\nBecause the manual query takes " +
\r
1025 "priority over the GUI, your recently updated settings will not be taken " +
\r
1026 "into account when encoding this job." +
\r
1027 Environment.NewLine + Environment.NewLine +
\r
1028 "Do you want to replace the manual query with the updated GUI-generated query?",
\r
1029 "Manual Query does not Match GUI",
\r
1030 MessageBoxButtons.YesNoCancel, MessageBoxIcon.Asterisk,
\r
1031 MessageBoxDefaultButton.Button3);
\r
1035 case DialogResult.Yes:
\r
1036 // Replace the manual query with the generated one
\r
1037 query = generatedQuery;
\r
1038 rtf_query.Text = generatedQuery;
\r
1040 case DialogResult.No:
\r
1041 // Use the manual query
\r
1042 query = specifiedQuery;
\r
1044 case DialogResult.Cancel:
\r
1045 // Don't start the encode
\r
1051 query = specifiedQuery;
\r
1054 DialogResult overwrite = DialogResult.Yes;
\r
1055 if (!string.IsNullOrEmpty(jobDestination) && File.Exists(jobDestination))
\r
1057 overwrite = MessageBox.Show(
\r
1058 "The destination file already exists. Are you sure you want to overwrite it?",
\r
1059 "Overwrite File?",
\r
1060 MessageBoxButtons.YesNo,
\r
1061 MessageBoxIcon.Question);
\r
1064 if (overwrite == DialogResult.Yes)
\r
1066 if (encodeQueue.Count == 0)
\r
1067 encodeQueue.Add(query, this.GetTitle(), jobSourcePath, jobDestination, (rtf_query.Text != string.Empty));
\r
1069 queueWindow.SetQueue();
\r
1070 if (encodeQueue.Count > 1)
\r
1071 queueWindow.Show(false);
\r
1073 SetEncodeStarted(); // Encode is running, so setup the GUI appropriately
\r
1074 encodeQueue.Start(); // Start The Queue Encoding Process
\r
1079 else if (string.IsNullOrEmpty(sourcePath) || string.IsNullOrEmpty(text_destination.Text))
\r
1080 MessageBox.Show("No source or destination selected.", "Warning", MessageBoxButtons.OK,
\r
1081 MessageBoxIcon.Warning);
\r
1086 /// Toolbar - Add the current job to the Queue
\r
1088 /// <param name="sender">
\r
1091 /// <param name="e">
\r
1094 private void btn_add2Queue_Click(object sender, EventArgs e)
\r
1096 // Get the CLI query or use the query editor if it's not empty.
\r
1097 string query = QueryGenerator.GenerateFullQuery(this);
\r
1098 if (!string.IsNullOrEmpty(rtf_query.Text))
\r
1099 query = rtf_query.Text;
\r
1101 // If we have a custom query, then we'll want to figure out what the new source and destination is, otherwise we'll just use the gui components.
\r
1102 string jobSourcePath = !string.IsNullOrEmpty(rtf_query.Text) ? Main.GetSourceFromQuery(rtf_query.Text) : sourcePath;
\r
1103 string jobDestination = !string.IsNullOrEmpty(rtf_query.Text) ? Main.GetDestinationFromQuery(rtf_query.Text) : text_destination.Text;
\r
1105 // Make sure we have a Source and Destination.
\r
1106 if (string.IsNullOrEmpty(jobSourcePath) || string.IsNullOrEmpty(jobDestination))
\r
1108 MessageBox.Show("No source or destination selected.", "Warning", MessageBoxButtons.OK, MessageBoxIcon.Warning);
\r
1112 // Make sure the destination path exists.
\r
1113 if (!Directory.Exists(Path.GetDirectoryName(jobDestination)))
\r
1115 MessageBox.Show("Destination Path does not exist.", "Warning", MessageBoxButtons.OK, MessageBoxIcon.Warning);
\r
1119 // Make sure we don't have a duplciate on the queue.
\r
1120 if (encodeQueue.CheckForDestinationDuplicate(jobDestination))
\r
1122 DialogResult result =
\r
1124 "There is already a queue item for this destination path. \n\n If you continue, the encode will be overwritten. Do you wish to continue?",
\r
1125 "Warning", MessageBoxButtons.YesNo, MessageBoxIcon.Warning);
\r
1126 if (result == DialogResult.Yes)
\r
1127 encodeQueue.Add(query, this.GetTitle(), jobSourcePath, jobDestination, (rtf_query.Text != string.Empty));
\r
1130 encodeQueue.Add(query, this.GetTitle(), jobSourcePath, jobDestination, (rtf_query.Text != string.Empty));
\r
1132 lbl_encode.Text = encodeQueue.Count + " encode(s) pending in the queue";
\r
1134 queueWindow.Show();
\r
1138 /// Toolbar - Show the Queue
\r
1140 /// <param name="sender">
\r
1143 /// <param name="e">
\r
1146 private void btn_showQueue_Click(object sender, EventArgs e)
\r
1148 queueWindow.Show();
\r
1149 queueWindow.Activate();
\r
1153 /// Toolbar - Show the Preview Window
\r
1155 /// <param name="sender">
\r
1158 /// <param name="e">
\r
1161 private void tb_preview_Click(object sender, EventArgs e)
\r
1163 if (string.IsNullOrEmpty(sourcePath) || string.IsNullOrEmpty(text_destination.Text))
\r
1164 MessageBox.Show("No source or destination selected.", "Warning", MessageBoxButtons.OK,
\r
1165 MessageBoxIcon.Warning);
\r
1168 if (qtpreview == null)
\r
1170 qtpreview = new frmPreview(this);
\r
1173 else if (qtpreview.IsDisposed)
\r
1175 qtpreview = new frmPreview(this);
\r
1179 MessageBox.Show(qtpreview, "The preview window is already open!", "Warning", MessageBoxButtons.OK,
\r
1180 MessageBoxIcon.Warning);
\r
1185 /// Toolbar - Show the Activity log Window
\r
1187 /// <param name="sender">
\r
1190 /// <param name="e">
\r
1193 private void btn_ActivityWindow_Click(object sender, EventArgs e)
\r
1195 if (this.activityWindow == null || !this.activityWindow.IsHandleCreated)
\r
1196 this.activityWindow = new frmActivityWindow(encodeQueue, SourceScan);
\r
1198 this.activityWindow.Show();
\r
1199 this.activityWindow.Activate();
\r
1204 #region System Tray Icon
\r
1207 /// Handle Resizing of the main window when deaing with the Notify Icon
\r
1209 /// <param name="sender">
\r
1212 /// <param name="e">
\r
1215 private void frmMain_Resize(object sender, EventArgs e)
\r
1217 if (FormWindowState.Minimized == this.WindowState)
\r
1219 notifyIcon.Visible = true;
\r
1222 else if (FormWindowState.Normal == this.WindowState)
\r
1223 notifyIcon.Visible = false;
\r
1227 /// Double Click the Tray Icon
\r
1229 /// <param name="sender">
\r
1232 /// <param name="e">
\r
1235 private void notifyIcon_MouseDoubleClick(object sender, MouseEventArgs e)
\r
1237 this.Visible = true;
\r
1239 this.WindowState = FormWindowState.Normal;
\r
1240 notifyIcon.Visible = false;
\r
1244 /// Tray Icon - Restore Menu Item - Resture the Window
\r
1246 /// <param name="sender">
\r
1249 /// <param name="e">
\r
1252 private void btn_restore_Click(object sender, EventArgs e)
\r
1254 this.Visible = true;
\r
1256 this.WindowState = FormWindowState.Normal;
\r
1257 notifyIcon.Visible = false;
\r
1262 #region Main Window and Tab Control
\r
1265 private void btn_dvd_source_Click(object sender, EventArgs e)
\r
1267 if (DVD_Open.ShowDialog() == DialogResult.OK)
\r
1269 this.selectedSourceType = SourceType.Folder;
\r
1270 SelectSource(DVD_Open.SelectedPath);
\r
1273 UpdateSourceLabel();
\r
1276 private void btn_file_source_Click(object sender, EventArgs e)
\r
1278 if (ISO_Open.ShowDialog() == DialogResult.OK)
\r
1280 this.selectedSourceType = SourceType.VideoFile;
\r
1281 SelectSource(ISO_Open.FileName);
\r
1284 UpdateSourceLabel();
\r
1287 private void mnu_dvd_drive_Click(object sender, EventArgs e)
\r
1289 ToolStripMenuItem item = sender as ToolStripMenuItem;
\r
1292 string driveId = item.Name.Replace("Drive", string.Empty);
\r
1294 if (int.TryParse(driveId, out id))
\r
1296 this.dvdDrivePath = drives[id].RootDirectory;
\r
1297 this.dvdDriveLabel = drives[id].VolumeLabel;
\r
1299 if (this.dvdDrivePath == null) return;
\r
1300 this.selectedSourceType = SourceType.DvdDrive;
\r
1301 SelectSource(this.dvdDrivePath);
\r
1306 private void SelectSource(string file)
\r
1308 Check_ChapterMarkers.Enabled = true;
\r
1309 sourcePath = string.Empty;
\r
1311 if (file == string.Empty) // Must have a file or path
\r
1313 UpdateSourceLabel();
\r
1317 sourcePath = Path.GetFileName(file);
\r
1318 StartScan(file, 0);
\r
1321 private void drp_dvdtitle_Click(object sender, EventArgs e)
\r
1323 if ((drp_dvdtitle.Items.Count == 1) && (drp_dvdtitle.Items[0].ToString() == "Automatic"))
\r
1325 "There are no titles to select. Please load a source file by clicking the 'Source' button above before trying to select a title.",
\r
1326 "Alert", MessageBoxButtons.OK, MessageBoxIcon.Asterisk);
\r
1329 private void drp_dvdtitle_SelectedIndexChanged(object sender, EventArgs e)
\r
1331 UnRegisterPresetEventHandler();
\r
1332 drop_mode.SelectedIndex = 0;
\r
1334 drop_chapterStart.Items.Clear();
\r
1335 drop_chapterFinish.Items.Clear();
\r
1337 // If the dropdown is set to automatic nothing else needs to be done.
\r
1338 // Otheriwse if its not, title data has to be loaded from parsing.
\r
1339 if (drp_dvdtitle.Text != "Automatic")
\r
1341 selectedTitle = drp_dvdtitle.SelectedItem as Title;
\r
1342 lbl_duration.Text = selectedTitle.Duration.ToString();
\r
1343 PictureSettings.CurrentlySelectedPreset = this.currentlySelectedPreset;
\r
1344 PictureSettings.Source = selectedTitle; // Setup Picture Settings Tab Control
\r
1346 // Populate the Angles dropdown
\r
1347 drop_angle.Items.Clear();
\r
1348 if (!Properties.Settings.Default.noDvdNav)
\r
1350 drop_angle.Visible = true;
\r
1351 lbl_angle.Visible = true;
\r
1353 for (int i = 1; i <= selectedTitle.AngleCount; i++)
\r
1354 drop_angle.Items.Add(i.ToString());
\r
1356 if (drop_angle.Items.Count != 0)
\r
1357 drop_angle.SelectedIndex = 0;
\r
1361 drop_angle.Visible = false;
\r
1362 lbl_angle.Visible = false;
\r
1365 // Populate the Start chapter Dropdown
\r
1366 drop_chapterStart.Items.Clear();
\r
1367 drop_chapterStart.Items.AddRange(selectedTitle.Chapters.ToArray());
\r
1368 if (drop_chapterStart.Items.Count > 0)
\r
1369 drop_chapterStart.Text = drop_chapterStart.Items[0].ToString();
\r
1371 // Populate the Final Chapter Dropdown
\r
1372 drop_chapterFinish.Items.Clear();
\r
1373 drop_chapterFinish.Items.AddRange(selectedTitle.Chapters.ToArray());
\r
1374 if (drop_chapterFinish.Items.Count > 0)
\r
1375 drop_chapterFinish.Text = drop_chapterFinish.Items[drop_chapterFinish.Items.Count - 1].ToString();
\r
1377 // Populate the Audio Channels Dropdown
\r
1378 AudioSettings.SetTrackList(selectedTitle, this.currentlySelectedPreset);
\r
1380 // Populate the Subtitles dropdown
\r
1381 Subtitles.SetSubtitleTrackAuto(selectedTitle.Subtitles.ToArray());
\r
1383 // Update the source label if we have multiple streams
\r
1384 if (selectedTitle != null)
\r
1385 if (!string.IsNullOrEmpty(selectedTitle.SourceName))
\r
1386 labelSource.Text = labelSource.Text = Path.GetFileName(selectedTitle.SourceName);
\r
1388 // Run the AutoName & ChapterNaming functions
\r
1389 if (Properties.Settings.Default.autoNaming)
\r
1391 string autoPath = Main.AutoName(this);
\r
1392 if (autoPath != null)
\r
1393 text_destination.Text = autoPath;
\r
1396 "You currently have \"Automatically name output files\" enabled for the destination file box, but you do not have a default directory set.\n\nYou should set a \"Default Path\" in HandBrakes preferences. (See 'Tools' menu -> 'Options' -> 'General' Tab -> 'Default Path')",
\r
1397 "Warning", MessageBoxButtons.OK, MessageBoxIcon.Warning);
\r
1400 data_chpt.Rows.Clear();
\r
1401 if (selectedTitle.Chapters.Count != 1)
\r
1403 DataGridView chapterGridView = Main.ChapterNaming(data_chpt, drop_chapterFinish.Text);
\r
1404 if (chapterGridView != null)
\r
1405 data_chpt = chapterGridView;
\r
1409 Check_ChapterMarkers.Checked = false;
\r
1410 Check_ChapterMarkers.Enabled = false;
\r
1413 // Hack to force the redraw of the scrollbars which don't resize properly when the control is disabled.
\r
1414 data_chpt.Columns[0].Width = 166;
\r
1415 data_chpt.Columns[0].Width = 165;
\r
1417 RegisterPresetEventHandler();
\r
1420 private void chapersChanged(object sender, EventArgs e)
\r
1422 if (drop_mode.SelectedIndex != 0) // Function is not used if we are not in chapters mode.
\r
1425 Control ctl = (Control)sender;
\r
1426 int chapterStart, chapterEnd;
\r
1427 int.TryParse(drop_chapterStart.Text, out chapterStart);
\r
1428 int.TryParse(drop_chapterFinish.Text, out chapterEnd);
\r
1432 case "drop_chapterStart":
\r
1433 if (drop_chapterFinish.SelectedIndex == -1 && drop_chapterFinish.Items.Count != 0)
\r
1434 drop_chapterFinish.SelectedIndex = drop_chapterFinish.Items.Count - 1;
\r
1436 if (chapterEnd != 0)
\r
1437 if (chapterStart > chapterEnd)
\r
1438 drop_chapterFinish.Text = chapterStart.ToString();
\r
1440 case "drop_chapterFinish":
\r
1441 if (drop_chapterStart.Items.Count >= 1 && drop_chapterStart.SelectedIndex == -1)
\r
1442 drop_chapterStart.SelectedIndex = 0;
\r
1444 if (chapterStart != 0)
\r
1445 if (chapterEnd < chapterStart)
\r
1446 drop_chapterFinish.Text = chapterStart.ToString();
\r
1448 // Add more rows to the Chapter menu if needed.
\r
1449 if (Check_ChapterMarkers.Checked)
\r
1451 int i = data_chpt.Rows.Count, finish = 0;
\r
1452 int.TryParse(drop_chapterFinish.Text, out finish);
\r
1454 while (i < finish)
\r
1456 int n = data_chpt.Rows.Add();
\r
1457 data_chpt.Rows[n].Cells[0].Value = (i + 1);
\r
1458 data_chpt.Rows[n].Cells[1].Value = "Chapter " + (i + 1);
\r
1459 data_chpt.Rows[n].Cells[0].ValueType = typeof(int);
\r
1460 data_chpt.Rows[n].Cells[1].ValueType = typeof(string);
\r
1467 // Update the Duration
\r
1468 lbl_duration.Text =
\r
1469 Main.CalculateDuration(drop_chapterStart.SelectedIndex, drop_chapterFinish.SelectedIndex, selectedTitle)
\r
1472 // Run the Autonaming function
\r
1473 if (Properties.Settings.Default.autoNaming)
\r
1474 text_destination.Text = Main.AutoName(this);
\r
1476 // Disable chapter markers if only 1 chapter is selected.
\r
1477 if (chapterStart == chapterEnd)
\r
1479 Check_ChapterMarkers.Enabled = false;
\r
1480 btn_importChapters.Enabled = false;
\r
1481 data_chpt.Enabled = false;
\r
1485 Check_ChapterMarkers.Enabled = true;
\r
1486 if (Check_ChapterMarkers.Checked)
\r
1488 btn_importChapters.Enabled = true;
\r
1489 data_chpt.Enabled = true;
\r
1494 private void SecondsOrFramesChanged(object sender, EventArgs e)
\r
1497 int.TryParse(drop_chapterStart.Text, out start);
\r
1498 int.TryParse(drop_chapterFinish.Text, out end);
\r
1499 double duration = end - start;
\r
1501 switch (drop_mode.SelectedIndex)
\r
1504 lbl_duration.Text = TimeSpan.FromSeconds(duration).ToString();
\r
1507 if (selectedTitle != null)
\r
1509 duration = duration / selectedTitle.Fps;
\r
1510 lbl_duration.Text = TimeSpan.FromSeconds(duration).ToString();
\r
1513 lbl_duration.Text = "--:--:--";
\r
1519 private void drop_mode_SelectedIndexChanged(object sender, EventArgs e)
\r
1522 this.drop_chapterFinish.TextChanged -= new EventHandler(this.SecondsOrFramesChanged);
\r
1523 this.drop_chapterStart.TextChanged -= new EventHandler(this.SecondsOrFramesChanged);
\r
1526 switch (drop_mode.SelectedIndex)
\r
1529 drop_chapterStart.DropDownStyle = ComboBoxStyle.DropDownList;
\r
1530 drop_chapterFinish.DropDownStyle = ComboBoxStyle.DropDownList;
\r
1531 if (drop_chapterStart.Items.Count != 0)
\r
1533 drop_chapterStart.SelectedIndex = 0;
\r
1534 drop_chapterFinish.SelectedIndex = drop_chapterFinish.Items.Count - 1;
\r
1537 lbl_duration.Text = "--:--:--";
\r
1540 this.drop_chapterStart.TextChanged += new EventHandler(this.SecondsOrFramesChanged);
\r
1541 this.drop_chapterFinish.TextChanged += new EventHandler(this.SecondsOrFramesChanged);
\r
1542 drop_chapterStart.DropDownStyle = ComboBoxStyle.Simple;
\r
1543 drop_chapterFinish.DropDownStyle = ComboBoxStyle.Simple;
\r
1544 if (selectedTitle != null)
\r
1546 drop_chapterStart.Text = "0";
\r
1547 drop_chapterFinish.Text = selectedTitle.Duration.TotalSeconds.ToString();
\r
1551 this.drop_chapterStart.TextChanged += new EventHandler(this.SecondsOrFramesChanged);
\r
1552 this.drop_chapterFinish.TextChanged += new EventHandler(this.SecondsOrFramesChanged);
\r
1553 drop_chapterStart.DropDownStyle = ComboBoxStyle.Simple;
\r
1554 drop_chapterFinish.DropDownStyle = ComboBoxStyle.Simple;
\r
1555 if (selectedTitle != null)
\r
1557 drop_chapterStart.Text = "0";
\r
1558 drop_chapterFinish.Text = (selectedTitle.Fps * selectedTitle.Duration.TotalSeconds).ToString();
\r
1565 private void btn_destBrowse_Click(object sender, EventArgs e)
\r
1567 // This removes the file extension from the filename box on the save file dialog.
\r
1568 // It's daft but some users don't realise that typing an extension overrides the dropdown extension selected.
\r
1569 DVD_Save.FileName = Path.GetFileNameWithoutExtension(text_destination.Text);
\r
1571 if (Path.IsPathRooted(text_destination.Text))
\r
1572 DVD_Save.InitialDirectory = Path.GetDirectoryName(text_destination.Text);
\r
1574 // Show the dialog and set the main form file path
\r
1575 if (drop_format.SelectedIndex.Equals(0))
\r
1576 DVD_Save.FilterIndex = 1;
\r
1577 else if (drop_format.SelectedIndex.Equals(1))
\r
1578 DVD_Save.FilterIndex = 2;
\r
1580 if (DVD_Save.ShowDialog() == DialogResult.OK)
\r
1582 // Add a file extension manually, as FileDialog.AddExtension has issues with dots in filenames
\r
1583 switch (DVD_Save.FilterIndex)
\r
1587 !Path.GetExtension(DVD_Save.FileName).Equals(".mp4",
\r
1588 StringComparison.InvariantCultureIgnoreCase))
\r
1589 if (Properties.Settings.Default.useM4v)
\r
1590 DVD_Save.FileName = DVD_Save.FileName.Replace(".mp4", ".m4v").Replace(".mkv", ".m4v");
\r
1592 DVD_Save.FileName = DVD_Save.FileName.Replace(".m4v", ".mp4").Replace(".mkv", ".mp4");
\r
1596 !Path.GetExtension(DVD_Save.FileName).Equals(".mkv", StringComparison.InvariantCultureIgnoreCase))
\r
1597 DVD_Save.FileName = DVD_Save.FileName.Replace(".mp4", ".mkv").Replace(".m4v", ".mkv");
\r
1603 text_destination.Text = DVD_Save.FileName;
\r
1605 // Quicktime requires .m4v file for chapter markers to work. If checked, change the extension to .m4v (mp4 and m4v are the same thing)
\r
1606 if (Check_ChapterMarkers.Checked && DVD_Save.FilterIndex != 2)
\r
1607 SetExtension(".m4v");
\r
1611 private void text_destination_TextChanged(object sender, EventArgs e)
\r
1613 string path = text_destination.Text;
\r
1614 if (path.EndsWith(".mp4") || path.EndsWith(".m4v"))
\r
1615 drop_format.SelectedIndex = 0;
\r
1616 else if (path.EndsWith(".mkv"))
\r
1617 drop_format.SelectedIndex = 1;
\r
1620 // Output Settings
\r
1621 private void drop_format_SelectedIndexChanged(object sender, EventArgs e)
\r
1623 switch (drop_format.SelectedIndex)
\r
1626 if (Properties.Settings.Default.useM4v || Check_ChapterMarkers.Checked ||
\r
1627 AudioSettings.RequiresM4V() || Subtitles.RequiresM4V())
\r
1628 SetExtension(".m4v");
\r
1630 SetExtension(".mp4");
\r
1633 SetExtension(".mkv");
\r
1637 AudioSettings.SetContainer(drop_format.Text);
\r
1639 if (drop_format.Text.Contains("MP4"))
\r
1641 if (drp_videoEncoder.Items.Contains("VP3 (Theora)"))
\r
1643 drp_videoEncoder.Items.Remove("VP3 (Theora)");
\r
1644 drp_videoEncoder.SelectedIndex = 1;
\r
1647 else if (drop_format.Text.Contains("MKV"))
\r
1648 drp_videoEncoder.Items.Add("VP3 (Theora)");
\r
1651 public void SetExtension(string newExtension)
\r
1653 if (newExtension == ".mp4" || newExtension == ".m4v")
\r
1654 if (Properties.Settings.Default.useM4v || Check_ChapterMarkers.Checked || AudioSettings.RequiresM4V() ||
\r
1655 Subtitles.RequiresM4V())
\r
1656 newExtension = ".m4v";
\r
1658 newExtension = ".mp4";
\r
1660 if (Path.HasExtension(newExtension))
\r
1661 text_destination.Text = Path.ChangeExtension(text_destination.Text, newExtension);
\r
1665 private void drp_videoEncoder_SelectedIndexChanged(object sender, EventArgs e)
\r
1667 setContainerOpts();
\r
1669 // Turn off some options which are H.264 only when the user selects a non h.264 encoder
\r
1670 if (drp_videoEncoder.Text.Contains("H.264"))
\r
1672 if (check_2PassEncode.CheckState == CheckState.Checked)
\r
1673 check_turbo.Enabled = true;
\r
1675 tab_advanced.Enabled = true;
\r
1676 if ((drop_format.Text.Contains("MP4")) || (drop_format.Text.Contains("M4V")))
\r
1677 check_iPodAtom.Enabled = true;
\r
1679 check_iPodAtom.Enabled = false;
\r
1683 check_turbo.CheckState = CheckState.Unchecked;
\r
1684 check_turbo.Enabled = false;
\r
1685 tab_advanced.Enabled = false;
\r
1686 x264Panel.X264Query = string.Empty;
\r
1687 check_iPodAtom.Enabled = false;
\r
1688 check_iPodAtom.Checked = false;
\r
1691 // Setup the CQ Slider
\r
1692 switch (drp_videoEncoder.Text)
\r
1694 case "MPEG-4 (FFmpeg)":
\r
1695 if (slider_videoQuality.Value > 31)
\r
1696 slider_videoQuality.Value = 20; // Just reset to 70% QP 10 on encode change.
\r
1697 slider_videoQuality.Minimum = 1;
\r
1698 slider_videoQuality.Maximum = 31;
\r
1700 case "H.264 (x264)":
\r
1701 slider_videoQuality.Minimum = 0;
\r
1702 slider_videoQuality.TickFrequency = 1;
\r
1704 CultureInfo culture = CultureInfo.CreateSpecificCulture("en-US");
\r
1705 double cqStep = Properties.Settings.Default.x264cqstep;
\r
1706 double multiplier = 1.0 / cqStep;
\r
1707 double value = slider_videoQuality.Value * multiplier;
\r
1709 slider_videoQuality.Maximum = (int)(51 / Properties.Settings.Default.x264cqstep);
\r
1711 if (value < slider_videoQuality.Maximum)
\r
1712 slider_videoQuality.Value = slider_videoQuality.Maximum - (int)value;
\r
1715 case "VP3 (Theora)":
\r
1716 if (slider_videoQuality.Value > 63)
\r
1717 slider_videoQuality.Value = 45; // Just reset to 70% QP 45 on encode change.
\r
1718 slider_videoQuality.Minimum = 0;
\r
1719 slider_videoQuality.Maximum = 63;
\r
1725 /// When the FrameRate is not Same As Source, show the Max/Constant Mode dropdown
\r
1727 /// <param name="sender">
\r
1730 /// <param name="e">
\r
1733 private void drp_videoFramerate_SelectedIndexChanged(object sender, EventArgs e)
\r
1735 if (this.drp_videoFramerate.SelectedIndex == 0)
\r
1737 this.checkMaximumFramerate.Visible = false;
\r
1738 this.checkMaximumFramerate.CheckState = CheckState.Unchecked;
\r
1742 this.checkMaximumFramerate.Visible = true;
\r
1747 /// Set the container format options
\r
1749 public void setContainerOpts()
\r
1751 if ((drop_format.Text.Contains("MP4")) || (drop_format.Text.Contains("M4V")))
\r
1753 check_largeFile.Enabled = true;
\r
1754 check_optimiseMP4.Enabled = true;
\r
1755 check_iPodAtom.Enabled = true;
\r
1759 check_largeFile.Enabled = false;
\r
1760 check_optimiseMP4.Enabled = false;
\r
1761 check_iPodAtom.Enabled = false;
\r
1762 check_largeFile.Checked = false;
\r
1763 check_optimiseMP4.Checked = false;
\r
1764 check_iPodAtom.Checked = false;
\r
1768 private double cachedCqStep = Properties.Settings.Default.x264cqstep;
\r
1771 /// Update the CQ slider for x264 for a new CQ step. This is set from option
\r
1773 public void setQualityFromSlider()
\r
1775 // Work out the current RF value.
\r
1776 double cqStep = this.cachedCqStep;
\r
1777 double rfValue = 51.0 - slider_videoQuality.Value * cqStep;
\r
1779 // Change the maximum value for the slider
\r
1780 slider_videoQuality.Maximum = (int)(51 / Properties.Settings.Default.x264cqstep);
\r
1782 // Reset the CQ slider to RF0
\r
1783 slider_videoQuality.Value = slider_videoQuality.Maximum;
\r
1785 // Reset the CQ slider back to the previous value as close as possible
\r
1786 double cqStepNew = Properties.Settings.Default.x264cqstep;
\r
1787 double rfValueCurrent = 51.0 - slider_videoQuality.Value * cqStepNew;
\r
1788 while (rfValueCurrent < rfValue)
\r
1790 slider_videoQuality.Value--;
\r
1791 rfValueCurrent = 51.0 - slider_videoQuality.Value * cqStepNew;
\r
1794 // Cache the CQ step for the next calculation
\r
1795 this.cachedCqStep = Properties.Settings.Default.x264cqstep;
\r
1798 private void slider_videoQuality_Scroll(object sender, EventArgs e)
\r
1800 double cqStep = Properties.Settings.Default.x264cqstep;
\r
1801 switch (drp_videoEncoder.Text)
\r
1803 case "MPEG-4 (FFmpeg)":
\r
1804 lbl_SliderValue.Text = "QP:" + (32 - slider_videoQuality.Value);
\r
1806 case "H.264 (x264)":
\r
1807 double rfValue = 51.0 - slider_videoQuality.Value * cqStep;
\r
1808 rfValue = Math.Round(rfValue, 2);
\r
1809 lbl_SliderValue.Text = "RF:" + rfValue.ToString(new CultureInfo("en-US"));
\r
1811 case "VP3 (Theora)":
\r
1812 lbl_SliderValue.Text = "QP:" + slider_videoQuality.Value;
\r
1817 private void radio_targetFilesize_CheckedChanged(object sender, EventArgs e)
\r
1819 text_bitrate.Enabled = false;
\r
1820 text_filesize.Enabled = true;
\r
1821 slider_videoQuality.Enabled = false;
\r
1823 check_2PassEncode.Enabled = true;
\r
1826 private void radio_avgBitrate_CheckedChanged(object sender, EventArgs e)
\r
1828 text_bitrate.Enabled = true;
\r
1829 text_filesize.Enabled = false;
\r
1830 slider_videoQuality.Enabled = false;
\r
1832 check_2PassEncode.Enabled = true;
\r
1835 private void radio_cq_CheckedChanged(object sender, EventArgs e)
\r
1837 text_bitrate.Enabled = false;
\r
1838 text_filesize.Enabled = false;
\r
1839 slider_videoQuality.Enabled = true;
\r
1841 check_2PassEncode.Enabled = false;
\r
1842 check_2PassEncode.CheckState = CheckState.Unchecked;
\r
1845 private void check_2PassEncode_CheckedChanged(object sender, EventArgs e)
\r
1847 if (check_2PassEncode.CheckState.ToString() == "Checked")
\r
1849 if (drp_videoEncoder.Text.Contains("H.264"))
\r
1850 check_turbo.Enabled = true;
\r
1854 check_turbo.Enabled = false;
\r
1855 check_turbo.CheckState = CheckState.Unchecked;
\r
1859 // Chapter Marker Tab
\r
1860 private void Check_ChapterMarkers_CheckedChanged(object sender, EventArgs e)
\r
1862 if (Check_ChapterMarkers.Checked)
\r
1864 if (drop_format.SelectedIndex != 1)
\r
1865 SetExtension(".m4v");
\r
1866 data_chpt.Enabled = true;
\r
1867 btn_importChapters.Enabled = true;
\r
1871 if (drop_format.SelectedIndex != 1 && !Properties.Settings.Default.useM4v)
\r
1872 SetExtension(".mp4");
\r
1873 data_chpt.Enabled = false;
\r
1874 btn_importChapters.Enabled = false;
\r
1878 private void btn_importChapters_Click(object sender, EventArgs e)
\r
1880 if (File_ChapterImport.ShowDialog() == DialogResult.OK)
\r
1882 string filename = File_ChapterImport.FileName;
\r
1883 DataGridView imported = Main.ImportChapterNames(data_chpt, filename);
\r
1884 if (imported != null)
\r
1885 data_chpt = imported;
\r
1889 private void btn_export_Click(object sender, EventArgs e)
\r
1891 SaveFileDialog saveFileDialog = new SaveFileDialog();
\r
1892 saveFileDialog.Filter = "Csv File|*.csv";
\r
1893 saveFileDialog.DefaultExt = "csv";
\r
1894 if (saveFileDialog.ShowDialog() == DialogResult.OK)
\r
1896 string filename = saveFileDialog.FileName;
\r
1898 Main.SaveChapterMarkersToCsv(this, filename);
\r
1902 private void mnu_resetChapters_Click(object sender, EventArgs e)
\r
1904 data_chpt.Rows.Clear();
\r
1905 DataGridView chapterGridView = Main.ChapterNaming(data_chpt, drop_chapterFinish.Text);
\r
1906 if (chapterGridView != null)
\r
1908 data_chpt = chapterGridView;
\r
1912 // Query Editor Tab
\r
1913 private void btn_generate_Query_Click(object sender, EventArgs e)
\r
1915 rtf_query.Text = QueryGenerator.GenerateFullQuery(this);
\r
1918 private void btn_clear_Click(object sender, EventArgs e)
\r
1920 rtf_query.Clear();
\r
1925 // MainWindow Components, Actions and Functions ***********************
\r
1927 #region Source Scan
\r
1930 /// Start the Scan Process
\r
1932 /// <param name="filename">
\r
1935 /// <param name="title">
\r
1938 private void StartScan(string filename, int title)
\r
1940 // Setup the GUI components for the scan.
\r
1941 sourcePath = filename;
\r
1943 this.DisableGUI();
\r
1948 SourceScan.Scan(sourcePath, title);
\r
1949 SourceScan.ScanStatusChanged += new EventHandler(SourceScan_ScanStatusChanged);
\r
1950 SourceScan.ScanCompleted += new EventHandler(SourceScan_ScanCompleted);
\r
1952 catch (Exception exc)
\r
1954 MessageBox.Show("frmMain.cs - StartScan " + exc, "Error", MessageBoxButtons.OK, MessageBoxIcon.Error);
\r
1959 /// Update the Status label for the scan
\r
1961 /// <param name="sender">
\r
1964 /// <param name="e">
\r
1967 private void SourceScan_ScanStatusChanged(object sender, EventArgs e)
\r
1969 UpdateScanStatusLabel();
\r
1973 /// Update the UI after the scan has completed
\r
1975 /// <param name="sender">
\r
1978 /// <param name="e">
\r
1981 private void SourceScan_ScanCompleted(object sender, EventArgs e)
\r
1983 UpdateGuiAfterScan();
\r
1987 /// Update the Scan Status Label
\r
1989 private void UpdateScanStatusLabel()
\r
1991 if (InvokeRequired)
\r
1993 BeginInvoke(new UpdateWindowHandler(UpdateScanStatusLabel));
\r
1996 lbl_encode.Text = SourceScan.ScanStatus;
\r
2000 /// Reset the GUI when the scan has completed
\r
2002 private void UpdateGuiAfterScan()
\r
2004 if (InvokeRequired)
\r
2006 BeginInvoke(new UpdateWindowHandler(UpdateGuiAfterScan));
\r
2012 currentSource = SourceScan.SouceData;
\r
2014 // Setup some GUI components
\r
2015 drp_dvdtitle.Items.Clear();
\r
2016 if (currentSource.Titles.Count != 0)
\r
2017 drp_dvdtitle.Items.AddRange(currentSource.Titles.ToArray());
\r
2019 foreach (Title title in currentSource.Titles)
\r
2021 if (title.MainTitle)
\r
2023 drp_dvdtitle.SelectedItem = title;
\r
2027 if (drp_dvdtitle.SelectedItem == null && drp_dvdtitle.Items.Count > 0)
\r
2029 drp_dvdtitle.SelectedIndex = 0;
\r
2032 // Enable the creation of chapter markers if the file is an image of a dvd
\r
2033 if (drop_chapterStart.Items.Count > 0)
\r
2036 int.TryParse(drop_chapterStart.Items[0].ToString(), out start);
\r
2037 int.TryParse(drop_chapterFinish.Items[drop_chapterFinish.Items.Count - 1].ToString(), out end);
\r
2038 if (end > start) Check_ChapterMarkers.Enabled = true;
\r
2041 Check_ChapterMarkers.Enabled = false;
\r
2042 Check_ChapterMarkers.Checked = false;
\r
2043 data_chpt.Rows.Clear();
\r
2047 // If no titles were found, Display an error message
\r
2048 if (drp_dvdtitle.Items.Count == 0)
\r
2051 "No Title(s) found. \n\nYour Source may be copy protected, badly mastered or in a format which HandBrake does not support. \nPlease refer to the Documentation and FAQ (see Help Menu).",
\r
2052 "Error", MessageBoxButtons.OK, MessageBoxIcon.Hand);
\r
2053 sourcePath = string.Empty;
\r
2055 UpdateSourceLabel();
\r
2057 // Enable the GUI components and enable any disabled components
\r
2060 catch (Exception exc)
\r
2062 MessageBox.Show("frmMain.cs - updateUIafterScan " + exc, "Error", MessageBoxButtons.OK,
\r
2063 MessageBoxIcon.Error);
\r
2069 /// Enable the GUI
\r
2071 private void EnableGUI()
\r
2075 if (InvokeRequired)
\r
2076 BeginInvoke(new UpdateWindowHandler(EnableGUI));
\r
2077 lbl_encode.Text = "Scan Completed";
\r
2078 foreach (Control ctrl in Controls)
\r
2079 ctrl.Enabled = true;
\r
2080 btn_start.Enabled = true;
\r
2081 btn_showQueue.Enabled = true;
\r
2082 btn_add2Queue.Enabled = true;
\r
2083 tb_preview.Enabled = true;
\r
2084 btn_source.Enabled = true;
\r
2085 mnu_killCLI.Visible = false;
\r
2087 catch (Exception exc)
\r
2089 MessageBox.Show("frmMain.cs - EnableGUI() " + exc, "Error", MessageBoxButtons.OK, MessageBoxIcon.Error);
\r
2094 /// Disable the GUI
\r
2096 private void DisableGUI()
\r
2098 foreach (Control ctrl in Controls)
\r
2099 if (!(ctrl is StatusStrip || ctrl is MenuStrip || ctrl is ToolStrip))
\r
2100 ctrl.Enabled = false;
\r
2102 lbl_encode.Visible = true;
\r
2103 lbl_encode.Text = "Scanning ...";
\r
2104 btn_source.Enabled = false;
\r
2105 btn_start.Enabled = false;
\r
2106 btn_showQueue.Enabled = false;
\r
2107 btn_add2Queue.Enabled = false;
\r
2108 tb_preview.Enabled = false;
\r
2109 mnu_killCLI.Visible = true;
\r
2115 private void KillScan()
\r
2117 SourceScan.ScanCompleted -= new EventHandler(SourceScan_ScanCompleted);
\r
2121 SourceScan.Stop();
\r
2123 lbl_encode.Text = "Scan Cancelled!";
\r
2129 private void ResetGUI()
\r
2131 drp_dvdtitle.Items.Clear();
\r
2132 drop_chapterStart.Items.Clear();
\r
2133 drop_chapterFinish.Items.Clear();
\r
2134 lbl_duration.Text = "Select a Title";
\r
2135 PictureSettings.lbl_src_res.Text = "Select a Title";
\r
2136 sourcePath = String.Empty;
\r
2137 text_destination.Text = String.Empty;
\r
2138 selectedTitle = null;
\r
2142 /// Update the Source Label
\r
2144 private void UpdateSourceLabel()
\r
2146 labelSource.Text = string.IsNullOrEmpty(sourcePath) ? "Select \"Source\" to continue." : this.SourceName;
\r
2148 if (selectedTitle != null)
\r
2149 if (!string.IsNullOrEmpty(selectedTitle.SourceName))
\r
2150 // If it's one of multiple source files, make sure we don't use the folder name
\r
2151 labelSource.Text = Path.GetFileName(selectedTitle.SourceName);
\r
2155 /// Take a job from the Queue, rescan it, and reload the GUI for that job.
\r
2157 /// <param name="job">
\r
2160 public void RecievingJob(Job job)
\r
2162 string query = job.Query;
\r
2163 StartScan(job.Source, job.Title);
\r
2165 if (query != null)
\r
2167 // Ok, Reset all the H264 widgets before changing the preset
\r
2168 x264Panel.Reset2Defaults();
\r
2170 // Send the query from the file to the Query Parser class
\r
2171 QueryParser presetQuery = QueryParser.Parse(query);
\r
2173 // Now load the preset
\r
2174 PresetLoader.LoadPreset(this, presetQuery, "Load Back From Queue");
\r
2176 // The x264 widgets will need updated, so do this now:
\r
2177 x264Panel.StandardizeOptString();
\r
2178 x264Panel.SetCurrentSettingsInPanel();
\r
2180 // Finally, let this window have a copy of the preset settings.
\r
2181 this.currentlySelectedPreset = null;
\r
2182 PictureSettings.SetPresetCropWarningLabel(null);
\r
2188 #region GUI Functions and Actions
\r
2191 /// Set the GUI to it's finished encoding state.
\r
2193 private void SetEncodeFinished()
\r
2197 if (InvokeRequired)
\r
2199 BeginInvoke(new UpdateWindowHandler(SetEncodeFinished));
\r
2203 lbl_encode.Text = "Encoding Finished";
\r
2204 ProgressBarStatus.Visible = false;
\r
2205 btn_start.Text = "Start";
\r
2206 btn_start.ToolTipText = "Start the encoding process";
\r
2207 btn_start.Image = Properties.Resources.Play;
\r
2209 // If the window is minimized, display the notification in a popup.
\r
2210 if (Properties.Settings.Default.trayIconAlerts)
\r
2211 if (FormWindowState.Minimized == this.WindowState)
\r
2213 notifyIcon.BalloonTipText = lbl_encode.Text;
\r
2214 notifyIcon.ShowBalloonTip(500);
\r
2217 catch (Exception exc)
\r
2219 MessageBox.Show(exc.ToString());
\r
2224 /// Set the GUI to it's started encoding state.
\r
2226 private void SetEncodeStarted()
\r
2230 if (InvokeRequired)
\r
2232 BeginInvoke(new UpdateWindowHandler(SetEncodeStarted));
\r
2235 lbl_encode.Visible = true;
\r
2236 ProgressBarStatus.Value = 0;
\r
2237 ProgressBarStatus.Visible = true;
\r
2238 lbl_encode.Text = "Encoding with " + encodeQueue.Count + " encode(s) pending";
\r
2239 btn_start.Text = "Stop";
\r
2240 btn_start.ToolTipText = "Stop the encoding process.";
\r
2241 btn_start.Image = Properties.Resources.stop;
\r
2243 catch (Exception exc)
\r
2245 MessageBox.Show(exc.ToString());
\r
2250 /// Display the Encode Status
\r
2252 /// <param name="sender">
\r
2255 /// <param name="e">
\r
2258 private void EncodeQueue_EncodeStatusChanged(object sender, HandBrake.ApplicationServices.EncodeProgressEventArgs e)
\r
2260 if (this.InvokeRequired)
\r
2262 this.BeginInvoke(new Encode.EncodeProgessStatus(EncodeQueue_EncodeStatusChanged), new[] { sender, e });
\r
2268 "{0:00.00}%, FPS: {1:000.0}, Avg FPS: {2:000.0}, Time Remaining: {3}, Encode(s) Pending {4}",
\r
2269 e.PercentComplete,
\r
2270 e.CurrentFrameRate,
\r
2271 e.AverageFrameRate,
\r
2272 e.EstimatedTimeLeft,
\r
2273 encodeQueue.Count);
\r
2275 ProgressBarStatus.Value = (int)Math.Round(e.PercentComplete);
\r
2279 /// Set the DVD Drive selection in the "Source" Menu
\r
2281 private void SetDriveSelectionMenuItem()
\r
2285 if (InvokeRequired)
\r
2287 BeginInvoke(new UpdateWindowHandler(SetDriveSelectionMenuItem));
\r
2291 drives = Main.GetDrives();
\r
2293 List<ToolStripMenuItem> menuItems = new List<ToolStripMenuItem>();
\r
2294 foreach (DriveInformation drive in drives)
\r
2296 ToolStripMenuItem menuItem = new ToolStripMenuItem
\r
2298 Name = drive.ToString(),
\r
2299 Text = drive.RootDirectory + " (" + drive.VolumeLabel + ")",
\r
2300 Image = Resources.disc_small
\r
2302 menuItem.Click += new EventHandler(mnu_dvd_drive_Click);
\r
2303 menuItems.Add(menuItem);
\r
2306 foreach (ToolStripMenuItem item in menuItems)
\r
2307 btn_source.DropDownItems.Add(item);
\r
2309 catch (Exception exc)
\r
2311 MessageBox.Show("Error in SetDriveSelectionMenuItem" + exc);
\r
2316 /// Access the preset Handler and setup the preset panel.
\r
2318 private void LoadPresetPanel()
\r
2320 if (presetHandler.CheckIfPresetsAreOutOfDate())
\r
2321 if (!Settings.Default.presetNotification)
\r
2322 MessageBox.Show(this,
\r
2323 "HandBrake has determined your built-in presets are out of date... These presets will now be updated.",
\r
2324 "Preset Update", MessageBoxButtons.OK, MessageBoxIcon.Information);
\r
2326 presetHandler.GetPresetPanel(ref treeView_presets);
\r
2327 treeView_presets.Update();
\r
2331 /// Get the title from the selected item in the title dropdown.
\r
2336 private int GetTitle()
\r
2339 if (drp_dvdtitle.SelectedItem != null)
\r
2341 string[] titleInfo = drp_dvdtitle.SelectedItem.ToString().Split(' ');
\r
2342 int.TryParse(titleInfo[0], out title);
\r
2349 /// Handle the Update Check Finishing.
\r
2351 /// <param name="result">
\r
2354 private void UpdateCheckDoneMenu(IAsyncResult result)
\r
2356 // Make sure it's running on the calling thread
\r
2357 if (InvokeRequired)
\r
2359 Invoke(new MethodInvoker(() => this.UpdateCheckDoneMenu(result)));
\r
2362 UpdateCheckInformation info;
\r
2365 // Get the information about the new build, if any, and close the window
\r
2366 info = Main.EndCheckForUpdates(result);
\r
2368 if (info.NewVersionAvailable && info.BuildInformation != null)
\r
2370 frmUpdater updateWindow = new frmUpdater(info.BuildInformation);
\r
2371 updateWindow.ShowDialog();
\r
2374 MessageBox.Show("There are no new updates at this time.", "Update Check", MessageBoxButtons.OK,
\r
2375 MessageBoxIcon.Information);
\r
2376 lbl_updateCheck.Visible = false;
\r
2379 catch (Exception ex)
\r
2381 if ((bool)result.AsyncState)
\r
2383 "Unable to check for updates, Please try again later.\n\nDetailed Error Information:\n" + ex,
\r
2384 "Error", MessageBoxButtons.OK, MessageBoxIcon.Error);
\r
2393 /// Handle GUI shortcuts
\r
2395 /// <param name="msg">Message</param>
\r
2396 /// <param name="keyData">Keys</param>
\r
2397 /// <returns>Bool</returns>
\r
2398 protected override bool ProcessCmdKey(ref Message msg, Keys keyData)
\r
2400 if (keyData == (Keys.Control | Keys.S))
\r
2402 btn_start_Click(this, new EventArgs());
\r
2406 if (keyData == (Keys.Control | Keys.A))
\r
2408 btn_add2Queue_Click(this, new EventArgs());
\r
2411 return base.ProcessCmdKey(ref msg, keyData);
\r
2415 /// If the queue is being processed, prompt the user to confirm application close.
\r
2417 /// <param name="e">FormClosingEventArgs</param>
\r
2418 protected override void OnFormClosing(FormClosingEventArgs e)
\r
2422 // If currently encoding, the queue isn't paused, and there are queue items to process, prompt to confirm close.
\r
2423 if (encodeQueue.IsEncoding)
\r
2425 DialogResult result =
\r
2427 "HandBrake is currently encoding. Closing HandBrake will stop the current encode and will result in an unplayable file.\n\nDo you want to close HandBrake?",
\r
2428 "Close HandBrake?",
\r
2429 MessageBoxButtons.YesNo,
\r
2430 MessageBoxIcon.Question);
\r
2432 if (result == DialogResult.No)
\r
2438 encodeQueue.Stop();
\r
2441 if (SourceScan.IsScanning)
\r
2443 SourceScan.ScanCompleted -= new EventHandler(SourceScan_ScanCompleted);
\r
2444 SourceScan.Stop();
\r
2447 catch (Exception exc)
\r
2449 Main.ShowExceptiowWindow("HandBrake was not able to shutdown properly. You may need to forcefully quit HandBrake CLI from TaskManager if it's still running.", exc.ToString());
\r
2453 base.OnFormClosing(e);
\r
2459 // This is the END of the road ****************************************
\r