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.ApplicationServices.EventArgs;
\r
20 using HandBrake.Framework.Model;
\r
21 using HandBrake.Framework.Services;
\r
22 using HandBrake.Framework.Views;
\r
23 using HandBrake.ApplicationServices.Functions;
\r
24 using HandBrake.ApplicationServices.Model;
\r
25 using HandBrake.ApplicationServices.Parsing;
\r
26 using HandBrake.ApplicationServices.Services;
\r
27 using HandBrake.ApplicationServices.Services.Interfaces;
\r
29 using Handbrake.ToolWindows;
\r
35 using Main = Handbrake.Functions.Main;
\r
40 public partial class frmMain : Form
\r
42 // Objects which may be used by one or more other objects *************
\r
43 private IQueue encodeQueue = new Queue();
\r
44 private PresetsHandler presetHandler = new PresetsHandler();
\r
46 // Windows ************************************************************
\r
47 private frmQueue queueWindow;
\r
48 private frmPreview qtpreview;
\r
49 private frmActivityWindow activityWindow;
\r
51 // Globals: Mainly used for tracking. *********************************
\r
52 public Title selectedTitle;
\r
53 public string sourcePath;
\r
54 private SourceType selectedSourceType;
\r
55 private string dvdDrivePath;
\r
56 private string dvdDriveLabel;
\r
57 private Preset currentlySelectedPreset;
\r
58 private DVD currentSource;
\r
59 private IScan SourceScan = new ScanService();
\r
60 private List<DriveInformation> drives;
\r
61 private QueueTask queueEdit;
\r
63 // Delegates **********************************************************
\r
64 private delegate void UpdateWindowHandler();
\r
66 // Applicaiton Startup ************************************************
\r
71 /// Gets SourceName.
\r
73 public string SourceName
\r
77 if (this.selectedSourceType == SourceType.DvdDrive)
\r
79 return this.dvdDriveLabel;
\r
82 if (selectedTitle != null && !string.IsNullOrEmpty(selectedTitle.SourceName))
\r
84 return Path.GetFileName(selectedTitle.SourceName);
\r
87 // We have a drive, selected as a folder.
\r
88 if (this.sourcePath.EndsWith("\\"))
\r
90 drives = Main.GetDrives();
\r
91 foreach (DriveInformation item in drives)
\r
93 if (item.RootDirectory.Contains(this.sourcePath))
\r
95 return item.VolumeLabel;
\r
100 if (Path.GetFileNameWithoutExtension(this.sourcePath) != "VIDEO_TS")
\r
101 return Path.GetFileNameWithoutExtension(this.sourcePath);
\r
103 return Path.GetFileNameWithoutExtension(Path.GetDirectoryName(this.sourcePath));
\r
109 #region Application Startup
\r
112 /// Initializes a new instance of the <see cref="frmMain"/> class.
\r
114 /// <param name="args">
\r
115 /// The arguments passed in on application startup.
\r
117 public frmMain(string[] args)
\r
119 InitializeComponent();
\r
121 // Update the users config file with the CLI version data.
\r
122 Main.SetCliVersionData();
\r
124 if (Settings.Default.hb_version.Contains("svn"))
\r
126 this.Text += " " + Settings.Default.hb_version;
\r
129 // Check for new versions, if update checking is enabled
\r
130 if (Settings.Default.updateStatus)
\r
132 if (DateTime.Now.Subtract(Settings.Default.lastUpdateCheckDate).TotalDays > Properties.Settings.Default.daysBetweenUpdateCheck)
\r
134 // Set when the last update was
\r
135 Settings.Default.lastUpdateCheckDate = DateTime.Now;
\r
136 Settings.Default.Save();
\r
137 string url = Settings.Default.hb_build.ToString().EndsWith("1")
\r
138 ? Settings.Default.appcast_unstable
\r
139 : Settings.Default.appcast;
\r
140 UpdateService.BeginCheckForUpdates(new AsyncCallback(UpdateCheckDone), false, url, Settings.Default.hb_build, Settings.Default.skipversion, Settings.Default.hb_version);
\r
144 // Clear the log files in the background
\r
145 if (Settings.Default.clearOldLogs)
\r
147 Thread clearLog = new Thread(Main.ClearOldLogs);
\r
151 // Setup the GUI components
\r
152 LoadPresetPanel(); // Load the Preset Panel
\r
153 treeView_presets.ExpandAll();
\r
154 lbl_encode.Text = string.Empty;
\r
155 drop_mode.SelectedIndex = 0;
\r
156 queueWindow = new frmQueue(encodeQueue, this); // Prepare the Queue
\r
157 if (!Settings.Default.QueryEditorTab)
\r
158 tabs_panel.TabPages.RemoveAt(7); // Remove the query editor tab if the user does not want it enabled.
\r
159 if (Settings.Default.tooltipEnable)
\r
160 ToolTip.Active = true;
\r
162 // Load the user's default settings or Normal Preset
\r
163 if (Settings.Default.defaultPreset != string.Empty && presetHandler.GetPreset(Properties.Settings.Default.defaultPreset) != null)
\r
165 string query = presetHandler.GetPreset(Settings.Default.defaultPreset).Query;
\r
168 x264Panel.Reset2Defaults();
\r
170 QueryParser presetQuery = QueryParser.Parse(query);
\r
171 PresetLoader.LoadPreset(this, presetQuery, Settings.Default.defaultPreset);
\r
173 x264Panel.StandardizeOptString();
\r
174 x264Panel.SetCurrentSettingsInPanel();
\r
178 loadNormalPreset();
\r
180 // Register with Growl (if not using Growl for the encoding completion action, this wont hurt anything)
\r
181 GrowlCommunicator.Register();
\r
183 // Event Handlers and Queue Recovery
\r
185 Main.RecoverQueue(encodeQueue);
\r
187 // If have a file passed in via command arguemtents, check it's a file and try scanning it.
\r
188 if (args.Length >= 1 && (File.Exists(args[0]) || Directory.Exists(args[0])))
\r
190 this.StartScan(args[0], 0);
\r
195 /// When the update check is done, process the results.
\r
197 /// <param name="result">IAsyncResult result</param>
\r
198 private void UpdateCheckDone(IAsyncResult result)
\r
200 if (InvokeRequired)
\r
202 Invoke(new MethodInvoker(() => UpdateCheckDone(result)));
\r
208 UpdateCheckInformation info = UpdateService.EndCheckForUpdates(result);
\r
210 if (info.NewVersionAvailable)
\r
212 UpdateInfo updateWindow = new UpdateInfo(info.BuildInformation, Settings.Default.hb_version, Settings.Default.hb_build.ToString());
\r
213 updateWindow.ShowDialog();
\r
216 catch (Exception ex)
\r
218 if ((bool)result.AsyncState)
\r
219 Main.ShowExceptiowWindow("Unable to check for updates, Please try again later.", ex.ToString());
\r
227 // Encoding Events for setting up the GUI
\r
228 private void events()
\r
230 // Handle Widget changes when preset is selected.
\r
231 RegisterPresetEventHandler();
\r
233 // Handle Window Resize
\r
234 if (Properties.Settings.Default.MainWindowMinimize)
\r
235 this.Resize += new EventHandler(frmMain_Resize);
\r
237 // Handle Encode Start / Finish / Pause
\r
238 encodeQueue.EncodeStarted += new EventHandler(encodeStarted);
\r
239 encodeQueue.EncodeEnded += new EventHandler(encodeEnded);
\r
241 // Scan Started and Completed Events
\r
242 SourceScan.ScanStatusChanged += this.SourceScanScanStatusChanged;
\r
243 SourceScan.ScanCompleted += this.SourceScanScanCompleted;
\r
245 // Handle a file being draged onto the GUI.
\r
246 this.DragEnter += new DragEventHandler(frmMain_DragEnter);
\r
247 this.DragDrop += new DragEventHandler(frmMain_DragDrop);
\r
250 // 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
251 private void RegisterPresetEventHandler()
\r
254 drop_format.SelectedIndexChanged += new EventHandler(changePresetLabel);
\r
255 check_largeFile.CheckedChanged += new EventHandler(changePresetLabel);
\r
256 check_iPodAtom.CheckedChanged += new EventHandler(changePresetLabel);
\r
257 check_optimiseMP4.CheckedChanged += new EventHandler(changePresetLabel);
\r
259 // Picture Settings
\r
260 PictureSettings.PictureSettingsChanged += new EventHandler(changePresetLabel);
\r
263 Filters.FilterSettingsChanged += new EventHandler(changePresetLabel);
\r
266 drp_videoEncoder.SelectedIndexChanged += new EventHandler(changePresetLabel);
\r
267 check_2PassEncode.CheckedChanged += new EventHandler(changePresetLabel);
\r
268 check_turbo.CheckedChanged += new EventHandler(changePresetLabel);
\r
269 text_filesize.TextChanged += new EventHandler(changePresetLabel);
\r
270 text_bitrate.TextChanged += new EventHandler(changePresetLabel);
\r
271 slider_videoQuality.ValueChanged += new EventHandler(changePresetLabel);
\r
274 AudioSettings.AudioListChanged += new EventHandler(changePresetLabel);
\r
277 x264Panel.rtf_x264Query.TextChanged += new EventHandler(changePresetLabel);
\r
280 private void UnRegisterPresetEventHandler()
\r
282 // Output Settings
\r
283 drop_format.SelectedIndexChanged -= new EventHandler(changePresetLabel);
\r
284 check_largeFile.CheckedChanged -= new EventHandler(changePresetLabel);
\r
285 check_iPodAtom.CheckedChanged -= new EventHandler(changePresetLabel);
\r
286 check_optimiseMP4.CheckedChanged -= new EventHandler(changePresetLabel);
\r
288 // Picture Settings
\r
289 PictureSettings.PictureSettingsChanged -= new EventHandler(changePresetLabel);
\r
292 Filters.FilterSettingsChanged -= new EventHandler(changePresetLabel);
\r
295 drp_videoEncoder.SelectedIndexChanged -= new EventHandler(changePresetLabel);
\r
296 check_2PassEncode.CheckedChanged -= new EventHandler(changePresetLabel);
\r
297 check_turbo.CheckedChanged -= new EventHandler(changePresetLabel);
\r
298 text_filesize.TextChanged -= new EventHandler(changePresetLabel);
\r
299 text_bitrate.TextChanged -= new EventHandler(changePresetLabel);
\r
300 slider_videoQuality.ValueChanged -= new EventHandler(changePresetLabel);
\r
303 AudioSettings.AudioListChanged -= new EventHandler(changePresetLabel);
\r
306 x264Panel.rtf_x264Query.TextChanged -= new EventHandler(changePresetLabel);
\r
309 private void changePresetLabel(object sender, EventArgs e)
\r
311 labelPreset.Text = "Output Settings (Preset: Custom)";
\r
312 this.currentlySelectedPreset = null;
\r
315 private static void frmMain_DragEnter(object sender, DragEventArgs e)
\r
317 if (e.Data.GetDataPresent(DataFormats.FileDrop, false))
\r
318 e.Effect = DragDropEffects.All;
\r
321 private void frmMain_DragDrop(object sender, DragEventArgs e)
\r
323 string[] fileList = e.Data.GetData(DataFormats.FileDrop) as string[];
\r
324 sourcePath = string.Empty;
\r
326 if (fileList != null)
\r
328 if (!string.IsNullOrEmpty(fileList[0]))
\r
330 this.selectedSourceType = SourceType.VideoFile;
\r
331 StartScan(fileList[0], 0);
\r
334 UpdateSourceLabel();
\r
337 UpdateSourceLabel();
\r
340 private void encodeStarted(object sender, EventArgs e)
\r
342 SetEncodeStarted();
\r
343 encodeQueue.EncodeStatusChanged += EncodeQueue_EncodeStatusChanged;
\r
346 private void encodeEnded(object sender, EventArgs e)
\r
348 encodeQueue.EncodeStatusChanged -= EncodeQueue_EncodeStatusChanged;
\r
349 SetEncodeFinished();
\r
353 // User Interface Menus / Tool Strips *********************************
\r
358 /// Kill The scan menu Item
\r
360 /// <param name="sender">
\r
363 /// <param name="e">
\r
366 private void mnu_killCLI_Click(object sender, EventArgs e)
\r
372 /// Exit the Application Menu Item
\r
374 /// <param name="sender">
\r
377 /// <param name="e">
\r
380 private void mnu_exit_Click(object sender, EventArgs e)
\r
382 Application.Exit();
\r
390 /// Menu - Start Button
\r
392 /// <param name="sender">
\r
395 /// <param name="e">
\r
398 private void mnu_encode_Click(object sender, EventArgs e)
\r
400 queueWindow.Show();
\r
404 /// Menu - Display the Log Window
\r
406 /// <param name="sender">
\r
409 /// <param name="e">
\r
412 private void mnu_encodeLog_Click(object sender, EventArgs e)
\r
414 this.btn_ActivityWindow_Click(this, null);
\r
418 /// Menu - Display the Options Window
\r
420 /// <param name="sender">
\r
423 /// <param name="e">
\r
426 private void mnu_options_Click(object sender, EventArgs e)
\r
428 Form options = new frmOptions(this);
\r
429 options.ShowDialog();
\r
434 #region Presets Menu
\r
437 /// Reset the Built in Presets
\r
439 /// <param name="sender">
\r
442 /// <param name="e">
\r
445 private void mnu_presetReset_Click(object sender, EventArgs e)
\r
447 presetHandler.UpdateBuiltInPresets();
\r
449 if (treeView_presets.Nodes.Count == 0)
\r
451 "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
452 "Error", MessageBoxButtons.OK, MessageBoxIcon.Error);
\r
454 MessageBox.Show("Presets have been updated!", "Alert", MessageBoxButtons.OK, MessageBoxIcon.Information);
\r
456 treeView_presets.ExpandAll();
\r
460 /// Delete the selected preset
\r
462 /// <param name="sender">
\r
465 /// <param name="e">
\r
468 private void mnu_delete_preset_Click(object sender, EventArgs e)
\r
470 presetHandler.RemoveBuiltInPresets();
\r
471 LoadPresetPanel(); // Reload the preset panel
\r
475 /// Select the Normal preset
\r
477 /// <param name="sender">
\r
480 /// <param name="e">
\r
483 private void mnu_SelectDefault_Click(object sender, EventArgs e)
\r
485 loadNormalPreset();
\r
489 /// Import a plist Preset
\r
491 /// <param name="sender">
\r
494 /// <param name="e">
\r
497 private void mnu_importMacPreset_Click(object sender, EventArgs e)
\r
503 /// Export a Plist Preset
\r
505 /// <param name="sender">
\r
508 /// <param name="e">
\r
511 private void mnu_exportMacPreset_Click(object sender, EventArgs e)
\r
517 /// Create a new Preset
\r
519 /// <param name="sender">
\r
522 /// <param name="e">
\r
525 private void btn_new_preset_Click(object sender, EventArgs e)
\r
527 Form preset = new frmAddPreset(this, presetHandler);
\r
528 if (preset.ShowDialog() == DialogResult.OK)
\r
530 TreeNode presetTreeview = new TreeNode(presetHandler.LastPresetAdded.Name) { ForeColor = Color.Black };
\r
531 treeView_presets.Nodes.Add(presetTreeview);
\r
532 presetHandler.LastPresetAdded = null;
\r
541 /// Menu - Display the User Guide Web Page
\r
543 /// <param name="sender">
\r
546 /// <param name="e">
\r
549 private void mnu_user_guide_Click(object sender, EventArgs e)
\r
551 Process.Start("http://trac.handbrake.fr/wiki/HandBrakeGuide");
\r
555 /// Menu - Check for Updates
\r
557 /// <param name="sender">
\r
560 /// <param name="e">
\r
563 private void mnu_UpdateCheck_Click(object sender, EventArgs e)
\r
565 lbl_updateCheck.Visible = true;
\r
566 Settings.Default.lastUpdateCheckDate = DateTime.Now;
\r
567 Settings.Default.Save();
\r
568 string url = Settings.Default.hb_build.ToString().EndsWith("1")
\r
569 ? Settings.Default.appcast_unstable
\r
570 : Settings.Default.appcast;
\r
571 UpdateService.BeginCheckForUpdates(new AsyncCallback(UpdateCheckDoneMenu), false, url, Settings.Default.hb_build, Settings.Default.skipversion, Settings.Default.hb_version);
\r
575 /// Menu - Display the About Window
\r
577 /// <param name="sender">
\r
580 /// <param name="e">
\r
583 private void mnu_about_Click(object sender, EventArgs e)
\r
585 using (frmAbout About = new frmAbout())
\r
587 About.ShowDialog();
\r
596 /// RMenu - Expand All
\r
598 /// <param name="sender">
\r
601 /// <param name="e">
\r
604 private void pmnu_expandAll_Click(object sender, EventArgs e)
\r
606 treeView_presets.ExpandAll();
\r
610 /// RMenu - Collaspe All
\r
612 /// <param name="sender">
\r
615 /// <param name="e">
\r
618 private void pmnu_collapse_Click(object sender, EventArgs e)
\r
620 treeView_presets.CollapseAll();
\r
624 /// Menu - Import Preset
\r
626 /// <param name="sender">
\r
629 /// <param name="e">
\r
632 private void pmnu_import_Click(object sender, EventArgs e)
\r
638 /// RMenu - Save Changes to Preset
\r
640 /// <param name="sender">
\r
643 /// <param name="e">
\r
646 private void pmnu_saveChanges_Click(object sender, EventArgs e)
\r
648 // TODO this requires a re-think since the Query Editor has changed.
\r
649 DialogResult result =
\r
651 "Do you wish to include picture settings when updating the preset: " +
\r
652 treeView_presets.SelectedNode.Text, "Update Preset", MessageBoxButtons.YesNoCancel,
\r
653 MessageBoxIcon.Question);
\r
654 if (result == DialogResult.Yes)
\r
655 presetHandler.Update(treeView_presets.SelectedNode.Text,
\r
656 QueryGenerator.GenerateQueryForPreset(this, QueryPictureSettingsMode.SourceMaximum, true, 0, 0), true);
\r
657 else if (result == DialogResult.No)
\r
658 presetHandler.Update(treeView_presets.SelectedNode.Text,
\r
659 QueryGenerator.GenerateQueryForPreset(this, QueryPictureSettingsMode.SourceMaximum, true, 0, 0), false);
\r
663 /// RMenu - Delete Preset
\r
665 /// <param name="sender">
\r
668 /// <param name="e">
\r
671 private void pmnu_delete_click(object sender, EventArgs e)
\r
673 if (treeView_presets.SelectedNode != null)
\r
675 presetHandler.Remove(treeView_presets.SelectedNode.Text);
\r
676 treeView_presets.Nodes.Remove(treeView_presets.SelectedNode);
\r
678 treeView_presets.Select();
\r
682 /// Preset Menu Is Opening. Setup the Menu
\r
684 /// <param name="sender">
\r
687 /// <param name="e">
\r
690 private void presets_menu_Opening(object sender, CancelEventArgs e)
\r
692 // Make sure that the save menu is always disabled by default
\r
693 pmnu_saveChanges.Enabled = false;
\r
695 // Now enable the save menu if the selected preset is a user preset
\r
696 if (treeView_presets.SelectedNode != null)
\r
697 if (presetHandler.CheckIfUserPresetExists(treeView_presets.SelectedNode.Text))
\r
698 pmnu_saveChanges.Enabled = true;
\r
700 treeView_presets.Select();
\r
703 // Presets Management
\r
706 /// Button - Add a preset
\r
708 /// <param name="sender">
\r
711 /// <param name="e">
\r
714 private void btn_addPreset_Click(object sender, EventArgs e)
\r
716 Form preset = new frmAddPreset(this, presetHandler);
\r
717 if (preset.ShowDialog() == DialogResult.OK)
\r
719 TreeNode presetTreeview = new TreeNode(presetHandler.LastPresetAdded.Name) { ForeColor = Color.Black };
\r
720 treeView_presets.Nodes.Add(presetTreeview);
\r
721 presetHandler.LastPresetAdded = null;
\r
726 /// Button - remove a Preset
\r
728 /// <param name="sender">
\r
731 /// <param name="e">
\r
734 private void btn_removePreset_Click(object sender, EventArgs e)
\r
736 DialogResult result = MessageBox.Show("Are you sure you wish to delete the selected preset?", "Preset",
\r
737 MessageBoxButtons.YesNo, MessageBoxIcon.Question);
\r
738 if (result == DialogResult.Yes)
\r
740 if (treeView_presets.SelectedNode != null)
\r
742 presetHandler.Remove(treeView_presets.SelectedNode.Text);
\r
743 treeView_presets.Nodes.Remove(treeView_presets.SelectedNode);
\r
746 treeView_presets.Select();
\r
750 /// Button - Set the selected preset as the default
\r
752 /// <param name="sender">
\r
755 /// <param name="e">
\r
758 private void btn_setDefault_Click(object sender, EventArgs e)
\r
760 if (treeView_presets.SelectedNode != null)
\r
762 DialogResult result = MessageBox.Show("Are you sure you wish to set this preset as the default?",
\r
763 "Preset", MessageBoxButtons.YesNo, MessageBoxIcon.Question);
\r
764 if (result == DialogResult.Yes)
\r
766 Properties.Settings.Default.defaultPreset = treeView_presets.SelectedNode.Text;
\r
767 Properties.Settings.Default.Save();
\r
768 MessageBox.Show("New default preset set.", "Alert", MessageBoxButtons.OK, MessageBoxIcon.Information);
\r
772 MessageBox.Show("Please select a preset first.", "Warning", MessageBoxButtons.OK, MessageBoxIcon.Warning);
\r
776 /// PresetBar Mouse Down event
\r
778 /// <param name="sender">
\r
781 /// <param name="e">
\r
784 private void treeview_presets_mouseUp(object sender, MouseEventArgs e)
\r
786 if (e.Button == MouseButtons.Right)
\r
787 treeView_presets.SelectedNode = treeView_presets.GetNodeAt(e.Location);
\r
788 else if (e.Button == MouseButtons.Left)
\r
790 if (treeView_presets.GetNodeAt(e.Location) != null)
\r
792 if (labelPreset.Text.Contains(treeView_presets.GetNodeAt(e.Location).Text))
\r
797 treeView_presets.Select();
\r
801 /// Preset Bar after selecting the preset
\r
803 /// <param name="sender">
\r
806 /// <param name="e">
\r
809 private void treeView_presets_AfterSelect(object sender, TreeViewEventArgs e)
\r
815 /// When the mouse moves, display a preset
\r
817 /// <param name="sender">The Sender</param>
\r
818 /// <param name="e">the MouseEventArgs</param>
\r
819 private void TreeViewPresetsMouseMove(object sender, MouseEventArgs e)
\r
821 TreeNode theNode = this.treeView_presets.GetNodeAt(e.X, e.Y);
\r
823 if ((theNode != null))
\r
825 // Change the ToolTip only if the pointer moved to a new node.
\r
826 if (theNode.ToolTipText != this.ToolTip.GetToolTip(this.treeView_presets))
\r
828 this.ToolTip.SetToolTip(this.treeView_presets, theNode.ToolTipText);
\r
831 else // Pointer is not over a node so clear the ToolTip.
\r
833 this.ToolTip.SetToolTip(this.treeView_presets, string.Empty);
\r
838 /// Preset Bar - Handle the Delete Key
\r
840 /// <param name="sender">
\r
843 /// <param name="e">
\r
846 private void treeView_presets_deleteKey(object sender, KeyEventArgs e)
\r
848 if (e.KeyCode == Keys.Delete)
\r
850 DialogResult result = MessageBox.Show("Are you sure you wish to delete the selected preset?", "Preset",
\r
851 MessageBoxButtons.YesNo, MessageBoxIcon.Question);
\r
852 if (result == DialogResult.Yes)
\r
854 if (treeView_presets.SelectedNode != null)
\r
855 presetHandler.Remove(treeView_presets.SelectedNode.Text);
\r
857 // Remember each nodes expanded status so we can reload it
\r
858 List<bool> nodeStatus = new List<bool>();
\r
859 foreach (TreeNode node in treeView_presets.Nodes)
\r
860 nodeStatus.Add(node.IsExpanded);
\r
862 // Now reload the preset panel
\r
865 // And finally, re-expand any of the nodes if required
\r
867 foreach (TreeNode node in treeView_presets.Nodes)
\r
879 /// Select the selected preset and setup the GUI
\r
881 private void selectPreset()
\r
883 if (treeView_presets.SelectedNode != null)
\r
885 // Ok, so, we've selected a preset. Now we want to load it.
\r
886 string presetName = treeView_presets.SelectedNode.Text;
\r
887 Preset preset = presetHandler.GetPreset(presetName);
\r
888 if (preset != null)
\r
890 string query = presetHandler.GetPreset(presetName).Query;
\r
894 // Ok, Reset all the H264 widgets before changing the preset
\r
895 x264Panel.Reset2Defaults();
\r
897 // Send the query from the file to the Query Parser class
\r
898 QueryParser presetQuery = QueryParser.Parse(query);
\r
900 // Now load the preset
\r
901 PresetLoader.LoadPreset(this, presetQuery, presetName);
\r
903 // The x264 widgets will need updated, so do this now:
\r
904 x264Panel.StandardizeOptString();
\r
905 x264Panel.SetCurrentSettingsInPanel();
\r
907 // Finally, let this window have a copy of the preset settings.
\r
908 this.currentlySelectedPreset = preset;
\r
909 PictureSettings.SetPresetCropWarningLabel(preset);
\r
916 /// Load the Normal Preset
\r
918 private void loadNormalPreset()
\r
920 foreach (TreeNode treenode in treeView_presets.Nodes)
\r
922 foreach (TreeNode node in treenode.Nodes)
\r
924 if (node.Text.Equals("Normal"))
\r
925 treeView_presets.SelectedNode = treeView_presets.Nodes[treenode.Index].Nodes[0];
\r
931 /// Import a plist preset
\r
933 private void ImportPreset()
\r
935 if (openPreset.ShowDialog() == DialogResult.OK)
\r
937 QueryParser parsed = PlistPresetHandler.Import(openPreset.FileName);
\r
938 if (presetHandler.CheckIfUserPresetExists(parsed.PresetName + " (Imported)"))
\r
940 DialogResult result =
\r
941 MessageBox.Show("This preset appears to already exist. Would you like to overwrite it?",
\r
942 "Overwrite preset?",
\r
943 MessageBoxButtons.YesNo, MessageBoxIcon.Warning);
\r
944 if (result == DialogResult.Yes)
\r
946 PresetLoader.LoadPreset(this, parsed, parsed.PresetName);
\r
947 presetHandler.Update(parsed.PresetName + " (Imported)",
\r
948 QueryGenerator.GenerateFullQuery(this),
\r
949 parsed.UsesPictureSettings);
\r
954 PresetLoader.LoadPreset(this, parsed, parsed.PresetName);
\r
955 if (presetHandler.Add(parsed.PresetName + " (Imported)",
\r
956 QueryGenerator.GenerateFullQuery(this),
\r
957 parsed.UsesPictureSettings, string.Empty))
\r
959 TreeNode preset_treeview = new TreeNode(parsed.PresetName + " (Imported)")
\r
961 ForeColor = Color.Black
\r
963 treeView_presets.Nodes.Add(preset_treeview);
\r
970 /// Export a plist Preset
\r
972 private void ExportPreset()
\r
974 SaveFileDialog savefiledialog = new SaveFileDialog { Filter = "plist|*.plist" };
\r
976 if (treeView_presets.SelectedNode != null)
\r
978 if (savefiledialog.ShowDialog() == DialogResult.OK)
\r
980 Preset preset = presetHandler.GetPreset(treeView_presets.SelectedNode.Text);
\r
981 PlistPresetHandler.Export(savefiledialog.FileName, preset);
\r
991 /// 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
993 /// <param name="sender">
\r
996 /// <param name="e">
\r
999 private void btn_source_Click(object sender, EventArgs e)
\r
1001 // Remove old Drive Menu Items.
\r
1002 List<ToolStripMenuItem> itemsToRemove = new List<ToolStripMenuItem>();
\r
1003 foreach (var item in btn_source.DropDownItems)
\r
1005 if (item.GetType() == typeof(ToolStripMenuItem))
\r
1007 ToolStripMenuItem menuItem = (ToolStripMenuItem)item;
\r
1008 if (menuItem.Name.StartsWith("Drive"))
\r
1010 itemsToRemove.Add(menuItem);
\r
1015 foreach (ToolStripMenuItem item in itemsToRemove)
\r
1016 btn_source.DropDownItems.Remove(item);
\r
1018 Thread driveInfoThread = new Thread(SetDriveSelectionMenuItem);
\r
1019 driveInfoThread.Start();
\r
1023 /// Toolbar - Start The Encode
\r
1025 /// <param name="sender">
\r
1028 /// <param name="e">
\r
1031 private void btn_start_Click(object sender, EventArgs e)
\r
1033 if (btn_start.Text == "Stop")
\r
1035 DialogResult result = !Properties.Settings.Default.showCliForInGuiEncodeStatus
\r
1036 ? MessageBox.Show(
\r
1037 "Are you sure you wish to cancel the encode?\n\nPlease note: Stopping this encode will render the file unplayable. ",
\r
1039 MessageBoxButtons.YesNo,
\r
1040 MessageBoxIcon.Question)
\r
1041 : MessageBox.Show(
\r
1042 "Are you sure you wish to cancel the encode?",
\r
1044 MessageBoxButtons.YesNo,
\r
1045 MessageBoxIcon.Question);
\r
1047 if (result == DialogResult.Yes)
\r
1049 // Pause The Queue
\r
1050 encodeQueue.Pause();
\r
1052 if (Settings.Default.showCliForInGuiEncodeStatus)
\r
1053 encodeQueue.SafelyClose();
\r
1055 encodeQueue.Stop();
\r
1060 // 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
1061 string jobSourcePath = !string.IsNullOrEmpty(rtf_query.Text) ? Main.GetSourceFromQuery(rtf_query.Text) : sourcePath;
\r
1062 string jobDestination = !string.IsNullOrEmpty(rtf_query.Text) ? Main.GetDestinationFromQuery(rtf_query.Text) : text_destination.Text;
\r
1064 if (encodeQueue.Count != 0 || (!string.IsNullOrEmpty(jobSourcePath) && !string.IsNullOrEmpty(jobDestination)))
\r
1066 string generatedQuery = QueryGenerator.GenerateFullQuery(this);
\r
1067 string specifiedQuery = rtf_query.Text != string.Empty
\r
1069 : QueryGenerator.GenerateFullQuery(this);
\r
1070 string query = string.Empty;
\r
1072 // Check to make sure the generated query matches the GUI settings
\r
1073 if (Properties.Settings.Default.PromptOnUnmatchingQueries && !string.IsNullOrEmpty(specifiedQuery) &&
\r
1074 generatedQuery != specifiedQuery)
\r
1076 DialogResult result = MessageBox.Show("The query under the \"Query Editor\" tab " +
\r
1077 "does not match the current GUI settings.\n\nBecause the manual query takes " +
\r
1078 "priority over the GUI, your recently updated settings will not be taken " +
\r
1079 "into account when encoding this job." +
\r
1080 Environment.NewLine + Environment.NewLine +
\r
1081 "Do you want to replace the manual query with the updated GUI-generated query?",
\r
1082 "Manual Query does not Match GUI",
\r
1083 MessageBoxButtons.YesNoCancel, MessageBoxIcon.Asterisk,
\r
1084 MessageBoxDefaultButton.Button3);
\r
1088 case DialogResult.Yes:
\r
1089 // Replace the manual query with the generated one
\r
1090 query = generatedQuery;
\r
1091 rtf_query.Text = generatedQuery;
\r
1093 case DialogResult.No:
\r
1094 // Use the manual query
\r
1095 query = specifiedQuery;
\r
1097 case DialogResult.Cancel:
\r
1098 // Don't start the encode
\r
1104 query = specifiedQuery;
\r
1107 DialogResult overwrite = DialogResult.Yes;
\r
1108 if (!string.IsNullOrEmpty(jobDestination) && File.Exists(jobDestination))
\r
1110 overwrite = MessageBox.Show(
\r
1111 "The destination file already exists. Are you sure you want to overwrite it?",
\r
1112 "Overwrite File?",
\r
1113 MessageBoxButtons.YesNo,
\r
1114 MessageBoxIcon.Question);
\r
1117 if (overwrite == DialogResult.Yes)
\r
1119 if (encodeQueue.Count == 0)
\r
1120 encodeQueue.Add(query, this.GetTitle(), jobSourcePath, jobDestination, (rtf_query.Text != string.Empty));
\r
1122 queueWindow.SetQueue();
\r
1123 if (encodeQueue.Count > 1)
\r
1124 queueWindow.Show(false);
\r
1126 SetEncodeStarted(); // Encode is running, so setup the GUI appropriately
\r
1127 encodeQueue.Start(); // Start The Queue Encoding Process
\r
1132 else if (string.IsNullOrEmpty(sourcePath) || string.IsNullOrEmpty(text_destination.Text))
\r
1133 MessageBox.Show("No source or destination selected.", "Warning", MessageBoxButtons.OK,
\r
1134 MessageBoxIcon.Warning);
\r
1139 /// Toolbar - Add the current job to the Queue
\r
1141 /// <param name="sender">
\r
1144 /// <param name="e">
\r
1147 private void btn_add2Queue_Click(object sender, EventArgs e)
\r
1149 // Add the item to the queue.
\r
1150 AddItemToQueue(true);
\r
1151 queueWindow.Show();
\r
1155 /// Add Multiple Items to the Queue at once.
\r
1157 /// <param name="sender">The Sender</param>
\r
1158 /// <param name="e">The EventArgs</param>
\r
1159 private void MnuAddMultiToQueueClick(object sender, EventArgs e)
\r
1161 if (!Settings.Default.autoNaming)
\r
1163 MessageBox.Show("Destination Auto Naming must be enabled in preferences for this feature to work.", "Error", MessageBoxButtons.OK, MessageBoxIcon.Error);
\r
1167 if (this.SourceScan.SouceData == null)
\r
1169 MessageBox.Show("You must first scan a source or collection of source to use this feature.", "Error", MessageBoxButtons.OK, MessageBoxIcon.Error);
\r
1173 BatchAdd batchAdd = new BatchAdd();
\r
1174 if (batchAdd.ShowDialog() == DialogResult.OK)
\r
1176 int min = batchAdd.Min;
\r
1177 int max = batchAdd.Max;
\r
1178 bool errors = false;
\r
1180 foreach (Title title in this.SourceScan.SouceData.Titles)
\r
1182 if (title.Duration.TotalMinutes > min && title.Duration.TotalMinutes < max)
\r
1185 this.drp_dvdtitle.SelectedItem = title;
\r
1187 if (!this.AddItemToQueue(false))
\r
1197 "One or more items could not be added to the queue. You should check your queue and manually add any missing jobs.",
\r
1199 MessageBoxButtons.OK,
\r
1200 MessageBoxIcon.Warning);
\r
1205 private bool AddItemToQueue(bool showError)
\r
1207 string query = QueryGenerator.GenerateFullQuery(this);
\r
1208 if (!string.IsNullOrEmpty(rtf_query.Text))
\r
1209 query = rtf_query.Text;
\r
1211 // 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
1212 string jobSourcePath = !string.IsNullOrEmpty(rtf_query.Text) ? Main.GetSourceFromQuery(rtf_query.Text) : sourcePath;
\r
1213 string jobDestination = !string.IsNullOrEmpty(rtf_query.Text) ? Main.GetDestinationFromQuery(rtf_query.Text) : text_destination.Text;
\r
1215 // Make sure we have a Source and Destination.
\r
1216 if (string.IsNullOrEmpty(jobSourcePath) || string.IsNullOrEmpty(jobDestination))
\r
1219 MessageBox.Show("No source or destination selected.", "Warning", MessageBoxButtons.OK, MessageBoxIcon.Warning);
\r
1223 // Make sure the destination path exists.
\r
1224 if (!Directory.Exists(Path.GetDirectoryName(jobDestination)))
\r
1227 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
1231 // Make sure we don't have a duplciate on the queue.
\r
1232 if (encodeQueue.CheckForDestinationDuplicate(jobDestination))
\r
1236 DialogResult result;
\r
1240 "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
1243 MessageBoxButtons.YesNo,
\r
1244 MessageBoxIcon.Warning);
\r
1246 if (result != DialogResult.Yes) return false;
\r
1255 encodeQueue.Add(query, this.GetTitle(), jobSourcePath, jobDestination, (rtf_query.Text != string.Empty));
\r
1257 lbl_encode.Text = encodeQueue.Count + " encode(s) pending in the queue";
\r
1263 /// Toolbar - Show the Queue
\r
1265 /// <param name="sender">
\r
1268 /// <param name="e">
\r
1271 private void btn_showQueue_Click(object sender, EventArgs e)
\r
1273 queueWindow.Show();
\r
1274 queueWindow.Activate();
\r
1278 /// Toolbar - Show the Preview Window
\r
1280 /// <param name="sender">
\r
1283 /// <param name="e">
\r
1286 private void tb_preview_Click(object sender, EventArgs e)
\r
1288 if (string.IsNullOrEmpty(sourcePath) || string.IsNullOrEmpty(text_destination.Text))
\r
1289 MessageBox.Show("No source or destination selected.", "Warning", MessageBoxButtons.OK,
\r
1290 MessageBoxIcon.Warning);
\r
1293 if (qtpreview == null)
\r
1295 qtpreview = new frmPreview(this);
\r
1298 else if (qtpreview.IsDisposed)
\r
1300 qtpreview = new frmPreview(this);
\r
1304 MessageBox.Show(qtpreview, "The preview window is already open!", "Warning", MessageBoxButtons.OK,
\r
1305 MessageBoxIcon.Warning);
\r
1310 /// Toolbar - Show the Activity log Window
\r
1312 /// <param name="sender">
\r
1315 /// <param name="e">
\r
1318 private void btn_ActivityWindow_Click(object sender, EventArgs e)
\r
1320 if (this.activityWindow == null || !this.activityWindow.IsHandleCreated)
\r
1321 this.activityWindow = new frmActivityWindow(encodeQueue, SourceScan);
\r
1323 this.activityWindow.Show();
\r
1324 this.activityWindow.Activate();
\r
1329 #region System Tray Icon
\r
1332 /// Handle Resizing of the main window when deaing with the Notify Icon
\r
1334 /// <param name="sender">
\r
1337 /// <param name="e">
\r
1340 private void frmMain_Resize(object sender, EventArgs e)
\r
1342 if (FormWindowState.Minimized == this.WindowState)
\r
1344 notifyIcon.Visible = true;
\r
1347 else if (FormWindowState.Normal == this.WindowState)
\r
1348 notifyIcon.Visible = false;
\r
1352 /// Double Click the Tray Icon
\r
1354 /// <param name="sender">
\r
1357 /// <param name="e">
\r
1360 private void notifyIcon_MouseDoubleClick(object sender, MouseEventArgs e)
\r
1362 this.Visible = true;
\r
1364 this.WindowState = FormWindowState.Normal;
\r
1365 notifyIcon.Visible = false;
\r
1369 /// Tray Icon - Restore Menu Item - Resture the Window
\r
1371 /// <param name="sender">
\r
1374 /// <param name="e">
\r
1377 private void btn_restore_Click(object sender, EventArgs e)
\r
1379 this.Visible = true;
\r
1381 this.WindowState = FormWindowState.Normal;
\r
1382 notifyIcon.Visible = false;
\r
1387 #region Main Window and Tab Control
\r
1390 private void BtnFolderScanClicked(object sender, EventArgs e)
\r
1392 this.btn_source.HideDropDown();
\r
1393 if (DVD_Open.ShowDialog() == DialogResult.OK)
\r
1395 this.selectedSourceType = SourceType.Folder;
\r
1396 SelectSource(DVD_Open.SelectedPath, 0);
\r
1399 UpdateSourceLabel();
\r
1402 private void BtnFileScanClicked(object sender, EventArgs e)
\r
1404 this.btn_source.HideDropDown();
\r
1405 if (ISO_Open.ShowDialog() == DialogResult.OK)
\r
1407 this.selectedSourceType = SourceType.VideoFile;
\r
1408 SelectSource(ISO_Open.FileName, 0);
\r
1411 UpdateSourceLabel();
\r
1414 private void MnuDvdDriveClick(object sender, EventArgs e)
\r
1416 ToolStripMenuItem item = sender as ToolStripMenuItem;
\r
1419 string driveId = item.Name.Replace("Drive", string.Empty);
\r
1421 if (int.TryParse(driveId, out id))
\r
1423 this.dvdDrivePath = drives[id].RootDirectory;
\r
1424 this.dvdDriveLabel = drives[id].VolumeLabel;
\r
1426 if (this.dvdDrivePath == null) return;
\r
1427 this.selectedSourceType = SourceType.DvdDrive;
\r
1428 SelectSource(this.dvdDrivePath, 0);
\r
1433 private void VideoTitleSpecificScanClick(object sender, EventArgs e)
\r
1435 this.btn_source.HideDropDown();
\r
1436 if (ISO_Open.ShowDialog() == DialogResult.OK)
\r
1438 this.selectedSourceType = SourceType.VideoFile;
\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(ISO_Open.FileName, sourceTitle);
\r
1449 UpdateSourceLabel();
\r
1452 private void FolderTitleSpecificScanClick(object sender, EventArgs e)
\r
1454 this.btn_source.HideDropDown();
\r
1455 if (DVD_Open.ShowDialog() == DialogResult.OK)
\r
1457 this.selectedSourceType = SourceType.Folder;
\r
1459 int sourceTitle = 0;
\r
1460 TitleSpecificScan title = new TitleSpecificScan();
\r
1461 if (title.ShowDialog() == DialogResult.OK)
\r
1463 sourceTitle = title.Title;
\r
1464 SelectSource(DVD_Open.SelectedPath, sourceTitle);
\r
1468 UpdateSourceLabel();
\r
1471 private void SelectSource(string file, int titleSpecific)
\r
1473 Check_ChapterMarkers.Enabled = true;
\r
1474 sourcePath = string.Empty;
\r
1476 if (file == string.Empty) // Must have a file or path
\r
1478 UpdateSourceLabel();
\r
1482 sourcePath = Path.GetFileName(file);
\r
1483 StartScan(file, titleSpecific);
\r
1486 private void drp_dvdtitle_Click(object sender, EventArgs e)
\r
1488 if ((drp_dvdtitle.Items.Count == 1) && (drp_dvdtitle.Items[0].ToString() == "Automatic"))
\r
1490 "There are no titles to select. Please load a source file by clicking the 'Source' button above before trying to select a title.",
\r
1491 "Alert", MessageBoxButtons.OK, MessageBoxIcon.Asterisk);
\r
1494 private void drp_dvdtitle_SelectedIndexChanged(object sender, EventArgs e)
\r
1496 UnRegisterPresetEventHandler();
\r
1497 drop_mode.SelectedIndex = 0;
\r
1499 drop_chapterStart.Items.Clear();
\r
1500 drop_chapterFinish.Items.Clear();
\r
1502 // If the dropdown is set to automatic nothing else needs to be done.
\r
1503 // Otheriwse if its not, title data has to be loaded from parsing.
\r
1504 if (drp_dvdtitle.Text != "Automatic")
\r
1506 selectedTitle = drp_dvdtitle.SelectedItem as Title;
\r
1507 lbl_duration.Text = selectedTitle.Duration.ToString();
\r
1508 PictureSettings.CurrentlySelectedPreset = this.currentlySelectedPreset;
\r
1509 PictureSettings.Source = selectedTitle; // Setup Picture Settings Tab Control
\r
1511 // Populate the Angles dropdown
\r
1512 drop_angle.Items.Clear();
\r
1513 if (!Properties.Settings.Default.noDvdNav)
\r
1515 drop_angle.Visible = true;
\r
1516 lbl_angle.Visible = true;
\r
1518 for (int i = 1; i <= selectedTitle.AngleCount; i++)
\r
1519 drop_angle.Items.Add(i.ToString());
\r
1521 if (drop_angle.Items.Count == 0)
\r
1523 drop_angle.Visible = false;
\r
1524 lbl_angle.Visible = false;
\r
1527 if (drop_angle.Items.Count != 0)
\r
1528 drop_angle.SelectedIndex = 0;
\r
1532 drop_angle.Visible = false;
\r
1533 lbl_angle.Visible = false;
\r
1536 // Populate the Start chapter Dropdown
\r
1537 drop_chapterStart.Items.Clear();
\r
1538 drop_chapterStart.Items.AddRange(selectedTitle.Chapters.ToArray());
\r
1539 if (drop_chapterStart.Items.Count > 0)
\r
1540 drop_chapterStart.Text = drop_chapterStart.Items[0].ToString();
\r
1542 // Populate the Final Chapter Dropdown
\r
1543 drop_chapterFinish.Items.Clear();
\r
1544 drop_chapterFinish.Items.AddRange(selectedTitle.Chapters.ToArray());
\r
1545 if (drop_chapterFinish.Items.Count > 0)
\r
1546 drop_chapterFinish.Text = drop_chapterFinish.Items[drop_chapterFinish.Items.Count - 1].ToString();
\r
1548 // Populate the Audio Channels Dropdown
\r
1549 AudioSettings.SetTrackListFromPreset(selectedTitle, this.currentlySelectedPreset);
\r
1551 // Populate the Subtitles dropdown
\r
1552 Subtitles.SetSubtitleTrackAuto(selectedTitle.Subtitles.ToArray());
\r
1554 // Update the source label if we have multiple streams
\r
1555 if (selectedTitle != null)
\r
1556 if (!string.IsNullOrEmpty(selectedTitle.SourceName))
\r
1557 labelSource.Text = Path.GetFileName(selectedTitle.SourceName);
\r
1559 // Run the AutoName & ChapterNaming functions
\r
1560 if (Properties.Settings.Default.autoNaming)
\r
1562 string autoPath = Main.AutoName(this);
\r
1563 if (autoPath != null)
\r
1564 text_destination.Text = autoPath;
\r
1567 "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
1568 "Warning", MessageBoxButtons.OK, MessageBoxIcon.Warning);
\r
1571 data_chpt.Rows.Clear();
\r
1572 if (selectedTitle.Chapters.Count != 1)
\r
1574 DataGridView chapterGridView = Main.ChapterNaming(selectedTitle, data_chpt, drop_chapterFinish.Text);
\r
1575 if (chapterGridView != null)
\r
1576 data_chpt = chapterGridView;
\r
1580 Check_ChapterMarkers.Checked = false;
\r
1581 Check_ChapterMarkers.Enabled = false;
\r
1584 // Hack to force the redraw of the scrollbars which don't resize properly when the control is disabled.
\r
1585 data_chpt.Columns[0].Width = 166;
\r
1586 data_chpt.Columns[0].Width = 165;
\r
1588 RegisterPresetEventHandler();
\r
1591 private void chapersChanged(object sender, EventArgs e)
\r
1593 if (drop_mode.SelectedIndex != 0) // Function is not used if we are not in chapters mode.
\r
1596 Control ctl = (Control)sender;
\r
1597 int chapterStart, chapterEnd;
\r
1598 int.TryParse(drop_chapterStart.Text, out chapterStart);
\r
1599 int.TryParse(drop_chapterFinish.Text, out chapterEnd);
\r
1603 case "drop_chapterStart":
\r
1604 if (drop_chapterFinish.SelectedIndex == -1 && drop_chapterFinish.Items.Count != 0)
\r
1605 drop_chapterFinish.SelectedIndex = drop_chapterFinish.Items.Count - 1;
\r
1607 if (chapterEnd != 0)
\r
1608 if (chapterStart > chapterEnd)
\r
1609 drop_chapterFinish.Text = chapterStart.ToString();
\r
1611 case "drop_chapterFinish":
\r
1612 if (drop_chapterStart.Items.Count >= 1 && drop_chapterStart.SelectedIndex == -1)
\r
1613 drop_chapterStart.SelectedIndex = 0;
\r
1615 if (chapterStart != 0)
\r
1616 if (chapterEnd < chapterStart)
\r
1617 drop_chapterFinish.Text = chapterStart.ToString();
\r
1619 // Add more rows to the Chapter menu if needed.
\r
1620 if (Check_ChapterMarkers.Checked)
\r
1622 int i = data_chpt.Rows.Count, finish = 0;
\r
1623 int.TryParse(drop_chapterFinish.Text, out finish);
\r
1625 while (i < finish)
\r
1627 int n = data_chpt.Rows.Add();
\r
1628 data_chpt.Rows[n].Cells[0].Value = (i + 1);
\r
1629 data_chpt.Rows[n].Cells[1].Value = "Chapter " + (i + 1);
\r
1630 data_chpt.Rows[n].Cells[0].ValueType = typeof(int);
\r
1631 data_chpt.Rows[n].Cells[1].ValueType = typeof(string);
\r
1638 // Update the Duration
\r
1639 lbl_duration.Text =
\r
1640 Main.CalculateDuration(drop_chapterStart.SelectedIndex, drop_chapterFinish.SelectedIndex, selectedTitle)
\r
1643 // Run the Autonaming function
\r
1644 if (Properties.Settings.Default.autoNaming)
\r
1645 text_destination.Text = Main.AutoName(this);
\r
1647 // Disable chapter markers if only 1 chapter is selected.
\r
1648 if (chapterStart == chapterEnd)
\r
1650 Check_ChapterMarkers.Enabled = false;
\r
1651 btn_importChapters.Enabled = false;
\r
1652 data_chpt.Enabled = false;
\r
1656 Check_ChapterMarkers.Enabled = true;
\r
1657 if (Check_ChapterMarkers.Checked)
\r
1659 btn_importChapters.Enabled = true;
\r
1660 data_chpt.Enabled = true;
\r
1665 private void SecondsOrFramesChanged(object sender, EventArgs e)
\r
1668 int.TryParse(drop_chapterStart.Text, out start);
\r
1669 int.TryParse(drop_chapterFinish.Text, out end);
\r
1670 double duration = end - start;
\r
1672 switch (drop_mode.SelectedIndex)
\r
1675 lbl_duration.Text = TimeSpan.FromSeconds(duration).ToString();
\r
1678 if (selectedTitle != null)
\r
1680 duration = duration / selectedTitle.Fps;
\r
1681 lbl_duration.Text = TimeSpan.FromSeconds(duration).ToString();
\r
1684 lbl_duration.Text = "--:--:--";
\r
1690 private void drop_mode_SelectedIndexChanged(object sender, EventArgs e)
\r
1693 this.drop_chapterFinish.TextChanged -= new EventHandler(this.SecondsOrFramesChanged);
\r
1694 this.drop_chapterStart.TextChanged -= new EventHandler(this.SecondsOrFramesChanged);
\r
1697 switch (drop_mode.SelectedIndex)
\r
1700 drop_chapterStart.DropDownStyle = ComboBoxStyle.DropDownList;
\r
1701 drop_chapterFinish.DropDownStyle = ComboBoxStyle.DropDownList;
\r
1702 if (drop_chapterStart.Items.Count != 0)
\r
1704 drop_chapterStart.SelectedIndex = 0;
\r
1705 drop_chapterFinish.SelectedIndex = drop_chapterFinish.Items.Count - 1;
\r
1708 lbl_duration.Text = "--:--:--";
\r
1711 this.drop_chapterStart.TextChanged += new EventHandler(this.SecondsOrFramesChanged);
\r
1712 this.drop_chapterFinish.TextChanged += new EventHandler(this.SecondsOrFramesChanged);
\r
1713 drop_chapterStart.DropDownStyle = ComboBoxStyle.Simple;
\r
1714 drop_chapterFinish.DropDownStyle = ComboBoxStyle.Simple;
\r
1715 if (selectedTitle != null)
\r
1717 drop_chapterStart.Text = "0";
\r
1718 drop_chapterFinish.Text = selectedTitle.Duration.TotalSeconds.ToString();
\r
1722 this.drop_chapterStart.TextChanged += new EventHandler(this.SecondsOrFramesChanged);
\r
1723 this.drop_chapterFinish.TextChanged += new EventHandler(this.SecondsOrFramesChanged);
\r
1724 drop_chapterStart.DropDownStyle = ComboBoxStyle.Simple;
\r
1725 drop_chapterFinish.DropDownStyle = ComboBoxStyle.Simple;
\r
1726 if (selectedTitle != null)
\r
1728 drop_chapterStart.Text = "0";
\r
1729 drop_chapterFinish.Text = (selectedTitle.Fps * selectedTitle.Duration.TotalSeconds).ToString();
\r
1736 private void btn_destBrowse_Click(object sender, EventArgs e)
\r
1738 // This removes the file extension from the filename box on the save file dialog.
\r
1739 // It's daft but some users don't realise that typing an extension overrides the dropdown extension selected.
\r
1740 DVD_Save.FileName = Path.GetFileNameWithoutExtension(text_destination.Text);
\r
1742 if (Path.IsPathRooted(text_destination.Text))
\r
1743 DVD_Save.InitialDirectory = Path.GetDirectoryName(text_destination.Text);
\r
1745 // Show the dialog and set the main form file path
\r
1746 if (drop_format.SelectedIndex.Equals(0))
\r
1747 DVD_Save.FilterIndex = 1;
\r
1748 else if (drop_format.SelectedIndex.Equals(1))
\r
1749 DVD_Save.FilterIndex = 2;
\r
1751 if (DVD_Save.ShowDialog() == DialogResult.OK)
\r
1753 // Add a file extension manually, as FileDialog.AddExtension has issues with dots in filenames
\r
1754 switch (DVD_Save.FilterIndex)
\r
1758 !Path.GetExtension(DVD_Save.FileName).Equals(".mp4",
\r
1759 StringComparison.InvariantCultureIgnoreCase))
\r
1760 if (Properties.Settings.Default.useM4v)
\r
1761 DVD_Save.FileName = DVD_Save.FileName.Replace(".mp4", ".m4v").Replace(".mkv", ".m4v");
\r
1763 DVD_Save.FileName = DVD_Save.FileName.Replace(".m4v", ".mp4").Replace(".mkv", ".mp4");
\r
1767 !Path.GetExtension(DVD_Save.FileName).Equals(".mkv", StringComparison.InvariantCultureIgnoreCase))
\r
1768 DVD_Save.FileName = DVD_Save.FileName.Replace(".mp4", ".mkv").Replace(".m4v", ".mkv");
\r
1774 text_destination.Text = DVD_Save.FileName;
\r
1776 // Quicktime requires .m4v file for chapter markers to work. If checked, change the extension to .m4v (mp4 and m4v are the same thing)
\r
1777 if (Check_ChapterMarkers.Checked && DVD_Save.FilterIndex != 2)
\r
1778 SetExtension(".m4v");
\r
1782 private void text_destination_TextChanged(object sender, EventArgs e)
\r
1784 string path = text_destination.Text;
\r
1785 if (path.EndsWith(".mp4") || path.EndsWith(".m4v"))
\r
1786 drop_format.SelectedIndex = 0;
\r
1787 else if (path.EndsWith(".mkv"))
\r
1788 drop_format.SelectedIndex = 1;
\r
1791 // Output Settings
\r
1792 private void drop_format_SelectedIndexChanged(object sender, EventArgs e)
\r
1794 switch (drop_format.SelectedIndex)
\r
1797 if (Properties.Settings.Default.useM4v || Check_ChapterMarkers.Checked ||
\r
1798 AudioSettings.RequiresM4V() || Subtitles.RequiresM4V())
\r
1799 SetExtension(".m4v");
\r
1801 SetExtension(".mp4");
\r
1804 SetExtension(".mkv");
\r
1808 AudioSettings.SetContainer(drop_format.Text);
\r
1810 if (drop_format.Text.Contains("MP4"))
\r
1812 if (drp_videoEncoder.Items.Contains("VP3 (Theora)"))
\r
1814 drp_videoEncoder.Items.Remove("VP3 (Theora)");
\r
1815 drp_videoEncoder.SelectedIndex = 1;
\r
1818 else if (drop_format.Text.Contains("MKV"))
\r
1819 drp_videoEncoder.Items.Add("VP3 (Theora)");
\r
1822 public void SetExtension(string newExtension)
\r
1824 if (newExtension == ".mp4" || newExtension == ".m4v")
\r
1825 if (Properties.Settings.Default.useM4v || Check_ChapterMarkers.Checked || AudioSettings.RequiresM4V() ||
\r
1826 Subtitles.RequiresM4V())
\r
1827 newExtension = ".m4v";
\r
1829 newExtension = ".mp4";
\r
1831 if (Path.HasExtension(newExtension))
\r
1832 text_destination.Text = Path.ChangeExtension(text_destination.Text, newExtension);
\r
1836 private void drp_videoEncoder_SelectedIndexChanged(object sender, EventArgs e)
\r
1838 setContainerOpts();
\r
1840 // Turn off some options which are H.264 only when the user selects a non h.264 encoder
\r
1841 if (drp_videoEncoder.Text.Contains("H.264"))
\r
1843 if (check_2PassEncode.CheckState == CheckState.Checked)
\r
1844 check_turbo.Enabled = true;
\r
1846 tab_advanced.Enabled = true;
\r
1847 if ((drop_format.Text.Contains("MP4")) || (drop_format.Text.Contains("M4V")))
\r
1848 check_iPodAtom.Enabled = true;
\r
1850 check_iPodAtom.Enabled = false;
\r
1854 check_turbo.CheckState = CheckState.Unchecked;
\r
1855 check_turbo.Enabled = false;
\r
1856 tab_advanced.Enabled = false;
\r
1857 x264Panel.X264Query = string.Empty;
\r
1858 check_iPodAtom.Enabled = false;
\r
1859 check_iPodAtom.Checked = false;
\r
1862 // Setup the CQ Slider
\r
1863 switch (drp_videoEncoder.Text)
\r
1865 case "MPEG-4 (FFmpeg)":
\r
1866 if (slider_videoQuality.Value > 31)
\r
1867 slider_videoQuality.Value = 20; // Just reset to 70% QP 10 on encode change.
\r
1868 slider_videoQuality.Minimum = 1;
\r
1869 slider_videoQuality.Maximum = 31;
\r
1871 case "H.264 (x264)":
\r
1872 slider_videoQuality.Minimum = 0;
\r
1873 slider_videoQuality.TickFrequency = 1;
\r
1875 CultureInfo culture = CultureInfo.CreateSpecificCulture("en-US");
\r
1876 double cqStep = Properties.Settings.Default.x264cqstep;
\r
1877 double multiplier = 1.0 / cqStep;
\r
1878 double value = slider_videoQuality.Value * multiplier;
\r
1880 slider_videoQuality.Maximum = (int)(51 / Properties.Settings.Default.x264cqstep);
\r
1882 if (value < slider_videoQuality.Maximum)
\r
1883 slider_videoQuality.Value = slider_videoQuality.Maximum - (int)value;
\r
1886 case "VP3 (Theora)":
\r
1887 if (slider_videoQuality.Value > 63)
\r
1888 slider_videoQuality.Value = 45; // Just reset to 70% QP 45 on encode change.
\r
1889 slider_videoQuality.Minimum = 0;
\r
1890 slider_videoQuality.Maximum = 63;
\r
1896 /// When the FrameRate is not Same As Source, show the Max/Constant Mode dropdown
\r
1898 /// <param name="sender">
\r
1901 /// <param name="e">
\r
1904 private void drp_videoFramerate_SelectedIndexChanged(object sender, EventArgs e)
\r
1906 if (this.drp_videoFramerate.SelectedIndex == 0)
\r
1908 this.checkMaximumFramerate.Visible = false;
\r
1909 this.checkMaximumFramerate.CheckState = CheckState.Unchecked;
\r
1913 this.checkMaximumFramerate.Visible = true;
\r
1918 /// Set the container format options
\r
1920 public void setContainerOpts()
\r
1922 if ((drop_format.Text.Contains("MP4")) || (drop_format.Text.Contains("M4V")))
\r
1924 check_largeFile.Enabled = true;
\r
1925 check_optimiseMP4.Enabled = true;
\r
1926 check_iPodAtom.Enabled = true;
\r
1930 check_largeFile.Enabled = false;
\r
1931 check_optimiseMP4.Enabled = false;
\r
1932 check_iPodAtom.Enabled = false;
\r
1933 check_largeFile.Checked = false;
\r
1934 check_optimiseMP4.Checked = false;
\r
1935 check_iPodAtom.Checked = false;
\r
1939 private double cachedCqStep = Properties.Settings.Default.x264cqstep;
\r
1942 /// Update the CQ slider for x264 for a new CQ step. This is set from option
\r
1944 public void setQualityFromSlider()
\r
1946 // Work out the current RF value.
\r
1947 double cqStep = this.cachedCqStep;
\r
1948 double rfValue = 51.0 - slider_videoQuality.Value * cqStep;
\r
1950 // Change the maximum value for the slider
\r
1951 slider_videoQuality.Maximum = (int)(51 / Properties.Settings.Default.x264cqstep);
\r
1953 // Reset the CQ slider to RF0
\r
1954 slider_videoQuality.Value = slider_videoQuality.Maximum;
\r
1956 // Reset the CQ slider back to the previous value as close as possible
\r
1957 double cqStepNew = Properties.Settings.Default.x264cqstep;
\r
1958 double rfValueCurrent = 51.0 - slider_videoQuality.Value * cqStepNew;
\r
1959 while (rfValueCurrent < rfValue)
\r
1961 slider_videoQuality.Value--;
\r
1962 rfValueCurrent = 51.0 - slider_videoQuality.Value * cqStepNew;
\r
1965 // Cache the CQ step for the next calculation
\r
1966 this.cachedCqStep = Properties.Settings.Default.x264cqstep;
\r
1969 private void slider_videoQuality_Scroll(object sender, EventArgs e)
\r
1971 double cqStep = Properties.Settings.Default.x264cqstep;
\r
1972 switch (drp_videoEncoder.Text)
\r
1974 case "MPEG-4 (FFmpeg)":
\r
1975 lbl_SliderValue.Text = "QP:" + (32 - slider_videoQuality.Value);
\r
1977 case "H.264 (x264)":
\r
1978 double rfValue = 51.0 - slider_videoQuality.Value * cqStep;
\r
1979 rfValue = Math.Round(rfValue, 2);
\r
1980 lbl_SliderValue.Text = "RF:" + rfValue.ToString(new CultureInfo("en-US"));
\r
1981 this.lbl_rfwarn.Visible = rfValue == 0;
\r
1983 case "VP3 (Theora)":
\r
1984 lbl_SliderValue.Text = "QP:" + slider_videoQuality.Value;
\r
1989 private void radio_targetFilesize_CheckedChanged(object sender, EventArgs e)
\r
1991 text_bitrate.Enabled = false;
\r
1992 text_filesize.Enabled = true;
\r
1993 slider_videoQuality.Enabled = false;
\r
1995 check_2PassEncode.Enabled = true;
\r
1998 private void radio_avgBitrate_CheckedChanged(object sender, EventArgs e)
\r
2000 text_bitrate.Enabled = true;
\r
2001 text_filesize.Enabled = false;
\r
2002 slider_videoQuality.Enabled = false;
\r
2004 check_2PassEncode.Enabled = true;
\r
2007 private void radio_cq_CheckedChanged(object sender, EventArgs e)
\r
2009 text_bitrate.Enabled = false;
\r
2010 text_filesize.Enabled = false;
\r
2011 slider_videoQuality.Enabled = true;
\r
2013 check_2PassEncode.Enabled = false;
\r
2014 check_2PassEncode.CheckState = CheckState.Unchecked;
\r
2017 private void check_2PassEncode_CheckedChanged(object sender, EventArgs e)
\r
2019 if (check_2PassEncode.CheckState.ToString() == "Checked")
\r
2021 if (drp_videoEncoder.Text.Contains("H.264"))
\r
2022 check_turbo.Enabled = true;
\r
2026 check_turbo.Enabled = false;
\r
2027 check_turbo.CheckState = CheckState.Unchecked;
\r
2031 // Chapter Marker Tab
\r
2032 private void Check_ChapterMarkers_CheckedChanged(object sender, EventArgs e)
\r
2034 if (Check_ChapterMarkers.Checked)
\r
2036 if (drop_format.SelectedIndex != 1)
\r
2037 SetExtension(".m4v");
\r
2038 data_chpt.Enabled = true;
\r
2039 btn_importChapters.Enabled = true;
\r
2043 if (drop_format.SelectedIndex != 1 && !Properties.Settings.Default.useM4v)
\r
2044 SetExtension(".mp4");
\r
2045 data_chpt.Enabled = false;
\r
2046 btn_importChapters.Enabled = false;
\r
2050 private void btn_importChapters_Click(object sender, EventArgs e)
\r
2052 if (File_ChapterImport.ShowDialog() == DialogResult.OK)
\r
2054 string filename = File_ChapterImport.FileName;
\r
2055 DataGridView imported = Main.ImportChapterNames(data_chpt, filename);
\r
2056 if (imported != null)
\r
2057 data_chpt = imported;
\r
2061 private void btn_export_Click(object sender, EventArgs e)
\r
2063 SaveFileDialog saveFileDialog = new SaveFileDialog();
\r
2064 saveFileDialog.Filter = "Csv File|*.csv";
\r
2065 saveFileDialog.DefaultExt = "csv";
\r
2066 if (saveFileDialog.ShowDialog() == DialogResult.OK)
\r
2068 string filename = saveFileDialog.FileName;
\r
2070 Main.SaveChapterMarkersToCsv(this, filename);
\r
2074 private void mnu_resetChapters_Click(object sender, EventArgs e)
\r
2076 data_chpt.Rows.Clear();
\r
2077 DataGridView chapterGridView = Main.ChapterNaming(selectedTitle, data_chpt, drop_chapterFinish.Text);
\r
2078 if (chapterGridView != null)
\r
2080 data_chpt = chapterGridView;
\r
2084 // Query Editor Tab
\r
2085 private void btn_generate_Query_Click(object sender, EventArgs e)
\r
2087 rtf_query.Text = QueryGenerator.GenerateFullQuery(this);
\r
2090 private void btn_clear_Click(object sender, EventArgs e)
\r
2092 rtf_query.Clear();
\r
2097 // MainWindow Components, Actions and Functions ***********************
\r
2099 #region Source Scan
\r
2102 /// Start the Scan Process
\r
2104 /// <param name="filename">
\r
2107 /// <param name="title">
\r
2110 private void StartScan(string filename, int title)
\r
2112 // Setup the GUI components for the scan.
\r
2113 sourcePath = filename;
\r
2115 this.DisableGUI();
\r
2120 SourceScan.Scan(sourcePath, title);
\r
2122 catch (Exception exc)
\r
2124 MessageBox.Show("frmMain.cs - StartScan " + exc, "Error", MessageBoxButtons.OK, MessageBoxIcon.Error);
\r
2129 /// Update the Status label for the scan
\r
2131 /// <param name="sender">
\r
2134 /// <param name="e">
\r
2137 private void SourceScanScanStatusChanged(object sender, ScanProgressEventArgs e)
\r
2139 if (this.InvokeRequired)
\r
2141 this.BeginInvoke(new ScanProgessStatus(this.SourceScanScanStatusChanged), new[] { sender, e });
\r
2145 labelSource.Text = string.Format("Processing Title: {0} of {1}", e.CurrentTitle, e.Titles);
\r
2149 /// Update the UI after the scan has completed
\r
2151 /// <param name="sender">
\r
2154 /// <param name="e">
\r
2157 private void SourceScanScanCompleted(object sender, EventArgs e)
\r
2159 if (this.InvokeRequired)
\r
2161 this.BeginInvoke(new ScanCompletedStatus(this.SourceScanScanCompleted), new[] { sender, e });
\r
2167 currentSource = SourceScan.SouceData;
\r
2169 // Setup some GUI components
\r
2170 drp_dvdtitle.Items.Clear();
\r
2171 if (currentSource.Titles.Count != 0)
\r
2172 drp_dvdtitle.Items.AddRange(currentSource.Titles.ToArray());
\r
2174 foreach (Title title in currentSource.Titles)
\r
2176 if (title.MainTitle)
\r
2178 drp_dvdtitle.SelectedItem = title;
\r
2182 if (drp_dvdtitle.SelectedItem == null && drp_dvdtitle.Items.Count > 0)
\r
2184 drp_dvdtitle.SelectedIndex = 0;
\r
2187 // Enable the creation of chapter markers if the file is an image of a dvd
\r
2188 if (drop_chapterStart.Items.Count > 0)
\r
2191 int.TryParse(drop_chapterStart.Items[0].ToString(), out start);
\r
2192 int.TryParse(drop_chapterFinish.Items[drop_chapterFinish.Items.Count - 1].ToString(), out end);
\r
2193 if (end > start) Check_ChapterMarkers.Enabled = true;
\r
2196 Check_ChapterMarkers.Enabled = false;
\r
2197 Check_ChapterMarkers.Checked = false;
\r
2198 data_chpt.Rows.Clear();
\r
2202 // If no titles were found, Display an error message
\r
2203 if (drp_dvdtitle.Items.Count == 0)
\r
2206 "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
2207 "Error", MessageBoxButtons.OK, MessageBoxIcon.Hand);
\r
2208 sourcePath = string.Empty;
\r
2210 UpdateSourceLabel();
\r
2212 // This is a bit of a hack to fix the queue editing.
\r
2213 // If afte the scan, we find a job sitting in queueEdit, then the user has rescaned the source from the queue by clicking edit.
\r
2214 // When this occures, we want to repopulate their old settings.
\r
2215 if (queueEdit != null)
\r
2218 if (queueEdit.Query != null)
\r
2220 // Send the query from the file to the Query Parser class
\r
2221 QueryParser presetQuery = QueryParser.Parse(queueEdit.Query);
\r
2223 // Now load the preset
\r
2224 PresetLoader.LoadPreset(this, presetQuery, "Load Back From Queue");
\r
2226 // Set the destination path
\r
2227 this.text_destination.Text = queueEdit.Destination;
\r
2229 // The x264 widgets will need updated, so do this now:
\r
2230 x264Panel.StandardizeOptString();
\r
2231 x264Panel.SetCurrentSettingsInPanel();
\r
2233 // Set the crop label
\r
2234 PictureSettings.SetPresetCropWarningLabel(null);
\r
2240 // Enable the GUI components and enable any disabled components
\r
2243 catch (Exception exc)
\r
2245 MessageBox.Show("frmMain.cs - updateUIafterScan " + exc, "Error", MessageBoxButtons.OK,
\r
2246 MessageBoxIcon.Error);
\r
2252 /// Enable the GUI
\r
2254 private void EnableGUI()
\r
2258 if (InvokeRequired)
\r
2259 BeginInvoke(new UpdateWindowHandler(EnableGUI));
\r
2260 foreach (Control ctrl in Controls)
\r
2261 ctrl.Enabled = true;
\r
2262 btn_start.Enabled = true;
\r
2263 btn_showQueue.Enabled = true;
\r
2264 btn_add2Queue.Enabled = true;
\r
2265 tb_preview.Enabled = true;
\r
2266 btn_source.Enabled = true;
\r
2267 mnu_killCLI.Visible = false;
\r
2269 catch (Exception exc)
\r
2271 MessageBox.Show("frmMain.cs - EnableGUI() " + exc, "Error", MessageBoxButtons.OK, MessageBoxIcon.Error);
\r
2276 /// Disable the GUI
\r
2278 private void DisableGUI()
\r
2280 foreach (Control ctrl in Controls)
\r
2281 if (!(ctrl is StatusStrip || ctrl is MenuStrip || ctrl is ToolStrip))
\r
2282 ctrl.Enabled = false;
\r
2284 labelSource.Enabled = true;
\r
2285 labelStaticSource.Enabled = true;
\r
2286 SourceLayoutPanel.Enabled = true;
\r
2287 btn_source.Enabled = false;
\r
2288 btn_start.Enabled = false;
\r
2289 btn_showQueue.Enabled = false;
\r
2290 btn_add2Queue.Enabled = false;
\r
2291 tb_preview.Enabled = false;
\r
2292 mnu_killCLI.Visible = true;
\r
2298 private void KillScan()
\r
2300 SourceScan.ScanCompleted -= this.SourceScanScanCompleted;
\r
2304 SourceScan.Stop();
\r
2306 labelSource.Text = "Scan Cancelled";
\r
2312 private void ResetGUI()
\r
2314 drp_dvdtitle.Items.Clear();
\r
2315 drop_chapterStart.Items.Clear();
\r
2316 drop_chapterFinish.Items.Clear();
\r
2317 lbl_duration.Text = "Select a Title";
\r
2318 PictureSettings.lbl_src_res.Text = "Select a Title";
\r
2319 sourcePath = String.Empty;
\r
2320 text_destination.Text = String.Empty;
\r
2321 selectedTitle = null;
\r
2325 /// Update the Source Label
\r
2327 private void UpdateSourceLabel()
\r
2329 labelSource.Text = string.IsNullOrEmpty(sourcePath) ? "Select \"Source\" to continue." : this.SourceName;
\r
2333 /// Take a job from the Queue, rescan it, and reload the GUI for that job.
\r
2335 /// <param name="job">
\r
2338 public void RecievingJob(QueueTask job)
\r
2341 this.currentlySelectedPreset = null;
\r
2342 x264Panel.Reset2Defaults();
\r
2345 queueEdit = job; // Nasty but will do for now. TODO
\r
2346 StartScan(job.Source, job.Title);
\r
2351 #region GUI Functions and Actions
\r
2354 /// Set the GUI to it's finished encoding state.
\r
2356 private void SetEncodeFinished()
\r
2360 if (InvokeRequired)
\r
2362 BeginInvoke(new UpdateWindowHandler(SetEncodeFinished));
\r
2366 lbl_encode.Text = "Encoding Finished";
\r
2367 ProgressBarStatus.Visible = false;
\r
2368 btn_start.Text = "Start";
\r
2369 btn_start.ToolTipText = "Start the encoding process";
\r
2370 btn_start.Image = Properties.Resources.Play;
\r
2372 // If the window is minimized, display the notification in a popup.
\r
2373 if (Properties.Settings.Default.trayIconAlerts)
\r
2374 if (FormWindowState.Minimized == this.WindowState)
\r
2376 notifyIcon.BalloonTipText = lbl_encode.Text;
\r
2377 notifyIcon.ShowBalloonTip(500);
\r
2380 catch (Exception exc)
\r
2382 MessageBox.Show(exc.ToString());
\r
2387 /// Set the GUI to it's started encoding state.
\r
2389 private void SetEncodeStarted()
\r
2393 if (InvokeRequired)
\r
2395 BeginInvoke(new UpdateWindowHandler(SetEncodeStarted));
\r
2398 lbl_encode.Visible = true;
\r
2399 ProgressBarStatus.Value = 0;
\r
2400 ProgressBarStatus.Visible = true;
\r
2401 lbl_encode.Text = "Encoding with " + encodeQueue.Count + " encode(s) pending";
\r
2402 btn_start.Text = "Stop";
\r
2403 btn_start.ToolTipText = "Stop the encoding process.";
\r
2404 btn_start.Image = Properties.Resources.stop;
\r
2406 catch (Exception exc)
\r
2408 MessageBox.Show(exc.ToString());
\r
2413 /// Display the Encode Status
\r
2415 /// <param name="sender">
\r
2418 /// <param name="e">
\r
2421 private void EncodeQueue_EncodeStatusChanged(object sender, EncodeProgressEventArgs e)
\r
2423 if (this.InvokeRequired)
\r
2425 this.BeginInvoke(new Encode.EncodeProgessStatus(EncodeQueue_EncodeStatusChanged), new[] { sender, e });
\r
2431 "{0:00.00}%, FPS: {1:000.0}, Avg FPS: {2:000.0}, Time Remaining: {3}, Encode(s) Pending {4}",
\r
2432 e.PercentComplete,
\r
2433 e.CurrentFrameRate,
\r
2434 e.AverageFrameRate,
\r
2435 e.EstimatedTimeLeft,
\r
2436 encodeQueue.Count);
\r
2438 ProgressBarStatus.Value = (int)Math.Round(e.PercentComplete);
\r
2442 /// Set the DVD Drive selection in the "Source" Menu
\r
2444 private void SetDriveSelectionMenuItem()
\r
2448 if (InvokeRequired)
\r
2450 BeginInvoke(new UpdateWindowHandler(SetDriveSelectionMenuItem));
\r
2454 drives = Main.GetDrives();
\r
2456 List<ToolStripMenuItem> menuItems = new List<ToolStripMenuItem>();
\r
2457 foreach (DriveInformation drive in drives)
\r
2459 ToolStripMenuItem menuItem = new ToolStripMenuItem
\r
2461 Name = drive.ToString(),
\r
2462 Text = drive.RootDirectory + " (" + drive.VolumeLabel + ")",
\r
2463 Image = Resources.disc_small
\r
2465 menuItem.Click += new EventHandler(MnuDvdDriveClick);
\r
2466 menuItems.Add(menuItem);
\r
2469 foreach (ToolStripMenuItem item in menuItems)
\r
2470 btn_source.DropDownItems.Add(item);
\r
2472 catch (Exception exc)
\r
2474 MessageBox.Show("Error in SetDriveSelectionMenuItem" + exc);
\r
2479 /// Access the preset Handler and setup the preset panel.
\r
2481 private void LoadPresetPanel()
\r
2483 if (presetHandler.CheckIfPresetsAreOutOfDate())
\r
2484 if (!Settings.Default.presetNotification)
\r
2485 MessageBox.Show(this,
\r
2486 "HandBrake has determined your built-in presets are out of date... These presets will now be updated.",
\r
2487 "Preset Update", MessageBoxButtons.OK, MessageBoxIcon.Information);
\r
2489 presetHandler.GetPresetPanel(ref treeView_presets);
\r
2490 treeView_presets.Update();
\r
2494 /// Get the title from the selected item in the title dropdown.
\r
2499 private int GetTitle()
\r
2502 if (drp_dvdtitle.SelectedItem != null)
\r
2504 string[] titleInfo = drp_dvdtitle.SelectedItem.ToString().Split(' ');
\r
2505 int.TryParse(titleInfo[0], out title);
\r
2512 /// Handle the Update Check Finishing.
\r
2514 /// <param name="result">
\r
2517 private void UpdateCheckDoneMenu(IAsyncResult result)
\r
2519 // Make sure it's running on the calling thread
\r
2520 if (InvokeRequired)
\r
2522 Invoke(new MethodInvoker(() => this.UpdateCheckDoneMenu(result)));
\r
2525 UpdateCheckInformation info;
\r
2528 // Get the information about the new build, if any, and close the window
\r
2529 info = UpdateService.EndCheckForUpdates(result);
\r
2531 if (info.NewVersionAvailable && info.BuildInformation != null)
\r
2533 UpdateInfo updateWindow = new UpdateInfo(info.BuildInformation, Settings.Default.hb_version, Settings.Default.hb_build.ToString());
\r
2534 updateWindow.ShowDialog();
\r
2537 MessageBox.Show("There are no new updates at this time.", "Update Check", MessageBoxButtons.OK,
\r
2538 MessageBoxIcon.Information);
\r
2539 lbl_updateCheck.Visible = false;
\r
2542 catch (Exception ex)
\r
2544 if ((bool)result.AsyncState)
\r
2546 "Unable to check for updates, Please try again later.\n\nDetailed Error Information:\n" + ex,
\r
2547 "Error", MessageBoxButtons.OK, MessageBoxIcon.Error);
\r
2556 /// Handle GUI shortcuts
\r
2558 /// <param name="msg">Message</param>
\r
2559 /// <param name="keyData">Keys</param>
\r
2560 /// <returns>Bool</returns>
\r
2561 protected override bool ProcessCmdKey(ref Message msg, Keys keyData)
\r
2563 if (keyData == (Keys.Control | Keys.S))
\r
2565 btn_start_Click(this, new EventArgs());
\r
2569 if (keyData == (Keys.Control | Keys.Shift | Keys.A))
\r
2571 btn_add2Queue_Click(this, new EventArgs());
\r
2574 return base.ProcessCmdKey(ref msg, keyData);
\r
2578 /// If the queue is being processed, prompt the user to confirm application close.
\r
2580 /// <param name="e">FormClosingEventArgs</param>
\r
2581 protected override void OnFormClosing(FormClosingEventArgs e)
\r
2585 // If currently encoding, the queue isn't paused, and there are queue items to process, prompt to confirm close.
\r
2586 if (encodeQueue.IsEncoding)
\r
2588 DialogResult result =
\r
2590 "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
2591 "Close HandBrake?",
\r
2592 MessageBoxButtons.YesNo,
\r
2593 MessageBoxIcon.Question);
\r
2595 if (result == DialogResult.No)
\r
2601 encodeQueue.Stop();
\r
2604 if (SourceScan.IsScanning)
\r
2606 SourceScan.Stop();
\r
2609 SourceScan.ScanCompleted -= this.SourceScanScanCompleted;
\r
2610 SourceScan.ScanStatusChanged -= this.SourceScanScanStatusChanged;
\r
2612 catch (Exception exc)
\r
2614 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
2618 base.OnFormClosing(e);
\r
2624 // This is the END of the road ****************************************
\r