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.Threading;
\r
16 using System.Windows.Forms;
\r
19 using HandBrake.Framework.Model;
\r
20 using HandBrake.Framework.Services;
\r
21 using HandBrake.Framework.Views;
\r
22 using HandBrake.ApplicationServices.Functions;
\r
23 using HandBrake.ApplicationServices.Model;
\r
24 using HandBrake.ApplicationServices.Parsing;
\r
25 using HandBrake.ApplicationServices.Services;
\r
26 using HandBrake.ApplicationServices.Services.Interfaces;
\r
28 using Handbrake.ToolWindows;
\r
34 using Main = Handbrake.Functions.Main;
\r
39 public partial class frmMain : Form
\r
41 // Objects which may be used by one or more other objects *************
\r
42 private IQueue encodeQueue = new Queue();
\r
43 private PresetsHandler presetHandler = new PresetsHandler();
\r
45 // Windows ************************************************************
\r
46 private frmQueue queueWindow;
\r
47 private frmPreview qtpreview;
\r
48 private frmActivityWindow activityWindow;
\r
50 // Globals: Mainly used for tracking. *********************************
\r
51 public Title selectedTitle;
\r
52 public string sourcePath;
\r
53 private SourceType selectedSourceType;
\r
54 private string dvdDrivePath;
\r
55 private string dvdDriveLabel;
\r
56 private Preset currentlySelectedPreset;
\r
57 private DVD currentSource;
\r
58 private IScan SourceScan = new ScanService();
\r
59 private List<DriveInformation> drives;
\r
61 // Delegates **********************************************************
\r
62 private delegate void UpdateWindowHandler();
\r
64 // Applicaiton Startup ************************************************
\r
69 /// Gets SourceName.
\r
71 public string SourceName
\r
75 if (this.selectedSourceType == SourceType.DvdDrive)
\r
77 return this.dvdDriveLabel;
\r
80 if (selectedTitle != null && !string.IsNullOrEmpty(selectedTitle.SourceName))
\r
82 return Path.GetFileName(selectedTitle.SourceName);
\r
85 if (Path.GetFileNameWithoutExtension(this.sourcePath) != "VIDEO_TS")
\r
86 return Path.GetFileNameWithoutExtension(this.sourcePath);
\r
88 return Path.GetFileNameWithoutExtension(Path.GetDirectoryName(this.sourcePath));
\r
94 #region Application Startup
\r
97 /// Initializes a new instance of the <see cref="frmMain"/> class.
\r
99 /// <param name="args">
\r
100 /// The arguments passed in on application startup.
\r
102 public frmMain(string[] args)
\r
104 InitializeComponent();
\r
106 // Update the users config file with the CLI version data.
\r
107 Main.SetCliVersionData();
\r
109 if (Settings.Default.hb_version.Contains("svn"))
\r
111 this.Text += " " + Settings.Default.hb_version;
\r
114 // Check for new versions, if update checking is enabled
\r
115 if (Settings.Default.updateStatus)
\r
117 if (DateTime.Now.Subtract(Settings.Default.lastUpdateCheckDate).TotalDays > Properties.Settings.Default.daysBetweenUpdateCheck)
\r
119 // Set when the last update was
\r
120 Settings.Default.lastUpdateCheckDate = DateTime.Now;
\r
121 Settings.Default.Save();
\r
122 string url = Settings.Default.hb_build.ToString().EndsWith("1")
\r
123 ? Settings.Default.appcast_unstable
\r
124 : Settings.Default.appcast;
\r
125 UpdateService.BeginCheckForUpdates(new AsyncCallback(UpdateCheckDone), false, url, Settings.Default.hb_build, Settings.Default.skipversion, Settings.Default.hb_version);
\r
129 // Clear the log files in the background
\r
130 if (Settings.Default.clearOldLogs)
\r
132 Thread clearLog = new Thread(Main.ClearOldLogs);
\r
136 // Setup the GUI components
\r
137 LoadPresetPanel(); // Load the Preset Panel
\r
138 treeView_presets.ExpandAll();
\r
139 lbl_encode.Text = string.Empty;
\r
140 drop_mode.SelectedIndex = 0;
\r
141 queueWindow = new frmQueue(encodeQueue, this); // Prepare the Queue
\r
142 if (!Settings.Default.QueryEditorTab)
\r
143 tabs_panel.TabPages.RemoveAt(7); // Remove the query editor tab if the user does not want it enabled.
\r
144 if (Settings.Default.tooltipEnable)
\r
145 ToolTip.Active = true;
\r
147 // Load the user's default settings or Normal Preset
\r
148 if (Settings.Default.defaultPreset != string.Empty && presetHandler.GetPreset(Properties.Settings.Default.defaultPreset) != null)
\r
150 string query = presetHandler.GetPreset(Settings.Default.defaultPreset).Query;
\r
153 x264Panel.Reset2Defaults();
\r
155 QueryParser presetQuery = QueryParser.Parse(query);
\r
156 PresetLoader.LoadPreset(this, presetQuery, Settings.Default.defaultPreset);
\r
158 x264Panel.StandardizeOptString();
\r
159 x264Panel.SetCurrentSettingsInPanel();
\r
163 loadNormalPreset();
\r
165 // Register with Growl (if not using Growl for the encoding completion action, this wont hurt anything)
\r
166 GrowlCommunicator.Register();
\r
168 // Event Handlers and Queue Recovery
\r
170 Main.RecoverQueue(encodeQueue);
\r
172 // If have a file passed in via command arguemtents, check it's a file and try scanning it.
\r
173 if (args.Length >= 1 && (File.Exists(args[0]) || Directory.Exists(args[0])))
\r
175 this.StartScan(args[0], 0);
\r
180 /// When the update check is done, process the results.
\r
182 /// <param name="result">IAsyncResult result</param>
\r
183 private void UpdateCheckDone(IAsyncResult result)
\r
185 if (InvokeRequired)
\r
187 Invoke(new MethodInvoker(() => UpdateCheckDone(result)));
\r
193 UpdateCheckInformation info = UpdateService.EndCheckForUpdates(result);
\r
195 if (info.NewVersionAvailable)
\r
197 UpdateInfo updateWindow = new UpdateInfo(info.BuildInformation, Settings.Default.hb_version, Settings.Default.hb_build.ToString());
\r
198 updateWindow.ShowDialog();
\r
201 catch (Exception ex)
\r
203 if ((bool)result.AsyncState)
\r
204 Main.ShowExceptiowWindow("Unable to check for updates, Please try again later.", ex.ToString());
\r
212 // Encoding Events for setting up the GUI
\r
213 private void events()
\r
215 // Handle Widget changes when preset is selected.
\r
216 RegisterPresetEventHandler();
\r
218 // Handle Window Resize
\r
219 if (Properties.Settings.Default.MainWindowMinimize)
\r
220 this.Resize += new EventHandler(frmMain_Resize);
\r
222 // Handle Encode Start / Finish / Pause
\r
223 encodeQueue.EncodeStarted += new EventHandler(encodeStarted);
\r
224 encodeQueue.EncodeEnded += new EventHandler(encodeEnded);
\r
226 // Handle a file being draged onto the GUI.
\r
227 this.DragEnter += new DragEventHandler(frmMain_DragEnter);
\r
228 this.DragDrop += new DragEventHandler(frmMain_DragDrop);
\r
231 // 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
232 private void RegisterPresetEventHandler()
\r
235 drop_format.SelectedIndexChanged += new EventHandler(changePresetLabel);
\r
236 check_largeFile.CheckedChanged += new EventHandler(changePresetLabel);
\r
237 check_iPodAtom.CheckedChanged += new EventHandler(changePresetLabel);
\r
238 check_optimiseMP4.CheckedChanged += new EventHandler(changePresetLabel);
\r
240 // Picture Settings
\r
241 PictureSettings.PictureSettingsChanged += new EventHandler(changePresetLabel);
\r
244 Filters.FilterSettingsChanged += new EventHandler(changePresetLabel);
\r
247 drp_videoEncoder.SelectedIndexChanged += new EventHandler(changePresetLabel);
\r
248 check_2PassEncode.CheckedChanged += new EventHandler(changePresetLabel);
\r
249 check_turbo.CheckedChanged += new EventHandler(changePresetLabel);
\r
250 text_filesize.TextChanged += new EventHandler(changePresetLabel);
\r
251 text_bitrate.TextChanged += new EventHandler(changePresetLabel);
\r
252 slider_videoQuality.ValueChanged += new EventHandler(changePresetLabel);
\r
255 AudioSettings.AudioListChanged += new EventHandler(changePresetLabel);
\r
258 x264Panel.rtf_x264Query.TextChanged += new EventHandler(changePresetLabel);
\r
261 private void UnRegisterPresetEventHandler()
\r
263 // Output Settings
\r
264 drop_format.SelectedIndexChanged -= new EventHandler(changePresetLabel);
\r
265 check_largeFile.CheckedChanged -= new EventHandler(changePresetLabel);
\r
266 check_iPodAtom.CheckedChanged -= new EventHandler(changePresetLabel);
\r
267 check_optimiseMP4.CheckedChanged -= new EventHandler(changePresetLabel);
\r
269 // Picture Settings
\r
270 PictureSettings.PictureSettingsChanged -= new EventHandler(changePresetLabel);
\r
273 Filters.FilterSettingsChanged -= new EventHandler(changePresetLabel);
\r
276 drp_videoEncoder.SelectedIndexChanged -= new EventHandler(changePresetLabel);
\r
277 check_2PassEncode.CheckedChanged -= new EventHandler(changePresetLabel);
\r
278 check_turbo.CheckedChanged -= new EventHandler(changePresetLabel);
\r
279 text_filesize.TextChanged -= new EventHandler(changePresetLabel);
\r
280 text_bitrate.TextChanged -= new EventHandler(changePresetLabel);
\r
281 slider_videoQuality.ValueChanged -= new EventHandler(changePresetLabel);
\r
284 AudioSettings.AudioListChanged -= new EventHandler(changePresetLabel);
\r
287 x264Panel.rtf_x264Query.TextChanged -= new EventHandler(changePresetLabel);
\r
290 private void changePresetLabel(object sender, EventArgs e)
\r
292 labelPreset.Text = "Output Settings (Preset: Custom)";
\r
293 this.currentlySelectedPreset = null;
\r
296 private static void frmMain_DragEnter(object sender, DragEventArgs e)
\r
298 if (e.Data.GetDataPresent(DataFormats.FileDrop, false))
\r
299 e.Effect = DragDropEffects.All;
\r
302 private void frmMain_DragDrop(object sender, DragEventArgs e)
\r
304 string[] fileList = e.Data.GetData(DataFormats.FileDrop) as string[];
\r
305 sourcePath = string.Empty;
\r
307 if (fileList != null)
\r
309 if (!string.IsNullOrEmpty(fileList[0]))
\r
311 this.selectedSourceType = SourceType.VideoFile;
\r
312 StartScan(fileList[0], 0);
\r
315 UpdateSourceLabel();
\r
318 UpdateSourceLabel();
\r
321 private void encodeStarted(object sender, EventArgs e)
\r
323 SetEncodeStarted();
\r
324 encodeQueue.EncodeStatusChanged += EncodeQueue_EncodeStatusChanged;
\r
327 private void encodeEnded(object sender, EventArgs e)
\r
329 encodeQueue.EncodeStatusChanged -= EncodeQueue_EncodeStatusChanged;
\r
330 SetEncodeFinished();
\r
334 // User Interface Menus / Tool Strips *********************************
\r
339 /// Kill The scan menu Item
\r
341 /// <param name="sender">
\r
344 /// <param name="e">
\r
347 private void mnu_killCLI_Click(object sender, EventArgs e)
\r
353 /// Exit the Application Menu Item
\r
355 /// <param name="sender">
\r
358 /// <param name="e">
\r
361 private void mnu_exit_Click(object sender, EventArgs e)
\r
363 Application.Exit();
\r
371 /// Menu - Start Button
\r
373 /// <param name="sender">
\r
376 /// <param name="e">
\r
379 private void mnu_encode_Click(object sender, EventArgs e)
\r
381 queueWindow.Show();
\r
385 /// Menu - Display the Log Window
\r
387 /// <param name="sender">
\r
390 /// <param name="e">
\r
393 private void mnu_encodeLog_Click(object sender, EventArgs e)
\r
395 this.btn_ActivityWindow_Click(this, null);
\r
399 /// Menu - Display the Options Window
\r
401 /// <param name="sender">
\r
404 /// <param name="e">
\r
407 private void mnu_options_Click(object sender, EventArgs e)
\r
409 Form options = new frmOptions(this);
\r
410 options.ShowDialog();
\r
415 #region Presets Menu
\r
418 /// Reset the Built in Presets
\r
420 /// <param name="sender">
\r
423 /// <param name="e">
\r
426 private void mnu_presetReset_Click(object sender, EventArgs e)
\r
428 presetHandler.UpdateBuiltInPresets();
\r
430 if (treeView_presets.Nodes.Count == 0)
\r
432 "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
433 "Error", MessageBoxButtons.OK, MessageBoxIcon.Error);
\r
435 MessageBox.Show("Presets have been updated!", "Alert", MessageBoxButtons.OK, MessageBoxIcon.Information);
\r
437 treeView_presets.ExpandAll();
\r
441 /// Delete the selected preset
\r
443 /// <param name="sender">
\r
446 /// <param name="e">
\r
449 private void mnu_delete_preset_Click(object sender, EventArgs e)
\r
451 presetHandler.RemoveBuiltInPresets();
\r
452 LoadPresetPanel(); // Reload the preset panel
\r
456 /// Select the Normal preset
\r
458 /// <param name="sender">
\r
461 /// <param name="e">
\r
464 private void mnu_SelectDefault_Click(object sender, EventArgs e)
\r
466 loadNormalPreset();
\r
470 /// Import a plist Preset
\r
472 /// <param name="sender">
\r
475 /// <param name="e">
\r
478 private void mnu_importMacPreset_Click(object sender, EventArgs e)
\r
484 /// Export a Plist Preset
\r
486 /// <param name="sender">
\r
489 /// <param name="e">
\r
492 private void mnu_exportMacPreset_Click(object sender, EventArgs e)
\r
498 /// Create a new Preset
\r
500 /// <param name="sender">
\r
503 /// <param name="e">
\r
506 private void btn_new_preset_Click(object sender, EventArgs e)
\r
508 Form preset = new frmAddPreset(this, presetHandler);
\r
509 if (preset.ShowDialog() == DialogResult.OK)
\r
511 TreeNode presetTreeview = new TreeNode(presetHandler.LastPresetAdded.Name) { ForeColor = Color.Black };
\r
512 treeView_presets.Nodes.Add(presetTreeview);
\r
513 presetHandler.LastPresetAdded = null;
\r
522 /// Menu - Display the User Guide Web Page
\r
524 /// <param name="sender">
\r
527 /// <param name="e">
\r
530 private void mnu_user_guide_Click(object sender, EventArgs e)
\r
532 Process.Start("http://trac.handbrake.fr/wiki/HandBrakeGuide");
\r
536 /// Menu - Check for Updates
\r
538 /// <param name="sender">
\r
541 /// <param name="e">
\r
544 private void mnu_UpdateCheck_Click(object sender, EventArgs e)
\r
546 lbl_updateCheck.Visible = true;
\r
547 Settings.Default.lastUpdateCheckDate = DateTime.Now;
\r
548 Settings.Default.Save();
\r
549 string url = Settings.Default.hb_build.ToString().EndsWith("1")
\r
550 ? Settings.Default.appcast_unstable
\r
551 : Settings.Default.appcast;
\r
552 UpdateService.BeginCheckForUpdates(new AsyncCallback(UpdateCheckDoneMenu), false, url, Settings.Default.hb_build, Settings.Default.skipversion, Settings.Default.hb_version);
\r
556 /// Menu - Display the About Window
\r
558 /// <param name="sender">
\r
561 /// <param name="e">
\r
564 private void mnu_about_Click(object sender, EventArgs e)
\r
566 using (frmAbout About = new frmAbout())
\r
568 About.ShowDialog();
\r
577 /// RMenu - Expand All
\r
579 /// <param name="sender">
\r
582 /// <param name="e">
\r
585 private void pmnu_expandAll_Click(object sender, EventArgs e)
\r
587 treeView_presets.ExpandAll();
\r
591 /// RMenu - Collaspe All
\r
593 /// <param name="sender">
\r
596 /// <param name="e">
\r
599 private void pmnu_collapse_Click(object sender, EventArgs e)
\r
601 treeView_presets.CollapseAll();
\r
605 /// Menu - Import Preset
\r
607 /// <param name="sender">
\r
610 /// <param name="e">
\r
613 private void pmnu_import_Click(object sender, EventArgs e)
\r
619 /// RMenu - Save Changes to Preset
\r
621 /// <param name="sender">
\r
624 /// <param name="e">
\r
627 private void pmnu_saveChanges_Click(object sender, EventArgs e)
\r
629 // TODO this requires a re-think since the Query Editor has changed.
\r
630 DialogResult result =
\r
632 "Do you wish to include picture settings when updating the preset: " +
\r
633 treeView_presets.SelectedNode.Text, "Update Preset", MessageBoxButtons.YesNoCancel,
\r
634 MessageBoxIcon.Question);
\r
635 if (result == DialogResult.Yes)
\r
636 presetHandler.Update(treeView_presets.SelectedNode.Text,
\r
637 QueryGenerator.GenerateQueryForPreset(this, QueryPictureSettingsMode.SourceMaximum, true, 0, 0), true);
\r
638 else if (result == DialogResult.No)
\r
639 presetHandler.Update(treeView_presets.SelectedNode.Text,
\r
640 QueryGenerator.GenerateQueryForPreset(this, QueryPictureSettingsMode.SourceMaximum, true, 0, 0), false);
\r
644 /// RMenu - Delete Preset
\r
646 /// <param name="sender">
\r
649 /// <param name="e">
\r
652 private void pmnu_delete_click(object sender, EventArgs e)
\r
654 if (treeView_presets.SelectedNode != null)
\r
656 presetHandler.Remove(treeView_presets.SelectedNode.Text);
\r
657 treeView_presets.Nodes.Remove(treeView_presets.SelectedNode);
\r
659 treeView_presets.Select();
\r
663 /// Preset Menu Is Opening. Setup the Menu
\r
665 /// <param name="sender">
\r
668 /// <param name="e">
\r
671 private void presets_menu_Opening(object sender, CancelEventArgs e)
\r
673 // Make sure that the save menu is always disabled by default
\r
674 pmnu_saveChanges.Enabled = false;
\r
676 // Now enable the save menu if the selected preset is a user preset
\r
677 if (treeView_presets.SelectedNode != null)
\r
678 if (presetHandler.CheckIfUserPresetExists(treeView_presets.SelectedNode.Text))
\r
679 pmnu_saveChanges.Enabled = true;
\r
681 treeView_presets.Select();
\r
684 // Presets Management
\r
687 /// Button - Add a preset
\r
689 /// <param name="sender">
\r
692 /// <param name="e">
\r
695 private void btn_addPreset_Click(object sender, EventArgs e)
\r
697 Form preset = new frmAddPreset(this, presetHandler);
\r
698 if (preset.ShowDialog() == DialogResult.OK)
\r
700 TreeNode presetTreeview = new TreeNode(presetHandler.LastPresetAdded.Name) { ForeColor = Color.Black };
\r
701 treeView_presets.Nodes.Add(presetTreeview);
\r
702 presetHandler.LastPresetAdded = null;
\r
707 /// Button - remove a Preset
\r
709 /// <param name="sender">
\r
712 /// <param name="e">
\r
715 private void btn_removePreset_Click(object sender, EventArgs e)
\r
717 DialogResult result = MessageBox.Show("Are you sure you wish to delete the selected preset?", "Preset",
\r
718 MessageBoxButtons.YesNo, MessageBoxIcon.Question);
\r
719 if (result == DialogResult.Yes)
\r
721 if (treeView_presets.SelectedNode != null)
\r
723 presetHandler.Remove(treeView_presets.SelectedNode.Text);
\r
724 treeView_presets.Nodes.Remove(treeView_presets.SelectedNode);
\r
727 treeView_presets.Select();
\r
731 /// Button - Set the selected preset as the default
\r
733 /// <param name="sender">
\r
736 /// <param name="e">
\r
739 private void btn_setDefault_Click(object sender, EventArgs e)
\r
741 if (treeView_presets.SelectedNode != null)
\r
743 DialogResult result = MessageBox.Show("Are you sure you wish to set this preset as the default?",
\r
744 "Preset", MessageBoxButtons.YesNo, MessageBoxIcon.Question);
\r
745 if (result == DialogResult.Yes)
\r
747 Properties.Settings.Default.defaultPreset = treeView_presets.SelectedNode.Text;
\r
748 Properties.Settings.Default.Save();
\r
749 MessageBox.Show("New default preset set.", "Alert", MessageBoxButtons.OK, MessageBoxIcon.Information);
\r
753 MessageBox.Show("Please select a preset first.", "Warning", MessageBoxButtons.OK, MessageBoxIcon.Warning);
\r
757 /// PresetBar Mouse Down event
\r
759 /// <param name="sender">
\r
762 /// <param name="e">
\r
765 private void treeview_presets_mouseUp(object sender, MouseEventArgs e)
\r
767 if (e.Button == MouseButtons.Right)
\r
768 treeView_presets.SelectedNode = treeView_presets.GetNodeAt(e.Location);
\r
769 else if (e.Button == MouseButtons.Left)
\r
771 if (treeView_presets.GetNodeAt(e.Location) != null)
\r
773 if (labelPreset.Text.Contains(treeView_presets.GetNodeAt(e.Location).Text))
\r
778 treeView_presets.Select();
\r
782 /// Preset Bar after selecting the preset
\r
784 /// <param name="sender">
\r
787 /// <param name="e">
\r
790 private void treeView_presets_AfterSelect(object sender, TreeViewEventArgs e)
\r
796 /// When the mouse moves, display a preset
\r
798 /// <param name="sender">The Sender</param>
\r
799 /// <param name="e">the MouseEventArgs</param>
\r
800 private void TreeViewPresetsMouseMove(object sender, MouseEventArgs e)
\r
802 TreeNode theNode = this.treeView_presets.GetNodeAt(e.X, e.Y);
\r
804 if ((theNode != null))
\r
806 // Change the ToolTip only if the pointer moved to a new node.
\r
807 if (theNode.ToolTipText != this.ToolTip.GetToolTip(this.treeView_presets))
\r
809 this.ToolTip.SetToolTip(this.treeView_presets, theNode.ToolTipText);
\r
812 else // Pointer is not over a node so clear the ToolTip.
\r
814 this.ToolTip.SetToolTip(this.treeView_presets, string.Empty);
\r
819 /// Preset Bar - Handle the Delete Key
\r
821 /// <param name="sender">
\r
824 /// <param name="e">
\r
827 private void treeView_presets_deleteKey(object sender, KeyEventArgs e)
\r
829 if (e.KeyCode == Keys.Delete)
\r
831 DialogResult result = MessageBox.Show("Are you sure you wish to delete the selected preset?", "Preset",
\r
832 MessageBoxButtons.YesNo, MessageBoxIcon.Question);
\r
833 if (result == DialogResult.Yes)
\r
835 if (treeView_presets.SelectedNode != null)
\r
836 presetHandler.Remove(treeView_presets.SelectedNode.Text);
\r
838 // Remember each nodes expanded status so we can reload it
\r
839 List<bool> nodeStatus = new List<bool>();
\r
840 foreach (TreeNode node in treeView_presets.Nodes)
\r
841 nodeStatus.Add(node.IsExpanded);
\r
843 // Now reload the preset panel
\r
846 // And finally, re-expand any of the nodes if required
\r
848 foreach (TreeNode node in treeView_presets.Nodes)
\r
860 /// Select the selected preset and setup the GUI
\r
862 private void selectPreset()
\r
864 if (treeView_presets.SelectedNode != null)
\r
866 // Ok, so, we've selected a preset. Now we want to load it.
\r
867 string presetName = treeView_presets.SelectedNode.Text;
\r
868 Preset preset = presetHandler.GetPreset(presetName);
\r
869 if (preset != null)
\r
871 string query = presetHandler.GetPreset(presetName).Query;
\r
875 // Ok, Reset all the H264 widgets before changing the preset
\r
876 x264Panel.Reset2Defaults();
\r
878 // Send the query from the file to the Query Parser class
\r
879 QueryParser presetQuery = QueryParser.Parse(query);
\r
881 // Now load the preset
\r
882 PresetLoader.LoadPreset(this, presetQuery, presetName);
\r
884 // The x264 widgets will need updated, so do this now:
\r
885 x264Panel.StandardizeOptString();
\r
886 x264Panel.SetCurrentSettingsInPanel();
\r
888 // Finally, let this window have a copy of the preset settings.
\r
889 this.currentlySelectedPreset = preset;
\r
890 PictureSettings.SetPresetCropWarningLabel(preset);
\r
897 /// Load the Normal Preset
\r
899 private void loadNormalPreset()
\r
901 foreach (TreeNode treenode in treeView_presets.Nodes)
\r
903 foreach (TreeNode node in treenode.Nodes)
\r
905 if (node.Text.Equals("Normal"))
\r
906 treeView_presets.SelectedNode = treeView_presets.Nodes[treenode.Index].Nodes[0];
\r
912 /// Import a plist preset
\r
914 private void ImportPreset()
\r
916 if (openPreset.ShowDialog() == DialogResult.OK)
\r
918 QueryParser parsed = PlistPresetHandler.Import(openPreset.FileName);
\r
919 if (presetHandler.CheckIfUserPresetExists(parsed.PresetName + " (Imported)"))
\r
921 DialogResult result =
\r
922 MessageBox.Show("This preset appears to already exist. Would you like to overwrite it?",
\r
923 "Overwrite preset?",
\r
924 MessageBoxButtons.YesNo, MessageBoxIcon.Warning);
\r
925 if (result == DialogResult.Yes)
\r
927 PresetLoader.LoadPreset(this, parsed, parsed.PresetName);
\r
928 presetHandler.Update(parsed.PresetName + " (Imported)",
\r
929 QueryGenerator.GenerateFullQuery(this),
\r
930 parsed.UsesPictureSettings);
\r
935 PresetLoader.LoadPreset(this, parsed, parsed.PresetName);
\r
936 if (presetHandler.Add(parsed.PresetName + " (Imported)",
\r
937 QueryGenerator.GenerateFullQuery(this),
\r
938 parsed.UsesPictureSettings, string.Empty))
\r
940 TreeNode preset_treeview = new TreeNode(parsed.PresetName + " (Imported)")
\r
942 ForeColor = Color.Black
\r
944 treeView_presets.Nodes.Add(preset_treeview);
\r
951 /// Export a plist Preset
\r
953 private void ExportPreset()
\r
955 SaveFileDialog savefiledialog = new SaveFileDialog { Filter = "plist|*.plist" };
\r
957 if (treeView_presets.SelectedNode != null)
\r
959 if (savefiledialog.ShowDialog() == DialogResult.OK)
\r
961 Preset preset = presetHandler.GetPreset(treeView_presets.SelectedNode.Text);
\r
962 PlistPresetHandler.Export(savefiledialog.FileName, preset);
\r
972 /// 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
974 /// <param name="sender">
\r
977 /// <param name="e">
\r
980 private void btn_source_Click(object sender, EventArgs e)
\r
982 // Remove old Drive Menu Items.
\r
983 List<ToolStripMenuItem> itemsToRemove = new List<ToolStripMenuItem>();
\r
984 foreach (var item in btn_source.DropDownItems)
\r
986 if (item.GetType() == typeof(ToolStripMenuItem))
\r
988 ToolStripMenuItem menuItem = (ToolStripMenuItem)item;
\r
989 if (menuItem.Name.StartsWith("Drive"))
\r
991 itemsToRemove.Add(menuItem);
\r
996 foreach (ToolStripMenuItem item in itemsToRemove)
\r
997 btn_source.DropDownItems.Remove(item);
\r
999 Thread driveInfoThread = new Thread(SetDriveSelectionMenuItem);
\r
1000 driveInfoThread.Start();
\r
1004 /// Toolbar - Start The Encode
\r
1006 /// <param name="sender">
\r
1009 /// <param name="e">
\r
1012 private void btn_start_Click(object sender, EventArgs e)
\r
1014 if (btn_start.Text == "Stop")
\r
1016 DialogResult result = !Properties.Settings.Default.showCliForInGuiEncodeStatus
\r
1017 ? MessageBox.Show(
\r
1018 "Are you sure you wish to cancel the encode?\n\nPlease note: Stopping this encode will render the file unplayable. ",
\r
1020 MessageBoxButtons.YesNo,
\r
1021 MessageBoxIcon.Question)
\r
1022 : MessageBox.Show(
\r
1023 "Are you sure you wish to cancel the encode?",
\r
1025 MessageBoxButtons.YesNo,
\r
1026 MessageBoxIcon.Question);
\r
1028 if (result == DialogResult.Yes)
\r
1030 // Pause The Queue
\r
1031 encodeQueue.Pause();
\r
1033 if (Settings.Default.showCliForInGuiEncodeStatus)
\r
1034 encodeQueue.SafelyClose();
\r
1036 encodeQueue.Stop();
\r
1041 // 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
1042 string jobSourcePath = !string.IsNullOrEmpty(rtf_query.Text) ? Main.GetSourceFromQuery(rtf_query.Text) : sourcePath;
\r
1043 string jobDestination = !string.IsNullOrEmpty(rtf_query.Text) ? Main.GetDestinationFromQuery(rtf_query.Text) : text_destination.Text;
\r
1045 if (encodeQueue.Count != 0 || (!string.IsNullOrEmpty(jobSourcePath) && !string.IsNullOrEmpty(jobDestination)))
\r
1047 string generatedQuery = QueryGenerator.GenerateFullQuery(this);
\r
1048 string specifiedQuery = rtf_query.Text != string.Empty
\r
1050 : QueryGenerator.GenerateFullQuery(this);
\r
1051 string query = string.Empty;
\r
1053 // Check to make sure the generated query matches the GUI settings
\r
1054 if (Properties.Settings.Default.PromptOnUnmatchingQueries && !string.IsNullOrEmpty(specifiedQuery) &&
\r
1055 generatedQuery != specifiedQuery)
\r
1057 DialogResult result = MessageBox.Show("The query under the \"Query Editor\" tab " +
\r
1058 "does not match the current GUI settings.\n\nBecause the manual query takes " +
\r
1059 "priority over the GUI, your recently updated settings will not be taken " +
\r
1060 "into account when encoding this job." +
\r
1061 Environment.NewLine + Environment.NewLine +
\r
1062 "Do you want to replace the manual query with the updated GUI-generated query?",
\r
1063 "Manual Query does not Match GUI",
\r
1064 MessageBoxButtons.YesNoCancel, MessageBoxIcon.Asterisk,
\r
1065 MessageBoxDefaultButton.Button3);
\r
1069 case DialogResult.Yes:
\r
1070 // Replace the manual query with the generated one
\r
1071 query = generatedQuery;
\r
1072 rtf_query.Text = generatedQuery;
\r
1074 case DialogResult.No:
\r
1075 // Use the manual query
\r
1076 query = specifiedQuery;
\r
1078 case DialogResult.Cancel:
\r
1079 // Don't start the encode
\r
1085 query = specifiedQuery;
\r
1088 DialogResult overwrite = DialogResult.Yes;
\r
1089 if (!string.IsNullOrEmpty(jobDestination) && File.Exists(jobDestination))
\r
1091 overwrite = MessageBox.Show(
\r
1092 "The destination file already exists. Are you sure you want to overwrite it?",
\r
1093 "Overwrite File?",
\r
1094 MessageBoxButtons.YesNo,
\r
1095 MessageBoxIcon.Question);
\r
1098 if (overwrite == DialogResult.Yes)
\r
1100 if (encodeQueue.Count == 0)
\r
1101 encodeQueue.Add(query, this.GetTitle(), jobSourcePath, jobDestination, (rtf_query.Text != string.Empty));
\r
1103 queueWindow.SetQueue();
\r
1104 if (encodeQueue.Count > 1)
\r
1105 queueWindow.Show(false);
\r
1107 SetEncodeStarted(); // Encode is running, so setup the GUI appropriately
\r
1108 encodeQueue.Start(); // Start The Queue Encoding Process
\r
1113 else if (string.IsNullOrEmpty(sourcePath) || string.IsNullOrEmpty(text_destination.Text))
\r
1114 MessageBox.Show("No source or destination selected.", "Warning", MessageBoxButtons.OK,
\r
1115 MessageBoxIcon.Warning);
\r
1120 /// Toolbar - Add the current job to the Queue
\r
1122 /// <param name="sender">
\r
1125 /// <param name="e">
\r
1128 private void btn_add2Queue_Click(object sender, EventArgs e)
\r
1130 // Add the item to the queue.
\r
1131 AddItemToQueue(true);
\r
1132 queueWindow.Show();
\r
1136 /// Add Multiple Items to the Queue at once.
\r
1138 /// <param name="sender">The Sender</param>
\r
1139 /// <param name="e">The EventArgs</param>
\r
1140 private void MnuAddMultiToQueueClick(object sender, EventArgs e)
\r
1142 if (!Settings.Default.autoNaming)
\r
1144 MessageBox.Show("Destination Auto Naming must be enabled in preferences for this feature to work.", "Error", MessageBoxButtons.OK, MessageBoxIcon.Error);
\r
1148 if (this.SourceScan.SouceData == null)
\r
1150 MessageBox.Show("You must first scan a source or collection of source to use this feature.", "Error", MessageBoxButtons.OK, MessageBoxIcon.Error);
\r
1154 BatchAdd batchAdd = new BatchAdd();
\r
1155 if (batchAdd.ShowDialog() == DialogResult.OK)
\r
1157 int min = batchAdd.Min;
\r
1158 int max = batchAdd.Max;
\r
1159 bool errors = false;
\r
1161 foreach (Title title in this.SourceScan.SouceData.Titles)
\r
1163 if (title.Duration.TotalMinutes > min && title.Duration.TotalMinutes < max)
\r
1166 this.drp_dvdtitle.SelectedItem = title;
\r
1168 if (!this.AddItemToQueue(false))
\r
1178 "One or more items could not be added to the queue. You should check your queue and manually add any missing jobs.",
\r
1180 MessageBoxButtons.OK,
\r
1181 MessageBoxIcon.Warning);
\r
1186 private bool AddItemToQueue(bool showError)
\r
1188 string query = QueryGenerator.GenerateFullQuery(this);
\r
1189 if (!string.IsNullOrEmpty(rtf_query.Text))
\r
1190 query = rtf_query.Text;
\r
1192 // 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
1193 string jobSourcePath = !string.IsNullOrEmpty(rtf_query.Text) ? Main.GetSourceFromQuery(rtf_query.Text) : sourcePath;
\r
1194 string jobDestination = !string.IsNullOrEmpty(rtf_query.Text) ? Main.GetDestinationFromQuery(rtf_query.Text) : text_destination.Text;
\r
1196 // Make sure we have a Source and Destination.
\r
1197 if (string.IsNullOrEmpty(jobSourcePath) || string.IsNullOrEmpty(jobDestination))
\r
1200 MessageBox.Show("No source or destination selected.", "Warning", MessageBoxButtons.OK, MessageBoxIcon.Warning);
\r
1204 // Make sure the destination path exists.
\r
1205 if (!Directory.Exists(Path.GetDirectoryName(jobDestination)))
\r
1208 MessageBox.Show(string.Format("Destination Path does not exist.\nPath: {0}\n\nThis item was not added to the Queue.", Path.GetDirectoryName(jobDestination)), "Warning", MessageBoxButtons.OK, MessageBoxIcon.Warning);
\r
1212 // Make sure we don't have a duplciate on the queue.
\r
1213 if (encodeQueue.CheckForDestinationDuplicate(jobDestination))
\r
1217 DialogResult result;
\r
1221 "There is already a queue item for this destination path.\nDestination Path: {0} \n\nIf you continue, the encode will be overwritten. Do you wish to continue?",
\r
1224 MessageBoxButtons.YesNo,
\r
1225 MessageBoxIcon.Warning);
\r
1227 if (result != DialogResult.Yes) return false;
\r
1236 encodeQueue.Add(query, this.GetTitle(), jobSourcePath, jobDestination, (rtf_query.Text != string.Empty));
\r
1238 lbl_encode.Text = encodeQueue.Count + " encode(s) pending in the queue";
\r
1244 /// Toolbar - Show the Queue
\r
1246 /// <param name="sender">
\r
1249 /// <param name="e">
\r
1252 private void btn_showQueue_Click(object sender, EventArgs e)
\r
1254 queueWindow.Show();
\r
1255 queueWindow.Activate();
\r
1259 /// Toolbar - Show the Preview Window
\r
1261 /// <param name="sender">
\r
1264 /// <param name="e">
\r
1267 private void tb_preview_Click(object sender, EventArgs e)
\r
1269 if (string.IsNullOrEmpty(sourcePath) || string.IsNullOrEmpty(text_destination.Text))
\r
1270 MessageBox.Show("No source or destination selected.", "Warning", MessageBoxButtons.OK,
\r
1271 MessageBoxIcon.Warning);
\r
1274 if (qtpreview == null)
\r
1276 qtpreview = new frmPreview(this);
\r
1279 else if (qtpreview.IsDisposed)
\r
1281 qtpreview = new frmPreview(this);
\r
1285 MessageBox.Show(qtpreview, "The preview window is already open!", "Warning", MessageBoxButtons.OK,
\r
1286 MessageBoxIcon.Warning);
\r
1291 /// Toolbar - Show the Activity log Window
\r
1293 /// <param name="sender">
\r
1296 /// <param name="e">
\r
1299 private void btn_ActivityWindow_Click(object sender, EventArgs e)
\r
1301 if (this.activityWindow == null || !this.activityWindow.IsHandleCreated)
\r
1302 this.activityWindow = new frmActivityWindow(encodeQueue, SourceScan);
\r
1304 this.activityWindow.Show();
\r
1305 this.activityWindow.Activate();
\r
1310 #region System Tray Icon
\r
1313 /// Handle Resizing of the main window when deaing with the Notify Icon
\r
1315 /// <param name="sender">
\r
1318 /// <param name="e">
\r
1321 private void frmMain_Resize(object sender, EventArgs e)
\r
1323 if (FormWindowState.Minimized == this.WindowState)
\r
1325 notifyIcon.Visible = true;
\r
1328 else if (FormWindowState.Normal == this.WindowState)
\r
1329 notifyIcon.Visible = false;
\r
1333 /// Double Click the Tray Icon
\r
1335 /// <param name="sender">
\r
1338 /// <param name="e">
\r
1341 private void notifyIcon_MouseDoubleClick(object sender, MouseEventArgs e)
\r
1343 this.Visible = true;
\r
1345 this.WindowState = FormWindowState.Normal;
\r
1346 notifyIcon.Visible = false;
\r
1350 /// Tray Icon - Restore Menu Item - Resture the Window
\r
1352 /// <param name="sender">
\r
1355 /// <param name="e">
\r
1358 private void btn_restore_Click(object sender, EventArgs e)
\r
1360 this.Visible = true;
\r
1362 this.WindowState = FormWindowState.Normal;
\r
1363 notifyIcon.Visible = false;
\r
1368 #region Main Window and Tab Control
\r
1371 private void BtnFolderScanClicked(object sender, EventArgs e)
\r
1373 this.btn_source.HideDropDown();
\r
1374 if (DVD_Open.ShowDialog() == DialogResult.OK)
\r
1376 this.selectedSourceType = SourceType.Folder;
\r
1377 SelectSource(DVD_Open.SelectedPath, 0);
\r
1380 UpdateSourceLabel();
\r
1383 private void BtnFileScanClicked(object sender, EventArgs e)
\r
1385 this.btn_source.HideDropDown();
\r
1386 if (ISO_Open.ShowDialog() == DialogResult.OK)
\r
1388 this.selectedSourceType = SourceType.VideoFile;
\r
1389 SelectSource(ISO_Open.FileName, 0);
\r
1392 UpdateSourceLabel();
\r
1395 private void MnuDvdDriveClick(object sender, EventArgs e)
\r
1397 ToolStripMenuItem item = sender as ToolStripMenuItem;
\r
1400 string driveId = item.Name.Replace("Drive", string.Empty);
\r
1402 if (int.TryParse(driveId, out id))
\r
1404 this.dvdDrivePath = drives[id].RootDirectory;
\r
1405 this.dvdDriveLabel = drives[id].VolumeLabel;
\r
1407 if (this.dvdDrivePath == null) return;
\r
1408 this.selectedSourceType = SourceType.DvdDrive;
\r
1409 SelectSource(this.dvdDrivePath, 0);
\r
1414 private void VideoTitleSpecificScanClick(object sender, EventArgs e)
\r
1416 this.btn_source.HideDropDown();
\r
1417 if (ISO_Open.ShowDialog() == DialogResult.OK)
\r
1419 this.selectedSourceType = SourceType.VideoFile;
\r
1421 int sourceTitle = 0;
\r
1422 TitleSpecificScan title = new TitleSpecificScan();
\r
1423 if (title.ShowDialog() == DialogResult.OK)
\r
1425 sourceTitle = title.Title;
\r
1426 SelectSource(ISO_Open.FileName, sourceTitle);
\r
1430 UpdateSourceLabel();
\r
1433 private void FolderTitleSpecificScanClick(object sender, EventArgs e)
\r
1435 this.btn_source.HideDropDown();
\r
1436 if (DVD_Open.ShowDialog() == DialogResult.OK)
\r
1438 this.selectedSourceType = SourceType.Folder;
\r
1440 int sourceTitle = 0;
\r
1441 TitleSpecificScan title = new TitleSpecificScan();
\r
1442 if (title.ShowDialog() == DialogResult.OK)
\r
1444 sourceTitle = title.Title;
\r
1445 SelectSource(DVD_Open.SelectedPath, sourceTitle);
\r
1449 UpdateSourceLabel();
\r
1452 private void SelectSource(string file, int titleSpecific)
\r
1454 Check_ChapterMarkers.Enabled = true;
\r
1455 sourcePath = string.Empty;
\r
1457 if (file == string.Empty) // Must have a file or path
\r
1459 UpdateSourceLabel();
\r
1463 sourcePath = Path.GetFileName(file);
\r
1464 StartScan(file, titleSpecific);
\r
1467 private void drp_dvdtitle_Click(object sender, EventArgs e)
\r
1469 if ((drp_dvdtitle.Items.Count == 1) && (drp_dvdtitle.Items[0].ToString() == "Automatic"))
\r
1471 "There are no titles to select. Please load a source file by clicking the 'Source' button above before trying to select a title.",
\r
1472 "Alert", MessageBoxButtons.OK, MessageBoxIcon.Asterisk);
\r
1475 private void drp_dvdtitle_SelectedIndexChanged(object sender, EventArgs e)
\r
1477 UnRegisterPresetEventHandler();
\r
1478 drop_mode.SelectedIndex = 0;
\r
1480 drop_chapterStart.Items.Clear();
\r
1481 drop_chapterFinish.Items.Clear();
\r
1483 // If the dropdown is set to automatic nothing else needs to be done.
\r
1484 // Otheriwse if its not, title data has to be loaded from parsing.
\r
1485 if (drp_dvdtitle.Text != "Automatic")
\r
1487 selectedTitle = drp_dvdtitle.SelectedItem as Title;
\r
1488 lbl_duration.Text = selectedTitle.Duration.ToString();
\r
1489 PictureSettings.CurrentlySelectedPreset = this.currentlySelectedPreset;
\r
1490 PictureSettings.Source = selectedTitle; // Setup Picture Settings Tab Control
\r
1492 // Populate the Angles dropdown
\r
1493 drop_angle.Items.Clear();
\r
1494 if (!Properties.Settings.Default.noDvdNav)
\r
1496 drop_angle.Visible = true;
\r
1497 lbl_angle.Visible = true;
\r
1499 for (int i = 1; i <= selectedTitle.AngleCount; i++)
\r
1500 drop_angle.Items.Add(i.ToString());
\r
1502 if (drop_angle.Items.Count == 0)
\r
1504 drop_angle.Visible = false;
\r
1505 lbl_angle.Visible = false;
\r
1508 if (drop_angle.Items.Count != 0)
\r
1509 drop_angle.SelectedIndex = 0;
\r
1513 drop_angle.Visible = false;
\r
1514 lbl_angle.Visible = false;
\r
1517 // Populate the Start chapter Dropdown
\r
1518 drop_chapterStart.Items.Clear();
\r
1519 drop_chapterStart.Items.AddRange(selectedTitle.Chapters.ToArray());
\r
1520 if (drop_chapterStart.Items.Count > 0)
\r
1521 drop_chapterStart.Text = drop_chapterStart.Items[0].ToString();
\r
1523 // Populate the Final Chapter Dropdown
\r
1524 drop_chapterFinish.Items.Clear();
\r
1525 drop_chapterFinish.Items.AddRange(selectedTitle.Chapters.ToArray());
\r
1526 if (drop_chapterFinish.Items.Count > 0)
\r
1527 drop_chapterFinish.Text = drop_chapterFinish.Items[drop_chapterFinish.Items.Count - 1].ToString();
\r
1529 // Populate the Audio Channels Dropdown
\r
1530 AudioSettings.SetTrackListFromPreset(selectedTitle, this.currentlySelectedPreset);
\r
1532 // Populate the Subtitles dropdown
\r
1533 Subtitles.SetSubtitleTrackAuto(selectedTitle.Subtitles.ToArray());
\r
1535 // Update the source label if we have multiple streams
\r
1536 if (selectedTitle != null)
\r
1537 if (!string.IsNullOrEmpty(selectedTitle.SourceName))
\r
1538 labelSource.Text = Path.GetFileName(selectedTitle.SourceName);
\r
1540 // Run the AutoName & ChapterNaming functions
\r
1541 if (Properties.Settings.Default.autoNaming)
\r
1543 string autoPath = Main.AutoName(this);
\r
1544 if (autoPath != null)
\r
1545 text_destination.Text = autoPath;
\r
1548 "You currently have \"Automatically name output files\" enabled for the destination file box, but you do not have a valid default directory set.\n\nYou should set a \"Default Path\" in HandBrakes preferences. (See 'Tools' menu -> 'Options' -> 'General' Tab -> 'Default Path')",
\r
1549 "Warning", MessageBoxButtons.OK, MessageBoxIcon.Warning);
\r
1552 data_chpt.Rows.Clear();
\r
1553 if (selectedTitle.Chapters.Count != 1)
\r
1555 DataGridView chapterGridView = Main.ChapterNaming(selectedTitle, data_chpt, drop_chapterFinish.Text);
\r
1556 if (chapterGridView != null)
\r
1557 data_chpt = chapterGridView;
\r
1561 Check_ChapterMarkers.Checked = false;
\r
1562 Check_ChapterMarkers.Enabled = false;
\r
1565 // Hack to force the redraw of the scrollbars which don't resize properly when the control is disabled.
\r
1566 data_chpt.Columns[0].Width = 166;
\r
1567 data_chpt.Columns[0].Width = 165;
\r
1569 RegisterPresetEventHandler();
\r
1572 private void chapersChanged(object sender, EventArgs e)
\r
1574 if (drop_mode.SelectedIndex != 0) // Function is not used if we are not in chapters mode.
\r
1577 Control ctl = (Control)sender;
\r
1578 int chapterStart, chapterEnd;
\r
1579 int.TryParse(drop_chapterStart.Text, out chapterStart);
\r
1580 int.TryParse(drop_chapterFinish.Text, out chapterEnd);
\r
1584 case "drop_chapterStart":
\r
1585 if (drop_chapterFinish.SelectedIndex == -1 && drop_chapterFinish.Items.Count != 0)
\r
1586 drop_chapterFinish.SelectedIndex = drop_chapterFinish.Items.Count - 1;
\r
1588 if (chapterEnd != 0)
\r
1589 if (chapterStart > chapterEnd)
\r
1590 drop_chapterFinish.Text = chapterStart.ToString();
\r
1592 case "drop_chapterFinish":
\r
1593 if (drop_chapterStart.Items.Count >= 1 && drop_chapterStart.SelectedIndex == -1)
\r
1594 drop_chapterStart.SelectedIndex = 0;
\r
1596 if (chapterStart != 0)
\r
1597 if (chapterEnd < chapterStart)
\r
1598 drop_chapterFinish.Text = chapterStart.ToString();
\r
1600 // Add more rows to the Chapter menu if needed.
\r
1601 if (Check_ChapterMarkers.Checked)
\r
1603 int i = data_chpt.Rows.Count, finish = 0;
\r
1604 int.TryParse(drop_chapterFinish.Text, out finish);
\r
1606 while (i < finish)
\r
1608 int n = data_chpt.Rows.Add();
\r
1609 data_chpt.Rows[n].Cells[0].Value = (i + 1);
\r
1610 data_chpt.Rows[n].Cells[1].Value = "Chapter " + (i + 1);
\r
1611 data_chpt.Rows[n].Cells[0].ValueType = typeof(int);
\r
1612 data_chpt.Rows[n].Cells[1].ValueType = typeof(string);
\r
1619 // Update the Duration
\r
1620 lbl_duration.Text =
\r
1621 Main.CalculateDuration(drop_chapterStart.SelectedIndex, drop_chapterFinish.SelectedIndex, selectedTitle)
\r
1624 // Run the Autonaming function
\r
1625 if (Properties.Settings.Default.autoNaming)
\r
1626 text_destination.Text = Main.AutoName(this);
\r
1628 // Disable chapter markers if only 1 chapter is selected.
\r
1629 if (chapterStart == chapterEnd)
\r
1631 Check_ChapterMarkers.Enabled = false;
\r
1632 btn_importChapters.Enabled = false;
\r
1633 data_chpt.Enabled = false;
\r
1637 Check_ChapterMarkers.Enabled = true;
\r
1638 if (Check_ChapterMarkers.Checked)
\r
1640 btn_importChapters.Enabled = true;
\r
1641 data_chpt.Enabled = true;
\r
1646 private void SecondsOrFramesChanged(object sender, EventArgs e)
\r
1649 int.TryParse(drop_chapterStart.Text, out start);
\r
1650 int.TryParse(drop_chapterFinish.Text, out end);
\r
1651 double duration = end - start;
\r
1653 switch (drop_mode.SelectedIndex)
\r
1656 lbl_duration.Text = TimeSpan.FromSeconds(duration).ToString();
\r
1659 if (selectedTitle != null)
\r
1661 duration = duration / selectedTitle.Fps;
\r
1662 lbl_duration.Text = TimeSpan.FromSeconds(duration).ToString();
\r
1665 lbl_duration.Text = "--:--:--";
\r
1671 private void drop_mode_SelectedIndexChanged(object sender, EventArgs e)
\r
1674 this.drop_chapterFinish.TextChanged -= new EventHandler(this.SecondsOrFramesChanged);
\r
1675 this.drop_chapterStart.TextChanged -= new EventHandler(this.SecondsOrFramesChanged);
\r
1678 switch (drop_mode.SelectedIndex)
\r
1681 drop_chapterStart.DropDownStyle = ComboBoxStyle.DropDownList;
\r
1682 drop_chapterFinish.DropDownStyle = ComboBoxStyle.DropDownList;
\r
1683 if (drop_chapterStart.Items.Count != 0)
\r
1685 drop_chapterStart.SelectedIndex = 0;
\r
1686 drop_chapterFinish.SelectedIndex = drop_chapterFinish.Items.Count - 1;
\r
1689 lbl_duration.Text = "--:--:--";
\r
1692 this.drop_chapterStart.TextChanged += new EventHandler(this.SecondsOrFramesChanged);
\r
1693 this.drop_chapterFinish.TextChanged += new EventHandler(this.SecondsOrFramesChanged);
\r
1694 drop_chapterStart.DropDownStyle = ComboBoxStyle.Simple;
\r
1695 drop_chapterFinish.DropDownStyle = ComboBoxStyle.Simple;
\r
1696 if (selectedTitle != null)
\r
1698 drop_chapterStart.Text = "0";
\r
1699 drop_chapterFinish.Text = selectedTitle.Duration.TotalSeconds.ToString();
\r
1703 this.drop_chapterStart.TextChanged += new EventHandler(this.SecondsOrFramesChanged);
\r
1704 this.drop_chapterFinish.TextChanged += new EventHandler(this.SecondsOrFramesChanged);
\r
1705 drop_chapterStart.DropDownStyle = ComboBoxStyle.Simple;
\r
1706 drop_chapterFinish.DropDownStyle = ComboBoxStyle.Simple;
\r
1707 if (selectedTitle != null)
\r
1709 drop_chapterStart.Text = "0";
\r
1710 drop_chapterFinish.Text = (selectedTitle.Fps * selectedTitle.Duration.TotalSeconds).ToString();
\r
1717 private void btn_destBrowse_Click(object sender, EventArgs e)
\r
1719 // This removes the file extension from the filename box on the save file dialog.
\r
1720 // It's daft but some users don't realise that typing an extension overrides the dropdown extension selected.
\r
1721 DVD_Save.FileName = Path.GetFileNameWithoutExtension(text_destination.Text);
\r
1723 if (Path.IsPathRooted(text_destination.Text))
\r
1724 DVD_Save.InitialDirectory = Path.GetDirectoryName(text_destination.Text);
\r
1726 // Show the dialog and set the main form file path
\r
1727 if (drop_format.SelectedIndex.Equals(0))
\r
1728 DVD_Save.FilterIndex = 1;
\r
1729 else if (drop_format.SelectedIndex.Equals(1))
\r
1730 DVD_Save.FilterIndex = 2;
\r
1732 if (DVD_Save.ShowDialog() == DialogResult.OK)
\r
1734 // Add a file extension manually, as FileDialog.AddExtension has issues with dots in filenames
\r
1735 switch (DVD_Save.FilterIndex)
\r
1739 !Path.GetExtension(DVD_Save.FileName).Equals(".mp4",
\r
1740 StringComparison.InvariantCultureIgnoreCase))
\r
1741 if (Properties.Settings.Default.useM4v)
\r
1742 DVD_Save.FileName = DVD_Save.FileName.Replace(".mp4", ".m4v").Replace(".mkv", ".m4v");
\r
1744 DVD_Save.FileName = DVD_Save.FileName.Replace(".m4v", ".mp4").Replace(".mkv", ".mp4");
\r
1748 !Path.GetExtension(DVD_Save.FileName).Equals(".mkv", StringComparison.InvariantCultureIgnoreCase))
\r
1749 DVD_Save.FileName = DVD_Save.FileName.Replace(".mp4", ".mkv").Replace(".m4v", ".mkv");
\r
1755 text_destination.Text = DVD_Save.FileName;
\r
1757 // Quicktime requires .m4v file for chapter markers to work. If checked, change the extension to .m4v (mp4 and m4v are the same thing)
\r
1758 if (Check_ChapterMarkers.Checked && DVD_Save.FilterIndex != 2)
\r
1759 SetExtension(".m4v");
\r
1763 private void text_destination_TextChanged(object sender, EventArgs e)
\r
1765 string path = text_destination.Text;
\r
1766 if (path.EndsWith(".mp4") || path.EndsWith(".m4v"))
\r
1767 drop_format.SelectedIndex = 0;
\r
1768 else if (path.EndsWith(".mkv"))
\r
1769 drop_format.SelectedIndex = 1;
\r
1772 // Output Settings
\r
1773 private void drop_format_SelectedIndexChanged(object sender, EventArgs e)
\r
1775 switch (drop_format.SelectedIndex)
\r
1778 if (Properties.Settings.Default.useM4v || Check_ChapterMarkers.Checked ||
\r
1779 AudioSettings.RequiresM4V() || Subtitles.RequiresM4V())
\r
1780 SetExtension(".m4v");
\r
1782 SetExtension(".mp4");
\r
1785 SetExtension(".mkv");
\r
1789 AudioSettings.SetContainer(drop_format.Text);
\r
1791 if (drop_format.Text.Contains("MP4"))
\r
1793 if (drp_videoEncoder.Items.Contains("VP3 (Theora)"))
\r
1795 drp_videoEncoder.Items.Remove("VP3 (Theora)");
\r
1796 drp_videoEncoder.SelectedIndex = 1;
\r
1799 else if (drop_format.Text.Contains("MKV"))
\r
1800 drp_videoEncoder.Items.Add("VP3 (Theora)");
\r
1803 public void SetExtension(string newExtension)
\r
1805 if (newExtension == ".mp4" || newExtension == ".m4v")
\r
1806 if (Properties.Settings.Default.useM4v || Check_ChapterMarkers.Checked || AudioSettings.RequiresM4V() ||
\r
1807 Subtitles.RequiresM4V())
\r
1808 newExtension = ".m4v";
\r
1810 newExtension = ".mp4";
\r
1812 if (Path.HasExtension(newExtension))
\r
1813 text_destination.Text = Path.ChangeExtension(text_destination.Text, newExtension);
\r
1817 private void drp_videoEncoder_SelectedIndexChanged(object sender, EventArgs e)
\r
1819 setContainerOpts();
\r
1821 // Turn off some options which are H.264 only when the user selects a non h.264 encoder
\r
1822 if (drp_videoEncoder.Text.Contains("H.264"))
\r
1824 if (check_2PassEncode.CheckState == CheckState.Checked)
\r
1825 check_turbo.Enabled = true;
\r
1827 tab_advanced.Enabled = true;
\r
1828 if ((drop_format.Text.Contains("MP4")) || (drop_format.Text.Contains("M4V")))
\r
1829 check_iPodAtom.Enabled = true;
\r
1831 check_iPodAtom.Enabled = false;
\r
1835 check_turbo.CheckState = CheckState.Unchecked;
\r
1836 check_turbo.Enabled = false;
\r
1837 tab_advanced.Enabled = false;
\r
1838 x264Panel.X264Query = string.Empty;
\r
1839 check_iPodAtom.Enabled = false;
\r
1840 check_iPodAtom.Checked = false;
\r
1843 // Setup the CQ Slider
\r
1844 switch (drp_videoEncoder.Text)
\r
1846 case "MPEG-4 (FFmpeg)":
\r
1847 if (slider_videoQuality.Value > 31)
\r
1848 slider_videoQuality.Value = 20; // Just reset to 70% QP 10 on encode change.
\r
1849 slider_videoQuality.Minimum = 1;
\r
1850 slider_videoQuality.Maximum = 31;
\r
1852 case "H.264 (x264)":
\r
1853 slider_videoQuality.Minimum = 0;
\r
1854 slider_videoQuality.TickFrequency = 1;
\r
1856 CultureInfo culture = CultureInfo.CreateSpecificCulture("en-US");
\r
1857 double cqStep = Properties.Settings.Default.x264cqstep;
\r
1858 double multiplier = 1.0 / cqStep;
\r
1859 double value = slider_videoQuality.Value * multiplier;
\r
1861 slider_videoQuality.Maximum = (int)(51 / Properties.Settings.Default.x264cqstep);
\r
1863 if (value < slider_videoQuality.Maximum)
\r
1864 slider_videoQuality.Value = slider_videoQuality.Maximum - (int)value;
\r
1867 case "VP3 (Theora)":
\r
1868 if (slider_videoQuality.Value > 63)
\r
1869 slider_videoQuality.Value = 45; // Just reset to 70% QP 45 on encode change.
\r
1870 slider_videoQuality.Minimum = 0;
\r
1871 slider_videoQuality.Maximum = 63;
\r
1877 /// When the FrameRate is not Same As Source, show the Max/Constant Mode dropdown
\r
1879 /// <param name="sender">
\r
1882 /// <param name="e">
\r
1885 private void drp_videoFramerate_SelectedIndexChanged(object sender, EventArgs e)
\r
1887 if (this.drp_videoFramerate.SelectedIndex == 0)
\r
1889 this.checkMaximumFramerate.Visible = false;
\r
1890 this.checkMaximumFramerate.CheckState = CheckState.Unchecked;
\r
1894 this.checkMaximumFramerate.Visible = true;
\r
1899 /// Set the container format options
\r
1901 public void setContainerOpts()
\r
1903 if ((drop_format.Text.Contains("MP4")) || (drop_format.Text.Contains("M4V")))
\r
1905 check_largeFile.Enabled = true;
\r
1906 check_optimiseMP4.Enabled = true;
\r
1907 check_iPodAtom.Enabled = true;
\r
1911 check_largeFile.Enabled = false;
\r
1912 check_optimiseMP4.Enabled = false;
\r
1913 check_iPodAtom.Enabled = false;
\r
1914 check_largeFile.Checked = false;
\r
1915 check_optimiseMP4.Checked = false;
\r
1916 check_iPodAtom.Checked = false;
\r
1920 private double cachedCqStep = Properties.Settings.Default.x264cqstep;
\r
1923 /// Update the CQ slider for x264 for a new CQ step. This is set from option
\r
1925 public void setQualityFromSlider()
\r
1927 // Work out the current RF value.
\r
1928 double cqStep = this.cachedCqStep;
\r
1929 double rfValue = 51.0 - slider_videoQuality.Value * cqStep;
\r
1931 // Change the maximum value for the slider
\r
1932 slider_videoQuality.Maximum = (int)(51 / Properties.Settings.Default.x264cqstep);
\r
1934 // Reset the CQ slider to RF0
\r
1935 slider_videoQuality.Value = slider_videoQuality.Maximum;
\r
1937 // Reset the CQ slider back to the previous value as close as possible
\r
1938 double cqStepNew = Properties.Settings.Default.x264cqstep;
\r
1939 double rfValueCurrent = 51.0 - slider_videoQuality.Value * cqStepNew;
\r
1940 while (rfValueCurrent < rfValue)
\r
1942 slider_videoQuality.Value--;
\r
1943 rfValueCurrent = 51.0 - slider_videoQuality.Value * cqStepNew;
\r
1946 // Cache the CQ step for the next calculation
\r
1947 this.cachedCqStep = Properties.Settings.Default.x264cqstep;
\r
1950 private void slider_videoQuality_Scroll(object sender, EventArgs e)
\r
1952 double cqStep = Properties.Settings.Default.x264cqstep;
\r
1953 switch (drp_videoEncoder.Text)
\r
1955 case "MPEG-4 (FFmpeg)":
\r
1956 lbl_SliderValue.Text = "QP:" + (32 - slider_videoQuality.Value);
\r
1958 case "H.264 (x264)":
\r
1959 double rfValue = 51.0 - slider_videoQuality.Value * cqStep;
\r
1960 rfValue = Math.Round(rfValue, 2);
\r
1961 lbl_SliderValue.Text = "RF:" + rfValue.ToString(new CultureInfo("en-US"));
\r
1963 case "VP3 (Theora)":
\r
1964 lbl_SliderValue.Text = "QP:" + slider_videoQuality.Value;
\r
1969 private void radio_targetFilesize_CheckedChanged(object sender, EventArgs e)
\r
1971 text_bitrate.Enabled = false;
\r
1972 text_filesize.Enabled = true;
\r
1973 slider_videoQuality.Enabled = false;
\r
1975 check_2PassEncode.Enabled = true;
\r
1978 private void radio_avgBitrate_CheckedChanged(object sender, EventArgs e)
\r
1980 text_bitrate.Enabled = true;
\r
1981 text_filesize.Enabled = false;
\r
1982 slider_videoQuality.Enabled = false;
\r
1984 check_2PassEncode.Enabled = true;
\r
1987 private void radio_cq_CheckedChanged(object sender, EventArgs e)
\r
1989 text_bitrate.Enabled = false;
\r
1990 text_filesize.Enabled = false;
\r
1991 slider_videoQuality.Enabled = true;
\r
1993 check_2PassEncode.Enabled = false;
\r
1994 check_2PassEncode.CheckState = CheckState.Unchecked;
\r
1997 private void check_2PassEncode_CheckedChanged(object sender, EventArgs e)
\r
1999 if (check_2PassEncode.CheckState.ToString() == "Checked")
\r
2001 if (drp_videoEncoder.Text.Contains("H.264"))
\r
2002 check_turbo.Enabled = true;
\r
2006 check_turbo.Enabled = false;
\r
2007 check_turbo.CheckState = CheckState.Unchecked;
\r
2011 // Chapter Marker Tab
\r
2012 private void Check_ChapterMarkers_CheckedChanged(object sender, EventArgs e)
\r
2014 if (Check_ChapterMarkers.Checked)
\r
2016 if (drop_format.SelectedIndex != 1)
\r
2017 SetExtension(".m4v");
\r
2018 data_chpt.Enabled = true;
\r
2019 btn_importChapters.Enabled = true;
\r
2023 if (drop_format.SelectedIndex != 1 && !Properties.Settings.Default.useM4v)
\r
2024 SetExtension(".mp4");
\r
2025 data_chpt.Enabled = false;
\r
2026 btn_importChapters.Enabled = false;
\r
2030 private void btn_importChapters_Click(object sender, EventArgs e)
\r
2032 if (File_ChapterImport.ShowDialog() == DialogResult.OK)
\r
2034 string filename = File_ChapterImport.FileName;
\r
2035 DataGridView imported = Main.ImportChapterNames(data_chpt, filename);
\r
2036 if (imported != null)
\r
2037 data_chpt = imported;
\r
2041 private void btn_export_Click(object sender, EventArgs e)
\r
2043 SaveFileDialog saveFileDialog = new SaveFileDialog();
\r
2044 saveFileDialog.Filter = "Csv File|*.csv";
\r
2045 saveFileDialog.DefaultExt = "csv";
\r
2046 if (saveFileDialog.ShowDialog() == DialogResult.OK)
\r
2048 string filename = saveFileDialog.FileName;
\r
2050 Main.SaveChapterMarkersToCsv(this, filename);
\r
2054 private void mnu_resetChapters_Click(object sender, EventArgs e)
\r
2056 data_chpt.Rows.Clear();
\r
2057 DataGridView chapterGridView = Main.ChapterNaming(selectedTitle, data_chpt, drop_chapterFinish.Text);
\r
2058 if (chapterGridView != null)
\r
2060 data_chpt = chapterGridView;
\r
2064 // Query Editor Tab
\r
2065 private void btn_generate_Query_Click(object sender, EventArgs e)
\r
2067 rtf_query.Text = QueryGenerator.GenerateFullQuery(this);
\r
2070 private void btn_clear_Click(object sender, EventArgs e)
\r
2072 rtf_query.Clear();
\r
2077 // MainWindow Components, Actions and Functions ***********************
\r
2079 #region Source Scan
\r
2082 /// Start the Scan Process
\r
2084 /// <param name="filename">
\r
2087 /// <param name="title">
\r
2090 private void StartScan(string filename, int title)
\r
2092 // Setup the GUI components for the scan.
\r
2093 sourcePath = filename;
\r
2095 this.DisableGUI();
\r
2100 SourceScan.Scan(sourcePath, title);
\r
2101 SourceScan.ScanStatusChanged += new EventHandler(SourceScan_ScanStatusChanged);
\r
2102 SourceScan.ScanCompleted += new EventHandler(SourceScan_ScanCompleted);
\r
2104 catch (Exception exc)
\r
2106 MessageBox.Show("frmMain.cs - StartScan " + exc, "Error", MessageBoxButtons.OK, MessageBoxIcon.Error);
\r
2111 /// Update the Status label for the scan
\r
2113 /// <param name="sender">
\r
2116 /// <param name="e">
\r
2119 private void SourceScan_ScanStatusChanged(object sender, EventArgs e)
\r
2121 UpdateScanStatusLabel();
\r
2125 /// Update the UI after the scan has completed
\r
2127 /// <param name="sender">
\r
2130 /// <param name="e">
\r
2133 private void SourceScan_ScanCompleted(object sender, EventArgs e)
\r
2135 UpdateGuiAfterScan();
\r
2139 /// Update the Scan Status Label
\r
2141 private void UpdateScanStatusLabel()
\r
2143 if (InvokeRequired)
\r
2145 BeginInvoke(new UpdateWindowHandler(UpdateScanStatusLabel));
\r
2148 labelSource.Text = SourceScan.ScanStatus;
\r
2152 /// Reset the GUI when the scan has completed
\r
2154 private void UpdateGuiAfterScan()
\r
2156 if (InvokeRequired)
\r
2158 BeginInvoke(new UpdateWindowHandler(UpdateGuiAfterScan));
\r
2164 currentSource = SourceScan.SouceData;
\r
2166 // Setup some GUI components
\r
2167 drp_dvdtitle.Items.Clear();
\r
2168 if (currentSource.Titles.Count != 0)
\r
2169 drp_dvdtitle.Items.AddRange(currentSource.Titles.ToArray());
\r
2171 foreach (Title title in currentSource.Titles)
\r
2173 if (title.MainTitle)
\r
2175 drp_dvdtitle.SelectedItem = title;
\r
2179 if (drp_dvdtitle.SelectedItem == null && drp_dvdtitle.Items.Count > 0)
\r
2181 drp_dvdtitle.SelectedIndex = 0;
\r
2184 // Enable the creation of chapter markers if the file is an image of a dvd
\r
2185 if (drop_chapterStart.Items.Count > 0)
\r
2188 int.TryParse(drop_chapterStart.Items[0].ToString(), out start);
\r
2189 int.TryParse(drop_chapterFinish.Items[drop_chapterFinish.Items.Count - 1].ToString(), out end);
\r
2190 if (end > start) Check_ChapterMarkers.Enabled = true;
\r
2193 Check_ChapterMarkers.Enabled = false;
\r
2194 Check_ChapterMarkers.Checked = false;
\r
2195 data_chpt.Rows.Clear();
\r
2199 // If no titles were found, Display an error message
\r
2200 if (drp_dvdtitle.Items.Count == 0)
\r
2203 "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
2204 "Error", MessageBoxButtons.OK, MessageBoxIcon.Hand);
\r
2205 sourcePath = string.Empty;
\r
2207 UpdateSourceLabel();
\r
2209 // Enable the GUI components and enable any disabled components
\r
2212 catch (Exception exc)
\r
2214 MessageBox.Show("frmMain.cs - updateUIafterScan " + exc, "Error", MessageBoxButtons.OK,
\r
2215 MessageBoxIcon.Error);
\r
2221 /// Enable the GUI
\r
2223 private void EnableGUI()
\r
2227 if (InvokeRequired)
\r
2228 BeginInvoke(new UpdateWindowHandler(EnableGUI));
\r
2229 foreach (Control ctrl in Controls)
\r
2230 ctrl.Enabled = true;
\r
2231 btn_start.Enabled = true;
\r
2232 btn_showQueue.Enabled = true;
\r
2233 btn_add2Queue.Enabled = true;
\r
2234 tb_preview.Enabled = true;
\r
2235 btn_source.Enabled = true;
\r
2236 mnu_killCLI.Visible = false;
\r
2238 catch (Exception exc)
\r
2240 MessageBox.Show("frmMain.cs - EnableGUI() " + exc, "Error", MessageBoxButtons.OK, MessageBoxIcon.Error);
\r
2245 /// Disable the GUI
\r
2247 private void DisableGUI()
\r
2249 foreach (Control ctrl in Controls)
\r
2250 if (!(ctrl is StatusStrip || ctrl is MenuStrip || ctrl is ToolStrip))
\r
2251 ctrl.Enabled = false;
\r
2253 labelSource.Enabled = true;
\r
2254 labelStaticSource.Enabled = true;
\r
2255 SourceLayoutPanel.Enabled = true;
\r
2256 btn_source.Enabled = false;
\r
2257 btn_start.Enabled = false;
\r
2258 btn_showQueue.Enabled = false;
\r
2259 btn_add2Queue.Enabled = false;
\r
2260 tb_preview.Enabled = false;
\r
2261 mnu_killCLI.Visible = true;
\r
2267 private void KillScan()
\r
2269 SourceScan.ScanCompleted -= new EventHandler(SourceScan_ScanCompleted);
\r
2273 SourceScan.Stop();
\r
2275 labelSource.Text = "Scan Cancelled";
\r
2281 private void ResetGUI()
\r
2283 drp_dvdtitle.Items.Clear();
\r
2284 drop_chapterStart.Items.Clear();
\r
2285 drop_chapterFinish.Items.Clear();
\r
2286 lbl_duration.Text = "Select a Title";
\r
2287 PictureSettings.lbl_src_res.Text = "Select a Title";
\r
2288 sourcePath = String.Empty;
\r
2289 text_destination.Text = String.Empty;
\r
2290 selectedTitle = null;
\r
2294 /// Update the Source Label
\r
2296 private void UpdateSourceLabel()
\r
2298 labelSource.Text = string.IsNullOrEmpty(sourcePath) ? "Select \"Source\" to continue." : this.SourceName;
\r
2302 /// Take a job from the Queue, rescan it, and reload the GUI for that job.
\r
2304 /// <param name="job">
\r
2307 public void RecievingJob(Job job)
\r
2309 string query = job.Query;
\r
2310 StartScan(job.Source, job.Title);
\r
2312 if (query != null)
\r
2314 // Ok, Reset all the H264 widgets before changing the preset
\r
2315 x264Panel.Reset2Defaults();
\r
2317 // Send the query from the file to the Query Parser class
\r
2318 QueryParser presetQuery = QueryParser.Parse(query);
\r
2320 // Now load the preset
\r
2321 PresetLoader.LoadPreset(this, presetQuery, "Load Back From Queue");
\r
2323 // The x264 widgets will need updated, so do this now:
\r
2324 x264Panel.StandardizeOptString();
\r
2325 x264Panel.SetCurrentSettingsInPanel();
\r
2327 // Finally, let this window have a copy of the preset settings.
\r
2328 this.currentlySelectedPreset = null;
\r
2329 PictureSettings.SetPresetCropWarningLabel(null);
\r
2335 #region GUI Functions and Actions
\r
2338 /// Set the GUI to it's finished encoding state.
\r
2340 private void SetEncodeFinished()
\r
2344 if (InvokeRequired)
\r
2346 BeginInvoke(new UpdateWindowHandler(SetEncodeFinished));
\r
2350 lbl_encode.Text = "Encoding Finished";
\r
2351 ProgressBarStatus.Visible = false;
\r
2352 btn_start.Text = "Start";
\r
2353 btn_start.ToolTipText = "Start the encoding process";
\r
2354 btn_start.Image = Properties.Resources.Play;
\r
2356 // If the window is minimized, display the notification in a popup.
\r
2357 if (Properties.Settings.Default.trayIconAlerts)
\r
2358 if (FormWindowState.Minimized == this.WindowState)
\r
2360 notifyIcon.BalloonTipText = lbl_encode.Text;
\r
2361 notifyIcon.ShowBalloonTip(500);
\r
2364 catch (Exception exc)
\r
2366 MessageBox.Show(exc.ToString());
\r
2371 /// Set the GUI to it's started encoding state.
\r
2373 private void SetEncodeStarted()
\r
2377 if (InvokeRequired)
\r
2379 BeginInvoke(new UpdateWindowHandler(SetEncodeStarted));
\r
2382 lbl_encode.Visible = true;
\r
2383 ProgressBarStatus.Value = 0;
\r
2384 ProgressBarStatus.Visible = true;
\r
2385 lbl_encode.Text = "Encoding with " + encodeQueue.Count + " encode(s) pending";
\r
2386 btn_start.Text = "Stop";
\r
2387 btn_start.ToolTipText = "Stop the encoding process.";
\r
2388 btn_start.Image = Properties.Resources.stop;
\r
2390 catch (Exception exc)
\r
2392 MessageBox.Show(exc.ToString());
\r
2397 /// Display the Encode Status
\r
2399 /// <param name="sender">
\r
2402 /// <param name="e">
\r
2405 private void EncodeQueue_EncodeStatusChanged(object sender, HandBrake.ApplicationServices.EncodeProgressEventArgs e)
\r
2407 if (this.InvokeRequired)
\r
2409 this.BeginInvoke(new Encode.EncodeProgessStatus(EncodeQueue_EncodeStatusChanged), new[] { sender, e });
\r
2415 "{0:00.00}%, FPS: {1:000.0}, Avg FPS: {2:000.0}, Time Remaining: {3}, Encode(s) Pending {4}",
\r
2416 e.PercentComplete,
\r
2417 e.CurrentFrameRate,
\r
2418 e.AverageFrameRate,
\r
2419 e.EstimatedTimeLeft,
\r
2420 encodeQueue.Count);
\r
2422 ProgressBarStatus.Value = (int)Math.Round(e.PercentComplete);
\r
2426 /// Set the DVD Drive selection in the "Source" Menu
\r
2428 private void SetDriveSelectionMenuItem()
\r
2432 if (InvokeRequired)
\r
2434 BeginInvoke(new UpdateWindowHandler(SetDriveSelectionMenuItem));
\r
2438 drives = Main.GetDrives();
\r
2440 List<ToolStripMenuItem> menuItems = new List<ToolStripMenuItem>();
\r
2441 foreach (DriveInformation drive in drives)
\r
2443 ToolStripMenuItem menuItem = new ToolStripMenuItem
\r
2445 Name = drive.ToString(),
\r
2446 Text = drive.RootDirectory + " (" + drive.VolumeLabel + ")",
\r
2447 Image = Resources.disc_small
\r
2449 menuItem.Click += new EventHandler(MnuDvdDriveClick);
\r
2450 menuItems.Add(menuItem);
\r
2453 foreach (ToolStripMenuItem item in menuItems)
\r
2454 btn_source.DropDownItems.Add(item);
\r
2456 catch (Exception exc)
\r
2458 MessageBox.Show("Error in SetDriveSelectionMenuItem" + exc);
\r
2463 /// Access the preset Handler and setup the preset panel.
\r
2465 private void LoadPresetPanel()
\r
2467 if (presetHandler.CheckIfPresetsAreOutOfDate())
\r
2468 if (!Settings.Default.presetNotification)
\r
2469 MessageBox.Show(this,
\r
2470 "HandBrake has determined your built-in presets are out of date... These presets will now be updated.",
\r
2471 "Preset Update", MessageBoxButtons.OK, MessageBoxIcon.Information);
\r
2473 presetHandler.GetPresetPanel(ref treeView_presets);
\r
2474 treeView_presets.Update();
\r
2478 /// Get the title from the selected item in the title dropdown.
\r
2483 private int GetTitle()
\r
2486 if (drp_dvdtitle.SelectedItem != null)
\r
2488 string[] titleInfo = drp_dvdtitle.SelectedItem.ToString().Split(' ');
\r
2489 int.TryParse(titleInfo[0], out title);
\r
2496 /// Handle the Update Check Finishing.
\r
2498 /// <param name="result">
\r
2501 private void UpdateCheckDoneMenu(IAsyncResult result)
\r
2503 // Make sure it's running on the calling thread
\r
2504 if (InvokeRequired)
\r
2506 Invoke(new MethodInvoker(() => this.UpdateCheckDoneMenu(result)));
\r
2509 UpdateCheckInformation info;
\r
2512 // Get the information about the new build, if any, and close the window
\r
2513 info = UpdateService.EndCheckForUpdates(result);
\r
2515 if (info.NewVersionAvailable && info.BuildInformation != null)
\r
2517 UpdateInfo updateWindow = new UpdateInfo(info.BuildInformation, Settings.Default.hb_version, Settings.Default.hb_build.ToString());
\r
2518 updateWindow.ShowDialog();
\r
2521 MessageBox.Show("There are no new updates at this time.", "Update Check", MessageBoxButtons.OK,
\r
2522 MessageBoxIcon.Information);
\r
2523 lbl_updateCheck.Visible = false;
\r
2526 catch (Exception ex)
\r
2528 if ((bool)result.AsyncState)
\r
2530 "Unable to check for updates, Please try again later.\n\nDetailed Error Information:\n" + ex,
\r
2531 "Error", MessageBoxButtons.OK, MessageBoxIcon.Error);
\r
2540 /// Handle GUI shortcuts
\r
2542 /// <param name="msg">Message</param>
\r
2543 /// <param name="keyData">Keys</param>
\r
2544 /// <returns>Bool</returns>
\r
2545 protected override bool ProcessCmdKey(ref Message msg, Keys keyData)
\r
2547 if (keyData == (Keys.Control | Keys.S))
\r
2549 btn_start_Click(this, new EventArgs());
\r
2553 if (keyData == (Keys.Control | Keys.Shift | Keys.A))
\r
2555 btn_add2Queue_Click(this, new EventArgs());
\r
2558 return base.ProcessCmdKey(ref msg, keyData);
\r
2562 /// If the queue is being processed, prompt the user to confirm application close.
\r
2564 /// <param name="e">FormClosingEventArgs</param>
\r
2565 protected override void OnFormClosing(FormClosingEventArgs e)
\r
2569 // If currently encoding, the queue isn't paused, and there are queue items to process, prompt to confirm close.
\r
2570 if (encodeQueue.IsEncoding)
\r
2572 DialogResult result =
\r
2574 "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
2575 "Close HandBrake?",
\r
2576 MessageBoxButtons.YesNo,
\r
2577 MessageBoxIcon.Question);
\r
2579 if (result == DialogResult.No)
\r
2585 encodeQueue.Stop();
\r
2588 if (SourceScan.IsScanning)
\r
2590 SourceScan.ScanCompleted -= new EventHandler(SourceScan_ScanCompleted);
\r
2591 SourceScan.Stop();
\r
2594 catch (Exception exc)
\r
2596 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
2600 base.OnFormClosing(e);
\r
2606 // This is the END of the road ****************************************
\r