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 // Scan Started and Completed Events
\r
227 SourceScan.ScanStatusChanged += new EventHandler(SourceScan_ScanStatusChanged);
\r
228 SourceScan.ScanCompleted += new EventHandler(SourceScan_ScanCompleted);
\r
230 // Handle a file being draged onto the GUI.
\r
231 this.DragEnter += new DragEventHandler(frmMain_DragEnter);
\r
232 this.DragDrop += new DragEventHandler(frmMain_DragDrop);
\r
235 // 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
236 private void RegisterPresetEventHandler()
\r
239 drop_format.SelectedIndexChanged += new EventHandler(changePresetLabel);
\r
240 check_largeFile.CheckedChanged += new EventHandler(changePresetLabel);
\r
241 check_iPodAtom.CheckedChanged += new EventHandler(changePresetLabel);
\r
242 check_optimiseMP4.CheckedChanged += new EventHandler(changePresetLabel);
\r
244 // Picture Settings
\r
245 PictureSettings.PictureSettingsChanged += new EventHandler(changePresetLabel);
\r
248 Filters.FilterSettingsChanged += new EventHandler(changePresetLabel);
\r
251 drp_videoEncoder.SelectedIndexChanged += new EventHandler(changePresetLabel);
\r
252 check_2PassEncode.CheckedChanged += new EventHandler(changePresetLabel);
\r
253 check_turbo.CheckedChanged += new EventHandler(changePresetLabel);
\r
254 text_filesize.TextChanged += new EventHandler(changePresetLabel);
\r
255 text_bitrate.TextChanged += new EventHandler(changePresetLabel);
\r
256 slider_videoQuality.ValueChanged += new EventHandler(changePresetLabel);
\r
259 AudioSettings.AudioListChanged += new EventHandler(changePresetLabel);
\r
262 x264Panel.rtf_x264Query.TextChanged += new EventHandler(changePresetLabel);
\r
265 private void UnRegisterPresetEventHandler()
\r
267 // Output Settings
\r
268 drop_format.SelectedIndexChanged -= new EventHandler(changePresetLabel);
\r
269 check_largeFile.CheckedChanged -= new EventHandler(changePresetLabel);
\r
270 check_iPodAtom.CheckedChanged -= new EventHandler(changePresetLabel);
\r
271 check_optimiseMP4.CheckedChanged -= new EventHandler(changePresetLabel);
\r
273 // Picture Settings
\r
274 PictureSettings.PictureSettingsChanged -= new EventHandler(changePresetLabel);
\r
277 Filters.FilterSettingsChanged -= new EventHandler(changePresetLabel);
\r
280 drp_videoEncoder.SelectedIndexChanged -= new EventHandler(changePresetLabel);
\r
281 check_2PassEncode.CheckedChanged -= new EventHandler(changePresetLabel);
\r
282 check_turbo.CheckedChanged -= new EventHandler(changePresetLabel);
\r
283 text_filesize.TextChanged -= new EventHandler(changePresetLabel);
\r
284 text_bitrate.TextChanged -= new EventHandler(changePresetLabel);
\r
285 slider_videoQuality.ValueChanged -= new EventHandler(changePresetLabel);
\r
288 AudioSettings.AudioListChanged -= new EventHandler(changePresetLabel);
\r
291 x264Panel.rtf_x264Query.TextChanged -= new EventHandler(changePresetLabel);
\r
294 private void changePresetLabel(object sender, EventArgs e)
\r
296 labelPreset.Text = "Output Settings (Preset: Custom)";
\r
297 this.currentlySelectedPreset = null;
\r
300 private static void frmMain_DragEnter(object sender, DragEventArgs e)
\r
302 if (e.Data.GetDataPresent(DataFormats.FileDrop, false))
\r
303 e.Effect = DragDropEffects.All;
\r
306 private void frmMain_DragDrop(object sender, DragEventArgs e)
\r
308 string[] fileList = e.Data.GetData(DataFormats.FileDrop) as string[];
\r
309 sourcePath = string.Empty;
\r
311 if (fileList != null)
\r
313 if (!string.IsNullOrEmpty(fileList[0]))
\r
315 this.selectedSourceType = SourceType.VideoFile;
\r
316 StartScan(fileList[0], 0);
\r
319 UpdateSourceLabel();
\r
322 UpdateSourceLabel();
\r
325 private void encodeStarted(object sender, EventArgs e)
\r
327 SetEncodeStarted();
\r
328 encodeQueue.EncodeStatusChanged += EncodeQueue_EncodeStatusChanged;
\r
331 private void encodeEnded(object sender, EventArgs e)
\r
333 encodeQueue.EncodeStatusChanged -= EncodeQueue_EncodeStatusChanged;
\r
334 SetEncodeFinished();
\r
338 // User Interface Menus / Tool Strips *********************************
\r
343 /// Kill The scan menu Item
\r
345 /// <param name="sender">
\r
348 /// <param name="e">
\r
351 private void mnu_killCLI_Click(object sender, EventArgs e)
\r
357 /// Exit the Application Menu Item
\r
359 /// <param name="sender">
\r
362 /// <param name="e">
\r
365 private void mnu_exit_Click(object sender, EventArgs e)
\r
367 Application.Exit();
\r
375 /// Menu - Start Button
\r
377 /// <param name="sender">
\r
380 /// <param name="e">
\r
383 private void mnu_encode_Click(object sender, EventArgs e)
\r
385 queueWindow.Show();
\r
389 /// Menu - Display the Log Window
\r
391 /// <param name="sender">
\r
394 /// <param name="e">
\r
397 private void mnu_encodeLog_Click(object sender, EventArgs e)
\r
399 this.btn_ActivityWindow_Click(this, null);
\r
403 /// Menu - Display the Options Window
\r
405 /// <param name="sender">
\r
408 /// <param name="e">
\r
411 private void mnu_options_Click(object sender, EventArgs e)
\r
413 Form options = new frmOptions(this);
\r
414 options.ShowDialog();
\r
419 #region Presets Menu
\r
422 /// Reset the Built in Presets
\r
424 /// <param name="sender">
\r
427 /// <param name="e">
\r
430 private void mnu_presetReset_Click(object sender, EventArgs e)
\r
432 presetHandler.UpdateBuiltInPresets();
\r
434 if (treeView_presets.Nodes.Count == 0)
\r
436 "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
437 "Error", MessageBoxButtons.OK, MessageBoxIcon.Error);
\r
439 MessageBox.Show("Presets have been updated!", "Alert", MessageBoxButtons.OK, MessageBoxIcon.Information);
\r
441 treeView_presets.ExpandAll();
\r
445 /// Delete the selected preset
\r
447 /// <param name="sender">
\r
450 /// <param name="e">
\r
453 private void mnu_delete_preset_Click(object sender, EventArgs e)
\r
455 presetHandler.RemoveBuiltInPresets();
\r
456 LoadPresetPanel(); // Reload the preset panel
\r
460 /// Select the Normal preset
\r
462 /// <param name="sender">
\r
465 /// <param name="e">
\r
468 private void mnu_SelectDefault_Click(object sender, EventArgs e)
\r
470 loadNormalPreset();
\r
474 /// Import a plist Preset
\r
476 /// <param name="sender">
\r
479 /// <param name="e">
\r
482 private void mnu_importMacPreset_Click(object sender, EventArgs e)
\r
488 /// Export a Plist Preset
\r
490 /// <param name="sender">
\r
493 /// <param name="e">
\r
496 private void mnu_exportMacPreset_Click(object sender, EventArgs e)
\r
502 /// Create a new Preset
\r
504 /// <param name="sender">
\r
507 /// <param name="e">
\r
510 private void btn_new_preset_Click(object sender, EventArgs e)
\r
512 Form preset = new frmAddPreset(this, presetHandler);
\r
513 if (preset.ShowDialog() == DialogResult.OK)
\r
515 TreeNode presetTreeview = new TreeNode(presetHandler.LastPresetAdded.Name) { ForeColor = Color.Black };
\r
516 treeView_presets.Nodes.Add(presetTreeview);
\r
517 presetHandler.LastPresetAdded = null;
\r
526 /// Menu - Display the User Guide Web Page
\r
528 /// <param name="sender">
\r
531 /// <param name="e">
\r
534 private void mnu_user_guide_Click(object sender, EventArgs e)
\r
536 Process.Start("http://trac.handbrake.fr/wiki/HandBrakeGuide");
\r
540 /// Menu - Check for Updates
\r
542 /// <param name="sender">
\r
545 /// <param name="e">
\r
548 private void mnu_UpdateCheck_Click(object sender, EventArgs e)
\r
550 lbl_updateCheck.Visible = true;
\r
551 Settings.Default.lastUpdateCheckDate = DateTime.Now;
\r
552 Settings.Default.Save();
\r
553 string url = Settings.Default.hb_build.ToString().EndsWith("1")
\r
554 ? Settings.Default.appcast_unstable
\r
555 : Settings.Default.appcast;
\r
556 UpdateService.BeginCheckForUpdates(new AsyncCallback(UpdateCheckDoneMenu), false, url, Settings.Default.hb_build, Settings.Default.skipversion, Settings.Default.hb_version);
\r
560 /// Menu - Display the About Window
\r
562 /// <param name="sender">
\r
565 /// <param name="e">
\r
568 private void mnu_about_Click(object sender, EventArgs e)
\r
570 using (frmAbout About = new frmAbout())
\r
572 About.ShowDialog();
\r
581 /// RMenu - Expand All
\r
583 /// <param name="sender">
\r
586 /// <param name="e">
\r
589 private void pmnu_expandAll_Click(object sender, EventArgs e)
\r
591 treeView_presets.ExpandAll();
\r
595 /// RMenu - Collaspe All
\r
597 /// <param name="sender">
\r
600 /// <param name="e">
\r
603 private void pmnu_collapse_Click(object sender, EventArgs e)
\r
605 treeView_presets.CollapseAll();
\r
609 /// Menu - Import Preset
\r
611 /// <param name="sender">
\r
614 /// <param name="e">
\r
617 private void pmnu_import_Click(object sender, EventArgs e)
\r
623 /// RMenu - Save Changes to Preset
\r
625 /// <param name="sender">
\r
628 /// <param name="e">
\r
631 private void pmnu_saveChanges_Click(object sender, EventArgs e)
\r
633 // TODO this requires a re-think since the Query Editor has changed.
\r
634 DialogResult result =
\r
636 "Do you wish to include picture settings when updating the preset: " +
\r
637 treeView_presets.SelectedNode.Text, "Update Preset", MessageBoxButtons.YesNoCancel,
\r
638 MessageBoxIcon.Question);
\r
639 if (result == DialogResult.Yes)
\r
640 presetHandler.Update(treeView_presets.SelectedNode.Text,
\r
641 QueryGenerator.GenerateQueryForPreset(this, QueryPictureSettingsMode.SourceMaximum, true, 0, 0), true);
\r
642 else if (result == DialogResult.No)
\r
643 presetHandler.Update(treeView_presets.SelectedNode.Text,
\r
644 QueryGenerator.GenerateQueryForPreset(this, QueryPictureSettingsMode.SourceMaximum, true, 0, 0), false);
\r
648 /// RMenu - Delete Preset
\r
650 /// <param name="sender">
\r
653 /// <param name="e">
\r
656 private void pmnu_delete_click(object sender, EventArgs e)
\r
658 if (treeView_presets.SelectedNode != null)
\r
660 presetHandler.Remove(treeView_presets.SelectedNode.Text);
\r
661 treeView_presets.Nodes.Remove(treeView_presets.SelectedNode);
\r
663 treeView_presets.Select();
\r
667 /// Preset Menu Is Opening. Setup the Menu
\r
669 /// <param name="sender">
\r
672 /// <param name="e">
\r
675 private void presets_menu_Opening(object sender, CancelEventArgs e)
\r
677 // Make sure that the save menu is always disabled by default
\r
678 pmnu_saveChanges.Enabled = false;
\r
680 // Now enable the save menu if the selected preset is a user preset
\r
681 if (treeView_presets.SelectedNode != null)
\r
682 if (presetHandler.CheckIfUserPresetExists(treeView_presets.SelectedNode.Text))
\r
683 pmnu_saveChanges.Enabled = true;
\r
685 treeView_presets.Select();
\r
688 // Presets Management
\r
691 /// Button - Add a preset
\r
693 /// <param name="sender">
\r
696 /// <param name="e">
\r
699 private void btn_addPreset_Click(object sender, EventArgs e)
\r
701 Form preset = new frmAddPreset(this, presetHandler);
\r
702 if (preset.ShowDialog() == DialogResult.OK)
\r
704 TreeNode presetTreeview = new TreeNode(presetHandler.LastPresetAdded.Name) { ForeColor = Color.Black };
\r
705 treeView_presets.Nodes.Add(presetTreeview);
\r
706 presetHandler.LastPresetAdded = null;
\r
711 /// Button - remove a Preset
\r
713 /// <param name="sender">
\r
716 /// <param name="e">
\r
719 private void btn_removePreset_Click(object sender, EventArgs e)
\r
721 DialogResult result = MessageBox.Show("Are you sure you wish to delete the selected preset?", "Preset",
\r
722 MessageBoxButtons.YesNo, MessageBoxIcon.Question);
\r
723 if (result == DialogResult.Yes)
\r
725 if (treeView_presets.SelectedNode != null)
\r
727 presetHandler.Remove(treeView_presets.SelectedNode.Text);
\r
728 treeView_presets.Nodes.Remove(treeView_presets.SelectedNode);
\r
731 treeView_presets.Select();
\r
735 /// Button - Set the selected preset as the default
\r
737 /// <param name="sender">
\r
740 /// <param name="e">
\r
743 private void btn_setDefault_Click(object sender, EventArgs e)
\r
745 if (treeView_presets.SelectedNode != null)
\r
747 DialogResult result = MessageBox.Show("Are you sure you wish to set this preset as the default?",
\r
748 "Preset", MessageBoxButtons.YesNo, MessageBoxIcon.Question);
\r
749 if (result == DialogResult.Yes)
\r
751 Properties.Settings.Default.defaultPreset = treeView_presets.SelectedNode.Text;
\r
752 Properties.Settings.Default.Save();
\r
753 MessageBox.Show("New default preset set.", "Alert", MessageBoxButtons.OK, MessageBoxIcon.Information);
\r
757 MessageBox.Show("Please select a preset first.", "Warning", MessageBoxButtons.OK, MessageBoxIcon.Warning);
\r
761 /// PresetBar Mouse Down event
\r
763 /// <param name="sender">
\r
766 /// <param name="e">
\r
769 private void treeview_presets_mouseUp(object sender, MouseEventArgs e)
\r
771 if (e.Button == MouseButtons.Right)
\r
772 treeView_presets.SelectedNode = treeView_presets.GetNodeAt(e.Location);
\r
773 else if (e.Button == MouseButtons.Left)
\r
775 if (treeView_presets.GetNodeAt(e.Location) != null)
\r
777 if (labelPreset.Text.Contains(treeView_presets.GetNodeAt(e.Location).Text))
\r
782 treeView_presets.Select();
\r
786 /// Preset Bar after selecting the preset
\r
788 /// <param name="sender">
\r
791 /// <param name="e">
\r
794 private void treeView_presets_AfterSelect(object sender, TreeViewEventArgs e)
\r
800 /// When the mouse moves, display a preset
\r
802 /// <param name="sender">The Sender</param>
\r
803 /// <param name="e">the MouseEventArgs</param>
\r
804 private void TreeViewPresetsMouseMove(object sender, MouseEventArgs e)
\r
806 TreeNode theNode = this.treeView_presets.GetNodeAt(e.X, e.Y);
\r
808 if ((theNode != null))
\r
810 // Change the ToolTip only if the pointer moved to a new node.
\r
811 if (theNode.ToolTipText != this.ToolTip.GetToolTip(this.treeView_presets))
\r
813 this.ToolTip.SetToolTip(this.treeView_presets, theNode.ToolTipText);
\r
816 else // Pointer is not over a node so clear the ToolTip.
\r
818 this.ToolTip.SetToolTip(this.treeView_presets, string.Empty);
\r
823 /// Preset Bar - Handle the Delete Key
\r
825 /// <param name="sender">
\r
828 /// <param name="e">
\r
831 private void treeView_presets_deleteKey(object sender, KeyEventArgs e)
\r
833 if (e.KeyCode == Keys.Delete)
\r
835 DialogResult result = MessageBox.Show("Are you sure you wish to delete the selected preset?", "Preset",
\r
836 MessageBoxButtons.YesNo, MessageBoxIcon.Question);
\r
837 if (result == DialogResult.Yes)
\r
839 if (treeView_presets.SelectedNode != null)
\r
840 presetHandler.Remove(treeView_presets.SelectedNode.Text);
\r
842 // Remember each nodes expanded status so we can reload it
\r
843 List<bool> nodeStatus = new List<bool>();
\r
844 foreach (TreeNode node in treeView_presets.Nodes)
\r
845 nodeStatus.Add(node.IsExpanded);
\r
847 // Now reload the preset panel
\r
850 // And finally, re-expand any of the nodes if required
\r
852 foreach (TreeNode node in treeView_presets.Nodes)
\r
864 /// Select the selected preset and setup the GUI
\r
866 private void selectPreset()
\r
868 if (treeView_presets.SelectedNode != null)
\r
870 // Ok, so, we've selected a preset. Now we want to load it.
\r
871 string presetName = treeView_presets.SelectedNode.Text;
\r
872 Preset preset = presetHandler.GetPreset(presetName);
\r
873 if (preset != null)
\r
875 string query = presetHandler.GetPreset(presetName).Query;
\r
879 // Ok, Reset all the H264 widgets before changing the preset
\r
880 x264Panel.Reset2Defaults();
\r
882 // Send the query from the file to the Query Parser class
\r
883 QueryParser presetQuery = QueryParser.Parse(query);
\r
885 // Now load the preset
\r
886 PresetLoader.LoadPreset(this, presetQuery, presetName);
\r
888 // The x264 widgets will need updated, so do this now:
\r
889 x264Panel.StandardizeOptString();
\r
890 x264Panel.SetCurrentSettingsInPanel();
\r
892 // Finally, let this window have a copy of the preset settings.
\r
893 this.currentlySelectedPreset = preset;
\r
894 PictureSettings.SetPresetCropWarningLabel(preset);
\r
901 /// Load the Normal Preset
\r
903 private void loadNormalPreset()
\r
905 foreach (TreeNode treenode in treeView_presets.Nodes)
\r
907 foreach (TreeNode node in treenode.Nodes)
\r
909 if (node.Text.Equals("Normal"))
\r
910 treeView_presets.SelectedNode = treeView_presets.Nodes[treenode.Index].Nodes[0];
\r
916 /// Import a plist preset
\r
918 private void ImportPreset()
\r
920 if (openPreset.ShowDialog() == DialogResult.OK)
\r
922 QueryParser parsed = PlistPresetHandler.Import(openPreset.FileName);
\r
923 if (presetHandler.CheckIfUserPresetExists(parsed.PresetName + " (Imported)"))
\r
925 DialogResult result =
\r
926 MessageBox.Show("This preset appears to already exist. Would you like to overwrite it?",
\r
927 "Overwrite preset?",
\r
928 MessageBoxButtons.YesNo, MessageBoxIcon.Warning);
\r
929 if (result == DialogResult.Yes)
\r
931 PresetLoader.LoadPreset(this, parsed, parsed.PresetName);
\r
932 presetHandler.Update(parsed.PresetName + " (Imported)",
\r
933 QueryGenerator.GenerateFullQuery(this),
\r
934 parsed.UsesPictureSettings);
\r
939 PresetLoader.LoadPreset(this, parsed, parsed.PresetName);
\r
940 if (presetHandler.Add(parsed.PresetName + " (Imported)",
\r
941 QueryGenerator.GenerateFullQuery(this),
\r
942 parsed.UsesPictureSettings, string.Empty))
\r
944 TreeNode preset_treeview = new TreeNode(parsed.PresetName + " (Imported)")
\r
946 ForeColor = Color.Black
\r
948 treeView_presets.Nodes.Add(preset_treeview);
\r
955 /// Export a plist Preset
\r
957 private void ExportPreset()
\r
959 SaveFileDialog savefiledialog = new SaveFileDialog { Filter = "plist|*.plist" };
\r
961 if (treeView_presets.SelectedNode != null)
\r
963 if (savefiledialog.ShowDialog() == DialogResult.OK)
\r
965 Preset preset = presetHandler.GetPreset(treeView_presets.SelectedNode.Text);
\r
966 PlistPresetHandler.Export(savefiledialog.FileName, preset);
\r
976 /// 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
978 /// <param name="sender">
\r
981 /// <param name="e">
\r
984 private void btn_source_Click(object sender, EventArgs e)
\r
986 // Remove old Drive Menu Items.
\r
987 List<ToolStripMenuItem> itemsToRemove = new List<ToolStripMenuItem>();
\r
988 foreach (var item in btn_source.DropDownItems)
\r
990 if (item.GetType() == typeof(ToolStripMenuItem))
\r
992 ToolStripMenuItem menuItem = (ToolStripMenuItem)item;
\r
993 if (menuItem.Name.StartsWith("Drive"))
\r
995 itemsToRemove.Add(menuItem);
\r
1000 foreach (ToolStripMenuItem item in itemsToRemove)
\r
1001 btn_source.DropDownItems.Remove(item);
\r
1003 Thread driveInfoThread = new Thread(SetDriveSelectionMenuItem);
\r
1004 driveInfoThread.Start();
\r
1008 /// Toolbar - Start The Encode
\r
1010 /// <param name="sender">
\r
1013 /// <param name="e">
\r
1016 private void btn_start_Click(object sender, EventArgs e)
\r
1018 if (btn_start.Text == "Stop")
\r
1020 DialogResult result = !Properties.Settings.Default.showCliForInGuiEncodeStatus
\r
1021 ? MessageBox.Show(
\r
1022 "Are you sure you wish to cancel the encode?\n\nPlease note: Stopping this encode will render the file unplayable. ",
\r
1024 MessageBoxButtons.YesNo,
\r
1025 MessageBoxIcon.Question)
\r
1026 : MessageBox.Show(
\r
1027 "Are you sure you wish to cancel the encode?",
\r
1029 MessageBoxButtons.YesNo,
\r
1030 MessageBoxIcon.Question);
\r
1032 if (result == DialogResult.Yes)
\r
1034 // Pause The Queue
\r
1035 encodeQueue.Pause();
\r
1037 if (Settings.Default.showCliForInGuiEncodeStatus)
\r
1038 encodeQueue.SafelyClose();
\r
1040 encodeQueue.Stop();
\r
1045 // 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
1046 string jobSourcePath = !string.IsNullOrEmpty(rtf_query.Text) ? Main.GetSourceFromQuery(rtf_query.Text) : sourcePath;
\r
1047 string jobDestination = !string.IsNullOrEmpty(rtf_query.Text) ? Main.GetDestinationFromQuery(rtf_query.Text) : text_destination.Text;
\r
1049 if (encodeQueue.Count != 0 || (!string.IsNullOrEmpty(jobSourcePath) && !string.IsNullOrEmpty(jobDestination)))
\r
1051 string generatedQuery = QueryGenerator.GenerateFullQuery(this);
\r
1052 string specifiedQuery = rtf_query.Text != string.Empty
\r
1054 : QueryGenerator.GenerateFullQuery(this);
\r
1055 string query = string.Empty;
\r
1057 // Check to make sure the generated query matches the GUI settings
\r
1058 if (Properties.Settings.Default.PromptOnUnmatchingQueries && !string.IsNullOrEmpty(specifiedQuery) &&
\r
1059 generatedQuery != specifiedQuery)
\r
1061 DialogResult result = MessageBox.Show("The query under the \"Query Editor\" tab " +
\r
1062 "does not match the current GUI settings.\n\nBecause the manual query takes " +
\r
1063 "priority over the GUI, your recently updated settings will not be taken " +
\r
1064 "into account when encoding this job." +
\r
1065 Environment.NewLine + Environment.NewLine +
\r
1066 "Do you want to replace the manual query with the updated GUI-generated query?",
\r
1067 "Manual Query does not Match GUI",
\r
1068 MessageBoxButtons.YesNoCancel, MessageBoxIcon.Asterisk,
\r
1069 MessageBoxDefaultButton.Button3);
\r
1073 case DialogResult.Yes:
\r
1074 // Replace the manual query with the generated one
\r
1075 query = generatedQuery;
\r
1076 rtf_query.Text = generatedQuery;
\r
1078 case DialogResult.No:
\r
1079 // Use the manual query
\r
1080 query = specifiedQuery;
\r
1082 case DialogResult.Cancel:
\r
1083 // Don't start the encode
\r
1089 query = specifiedQuery;
\r
1092 DialogResult overwrite = DialogResult.Yes;
\r
1093 if (!string.IsNullOrEmpty(jobDestination) && File.Exists(jobDestination))
\r
1095 overwrite = MessageBox.Show(
\r
1096 "The destination file already exists. Are you sure you want to overwrite it?",
\r
1097 "Overwrite File?",
\r
1098 MessageBoxButtons.YesNo,
\r
1099 MessageBoxIcon.Question);
\r
1102 if (overwrite == DialogResult.Yes)
\r
1104 if (encodeQueue.Count == 0)
\r
1105 encodeQueue.Add(query, this.GetTitle(), jobSourcePath, jobDestination, (rtf_query.Text != string.Empty));
\r
1107 queueWindow.SetQueue();
\r
1108 if (encodeQueue.Count > 1)
\r
1109 queueWindow.Show(false);
\r
1111 SetEncodeStarted(); // Encode is running, so setup the GUI appropriately
\r
1112 encodeQueue.Start(); // Start The Queue Encoding Process
\r
1117 else if (string.IsNullOrEmpty(sourcePath) || string.IsNullOrEmpty(text_destination.Text))
\r
1118 MessageBox.Show("No source or destination selected.", "Warning", MessageBoxButtons.OK,
\r
1119 MessageBoxIcon.Warning);
\r
1124 /// Toolbar - Add the current job to the Queue
\r
1126 /// <param name="sender">
\r
1129 /// <param name="e">
\r
1132 private void btn_add2Queue_Click(object sender, EventArgs e)
\r
1134 // Add the item to the queue.
\r
1135 AddItemToQueue(true);
\r
1136 queueWindow.Show();
\r
1140 /// Add Multiple Items to the Queue at once.
\r
1142 /// <param name="sender">The Sender</param>
\r
1143 /// <param name="e">The EventArgs</param>
\r
1144 private void MnuAddMultiToQueueClick(object sender, EventArgs e)
\r
1146 if (!Settings.Default.autoNaming)
\r
1148 MessageBox.Show("Destination Auto Naming must be enabled in preferences for this feature to work.", "Error", MessageBoxButtons.OK, MessageBoxIcon.Error);
\r
1152 if (this.SourceScan.SouceData == null)
\r
1154 MessageBox.Show("You must first scan a source or collection of source to use this feature.", "Error", MessageBoxButtons.OK, MessageBoxIcon.Error);
\r
1158 BatchAdd batchAdd = new BatchAdd();
\r
1159 if (batchAdd.ShowDialog() == DialogResult.OK)
\r
1161 int min = batchAdd.Min;
\r
1162 int max = batchAdd.Max;
\r
1163 bool errors = false;
\r
1165 foreach (Title title in this.SourceScan.SouceData.Titles)
\r
1167 if (title.Duration.TotalMinutes > min && title.Duration.TotalMinutes < max)
\r
1170 this.drp_dvdtitle.SelectedItem = title;
\r
1172 if (!this.AddItemToQueue(false))
\r
1182 "One or more items could not be added to the queue. You should check your queue and manually add any missing jobs.",
\r
1184 MessageBoxButtons.OK,
\r
1185 MessageBoxIcon.Warning);
\r
1190 private bool AddItemToQueue(bool showError)
\r
1192 string query = QueryGenerator.GenerateFullQuery(this);
\r
1193 if (!string.IsNullOrEmpty(rtf_query.Text))
\r
1194 query = rtf_query.Text;
\r
1196 // 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
1197 string jobSourcePath = !string.IsNullOrEmpty(rtf_query.Text) ? Main.GetSourceFromQuery(rtf_query.Text) : sourcePath;
\r
1198 string jobDestination = !string.IsNullOrEmpty(rtf_query.Text) ? Main.GetDestinationFromQuery(rtf_query.Text) : text_destination.Text;
\r
1200 // Make sure we have a Source and Destination.
\r
1201 if (string.IsNullOrEmpty(jobSourcePath) || string.IsNullOrEmpty(jobDestination))
\r
1204 MessageBox.Show("No source or destination selected.", "Warning", MessageBoxButtons.OK, MessageBoxIcon.Warning);
\r
1208 // Make sure the destination path exists.
\r
1209 if (!Directory.Exists(Path.GetDirectoryName(jobDestination)))
\r
1212 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
1216 // Make sure we don't have a duplciate on the queue.
\r
1217 if (encodeQueue.CheckForDestinationDuplicate(jobDestination))
\r
1221 DialogResult result;
\r
1225 "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
1228 MessageBoxButtons.YesNo,
\r
1229 MessageBoxIcon.Warning);
\r
1231 if (result != DialogResult.Yes) return false;
\r
1240 encodeQueue.Add(query, this.GetTitle(), jobSourcePath, jobDestination, (rtf_query.Text != string.Empty));
\r
1242 lbl_encode.Text = encodeQueue.Count + " encode(s) pending in the queue";
\r
1248 /// Toolbar - Show the Queue
\r
1250 /// <param name="sender">
\r
1253 /// <param name="e">
\r
1256 private void btn_showQueue_Click(object sender, EventArgs e)
\r
1258 queueWindow.Show();
\r
1259 queueWindow.Activate();
\r
1263 /// Toolbar - Show the Preview Window
\r
1265 /// <param name="sender">
\r
1268 /// <param name="e">
\r
1271 private void tb_preview_Click(object sender, EventArgs e)
\r
1273 if (string.IsNullOrEmpty(sourcePath) || string.IsNullOrEmpty(text_destination.Text))
\r
1274 MessageBox.Show("No source or destination selected.", "Warning", MessageBoxButtons.OK,
\r
1275 MessageBoxIcon.Warning);
\r
1278 if (qtpreview == null)
\r
1280 qtpreview = new frmPreview(this);
\r
1283 else if (qtpreview.IsDisposed)
\r
1285 qtpreview = new frmPreview(this);
\r
1289 MessageBox.Show(qtpreview, "The preview window is already open!", "Warning", MessageBoxButtons.OK,
\r
1290 MessageBoxIcon.Warning);
\r
1295 /// Toolbar - Show the Activity log Window
\r
1297 /// <param name="sender">
\r
1300 /// <param name="e">
\r
1303 private void btn_ActivityWindow_Click(object sender, EventArgs e)
\r
1305 if (this.activityWindow == null || !this.activityWindow.IsHandleCreated)
\r
1306 this.activityWindow = new frmActivityWindow(encodeQueue, SourceScan);
\r
1308 this.activityWindow.Show();
\r
1309 this.activityWindow.Activate();
\r
1314 #region System Tray Icon
\r
1317 /// Handle Resizing of the main window when deaing with the Notify Icon
\r
1319 /// <param name="sender">
\r
1322 /// <param name="e">
\r
1325 private void frmMain_Resize(object sender, EventArgs e)
\r
1327 if (FormWindowState.Minimized == this.WindowState)
\r
1329 notifyIcon.Visible = true;
\r
1332 else if (FormWindowState.Normal == this.WindowState)
\r
1333 notifyIcon.Visible = false;
\r
1337 /// Double Click the Tray Icon
\r
1339 /// <param name="sender">
\r
1342 /// <param name="e">
\r
1345 private void notifyIcon_MouseDoubleClick(object sender, MouseEventArgs e)
\r
1347 this.Visible = true;
\r
1349 this.WindowState = FormWindowState.Normal;
\r
1350 notifyIcon.Visible = false;
\r
1354 /// Tray Icon - Restore Menu Item - Resture the Window
\r
1356 /// <param name="sender">
\r
1359 /// <param name="e">
\r
1362 private void btn_restore_Click(object sender, EventArgs e)
\r
1364 this.Visible = true;
\r
1366 this.WindowState = FormWindowState.Normal;
\r
1367 notifyIcon.Visible = false;
\r
1372 #region Main Window and Tab Control
\r
1375 private void BtnFolderScanClicked(object sender, EventArgs e)
\r
1377 this.btn_source.HideDropDown();
\r
1378 if (DVD_Open.ShowDialog() == DialogResult.OK)
\r
1380 this.selectedSourceType = SourceType.Folder;
\r
1381 SelectSource(DVD_Open.SelectedPath, 0);
\r
1384 UpdateSourceLabel();
\r
1387 private void BtnFileScanClicked(object sender, EventArgs e)
\r
1389 this.btn_source.HideDropDown();
\r
1390 if (ISO_Open.ShowDialog() == DialogResult.OK)
\r
1392 this.selectedSourceType = SourceType.VideoFile;
\r
1393 SelectSource(ISO_Open.FileName, 0);
\r
1396 UpdateSourceLabel();
\r
1399 private void MnuDvdDriveClick(object sender, EventArgs e)
\r
1401 ToolStripMenuItem item = sender as ToolStripMenuItem;
\r
1404 string driveId = item.Name.Replace("Drive", string.Empty);
\r
1406 if (int.TryParse(driveId, out id))
\r
1408 this.dvdDrivePath = drives[id].RootDirectory;
\r
1409 this.dvdDriveLabel = drives[id].VolumeLabel;
\r
1411 if (this.dvdDrivePath == null) return;
\r
1412 this.selectedSourceType = SourceType.DvdDrive;
\r
1413 SelectSource(this.dvdDrivePath, 0);
\r
1418 private void VideoTitleSpecificScanClick(object sender, EventArgs e)
\r
1420 this.btn_source.HideDropDown();
\r
1421 if (ISO_Open.ShowDialog() == DialogResult.OK)
\r
1423 this.selectedSourceType = SourceType.VideoFile;
\r
1425 int sourceTitle = 0;
\r
1426 TitleSpecificScan title = new TitleSpecificScan();
\r
1427 if (title.ShowDialog() == DialogResult.OK)
\r
1429 sourceTitle = title.Title;
\r
1430 SelectSource(ISO_Open.FileName, sourceTitle);
\r
1434 UpdateSourceLabel();
\r
1437 private void FolderTitleSpecificScanClick(object sender, EventArgs e)
\r
1439 this.btn_source.HideDropDown();
\r
1440 if (DVD_Open.ShowDialog() == DialogResult.OK)
\r
1442 this.selectedSourceType = SourceType.Folder;
\r
1444 int sourceTitle = 0;
\r
1445 TitleSpecificScan title = new TitleSpecificScan();
\r
1446 if (title.ShowDialog() == DialogResult.OK)
\r
1448 sourceTitle = title.Title;
\r
1449 SelectSource(DVD_Open.SelectedPath, sourceTitle);
\r
1453 UpdateSourceLabel();
\r
1456 private void SelectSource(string file, int titleSpecific)
\r
1458 Check_ChapterMarkers.Enabled = true;
\r
1459 sourcePath = string.Empty;
\r
1461 if (file == string.Empty) // Must have a file or path
\r
1463 UpdateSourceLabel();
\r
1467 sourcePath = Path.GetFileName(file);
\r
1468 StartScan(file, titleSpecific);
\r
1471 private void drp_dvdtitle_Click(object sender, EventArgs e)
\r
1473 if ((drp_dvdtitle.Items.Count == 1) && (drp_dvdtitle.Items[0].ToString() == "Automatic"))
\r
1475 "There are no titles to select. Please load a source file by clicking the 'Source' button above before trying to select a title.",
\r
1476 "Alert", MessageBoxButtons.OK, MessageBoxIcon.Asterisk);
\r
1479 private void drp_dvdtitle_SelectedIndexChanged(object sender, EventArgs e)
\r
1481 UnRegisterPresetEventHandler();
\r
1482 drop_mode.SelectedIndex = 0;
\r
1484 drop_chapterStart.Items.Clear();
\r
1485 drop_chapterFinish.Items.Clear();
\r
1487 // If the dropdown is set to automatic nothing else needs to be done.
\r
1488 // Otheriwse if its not, title data has to be loaded from parsing.
\r
1489 if (drp_dvdtitle.Text != "Automatic")
\r
1491 selectedTitle = drp_dvdtitle.SelectedItem as Title;
\r
1492 lbl_duration.Text = selectedTitle.Duration.ToString();
\r
1493 PictureSettings.CurrentlySelectedPreset = this.currentlySelectedPreset;
\r
1494 PictureSettings.Source = selectedTitle; // Setup Picture Settings Tab Control
\r
1496 // Populate the Angles dropdown
\r
1497 drop_angle.Items.Clear();
\r
1498 if (!Properties.Settings.Default.noDvdNav)
\r
1500 drop_angle.Visible = true;
\r
1501 lbl_angle.Visible = true;
\r
1503 for (int i = 1; i <= selectedTitle.AngleCount; i++)
\r
1504 drop_angle.Items.Add(i.ToString());
\r
1506 if (drop_angle.Items.Count == 0)
\r
1508 drop_angle.Visible = false;
\r
1509 lbl_angle.Visible = false;
\r
1512 if (drop_angle.Items.Count != 0)
\r
1513 drop_angle.SelectedIndex = 0;
\r
1517 drop_angle.Visible = false;
\r
1518 lbl_angle.Visible = false;
\r
1521 // Populate the Start chapter Dropdown
\r
1522 drop_chapterStart.Items.Clear();
\r
1523 drop_chapterStart.Items.AddRange(selectedTitle.Chapters.ToArray());
\r
1524 if (drop_chapterStart.Items.Count > 0)
\r
1525 drop_chapterStart.Text = drop_chapterStart.Items[0].ToString();
\r
1527 // Populate the Final Chapter Dropdown
\r
1528 drop_chapterFinish.Items.Clear();
\r
1529 drop_chapterFinish.Items.AddRange(selectedTitle.Chapters.ToArray());
\r
1530 if (drop_chapterFinish.Items.Count > 0)
\r
1531 drop_chapterFinish.Text = drop_chapterFinish.Items[drop_chapterFinish.Items.Count - 1].ToString();
\r
1533 // Populate the Audio Channels Dropdown
\r
1534 AudioSettings.SetTrackListFromPreset(selectedTitle, this.currentlySelectedPreset);
\r
1536 // Populate the Subtitles dropdown
\r
1537 Subtitles.SetSubtitleTrackAuto(selectedTitle.Subtitles.ToArray());
\r
1539 // Update the source label if we have multiple streams
\r
1540 if (selectedTitle != null)
\r
1541 if (!string.IsNullOrEmpty(selectedTitle.SourceName))
\r
1542 labelSource.Text = Path.GetFileName(selectedTitle.SourceName);
\r
1544 // Run the AutoName & ChapterNaming functions
\r
1545 if (Properties.Settings.Default.autoNaming)
\r
1547 string autoPath = Main.AutoName(this);
\r
1548 if (autoPath != null)
\r
1549 text_destination.Text = autoPath;
\r
1552 "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
1553 "Warning", MessageBoxButtons.OK, MessageBoxIcon.Warning);
\r
1556 data_chpt.Rows.Clear();
\r
1557 if (selectedTitle.Chapters.Count != 1)
\r
1559 DataGridView chapterGridView = Main.ChapterNaming(selectedTitle, data_chpt, drop_chapterFinish.Text);
\r
1560 if (chapterGridView != null)
\r
1561 data_chpt = chapterGridView;
\r
1565 Check_ChapterMarkers.Checked = false;
\r
1566 Check_ChapterMarkers.Enabled = false;
\r
1569 // Hack to force the redraw of the scrollbars which don't resize properly when the control is disabled.
\r
1570 data_chpt.Columns[0].Width = 166;
\r
1571 data_chpt.Columns[0].Width = 165;
\r
1573 RegisterPresetEventHandler();
\r
1576 private void chapersChanged(object sender, EventArgs e)
\r
1578 if (drop_mode.SelectedIndex != 0) // Function is not used if we are not in chapters mode.
\r
1581 Control ctl = (Control)sender;
\r
1582 int chapterStart, chapterEnd;
\r
1583 int.TryParse(drop_chapterStart.Text, out chapterStart);
\r
1584 int.TryParse(drop_chapterFinish.Text, out chapterEnd);
\r
1588 case "drop_chapterStart":
\r
1589 if (drop_chapterFinish.SelectedIndex == -1 && drop_chapterFinish.Items.Count != 0)
\r
1590 drop_chapterFinish.SelectedIndex = drop_chapterFinish.Items.Count - 1;
\r
1592 if (chapterEnd != 0)
\r
1593 if (chapterStart > chapterEnd)
\r
1594 drop_chapterFinish.Text = chapterStart.ToString();
\r
1596 case "drop_chapterFinish":
\r
1597 if (drop_chapterStart.Items.Count >= 1 && drop_chapterStart.SelectedIndex == -1)
\r
1598 drop_chapterStart.SelectedIndex = 0;
\r
1600 if (chapterStart != 0)
\r
1601 if (chapterEnd < chapterStart)
\r
1602 drop_chapterFinish.Text = chapterStart.ToString();
\r
1604 // Add more rows to the Chapter menu if needed.
\r
1605 if (Check_ChapterMarkers.Checked)
\r
1607 int i = data_chpt.Rows.Count, finish = 0;
\r
1608 int.TryParse(drop_chapterFinish.Text, out finish);
\r
1610 while (i < finish)
\r
1612 int n = data_chpt.Rows.Add();
\r
1613 data_chpt.Rows[n].Cells[0].Value = (i + 1);
\r
1614 data_chpt.Rows[n].Cells[1].Value = "Chapter " + (i + 1);
\r
1615 data_chpt.Rows[n].Cells[0].ValueType = typeof(int);
\r
1616 data_chpt.Rows[n].Cells[1].ValueType = typeof(string);
\r
1623 // Update the Duration
\r
1624 lbl_duration.Text =
\r
1625 Main.CalculateDuration(drop_chapterStart.SelectedIndex, drop_chapterFinish.SelectedIndex, selectedTitle)
\r
1628 // Run the Autonaming function
\r
1629 if (Properties.Settings.Default.autoNaming)
\r
1630 text_destination.Text = Main.AutoName(this);
\r
1632 // Disable chapter markers if only 1 chapter is selected.
\r
1633 if (chapterStart == chapterEnd)
\r
1635 Check_ChapterMarkers.Enabled = false;
\r
1636 btn_importChapters.Enabled = false;
\r
1637 data_chpt.Enabled = false;
\r
1641 Check_ChapterMarkers.Enabled = true;
\r
1642 if (Check_ChapterMarkers.Checked)
\r
1644 btn_importChapters.Enabled = true;
\r
1645 data_chpt.Enabled = true;
\r
1650 private void SecondsOrFramesChanged(object sender, EventArgs e)
\r
1653 int.TryParse(drop_chapterStart.Text, out start);
\r
1654 int.TryParse(drop_chapterFinish.Text, out end);
\r
1655 double duration = end - start;
\r
1657 switch (drop_mode.SelectedIndex)
\r
1660 lbl_duration.Text = TimeSpan.FromSeconds(duration).ToString();
\r
1663 if (selectedTitle != null)
\r
1665 duration = duration / selectedTitle.Fps;
\r
1666 lbl_duration.Text = TimeSpan.FromSeconds(duration).ToString();
\r
1669 lbl_duration.Text = "--:--:--";
\r
1675 private void drop_mode_SelectedIndexChanged(object sender, EventArgs e)
\r
1678 this.drop_chapterFinish.TextChanged -= new EventHandler(this.SecondsOrFramesChanged);
\r
1679 this.drop_chapterStart.TextChanged -= new EventHandler(this.SecondsOrFramesChanged);
\r
1682 switch (drop_mode.SelectedIndex)
\r
1685 drop_chapterStart.DropDownStyle = ComboBoxStyle.DropDownList;
\r
1686 drop_chapterFinish.DropDownStyle = ComboBoxStyle.DropDownList;
\r
1687 if (drop_chapterStart.Items.Count != 0)
\r
1689 drop_chapterStart.SelectedIndex = 0;
\r
1690 drop_chapterFinish.SelectedIndex = drop_chapterFinish.Items.Count - 1;
\r
1693 lbl_duration.Text = "--:--:--";
\r
1696 this.drop_chapterStart.TextChanged += new EventHandler(this.SecondsOrFramesChanged);
\r
1697 this.drop_chapterFinish.TextChanged += new EventHandler(this.SecondsOrFramesChanged);
\r
1698 drop_chapterStart.DropDownStyle = ComboBoxStyle.Simple;
\r
1699 drop_chapterFinish.DropDownStyle = ComboBoxStyle.Simple;
\r
1700 if (selectedTitle != null)
\r
1702 drop_chapterStart.Text = "0";
\r
1703 drop_chapterFinish.Text = selectedTitle.Duration.TotalSeconds.ToString();
\r
1707 this.drop_chapterStart.TextChanged += new EventHandler(this.SecondsOrFramesChanged);
\r
1708 this.drop_chapterFinish.TextChanged += new EventHandler(this.SecondsOrFramesChanged);
\r
1709 drop_chapterStart.DropDownStyle = ComboBoxStyle.Simple;
\r
1710 drop_chapterFinish.DropDownStyle = ComboBoxStyle.Simple;
\r
1711 if (selectedTitle != null)
\r
1713 drop_chapterStart.Text = "0";
\r
1714 drop_chapterFinish.Text = (selectedTitle.Fps * selectedTitle.Duration.TotalSeconds).ToString();
\r
1721 private void btn_destBrowse_Click(object sender, EventArgs e)
\r
1723 // This removes the file extension from the filename box on the save file dialog.
\r
1724 // It's daft but some users don't realise that typing an extension overrides the dropdown extension selected.
\r
1725 DVD_Save.FileName = Path.GetFileNameWithoutExtension(text_destination.Text);
\r
1727 if (Path.IsPathRooted(text_destination.Text))
\r
1728 DVD_Save.InitialDirectory = Path.GetDirectoryName(text_destination.Text);
\r
1730 // Show the dialog and set the main form file path
\r
1731 if (drop_format.SelectedIndex.Equals(0))
\r
1732 DVD_Save.FilterIndex = 1;
\r
1733 else if (drop_format.SelectedIndex.Equals(1))
\r
1734 DVD_Save.FilterIndex = 2;
\r
1736 if (DVD_Save.ShowDialog() == DialogResult.OK)
\r
1738 // Add a file extension manually, as FileDialog.AddExtension has issues with dots in filenames
\r
1739 switch (DVD_Save.FilterIndex)
\r
1743 !Path.GetExtension(DVD_Save.FileName).Equals(".mp4",
\r
1744 StringComparison.InvariantCultureIgnoreCase))
\r
1745 if (Properties.Settings.Default.useM4v)
\r
1746 DVD_Save.FileName = DVD_Save.FileName.Replace(".mp4", ".m4v").Replace(".mkv", ".m4v");
\r
1748 DVD_Save.FileName = DVD_Save.FileName.Replace(".m4v", ".mp4").Replace(".mkv", ".mp4");
\r
1752 !Path.GetExtension(DVD_Save.FileName).Equals(".mkv", StringComparison.InvariantCultureIgnoreCase))
\r
1753 DVD_Save.FileName = DVD_Save.FileName.Replace(".mp4", ".mkv").Replace(".m4v", ".mkv");
\r
1759 text_destination.Text = DVD_Save.FileName;
\r
1761 // Quicktime requires .m4v file for chapter markers to work. If checked, change the extension to .m4v (mp4 and m4v are the same thing)
\r
1762 if (Check_ChapterMarkers.Checked && DVD_Save.FilterIndex != 2)
\r
1763 SetExtension(".m4v");
\r
1767 private void text_destination_TextChanged(object sender, EventArgs e)
\r
1769 string path = text_destination.Text;
\r
1770 if (path.EndsWith(".mp4") || path.EndsWith(".m4v"))
\r
1771 drop_format.SelectedIndex = 0;
\r
1772 else if (path.EndsWith(".mkv"))
\r
1773 drop_format.SelectedIndex = 1;
\r
1776 // Output Settings
\r
1777 private void drop_format_SelectedIndexChanged(object sender, EventArgs e)
\r
1779 switch (drop_format.SelectedIndex)
\r
1782 if (Properties.Settings.Default.useM4v || Check_ChapterMarkers.Checked ||
\r
1783 AudioSettings.RequiresM4V() || Subtitles.RequiresM4V())
\r
1784 SetExtension(".m4v");
\r
1786 SetExtension(".mp4");
\r
1789 SetExtension(".mkv");
\r
1793 AudioSettings.SetContainer(drop_format.Text);
\r
1795 if (drop_format.Text.Contains("MP4"))
\r
1797 if (drp_videoEncoder.Items.Contains("VP3 (Theora)"))
\r
1799 drp_videoEncoder.Items.Remove("VP3 (Theora)");
\r
1800 drp_videoEncoder.SelectedIndex = 1;
\r
1803 else if (drop_format.Text.Contains("MKV"))
\r
1804 drp_videoEncoder.Items.Add("VP3 (Theora)");
\r
1807 public void SetExtension(string newExtension)
\r
1809 if (newExtension == ".mp4" || newExtension == ".m4v")
\r
1810 if (Properties.Settings.Default.useM4v || Check_ChapterMarkers.Checked || AudioSettings.RequiresM4V() ||
\r
1811 Subtitles.RequiresM4V())
\r
1812 newExtension = ".m4v";
\r
1814 newExtension = ".mp4";
\r
1816 if (Path.HasExtension(newExtension))
\r
1817 text_destination.Text = Path.ChangeExtension(text_destination.Text, newExtension);
\r
1821 private void drp_videoEncoder_SelectedIndexChanged(object sender, EventArgs e)
\r
1823 setContainerOpts();
\r
1825 // Turn off some options which are H.264 only when the user selects a non h.264 encoder
\r
1826 if (drp_videoEncoder.Text.Contains("H.264"))
\r
1828 if (check_2PassEncode.CheckState == CheckState.Checked)
\r
1829 check_turbo.Enabled = true;
\r
1831 tab_advanced.Enabled = true;
\r
1832 if ((drop_format.Text.Contains("MP4")) || (drop_format.Text.Contains("M4V")))
\r
1833 check_iPodAtom.Enabled = true;
\r
1835 check_iPodAtom.Enabled = false;
\r
1839 check_turbo.CheckState = CheckState.Unchecked;
\r
1840 check_turbo.Enabled = false;
\r
1841 tab_advanced.Enabled = false;
\r
1842 x264Panel.X264Query = string.Empty;
\r
1843 check_iPodAtom.Enabled = false;
\r
1844 check_iPodAtom.Checked = false;
\r
1847 // Setup the CQ Slider
\r
1848 switch (drp_videoEncoder.Text)
\r
1850 case "MPEG-4 (FFmpeg)":
\r
1851 if (slider_videoQuality.Value > 31)
\r
1852 slider_videoQuality.Value = 20; // Just reset to 70% QP 10 on encode change.
\r
1853 slider_videoQuality.Minimum = 1;
\r
1854 slider_videoQuality.Maximum = 31;
\r
1856 case "H.264 (x264)":
\r
1857 slider_videoQuality.Minimum = 0;
\r
1858 slider_videoQuality.TickFrequency = 1;
\r
1860 CultureInfo culture = CultureInfo.CreateSpecificCulture("en-US");
\r
1861 double cqStep = Properties.Settings.Default.x264cqstep;
\r
1862 double multiplier = 1.0 / cqStep;
\r
1863 double value = slider_videoQuality.Value * multiplier;
\r
1865 slider_videoQuality.Maximum = (int)(51 / Properties.Settings.Default.x264cqstep);
\r
1867 if (value < slider_videoQuality.Maximum)
\r
1868 slider_videoQuality.Value = slider_videoQuality.Maximum - (int)value;
\r
1871 case "VP3 (Theora)":
\r
1872 if (slider_videoQuality.Value > 63)
\r
1873 slider_videoQuality.Value = 45; // Just reset to 70% QP 45 on encode change.
\r
1874 slider_videoQuality.Minimum = 0;
\r
1875 slider_videoQuality.Maximum = 63;
\r
1881 /// When the FrameRate is not Same As Source, show the Max/Constant Mode dropdown
\r
1883 /// <param name="sender">
\r
1886 /// <param name="e">
\r
1889 private void drp_videoFramerate_SelectedIndexChanged(object sender, EventArgs e)
\r
1891 if (this.drp_videoFramerate.SelectedIndex == 0)
\r
1893 this.checkMaximumFramerate.Visible = false;
\r
1894 this.checkMaximumFramerate.CheckState = CheckState.Unchecked;
\r
1898 this.checkMaximumFramerate.Visible = true;
\r
1903 /// Set the container format options
\r
1905 public void setContainerOpts()
\r
1907 if ((drop_format.Text.Contains("MP4")) || (drop_format.Text.Contains("M4V")))
\r
1909 check_largeFile.Enabled = true;
\r
1910 check_optimiseMP4.Enabled = true;
\r
1911 check_iPodAtom.Enabled = true;
\r
1915 check_largeFile.Enabled = false;
\r
1916 check_optimiseMP4.Enabled = false;
\r
1917 check_iPodAtom.Enabled = false;
\r
1918 check_largeFile.Checked = false;
\r
1919 check_optimiseMP4.Checked = false;
\r
1920 check_iPodAtom.Checked = false;
\r
1924 private double cachedCqStep = Properties.Settings.Default.x264cqstep;
\r
1927 /// Update the CQ slider for x264 for a new CQ step. This is set from option
\r
1929 public void setQualityFromSlider()
\r
1931 // Work out the current RF value.
\r
1932 double cqStep = this.cachedCqStep;
\r
1933 double rfValue = 51.0 - slider_videoQuality.Value * cqStep;
\r
1935 // Change the maximum value for the slider
\r
1936 slider_videoQuality.Maximum = (int)(51 / Properties.Settings.Default.x264cqstep);
\r
1938 // Reset the CQ slider to RF0
\r
1939 slider_videoQuality.Value = slider_videoQuality.Maximum;
\r
1941 // Reset the CQ slider back to the previous value as close as possible
\r
1942 double cqStepNew = Properties.Settings.Default.x264cqstep;
\r
1943 double rfValueCurrent = 51.0 - slider_videoQuality.Value * cqStepNew;
\r
1944 while (rfValueCurrent < rfValue)
\r
1946 slider_videoQuality.Value--;
\r
1947 rfValueCurrent = 51.0 - slider_videoQuality.Value * cqStepNew;
\r
1950 // Cache the CQ step for the next calculation
\r
1951 this.cachedCqStep = Properties.Settings.Default.x264cqstep;
\r
1954 private void slider_videoQuality_Scroll(object sender, EventArgs e)
\r
1956 double cqStep = Properties.Settings.Default.x264cqstep;
\r
1957 switch (drp_videoEncoder.Text)
\r
1959 case "MPEG-4 (FFmpeg)":
\r
1960 lbl_SliderValue.Text = "QP:" + (32 - slider_videoQuality.Value);
\r
1962 case "H.264 (x264)":
\r
1963 double rfValue = 51.0 - slider_videoQuality.Value * cqStep;
\r
1964 rfValue = Math.Round(rfValue, 2);
\r
1965 lbl_SliderValue.Text = "RF:" + rfValue.ToString(new CultureInfo("en-US"));
\r
1967 case "VP3 (Theora)":
\r
1968 lbl_SliderValue.Text = "QP:" + slider_videoQuality.Value;
\r
1973 private void radio_targetFilesize_CheckedChanged(object sender, EventArgs e)
\r
1975 text_bitrate.Enabled = false;
\r
1976 text_filesize.Enabled = true;
\r
1977 slider_videoQuality.Enabled = false;
\r
1979 check_2PassEncode.Enabled = true;
\r
1982 private void radio_avgBitrate_CheckedChanged(object sender, EventArgs e)
\r
1984 text_bitrate.Enabled = true;
\r
1985 text_filesize.Enabled = false;
\r
1986 slider_videoQuality.Enabled = false;
\r
1988 check_2PassEncode.Enabled = true;
\r
1991 private void radio_cq_CheckedChanged(object sender, EventArgs e)
\r
1993 text_bitrate.Enabled = false;
\r
1994 text_filesize.Enabled = false;
\r
1995 slider_videoQuality.Enabled = true;
\r
1997 check_2PassEncode.Enabled = false;
\r
1998 check_2PassEncode.CheckState = CheckState.Unchecked;
\r
2001 private void check_2PassEncode_CheckedChanged(object sender, EventArgs e)
\r
2003 if (check_2PassEncode.CheckState.ToString() == "Checked")
\r
2005 if (drp_videoEncoder.Text.Contains("H.264"))
\r
2006 check_turbo.Enabled = true;
\r
2010 check_turbo.Enabled = false;
\r
2011 check_turbo.CheckState = CheckState.Unchecked;
\r
2015 // Chapter Marker Tab
\r
2016 private void Check_ChapterMarkers_CheckedChanged(object sender, EventArgs e)
\r
2018 if (Check_ChapterMarkers.Checked)
\r
2020 if (drop_format.SelectedIndex != 1)
\r
2021 SetExtension(".m4v");
\r
2022 data_chpt.Enabled = true;
\r
2023 btn_importChapters.Enabled = true;
\r
2027 if (drop_format.SelectedIndex != 1 && !Properties.Settings.Default.useM4v)
\r
2028 SetExtension(".mp4");
\r
2029 data_chpt.Enabled = false;
\r
2030 btn_importChapters.Enabled = false;
\r
2034 private void btn_importChapters_Click(object sender, EventArgs e)
\r
2036 if (File_ChapterImport.ShowDialog() == DialogResult.OK)
\r
2038 string filename = File_ChapterImport.FileName;
\r
2039 DataGridView imported = Main.ImportChapterNames(data_chpt, filename);
\r
2040 if (imported != null)
\r
2041 data_chpt = imported;
\r
2045 private void btn_export_Click(object sender, EventArgs e)
\r
2047 SaveFileDialog saveFileDialog = new SaveFileDialog();
\r
2048 saveFileDialog.Filter = "Csv File|*.csv";
\r
2049 saveFileDialog.DefaultExt = "csv";
\r
2050 if (saveFileDialog.ShowDialog() == DialogResult.OK)
\r
2052 string filename = saveFileDialog.FileName;
\r
2054 Main.SaveChapterMarkersToCsv(this, filename);
\r
2058 private void mnu_resetChapters_Click(object sender, EventArgs e)
\r
2060 data_chpt.Rows.Clear();
\r
2061 DataGridView chapterGridView = Main.ChapterNaming(selectedTitle, data_chpt, drop_chapterFinish.Text);
\r
2062 if (chapterGridView != null)
\r
2064 data_chpt = chapterGridView;
\r
2068 // Query Editor Tab
\r
2069 private void btn_generate_Query_Click(object sender, EventArgs e)
\r
2071 rtf_query.Text = QueryGenerator.GenerateFullQuery(this);
\r
2074 private void btn_clear_Click(object sender, EventArgs e)
\r
2076 rtf_query.Clear();
\r
2081 // MainWindow Components, Actions and Functions ***********************
\r
2083 #region Source Scan
\r
2086 /// Start the Scan Process
\r
2088 /// <param name="filename">
\r
2091 /// <param name="title">
\r
2094 private void StartScan(string filename, int title)
\r
2096 // Setup the GUI components for the scan.
\r
2097 sourcePath = filename;
\r
2099 this.DisableGUI();
\r
2104 SourceScan.Scan(sourcePath, title);
\r
2106 catch (Exception exc)
\r
2108 MessageBox.Show("frmMain.cs - StartScan " + exc, "Error", MessageBoxButtons.OK, MessageBoxIcon.Error);
\r
2113 /// Update the Status label for the scan
\r
2115 /// <param name="sender">
\r
2118 /// <param name="e">
\r
2121 private void SourceScan_ScanStatusChanged(object sender, EventArgs e)
\r
2123 UpdateScanStatusLabel();
\r
2127 /// Update the UI after the scan has completed
\r
2129 /// <param name="sender">
\r
2132 /// <param name="e">
\r
2135 private void SourceScan_ScanCompleted(object sender, EventArgs e)
\r
2137 UpdateGuiAfterScan();
\r
2141 /// Update the Scan Status Label
\r
2143 private void UpdateScanStatusLabel()
\r
2145 if (InvokeRequired)
\r
2147 BeginInvoke(new UpdateWindowHandler(UpdateScanStatusLabel));
\r
2150 labelSource.Text = SourceScan.ScanStatus;
\r
2154 /// Reset the GUI when the scan has completed
\r
2156 private void UpdateGuiAfterScan()
\r
2158 if (InvokeRequired)
\r
2160 BeginInvoke(new UpdateWindowHandler(UpdateGuiAfterScan));
\r
2166 currentSource = SourceScan.SouceData;
\r
2168 // Setup some GUI components
\r
2169 drp_dvdtitle.Items.Clear();
\r
2170 if (currentSource.Titles.Count != 0)
\r
2171 drp_dvdtitle.Items.AddRange(currentSource.Titles.ToArray());
\r
2173 foreach (Title title in currentSource.Titles)
\r
2175 if (title.MainTitle)
\r
2177 drp_dvdtitle.SelectedItem = title;
\r
2181 if (drp_dvdtitle.SelectedItem == null && drp_dvdtitle.Items.Count > 0)
\r
2183 drp_dvdtitle.SelectedIndex = 0;
\r
2186 // Enable the creation of chapter markers if the file is an image of a dvd
\r
2187 if (drop_chapterStart.Items.Count > 0)
\r
2190 int.TryParse(drop_chapterStart.Items[0].ToString(), out start);
\r
2191 int.TryParse(drop_chapterFinish.Items[drop_chapterFinish.Items.Count - 1].ToString(), out end);
\r
2192 if (end > start) Check_ChapterMarkers.Enabled = true;
\r
2195 Check_ChapterMarkers.Enabled = false;
\r
2196 Check_ChapterMarkers.Checked = false;
\r
2197 data_chpt.Rows.Clear();
\r
2201 // If no titles were found, Display an error message
\r
2202 if (drp_dvdtitle.Items.Count == 0)
\r
2205 "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
2206 "Error", MessageBoxButtons.OK, MessageBoxIcon.Hand);
\r
2207 sourcePath = string.Empty;
\r
2209 UpdateSourceLabel();
\r
2211 // Enable the GUI components and enable any disabled components
\r
2214 catch (Exception exc)
\r
2216 MessageBox.Show("frmMain.cs - updateUIafterScan " + exc, "Error", MessageBoxButtons.OK,
\r
2217 MessageBoxIcon.Error);
\r
2223 /// Enable the GUI
\r
2225 private void EnableGUI()
\r
2229 if (InvokeRequired)
\r
2230 BeginInvoke(new UpdateWindowHandler(EnableGUI));
\r
2231 foreach (Control ctrl in Controls)
\r
2232 ctrl.Enabled = true;
\r
2233 btn_start.Enabled = true;
\r
2234 btn_showQueue.Enabled = true;
\r
2235 btn_add2Queue.Enabled = true;
\r
2236 tb_preview.Enabled = true;
\r
2237 btn_source.Enabled = true;
\r
2238 mnu_killCLI.Visible = false;
\r
2240 catch (Exception exc)
\r
2242 MessageBox.Show("frmMain.cs - EnableGUI() " + exc, "Error", MessageBoxButtons.OK, MessageBoxIcon.Error);
\r
2247 /// Disable the GUI
\r
2249 private void DisableGUI()
\r
2251 foreach (Control ctrl in Controls)
\r
2252 if (!(ctrl is StatusStrip || ctrl is MenuStrip || ctrl is ToolStrip))
\r
2253 ctrl.Enabled = false;
\r
2255 labelSource.Enabled = true;
\r
2256 labelStaticSource.Enabled = true;
\r
2257 SourceLayoutPanel.Enabled = true;
\r
2258 btn_source.Enabled = false;
\r
2259 btn_start.Enabled = false;
\r
2260 btn_showQueue.Enabled = false;
\r
2261 btn_add2Queue.Enabled = false;
\r
2262 tb_preview.Enabled = false;
\r
2263 mnu_killCLI.Visible = true;
\r
2269 private void KillScan()
\r
2271 SourceScan.ScanCompleted -= new EventHandler(SourceScan_ScanCompleted);
\r
2275 SourceScan.Stop();
\r
2277 labelSource.Text = "Scan Cancelled";
\r
2283 private void ResetGUI()
\r
2285 drp_dvdtitle.Items.Clear();
\r
2286 drop_chapterStart.Items.Clear();
\r
2287 drop_chapterFinish.Items.Clear();
\r
2288 lbl_duration.Text = "Select a Title";
\r
2289 PictureSettings.lbl_src_res.Text = "Select a Title";
\r
2290 sourcePath = String.Empty;
\r
2291 text_destination.Text = String.Empty;
\r
2292 selectedTitle = null;
\r
2296 /// Update the Source Label
\r
2298 private void UpdateSourceLabel()
\r
2300 labelSource.Text = string.IsNullOrEmpty(sourcePath) ? "Select \"Source\" to continue." : this.SourceName;
\r
2304 /// Take a job from the Queue, rescan it, and reload the GUI for that job.
\r
2306 /// <param name="job">
\r
2309 public void RecievingJob(Job job)
\r
2311 string query = job.Query;
\r
2312 StartScan(job.Source, job.Title);
\r
2314 if (query != null)
\r
2316 // Ok, Reset all the H264 widgets before changing the preset
\r
2317 x264Panel.Reset2Defaults();
\r
2319 // Send the query from the file to the Query Parser class
\r
2320 QueryParser presetQuery = QueryParser.Parse(query);
\r
2322 // Now load the preset
\r
2323 PresetLoader.LoadPreset(this, presetQuery, "Load Back From Queue");
\r
2325 // The x264 widgets will need updated, so do this now:
\r
2326 x264Panel.StandardizeOptString();
\r
2327 x264Panel.SetCurrentSettingsInPanel();
\r
2329 // Finally, let this window have a copy of the preset settings.
\r
2330 this.currentlySelectedPreset = null;
\r
2331 PictureSettings.SetPresetCropWarningLabel(null);
\r
2337 #region GUI Functions and Actions
\r
2340 /// Set the GUI to it's finished encoding state.
\r
2342 private void SetEncodeFinished()
\r
2346 if (InvokeRequired)
\r
2348 BeginInvoke(new UpdateWindowHandler(SetEncodeFinished));
\r
2352 lbl_encode.Text = "Encoding Finished";
\r
2353 ProgressBarStatus.Visible = false;
\r
2354 btn_start.Text = "Start";
\r
2355 btn_start.ToolTipText = "Start the encoding process";
\r
2356 btn_start.Image = Properties.Resources.Play;
\r
2358 // If the window is minimized, display the notification in a popup.
\r
2359 if (Properties.Settings.Default.trayIconAlerts)
\r
2360 if (FormWindowState.Minimized == this.WindowState)
\r
2362 notifyIcon.BalloonTipText = lbl_encode.Text;
\r
2363 notifyIcon.ShowBalloonTip(500);
\r
2366 catch (Exception exc)
\r
2368 MessageBox.Show(exc.ToString());
\r
2373 /// Set the GUI to it's started encoding state.
\r
2375 private void SetEncodeStarted()
\r
2379 if (InvokeRequired)
\r
2381 BeginInvoke(new UpdateWindowHandler(SetEncodeStarted));
\r
2384 lbl_encode.Visible = true;
\r
2385 ProgressBarStatus.Value = 0;
\r
2386 ProgressBarStatus.Visible = true;
\r
2387 lbl_encode.Text = "Encoding with " + encodeQueue.Count + " encode(s) pending";
\r
2388 btn_start.Text = "Stop";
\r
2389 btn_start.ToolTipText = "Stop the encoding process.";
\r
2390 btn_start.Image = Properties.Resources.stop;
\r
2392 catch (Exception exc)
\r
2394 MessageBox.Show(exc.ToString());
\r
2399 /// Display the Encode Status
\r
2401 /// <param name="sender">
\r
2404 /// <param name="e">
\r
2407 private void EncodeQueue_EncodeStatusChanged(object sender, HandBrake.ApplicationServices.EncodeProgressEventArgs e)
\r
2409 if (this.InvokeRequired)
\r
2411 this.BeginInvoke(new Encode.EncodeProgessStatus(EncodeQueue_EncodeStatusChanged), new[] { sender, e });
\r
2417 "{0:00.00}%, FPS: {1:000.0}, Avg FPS: {2:000.0}, Time Remaining: {3}, Encode(s) Pending {4}",
\r
2418 e.PercentComplete,
\r
2419 e.CurrentFrameRate,
\r
2420 e.AverageFrameRate,
\r
2421 e.EstimatedTimeLeft,
\r
2422 encodeQueue.Count);
\r
2424 ProgressBarStatus.Value = (int)Math.Round(e.PercentComplete);
\r
2428 /// Set the DVD Drive selection in the "Source" Menu
\r
2430 private void SetDriveSelectionMenuItem()
\r
2434 if (InvokeRequired)
\r
2436 BeginInvoke(new UpdateWindowHandler(SetDriveSelectionMenuItem));
\r
2440 drives = Main.GetDrives();
\r
2442 List<ToolStripMenuItem> menuItems = new List<ToolStripMenuItem>();
\r
2443 foreach (DriveInformation drive in drives)
\r
2445 ToolStripMenuItem menuItem = new ToolStripMenuItem
\r
2447 Name = drive.ToString(),
\r
2448 Text = drive.RootDirectory + " (" + drive.VolumeLabel + ")",
\r
2449 Image = Resources.disc_small
\r
2451 menuItem.Click += new EventHandler(MnuDvdDriveClick);
\r
2452 menuItems.Add(menuItem);
\r
2455 foreach (ToolStripMenuItem item in menuItems)
\r
2456 btn_source.DropDownItems.Add(item);
\r
2458 catch (Exception exc)
\r
2460 MessageBox.Show("Error in SetDriveSelectionMenuItem" + exc);
\r
2465 /// Access the preset Handler and setup the preset panel.
\r
2467 private void LoadPresetPanel()
\r
2469 if (presetHandler.CheckIfPresetsAreOutOfDate())
\r
2470 if (!Settings.Default.presetNotification)
\r
2471 MessageBox.Show(this,
\r
2472 "HandBrake has determined your built-in presets are out of date... These presets will now be updated.",
\r
2473 "Preset Update", MessageBoxButtons.OK, MessageBoxIcon.Information);
\r
2475 presetHandler.GetPresetPanel(ref treeView_presets);
\r
2476 treeView_presets.Update();
\r
2480 /// Get the title from the selected item in the title dropdown.
\r
2485 private int GetTitle()
\r
2488 if (drp_dvdtitle.SelectedItem != null)
\r
2490 string[] titleInfo = drp_dvdtitle.SelectedItem.ToString().Split(' ');
\r
2491 int.TryParse(titleInfo[0], out title);
\r
2498 /// Handle the Update Check Finishing.
\r
2500 /// <param name="result">
\r
2503 private void UpdateCheckDoneMenu(IAsyncResult result)
\r
2505 // Make sure it's running on the calling thread
\r
2506 if (InvokeRequired)
\r
2508 Invoke(new MethodInvoker(() => this.UpdateCheckDoneMenu(result)));
\r
2511 UpdateCheckInformation info;
\r
2514 // Get the information about the new build, if any, and close the window
\r
2515 info = UpdateService.EndCheckForUpdates(result);
\r
2517 if (info.NewVersionAvailable && info.BuildInformation != null)
\r
2519 UpdateInfo updateWindow = new UpdateInfo(info.BuildInformation, Settings.Default.hb_version, Settings.Default.hb_build.ToString());
\r
2520 updateWindow.ShowDialog();
\r
2523 MessageBox.Show("There are no new updates at this time.", "Update Check", MessageBoxButtons.OK,
\r
2524 MessageBoxIcon.Information);
\r
2525 lbl_updateCheck.Visible = false;
\r
2528 catch (Exception ex)
\r
2530 if ((bool)result.AsyncState)
\r
2532 "Unable to check for updates, Please try again later.\n\nDetailed Error Information:\n" + ex,
\r
2533 "Error", MessageBoxButtons.OK, MessageBoxIcon.Error);
\r
2542 /// Handle GUI shortcuts
\r
2544 /// <param name="msg">Message</param>
\r
2545 /// <param name="keyData">Keys</param>
\r
2546 /// <returns>Bool</returns>
\r
2547 protected override bool ProcessCmdKey(ref Message msg, Keys keyData)
\r
2549 if (keyData == (Keys.Control | Keys.S))
\r
2551 btn_start_Click(this, new EventArgs());
\r
2555 if (keyData == (Keys.Control | Keys.Shift | Keys.A))
\r
2557 btn_add2Queue_Click(this, new EventArgs());
\r
2560 return base.ProcessCmdKey(ref msg, keyData);
\r
2564 /// If the queue is being processed, prompt the user to confirm application close.
\r
2566 /// <param name="e">FormClosingEventArgs</param>
\r
2567 protected override void OnFormClosing(FormClosingEventArgs e)
\r
2571 // If currently encoding, the queue isn't paused, and there are queue items to process, prompt to confirm close.
\r
2572 if (encodeQueue.IsEncoding)
\r
2574 DialogResult result =
\r
2576 "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
2577 "Close HandBrake?",
\r
2578 MessageBoxButtons.YesNo,
\r
2579 MessageBoxIcon.Question);
\r
2581 if (result == DialogResult.No)
\r
2587 encodeQueue.Stop();
\r
2590 if (SourceScan.IsScanning)
\r
2592 SourceScan.ScanCompleted -= new EventHandler(SourceScan_ScanCompleted);
\r
2593 SourceScan.Stop();
\r
2596 catch (Exception exc)
\r
2598 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
2602 base.OnFormClosing(e);
\r
2608 // This is the END of the road ****************************************
\r