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 IQueueProcessor queueProcessor = new QueueProcessor(Program.InstanceId);
\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(this.queueProcessor, 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(this.queueProcessor);
\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 (Settings.Default.MainWindowMinimize)
\r
235 this.Resize += this.frmMain_Resize;
\r
237 // Handle Encode Start / Finish / Pause
\r
238 this.queueProcessor.EncodeService.EncodeStarted += this.encodeStarted;
\r
239 this.queueProcessor.EncodeService.EncodeCompleted += 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 += frmMain_DragEnter;
\r
247 this.DragDrop += this.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 += this.changePresetLabel;
\r
255 check_largeFile.CheckedChanged += this.changePresetLabel;
\r
256 check_iPodAtom.CheckedChanged += this.changePresetLabel;
\r
257 check_optimiseMP4.CheckedChanged += this.changePresetLabel;
\r
259 // Picture Settings
\r
260 PictureSettings.PictureSettingsChanged += this.changePresetLabel;
\r
263 Filters.FilterSettingsChanged += this.changePresetLabel;
\r
266 drp_videoEncoder.SelectedIndexChanged += this.changePresetLabel;
\r
267 check_2PassEncode.CheckedChanged += this.changePresetLabel;
\r
268 check_turbo.CheckedChanged += this.changePresetLabel;
\r
269 text_filesize.TextChanged += this.changePresetLabel;
\r
270 text_bitrate.TextChanged += this.changePresetLabel;
\r
271 slider_videoQuality.ValueChanged += this.changePresetLabel;
\r
274 AudioSettings.AudioListChanged += this.changePresetLabel;
\r
277 x264Panel.rtf_x264Query.TextChanged += this.changePresetLabel;
\r
280 private void UnRegisterPresetEventHandler()
\r
282 // Output Settings
\r
283 drop_format.SelectedIndexChanged -= this.changePresetLabel;
\r
284 check_largeFile.CheckedChanged -= this.changePresetLabel;
\r
285 check_iPodAtom.CheckedChanged -= this.changePresetLabel;
\r
286 check_optimiseMP4.CheckedChanged -= this.changePresetLabel;
\r
288 // Picture Settings
\r
289 PictureSettings.PictureSettingsChanged -= this.changePresetLabel;
\r
292 Filters.FilterSettingsChanged -= this.changePresetLabel;
\r
295 drp_videoEncoder.SelectedIndexChanged -= this.changePresetLabel;
\r
296 check_2PassEncode.CheckedChanged -= this.changePresetLabel;
\r
297 check_turbo.CheckedChanged -= this.changePresetLabel;
\r
298 text_filesize.TextChanged -= this.changePresetLabel;
\r
299 text_bitrate.TextChanged -= this.changePresetLabel;
\r
300 slider_videoQuality.ValueChanged -= this.changePresetLabel;
\r
303 AudioSettings.AudioListChanged -= this.changePresetLabel;
\r
306 x264Panel.rtf_x264Query.TextChanged -= this.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 this.queueProcessor.EncodeService.EncodeStatusChanged += EncodeQueue_EncodeStatusChanged;
\r
346 private void encodeEnded(object sender, EventArgs e)
\r
348 this.queueProcessor.EncodeService.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 this.queueProcessor.Pause();
\r
1052 if (Settings.Default.showCliForInGuiEncodeStatus)
\r
1053 this.queueProcessor.EncodeService.SafelyStop();
\r
1055 this.queueProcessor.EncodeService.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 (this.queueProcessor.QueueManager.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 QueueTask task = new QueueTask(query)
\r
1121 Title = this.GetTitle(),
\r
1122 Source = jobSourcePath,
\r
1123 Destination = jobDestination,
\r
1124 CustomQuery = (this.rtf_query.Text != string.Empty)
\r
1127 if (this.queueProcessor.QueueManager.Count == 0)
\r
1128 this.queueProcessor.QueueManager.Add(task);
\r
1130 queueWindow.SetQueue();
\r
1131 if (this.queueProcessor.QueueManager.Count > 1)
\r
1132 queueWindow.Show(false);
\r
1134 SetEncodeStarted(); // Encode is running, so setup the GUI appropriately
\r
1135 this.queueProcessor.Start(); // Start The Queue Encoding Process
\r
1140 else if (string.IsNullOrEmpty(sourcePath) || string.IsNullOrEmpty(text_destination.Text))
\r
1141 MessageBox.Show("No source or destination selected.", "Warning", MessageBoxButtons.OK,
\r
1142 MessageBoxIcon.Warning);
\r
1147 /// Toolbar - Add the current job to the Queue
\r
1149 /// <param name="sender">
\r
1152 /// <param name="e">
\r
1155 private void btn_add2Queue_Click(object sender, EventArgs e)
\r
1157 // Add the item to the queue.
\r
1158 AddItemToQueue(true);
\r
1159 queueWindow.Show();
\r
1163 /// Add Multiple Items to the Queue at once.
\r
1165 /// <param name="sender">The Sender</param>
\r
1166 /// <param name="e">The EventArgs</param>
\r
1167 private void MnuAddMultiToQueueClick(object sender, EventArgs e)
\r
1169 if (!Settings.Default.autoNaming)
\r
1171 MessageBox.Show("Destination Auto Naming must be enabled in preferences for this feature to work.", "Error", MessageBoxButtons.OK, MessageBoxIcon.Error);
\r
1175 if (this.SourceScan.SouceData == null)
\r
1177 MessageBox.Show("You must first scan a source or collection of source to use this feature.", "Error", MessageBoxButtons.OK, MessageBoxIcon.Error);
\r
1181 BatchAdd batchAdd = new BatchAdd();
\r
1182 if (batchAdd.ShowDialog() == DialogResult.OK)
\r
1184 int min = batchAdd.Min;
\r
1185 int max = batchAdd.Max;
\r
1186 bool errors = false;
\r
1188 foreach (Title title in this.SourceScan.SouceData.Titles)
\r
1190 if (title.Duration.TotalMinutes > min && title.Duration.TotalMinutes < max)
\r
1193 this.drp_dvdtitle.SelectedItem = title;
\r
1195 if (!this.AddItemToQueue(false))
\r
1205 "One or more items could not be added to the queue. You should check your queue and manually add any missing jobs.",
\r
1207 MessageBoxButtons.OK,
\r
1208 MessageBoxIcon.Warning);
\r
1213 private bool AddItemToQueue(bool showError)
\r
1215 string query = QueryGenerator.GenerateFullQuery(this);
\r
1216 if (!string.IsNullOrEmpty(rtf_query.Text))
\r
1217 query = rtf_query.Text;
\r
1219 // 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
1220 string jobSourcePath = !string.IsNullOrEmpty(rtf_query.Text) ? Main.GetSourceFromQuery(rtf_query.Text) : sourcePath;
\r
1221 string jobDestination = !string.IsNullOrEmpty(rtf_query.Text) ? Main.GetDestinationFromQuery(rtf_query.Text) : text_destination.Text;
\r
1223 // Make sure we have a Source and Destination.
\r
1224 if (string.IsNullOrEmpty(jobSourcePath) || string.IsNullOrEmpty(jobDestination))
\r
1227 MessageBox.Show("No source or destination selected.", "Warning", MessageBoxButtons.OK, MessageBoxIcon.Warning);
\r
1231 // Make sure the destination path exists.
\r
1232 if (!Directory.Exists(Path.GetDirectoryName(jobDestination)))
\r
1235 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
1239 // Make sure we don't have a duplciate on the queue.
\r
1240 if (this.queueProcessor.QueueManager.CheckForDestinationPathDuplicates(jobDestination))
\r
1244 DialogResult result;
\r
1248 "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
1251 MessageBoxButtons.YesNo,
\r
1252 MessageBoxIcon.Warning);
\r
1254 if (result != DialogResult.Yes) return false;
\r
1263 QueueTask task = new QueueTask(query)
\r
1265 Title = this.GetTitle(),
\r
1266 Source = jobSourcePath,
\r
1267 Destination = jobDestination,
\r
1268 CustomQuery = (this.rtf_query.Text != string.Empty)
\r
1270 this.queueProcessor.QueueManager.Add(task);
\r
1272 lbl_encode.Text = this.queueProcessor.QueueManager.Count + " encode(s) pending in the queue";
\r
1278 /// Toolbar - Show the Queue
\r
1280 /// <param name="sender">
\r
1283 /// <param name="e">
\r
1286 private void btn_showQueue_Click(object sender, EventArgs e)
\r
1288 queueWindow.Show();
\r
1289 queueWindow.Activate();
\r
1293 /// Toolbar - Show the Preview Window
\r
1295 /// <param name="sender">
\r
1298 /// <param name="e">
\r
1301 private void tb_preview_Click(object sender, EventArgs e)
\r
1303 if (string.IsNullOrEmpty(sourcePath) || string.IsNullOrEmpty(text_destination.Text))
\r
1304 MessageBox.Show("No source or destination selected.", "Warning", MessageBoxButtons.OK,
\r
1305 MessageBoxIcon.Warning);
\r
1308 if (qtpreview == null)
\r
1310 qtpreview = new frmPreview(this);
\r
1313 else if (qtpreview.IsDisposed)
\r
1315 qtpreview = new frmPreview(this);
\r
1319 MessageBox.Show(qtpreview, "The preview window is already open!", "Warning", MessageBoxButtons.OK,
\r
1320 MessageBoxIcon.Warning);
\r
1325 /// Toolbar - Show the Activity log Window
\r
1327 /// <param name="sender">
\r
1330 /// <param name="e">
\r
1333 private void btn_ActivityWindow_Click(object sender, EventArgs e)
\r
1335 if (this.activityWindow == null || !this.activityWindow.IsHandleCreated)
\r
1336 this.activityWindow = new frmActivityWindow(this.queueProcessor.EncodeService, SourceScan);
\r
1338 this.activityWindow.Show();
\r
1339 this.activityWindow.Activate();
\r
1344 #region System Tray Icon
\r
1347 /// Handle Resizing of the main window when deaing with the Notify Icon
\r
1349 /// <param name="sender">
\r
1352 /// <param name="e">
\r
1355 private void frmMain_Resize(object sender, EventArgs e)
\r
1357 if (FormWindowState.Minimized == this.WindowState)
\r
1359 notifyIcon.Visible = true;
\r
1362 else if (FormWindowState.Normal == this.WindowState)
\r
1363 notifyIcon.Visible = false;
\r
1367 /// Double Click the Tray Icon
\r
1369 /// <param name="sender">
\r
1372 /// <param name="e">
\r
1375 private void notifyIcon_MouseDoubleClick(object sender, MouseEventArgs e)
\r
1377 this.Visible = true;
\r
1379 this.WindowState = FormWindowState.Normal;
\r
1380 notifyIcon.Visible = false;
\r
1384 /// Tray Icon - Restore Menu Item - Resture the Window
\r
1386 /// <param name="sender">
\r
1389 /// <param name="e">
\r
1392 private void btn_restore_Click(object sender, EventArgs e)
\r
1394 this.Visible = true;
\r
1396 this.WindowState = FormWindowState.Normal;
\r
1397 notifyIcon.Visible = false;
\r
1402 #region Main Window and Tab Control
\r
1405 private void BtnFolderScanClicked(object sender, EventArgs e)
\r
1407 this.btn_source.HideDropDown();
\r
1408 if (DVD_Open.ShowDialog() == DialogResult.OK)
\r
1410 this.selectedSourceType = SourceType.Folder;
\r
1411 SelectSource(DVD_Open.SelectedPath, 0);
\r
1414 UpdateSourceLabel();
\r
1417 private void BtnFileScanClicked(object sender, EventArgs e)
\r
1419 this.btn_source.HideDropDown();
\r
1420 if (ISO_Open.ShowDialog() == DialogResult.OK)
\r
1422 this.selectedSourceType = SourceType.VideoFile;
\r
1423 SelectSource(ISO_Open.FileName, 0);
\r
1426 UpdateSourceLabel();
\r
1429 private void MnuDvdDriveClick(object sender, EventArgs e)
\r
1431 ToolStripMenuItem item = sender as ToolStripMenuItem;
\r
1434 string driveId = item.Name.Replace("Drive", string.Empty);
\r
1436 if (int.TryParse(driveId, out id))
\r
1438 this.dvdDrivePath = drives[id].RootDirectory;
\r
1439 this.dvdDriveLabel = drives[id].VolumeLabel;
\r
1441 if (this.dvdDrivePath == null) return;
\r
1442 this.selectedSourceType = SourceType.DvdDrive;
\r
1443 SelectSource(this.dvdDrivePath, 0);
\r
1448 private void VideoTitleSpecificScanClick(object sender, EventArgs e)
\r
1450 this.btn_source.HideDropDown();
\r
1451 if (ISO_Open.ShowDialog() == DialogResult.OK)
\r
1453 this.selectedSourceType = SourceType.VideoFile;
\r
1455 int sourceTitle = 0;
\r
1456 TitleSpecificScan title = new TitleSpecificScan();
\r
1457 if (title.ShowDialog() == DialogResult.OK)
\r
1459 sourceTitle = title.Title;
\r
1460 SelectSource(ISO_Open.FileName, sourceTitle);
\r
1464 UpdateSourceLabel();
\r
1467 private void FolderTitleSpecificScanClick(object sender, EventArgs e)
\r
1469 this.btn_source.HideDropDown();
\r
1470 if (DVD_Open.ShowDialog() == DialogResult.OK)
\r
1472 this.selectedSourceType = SourceType.Folder;
\r
1474 int sourceTitle = 0;
\r
1475 TitleSpecificScan title = new TitleSpecificScan();
\r
1476 if (title.ShowDialog() == DialogResult.OK)
\r
1478 sourceTitle = title.Title;
\r
1479 SelectSource(DVD_Open.SelectedPath, sourceTitle);
\r
1483 UpdateSourceLabel();
\r
1486 private void SelectSource(string file, int titleSpecific)
\r
1488 Check_ChapterMarkers.Enabled = true;
\r
1489 sourcePath = string.Empty;
\r
1491 if (file == string.Empty) // Must have a file or path
\r
1493 UpdateSourceLabel();
\r
1497 sourcePath = Path.GetFileName(file);
\r
1498 StartScan(file, titleSpecific);
\r
1501 private void drp_dvdtitle_Click(object sender, EventArgs e)
\r
1503 if ((drp_dvdtitle.Items.Count == 1) && (drp_dvdtitle.Items[0].ToString() == "Automatic"))
\r
1505 "There are no titles to select. Please load a source file by clicking the 'Source' button above before trying to select a title.",
\r
1506 "Alert", MessageBoxButtons.OK, MessageBoxIcon.Asterisk);
\r
1509 private void drp_dvdtitle_SelectedIndexChanged(object sender, EventArgs e)
\r
1511 UnRegisterPresetEventHandler();
\r
1512 drop_mode.SelectedIndex = 0;
\r
1514 drop_chapterStart.Items.Clear();
\r
1515 drop_chapterFinish.Items.Clear();
\r
1517 // If the dropdown is set to automatic nothing else needs to be done.
\r
1518 // Otheriwse if its not, title data has to be loaded from parsing.
\r
1519 if (drp_dvdtitle.Text != "Automatic")
\r
1521 selectedTitle = drp_dvdtitle.SelectedItem as Title;
\r
1522 lbl_duration.Text = selectedTitle.Duration.ToString();
\r
1523 PictureSettings.CurrentlySelectedPreset = this.currentlySelectedPreset;
\r
1524 PictureSettings.Source = selectedTitle; // Setup Picture Settings Tab Control
\r
1526 // Populate the Angles dropdown
\r
1527 drop_angle.Items.Clear();
\r
1528 if (!Properties.Settings.Default.noDvdNav)
\r
1530 drop_angle.Visible = true;
\r
1531 lbl_angle.Visible = true;
\r
1533 for (int i = 1; i <= selectedTitle.AngleCount; i++)
\r
1534 drop_angle.Items.Add(i.ToString());
\r
1536 if (drop_angle.Items.Count == 0)
\r
1538 drop_angle.Visible = false;
\r
1539 lbl_angle.Visible = false;
\r
1542 if (drop_angle.Items.Count != 0)
\r
1543 drop_angle.SelectedIndex = 0;
\r
1547 drop_angle.Visible = false;
\r
1548 lbl_angle.Visible = false;
\r
1551 // Populate the Start chapter Dropdown
\r
1552 drop_chapterStart.Items.Clear();
\r
1553 drop_chapterStart.Items.AddRange(selectedTitle.Chapters.ToArray());
\r
1554 if (drop_chapterStart.Items.Count > 0)
\r
1555 drop_chapterStart.Text = drop_chapterStart.Items[0].ToString();
\r
1557 // Populate the Final Chapter Dropdown
\r
1558 drop_chapterFinish.Items.Clear();
\r
1559 drop_chapterFinish.Items.AddRange(selectedTitle.Chapters.ToArray());
\r
1560 if (drop_chapterFinish.Items.Count > 0)
\r
1561 drop_chapterFinish.Text = drop_chapterFinish.Items[drop_chapterFinish.Items.Count - 1].ToString();
\r
1563 // Populate the Audio Channels Dropdown
\r
1564 AudioSettings.SetTrackListFromPreset(selectedTitle, this.currentlySelectedPreset);
\r
1566 // Populate the Subtitles dropdown
\r
1567 Subtitles.SetSubtitleTrackAuto(selectedTitle.Subtitles.ToArray());
\r
1569 // Update the source label if we have multiple streams
\r
1570 if (selectedTitle != null)
\r
1571 if (!string.IsNullOrEmpty(selectedTitle.SourceName))
\r
1572 labelSource.Text = Path.GetFileName(selectedTitle.SourceName);
\r
1574 // Run the AutoName & ChapterNaming functions
\r
1575 if (Properties.Settings.Default.autoNaming)
\r
1577 string autoPath = Main.AutoName(this);
\r
1578 if (autoPath != null)
\r
1579 text_destination.Text = autoPath;
\r
1582 "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
1583 "Warning", MessageBoxButtons.OK, MessageBoxIcon.Warning);
\r
1586 data_chpt.Rows.Clear();
\r
1587 if (selectedTitle.Chapters.Count != 1)
\r
1589 DataGridView chapterGridView = Main.ChapterNaming(selectedTitle, data_chpt, drop_chapterFinish.Text);
\r
1590 if (chapterGridView != null)
\r
1591 data_chpt = chapterGridView;
\r
1595 Check_ChapterMarkers.Checked = false;
\r
1596 Check_ChapterMarkers.Enabled = false;
\r
1599 // Hack to force the redraw of the scrollbars which don't resize properly when the control is disabled.
\r
1600 data_chpt.Columns[0].Width = 166;
\r
1601 data_chpt.Columns[0].Width = 165;
\r
1603 RegisterPresetEventHandler();
\r
1606 private void chapersChanged(object sender, EventArgs e)
\r
1608 if (drop_mode.SelectedIndex != 0) // Function is not used if we are not in chapters mode.
\r
1611 Control ctl = (Control)sender;
\r
1612 int chapterStart, chapterEnd;
\r
1613 int.TryParse(drop_chapterStart.Text, out chapterStart);
\r
1614 int.TryParse(drop_chapterFinish.Text, out chapterEnd);
\r
1618 case "drop_chapterStart":
\r
1619 if (drop_chapterFinish.SelectedIndex == -1 && drop_chapterFinish.Items.Count != 0)
\r
1620 drop_chapterFinish.SelectedIndex = drop_chapterFinish.Items.Count - 1;
\r
1622 if (chapterEnd != 0)
\r
1623 if (chapterStart > chapterEnd)
\r
1624 drop_chapterFinish.Text = chapterStart.ToString();
\r
1626 case "drop_chapterFinish":
\r
1627 if (drop_chapterStart.Items.Count >= 1 && drop_chapterStart.SelectedIndex == -1)
\r
1628 drop_chapterStart.SelectedIndex = 0;
\r
1630 if (chapterStart != 0)
\r
1631 if (chapterEnd < chapterStart)
\r
1632 drop_chapterFinish.Text = chapterStart.ToString();
\r
1634 // Add more rows to the Chapter menu if needed.
\r
1635 if (Check_ChapterMarkers.Checked)
\r
1637 int i = data_chpt.Rows.Count, finish = 0;
\r
1638 int.TryParse(drop_chapterFinish.Text, out finish);
\r
1640 while (i < finish)
\r
1642 int n = data_chpt.Rows.Add();
\r
1643 data_chpt.Rows[n].Cells[0].Value = (i + 1);
\r
1644 data_chpt.Rows[n].Cells[1].Value = "Chapter " + (i + 1);
\r
1645 data_chpt.Rows[n].Cells[0].ValueType = typeof(int);
\r
1646 data_chpt.Rows[n].Cells[1].ValueType = typeof(string);
\r
1653 // Update the Duration
\r
1654 lbl_duration.Text =
\r
1655 Main.CalculateDuration(drop_chapterStart.SelectedIndex, drop_chapterFinish.SelectedIndex, selectedTitle)
\r
1658 // Run the Autonaming function
\r
1659 if (Properties.Settings.Default.autoNaming)
\r
1660 text_destination.Text = Main.AutoName(this);
\r
1662 // Disable chapter markers if only 1 chapter is selected.
\r
1663 if (chapterStart == chapterEnd)
\r
1665 Check_ChapterMarkers.Enabled = false;
\r
1666 btn_importChapters.Enabled = false;
\r
1667 data_chpt.Enabled = false;
\r
1671 Check_ChapterMarkers.Enabled = true;
\r
1672 if (Check_ChapterMarkers.Checked)
\r
1674 btn_importChapters.Enabled = true;
\r
1675 data_chpt.Enabled = true;
\r
1680 private void SecondsOrFramesChanged(object sender, EventArgs e)
\r
1683 int.TryParse(drop_chapterStart.Text, out start);
\r
1684 int.TryParse(drop_chapterFinish.Text, out end);
\r
1685 double duration = end - start;
\r
1687 switch (drop_mode.SelectedIndex)
\r
1690 lbl_duration.Text = TimeSpan.FromSeconds(duration).ToString();
\r
1693 if (selectedTitle != null)
\r
1695 duration = duration / selectedTitle.Fps;
\r
1696 lbl_duration.Text = TimeSpan.FromSeconds(duration).ToString();
\r
1699 lbl_duration.Text = "--:--:--";
\r
1705 private void drop_mode_SelectedIndexChanged(object sender, EventArgs e)
\r
1708 this.drop_chapterFinish.TextChanged -= new EventHandler(this.SecondsOrFramesChanged);
\r
1709 this.drop_chapterStart.TextChanged -= new EventHandler(this.SecondsOrFramesChanged);
\r
1712 switch (drop_mode.SelectedIndex)
\r
1715 drop_chapterStart.DropDownStyle = ComboBoxStyle.DropDownList;
\r
1716 drop_chapterFinish.DropDownStyle = ComboBoxStyle.DropDownList;
\r
1717 if (drop_chapterStart.Items.Count != 0)
\r
1719 drop_chapterStart.SelectedIndex = 0;
\r
1720 drop_chapterFinish.SelectedIndex = drop_chapterFinish.Items.Count - 1;
\r
1723 lbl_duration.Text = "--:--:--";
\r
1726 this.drop_chapterStart.TextChanged += new EventHandler(this.SecondsOrFramesChanged);
\r
1727 this.drop_chapterFinish.TextChanged += new EventHandler(this.SecondsOrFramesChanged);
\r
1728 drop_chapterStart.DropDownStyle = ComboBoxStyle.Simple;
\r
1729 drop_chapterFinish.DropDownStyle = ComboBoxStyle.Simple;
\r
1730 if (selectedTitle != null)
\r
1732 drop_chapterStart.Text = "0";
\r
1733 drop_chapterFinish.Text = selectedTitle.Duration.TotalSeconds.ToString();
\r
1737 this.drop_chapterStart.TextChanged += new EventHandler(this.SecondsOrFramesChanged);
\r
1738 this.drop_chapterFinish.TextChanged += new EventHandler(this.SecondsOrFramesChanged);
\r
1739 drop_chapterStart.DropDownStyle = ComboBoxStyle.Simple;
\r
1740 drop_chapterFinish.DropDownStyle = ComboBoxStyle.Simple;
\r
1741 if (selectedTitle != null)
\r
1743 drop_chapterStart.Text = "0";
\r
1744 drop_chapterFinish.Text = (selectedTitle.Fps * selectedTitle.Duration.TotalSeconds).ToString();
\r
1751 private void btn_destBrowse_Click(object sender, EventArgs e)
\r
1753 // This removes the file extension from the filename box on the save file dialog.
\r
1754 // It's daft but some users don't realise that typing an extension overrides the dropdown extension selected.
\r
1755 DVD_Save.FileName = Path.GetFileNameWithoutExtension(text_destination.Text);
\r
1757 if (Path.IsPathRooted(text_destination.Text))
\r
1758 DVD_Save.InitialDirectory = Path.GetDirectoryName(text_destination.Text);
\r
1760 // Show the dialog and set the main form file path
\r
1761 if (drop_format.SelectedIndex.Equals(0))
\r
1762 DVD_Save.FilterIndex = 1;
\r
1763 else if (drop_format.SelectedIndex.Equals(1))
\r
1764 DVD_Save.FilterIndex = 2;
\r
1766 if (DVD_Save.ShowDialog() == DialogResult.OK)
\r
1768 // Add a file extension manually, as FileDialog.AddExtension has issues with dots in filenames
\r
1769 switch (DVD_Save.FilterIndex)
\r
1773 !Path.GetExtension(DVD_Save.FileName).Equals(".mp4",
\r
1774 StringComparison.InvariantCultureIgnoreCase))
\r
1775 if (Properties.Settings.Default.useM4v)
\r
1776 DVD_Save.FileName = DVD_Save.FileName.Replace(".mp4", ".m4v").Replace(".mkv", ".m4v");
\r
1778 DVD_Save.FileName = DVD_Save.FileName.Replace(".m4v", ".mp4").Replace(".mkv", ".mp4");
\r
1782 !Path.GetExtension(DVD_Save.FileName).Equals(".mkv", StringComparison.InvariantCultureIgnoreCase))
\r
1783 DVD_Save.FileName = DVD_Save.FileName.Replace(".mp4", ".mkv").Replace(".m4v", ".mkv");
\r
1789 text_destination.Text = DVD_Save.FileName;
\r
1791 // Quicktime requires .m4v file for chapter markers to work. If checked, change the extension to .m4v (mp4 and m4v are the same thing)
\r
1792 if (Check_ChapterMarkers.Checked && DVD_Save.FilterIndex != 2)
\r
1793 SetExtension(".m4v");
\r
1797 private void text_destination_TextChanged(object sender, EventArgs e)
\r
1799 string path = text_destination.Text;
\r
1800 if (path.EndsWith(".mp4") || path.EndsWith(".m4v"))
\r
1801 drop_format.SelectedIndex = 0;
\r
1802 else if (path.EndsWith(".mkv"))
\r
1803 drop_format.SelectedIndex = 1;
\r
1806 // Output Settings
\r
1807 private void drop_format_SelectedIndexChanged(object sender, EventArgs e)
\r
1809 switch (drop_format.SelectedIndex)
\r
1812 if (Properties.Settings.Default.useM4v || Check_ChapterMarkers.Checked ||
\r
1813 AudioSettings.RequiresM4V() || Subtitles.RequiresM4V())
\r
1814 SetExtension(".m4v");
\r
1816 SetExtension(".mp4");
\r
1819 SetExtension(".mkv");
\r
1823 AudioSettings.SetContainer(drop_format.Text);
\r
1825 if (drop_format.Text.Contains("MP4"))
\r
1827 if (drp_videoEncoder.Items.Contains("VP3 (Theora)"))
\r
1829 drp_videoEncoder.Items.Remove("VP3 (Theora)");
\r
1830 drp_videoEncoder.SelectedIndex = 1;
\r
1833 else if (drop_format.Text.Contains("MKV"))
\r
1834 drp_videoEncoder.Items.Add("VP3 (Theora)");
\r
1837 public void SetExtension(string newExtension)
\r
1839 if (newExtension == ".mp4" || newExtension == ".m4v")
\r
1840 if (Properties.Settings.Default.useM4v || Check_ChapterMarkers.Checked || AudioSettings.RequiresM4V() ||
\r
1841 Subtitles.RequiresM4V())
\r
1842 newExtension = ".m4v";
\r
1844 newExtension = ".mp4";
\r
1846 if (Path.HasExtension(newExtension))
\r
1847 text_destination.Text = Path.ChangeExtension(text_destination.Text, newExtension);
\r
1851 private void drp_videoEncoder_SelectedIndexChanged(object sender, EventArgs e)
\r
1853 setContainerOpts();
\r
1855 // Turn off some options which are H.264 only when the user selects a non h.264 encoder
\r
1856 if (drp_videoEncoder.Text.Contains("H.264"))
\r
1858 if (check_2PassEncode.CheckState == CheckState.Checked)
\r
1859 check_turbo.Enabled = true;
\r
1861 tab_advanced.Enabled = true;
\r
1862 if ((drop_format.Text.Contains("MP4")) || (drop_format.Text.Contains("M4V")))
\r
1863 check_iPodAtom.Enabled = true;
\r
1865 check_iPodAtom.Enabled = false;
\r
1869 check_turbo.CheckState = CheckState.Unchecked;
\r
1870 check_turbo.Enabled = false;
\r
1871 tab_advanced.Enabled = false;
\r
1872 x264Panel.X264Query = string.Empty;
\r
1873 check_iPodAtom.Enabled = false;
\r
1874 check_iPodAtom.Checked = false;
\r
1877 // Setup the CQ Slider
\r
1878 switch (drp_videoEncoder.Text)
\r
1880 case "MPEG-4 (FFmpeg)":
\r
1881 if (slider_videoQuality.Value > 31)
\r
1882 slider_videoQuality.Value = 20; // Just reset to 70% QP 10 on encode change.
\r
1883 slider_videoQuality.Minimum = 1;
\r
1884 slider_videoQuality.Maximum = 31;
\r
1886 case "H.264 (x264)":
\r
1887 slider_videoQuality.Minimum = 0;
\r
1888 slider_videoQuality.TickFrequency = 1;
\r
1890 CultureInfo culture = CultureInfo.CreateSpecificCulture("en-US");
\r
1891 double cqStep = Properties.Settings.Default.x264cqstep;
\r
1892 double multiplier = 1.0 / cqStep;
\r
1893 double value = slider_videoQuality.Value * multiplier;
\r
1895 slider_videoQuality.Maximum = (int)(51 / Properties.Settings.Default.x264cqstep);
\r
1897 if (value < slider_videoQuality.Maximum)
\r
1898 slider_videoQuality.Value = slider_videoQuality.Maximum - (int)value;
\r
1901 case "VP3 (Theora)":
\r
1902 if (slider_videoQuality.Value > 63)
\r
1903 slider_videoQuality.Value = 45; // Just reset to 70% QP 45 on encode change.
\r
1904 slider_videoQuality.Minimum = 0;
\r
1905 slider_videoQuality.Maximum = 63;
\r
1911 /// When the FrameRate is not Same As Source, show the Max/Constant Mode dropdown
\r
1913 /// <param name="sender">
\r
1916 /// <param name="e">
\r
1919 private void drp_videoFramerate_SelectedIndexChanged(object sender, EventArgs e)
\r
1921 if (this.drp_videoFramerate.SelectedIndex == 0)
\r
1923 this.checkMaximumFramerate.Visible = false;
\r
1924 this.checkMaximumFramerate.CheckState = CheckState.Unchecked;
\r
1928 this.checkMaximumFramerate.Visible = true;
\r
1933 /// Set the container format options
\r
1935 public void setContainerOpts()
\r
1937 if ((drop_format.Text.Contains("MP4")) || (drop_format.Text.Contains("M4V")))
\r
1939 check_largeFile.Enabled = true;
\r
1940 check_optimiseMP4.Enabled = true;
\r
1941 check_iPodAtom.Enabled = true;
\r
1945 check_largeFile.Enabled = false;
\r
1946 check_optimiseMP4.Enabled = false;
\r
1947 check_iPodAtom.Enabled = false;
\r
1948 check_largeFile.Checked = false;
\r
1949 check_optimiseMP4.Checked = false;
\r
1950 check_iPodAtom.Checked = false;
\r
1954 private double cachedCqStep = Properties.Settings.Default.x264cqstep;
\r
1957 /// Update the CQ slider for x264 for a new CQ step. This is set from option
\r
1959 public void setQualityFromSlider()
\r
1961 // Work out the current RF value.
\r
1962 double cqStep = this.cachedCqStep;
\r
1963 double rfValue = 51.0 - slider_videoQuality.Value * cqStep;
\r
1965 // Change the maximum value for the slider
\r
1966 slider_videoQuality.Maximum = (int)(51 / Properties.Settings.Default.x264cqstep);
\r
1968 // Reset the CQ slider to RF0
\r
1969 slider_videoQuality.Value = slider_videoQuality.Maximum;
\r
1971 // Reset the CQ slider back to the previous value as close as possible
\r
1972 double cqStepNew = Properties.Settings.Default.x264cqstep;
\r
1973 double rfValueCurrent = 51.0 - slider_videoQuality.Value * cqStepNew;
\r
1974 while (rfValueCurrent < rfValue)
\r
1976 slider_videoQuality.Value--;
\r
1977 rfValueCurrent = 51.0 - slider_videoQuality.Value * cqStepNew;
\r
1980 // Cache the CQ step for the next calculation
\r
1981 this.cachedCqStep = Properties.Settings.Default.x264cqstep;
\r
1984 private void slider_videoQuality_Scroll(object sender, EventArgs e)
\r
1986 double cqStep = Properties.Settings.Default.x264cqstep;
\r
1987 switch (drp_videoEncoder.Text)
\r
1989 case "MPEG-4 (FFmpeg)":
\r
1990 lbl_SliderValue.Text = "QP:" + (32 - slider_videoQuality.Value);
\r
1992 case "H.264 (x264)":
\r
1993 double rfValue = 51.0 - slider_videoQuality.Value * cqStep;
\r
1994 rfValue = Math.Round(rfValue, 2);
\r
1995 lbl_SliderValue.Text = "RF:" + rfValue.ToString(new CultureInfo("en-US"));
\r
1996 this.lbl_rfwarn.Visible = rfValue == 0;
\r
1998 case "VP3 (Theora)":
\r
1999 lbl_SliderValue.Text = "QP:" + slider_videoQuality.Value;
\r
2004 private void radio_targetFilesize_CheckedChanged(object sender, EventArgs e)
\r
2006 text_bitrate.Enabled = false;
\r
2007 text_filesize.Enabled = true;
\r
2008 slider_videoQuality.Enabled = false;
\r
2010 check_2PassEncode.Enabled = true;
\r
2013 private void radio_avgBitrate_CheckedChanged(object sender, EventArgs e)
\r
2015 text_bitrate.Enabled = true;
\r
2016 text_filesize.Enabled = false;
\r
2017 slider_videoQuality.Enabled = false;
\r
2019 check_2PassEncode.Enabled = true;
\r
2022 private void radio_cq_CheckedChanged(object sender, EventArgs e)
\r
2024 text_bitrate.Enabled = false;
\r
2025 text_filesize.Enabled = false;
\r
2026 slider_videoQuality.Enabled = true;
\r
2028 check_2PassEncode.Enabled = false;
\r
2029 check_2PassEncode.CheckState = CheckState.Unchecked;
\r
2032 private void check_2PassEncode_CheckedChanged(object sender, EventArgs e)
\r
2034 if (check_2PassEncode.CheckState.ToString() == "Checked")
\r
2036 if (drp_videoEncoder.Text.Contains("H.264"))
\r
2037 check_turbo.Enabled = true;
\r
2041 check_turbo.Enabled = false;
\r
2042 check_turbo.CheckState = CheckState.Unchecked;
\r
2046 // Chapter Marker Tab
\r
2047 private void Check_ChapterMarkers_CheckedChanged(object sender, EventArgs e)
\r
2049 if (Check_ChapterMarkers.Checked)
\r
2051 if (drop_format.SelectedIndex != 1)
\r
2052 SetExtension(".m4v");
\r
2053 data_chpt.Enabled = true;
\r
2054 btn_importChapters.Enabled = true;
\r
2058 if (drop_format.SelectedIndex != 1 && !Properties.Settings.Default.useM4v)
\r
2059 SetExtension(".mp4");
\r
2060 data_chpt.Enabled = false;
\r
2061 btn_importChapters.Enabled = false;
\r
2065 private void btn_importChapters_Click(object sender, EventArgs e)
\r
2067 if (File_ChapterImport.ShowDialog() == DialogResult.OK)
\r
2069 string filename = File_ChapterImport.FileName;
\r
2070 DataGridView imported = Main.ImportChapterNames(data_chpt, filename);
\r
2071 if (imported != null)
\r
2072 data_chpt = imported;
\r
2076 private void btn_export_Click(object sender, EventArgs e)
\r
2078 SaveFileDialog saveFileDialog = new SaveFileDialog();
\r
2079 saveFileDialog.Filter = "Csv File|*.csv";
\r
2080 saveFileDialog.DefaultExt = "csv";
\r
2081 if (saveFileDialog.ShowDialog() == DialogResult.OK)
\r
2083 string filename = saveFileDialog.FileName;
\r
2085 Main.SaveChapterMarkersToCsv(this, filename);
\r
2089 private void mnu_resetChapters_Click(object sender, EventArgs e)
\r
2091 data_chpt.Rows.Clear();
\r
2092 DataGridView chapterGridView = Main.ChapterNaming(selectedTitle, data_chpt, drop_chapterFinish.Text);
\r
2093 if (chapterGridView != null)
\r
2095 data_chpt = chapterGridView;
\r
2099 // Query Editor Tab
\r
2100 private void btn_generate_Query_Click(object sender, EventArgs e)
\r
2102 rtf_query.Text = QueryGenerator.GenerateFullQuery(this);
\r
2105 private void btn_clear_Click(object sender, EventArgs e)
\r
2107 rtf_query.Clear();
\r
2112 // MainWindow Components, Actions and Functions ***********************
\r
2114 #region Source Scan
\r
2117 /// Start the Scan Process
\r
2119 /// <param name="filename">
\r
2122 /// <param name="title">
\r
2125 private void StartScan(string filename, int title)
\r
2127 // Setup the GUI components for the scan.
\r
2128 sourcePath = filename;
\r
2130 this.DisableGUI();
\r
2135 SourceScan.Scan(sourcePath, title);
\r
2137 catch (Exception exc)
\r
2139 MessageBox.Show("frmMain.cs - StartScan " + exc, "Error", MessageBoxButtons.OK, MessageBoxIcon.Error);
\r
2144 /// Update the Status label for the scan
\r
2146 /// <param name="sender">
\r
2149 /// <param name="e">
\r
2152 private void SourceScanScanStatusChanged(object sender, ScanProgressEventArgs e)
\r
2154 if (this.InvokeRequired)
\r
2156 this.BeginInvoke(new ScanProgessStatus(this.SourceScanScanStatusChanged), new[] { sender, e });
\r
2160 labelSource.Text = string.Format("Processing Title: {0} of {1}", e.CurrentTitle, e.Titles);
\r
2164 /// Update the UI after the scan has completed
\r
2166 /// <param name="sender">
\r
2169 /// <param name="e">
\r
2172 private void SourceScanScanCompleted(object sender, EventArgs e)
\r
2174 if (this.InvokeRequired)
\r
2176 this.BeginInvoke(new ScanCompletedStatus(this.SourceScanScanCompleted), new[] { sender, e });
\r
2182 currentSource = SourceScan.SouceData;
\r
2184 // Setup some GUI components
\r
2185 drp_dvdtitle.Items.Clear();
\r
2186 if (currentSource.Titles.Count != 0)
\r
2187 drp_dvdtitle.Items.AddRange(currentSource.Titles.ToArray());
\r
2189 foreach (Title title in currentSource.Titles)
\r
2191 if (title.MainTitle)
\r
2193 drp_dvdtitle.SelectedItem = title;
\r
2197 if (drp_dvdtitle.SelectedItem == null && drp_dvdtitle.Items.Count > 0)
\r
2199 drp_dvdtitle.SelectedIndex = 0;
\r
2202 // Enable the creation of chapter markers if the file is an image of a dvd
\r
2203 if (drop_chapterStart.Items.Count > 0)
\r
2206 int.TryParse(drop_chapterStart.Items[0].ToString(), out start);
\r
2207 int.TryParse(drop_chapterFinish.Items[drop_chapterFinish.Items.Count - 1].ToString(), out end);
\r
2208 if (end > start) Check_ChapterMarkers.Enabled = true;
\r
2211 Check_ChapterMarkers.Enabled = false;
\r
2212 Check_ChapterMarkers.Checked = false;
\r
2213 data_chpt.Rows.Clear();
\r
2217 // If no titles were found, Display an error message
\r
2218 if (drp_dvdtitle.Items.Count == 0)
\r
2221 "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
2222 "Error", MessageBoxButtons.OK, MessageBoxIcon.Hand);
\r
2223 sourcePath = string.Empty;
\r
2225 UpdateSourceLabel();
\r
2227 // This is a bit of a hack to fix the queue editing.
\r
2228 // 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
2229 // When this occures, we want to repopulate their old settings.
\r
2230 if (queueEdit != null)
\r
2233 if (queueEdit.Query != null)
\r
2235 // Send the query from the file to the Query Parser class
\r
2236 QueryParser presetQuery = QueryParser.Parse(queueEdit.Query);
\r
2238 // Now load the preset
\r
2239 PresetLoader.LoadPreset(this, presetQuery, "Load Back From Queue");
\r
2241 // Set the destination path
\r
2242 this.text_destination.Text = queueEdit.Destination;
\r
2244 // The x264 widgets will need updated, so do this now:
\r
2245 x264Panel.StandardizeOptString();
\r
2246 x264Panel.SetCurrentSettingsInPanel();
\r
2248 // Set the crop label
\r
2249 PictureSettings.SetPresetCropWarningLabel(null);
\r
2255 // Enable the GUI components and enable any disabled components
\r
2258 catch (Exception exc)
\r
2260 MessageBox.Show("frmMain.cs - updateUIafterScan " + exc, "Error", MessageBoxButtons.OK,
\r
2261 MessageBoxIcon.Error);
\r
2267 /// Enable the GUI
\r
2269 private void EnableGUI()
\r
2273 if (InvokeRequired)
\r
2274 BeginInvoke(new UpdateWindowHandler(EnableGUI));
\r
2275 foreach (Control ctrl in Controls)
\r
2276 ctrl.Enabled = true;
\r
2277 btn_start.Enabled = true;
\r
2278 btn_showQueue.Enabled = true;
\r
2279 btn_add2Queue.Enabled = true;
\r
2280 tb_preview.Enabled = true;
\r
2281 btn_source.Enabled = true;
\r
2282 mnu_killCLI.Visible = false;
\r
2284 catch (Exception exc)
\r
2286 MessageBox.Show("frmMain.cs - EnableGUI() " + exc, "Error", MessageBoxButtons.OK, MessageBoxIcon.Error);
\r
2291 /// Disable the GUI
\r
2293 private void DisableGUI()
\r
2295 foreach (Control ctrl in Controls)
\r
2296 if (!(ctrl is StatusStrip || ctrl is MenuStrip || ctrl is ToolStrip))
\r
2297 ctrl.Enabled = false;
\r
2299 labelSource.Enabled = true;
\r
2300 labelStaticSource.Enabled = true;
\r
2301 SourceLayoutPanel.Enabled = true;
\r
2302 btn_source.Enabled = false;
\r
2303 btn_start.Enabled = false;
\r
2304 btn_showQueue.Enabled = false;
\r
2305 btn_add2Queue.Enabled = false;
\r
2306 tb_preview.Enabled = false;
\r
2307 mnu_killCLI.Visible = true;
\r
2313 private void KillScan()
\r
2315 SourceScan.ScanCompleted -= this.SourceScanScanCompleted;
\r
2319 SourceScan.Stop();
\r
2321 labelSource.Text = "Scan Cancelled";
\r
2327 private void ResetGUI()
\r
2329 drp_dvdtitle.Items.Clear();
\r
2330 drop_chapterStart.Items.Clear();
\r
2331 drop_chapterFinish.Items.Clear();
\r
2332 lbl_duration.Text = "Select a Title";
\r
2333 PictureSettings.lbl_src_res.Text = "Select a Title";
\r
2334 sourcePath = String.Empty;
\r
2335 text_destination.Text = String.Empty;
\r
2336 selectedTitle = null;
\r
2340 /// Update the Source Label
\r
2342 private void UpdateSourceLabel()
\r
2344 labelSource.Text = string.IsNullOrEmpty(sourcePath) ? "Select \"Source\" to continue." : this.SourceName;
\r
2348 /// Take a job from the Queue, rescan it, and reload the GUI for that job.
\r
2350 /// <param name="job">
\r
2353 public void RecievingJob(QueueTask job)
\r
2356 this.currentlySelectedPreset = null;
\r
2357 x264Panel.Reset2Defaults();
\r
2360 queueEdit = job; // Nasty but will do for now. TODO
\r
2361 StartScan(job.Source, job.Title);
\r
2366 #region GUI Functions and Actions
\r
2369 /// Set the GUI to it's finished encoding state.
\r
2371 private void SetEncodeFinished()
\r
2375 if (InvokeRequired)
\r
2377 BeginInvoke(new UpdateWindowHandler(SetEncodeFinished));
\r
2381 lbl_encode.Text = "Encoding Finished";
\r
2382 ProgressBarStatus.Visible = false;
\r
2383 btn_start.Text = "Start";
\r
2384 btn_start.ToolTipText = "Start the encoding process";
\r
2385 btn_start.Image = Properties.Resources.Play;
\r
2387 // If the window is minimized, display the notification in a popup.
\r
2388 if (Properties.Settings.Default.trayIconAlerts)
\r
2389 if (FormWindowState.Minimized == this.WindowState)
\r
2391 notifyIcon.BalloonTipText = lbl_encode.Text;
\r
2392 notifyIcon.ShowBalloonTip(500);
\r
2395 catch (Exception exc)
\r
2397 MessageBox.Show(exc.ToString());
\r
2402 /// Set the GUI to it's started encoding state.
\r
2404 private void SetEncodeStarted()
\r
2408 if (InvokeRequired)
\r
2410 BeginInvoke(new UpdateWindowHandler(SetEncodeStarted));
\r
2413 lbl_encode.Visible = true;
\r
2414 ProgressBarStatus.Value = 0;
\r
2415 ProgressBarStatus.Visible = true;
\r
2416 lbl_encode.Text = "Encoding with " + this.queueProcessor.QueueManager.Count + " encode(s) pending";
\r
2417 btn_start.Text = "Stop";
\r
2418 btn_start.ToolTipText = "Stop the encoding process.";
\r
2419 btn_start.Image = Properties.Resources.stop;
\r
2421 catch (Exception exc)
\r
2423 MessageBox.Show(exc.ToString());
\r
2428 /// Display the Encode Status
\r
2430 /// <param name="sender">
\r
2433 /// <param name="e">
\r
2436 private void EncodeQueue_EncodeStatusChanged(object sender, EncodeProgressEventArgs e)
\r
2438 if (this.InvokeRequired)
\r
2440 this.BeginInvoke(new EncodeProgessStatus(EncodeQueue_EncodeStatusChanged), new[] { sender, e });
\r
2446 "{0:00.00}%, FPS: {1:000.0}, Avg FPS: {2:000.0}, Time Remaining: {3}, Encode(s) Pending {4}",
\r
2447 e.PercentComplete,
\r
2448 e.CurrentFrameRate,
\r
2449 e.AverageFrameRate,
\r
2450 e.EstimatedTimeLeft,
\r
2451 this.queueProcessor.QueueManager.Count);
\r
2453 ProgressBarStatus.Value = (int)Math.Round(e.PercentComplete);
\r
2457 /// Set the DVD Drive selection in the "Source" Menu
\r
2459 private void SetDriveSelectionMenuItem()
\r
2463 if (InvokeRequired)
\r
2465 BeginInvoke(new UpdateWindowHandler(SetDriveSelectionMenuItem));
\r
2469 drives = Main.GetDrives();
\r
2471 List<ToolStripMenuItem> menuItems = new List<ToolStripMenuItem>();
\r
2472 foreach (DriveInformation drive in drives)
\r
2474 ToolStripMenuItem menuItem = new ToolStripMenuItem
\r
2476 Name = drive.ToString(),
\r
2477 Text = drive.RootDirectory + " (" + drive.VolumeLabel + ")",
\r
2478 Image = Resources.disc_small
\r
2480 menuItem.Click += new EventHandler(MnuDvdDriveClick);
\r
2481 menuItems.Add(menuItem);
\r
2484 foreach (ToolStripMenuItem item in menuItems)
\r
2485 btn_source.DropDownItems.Add(item);
\r
2487 catch (Exception exc)
\r
2489 MessageBox.Show("Error in SetDriveSelectionMenuItem" + exc);
\r
2494 /// Access the preset Handler and setup the preset panel.
\r
2496 private void LoadPresetPanel()
\r
2498 if (presetHandler.CheckIfPresetsAreOutOfDate())
\r
2499 if (!Settings.Default.presetNotification)
\r
2500 MessageBox.Show(this,
\r
2501 "HandBrake has determined your built-in presets are out of date... These presets will now be updated.",
\r
2502 "Preset Update", MessageBoxButtons.OK, MessageBoxIcon.Information);
\r
2504 presetHandler.GetPresetPanel(ref treeView_presets);
\r
2505 treeView_presets.Update();
\r
2509 /// Get the title from the selected item in the title dropdown.
\r
2514 private int GetTitle()
\r
2517 if (drp_dvdtitle.SelectedItem != null)
\r
2519 string[] titleInfo = drp_dvdtitle.SelectedItem.ToString().Split(' ');
\r
2520 int.TryParse(titleInfo[0], out title);
\r
2527 /// Handle the Update Check Finishing.
\r
2529 /// <param name="result">
\r
2532 private void UpdateCheckDoneMenu(IAsyncResult result)
\r
2534 // Make sure it's running on the calling thread
\r
2535 if (InvokeRequired)
\r
2537 Invoke(new MethodInvoker(() => this.UpdateCheckDoneMenu(result)));
\r
2540 UpdateCheckInformation info;
\r
2543 // Get the information about the new build, if any, and close the window
\r
2544 info = UpdateService.EndCheckForUpdates(result);
\r
2546 if (info.NewVersionAvailable && info.BuildInformation != null)
\r
2548 UpdateInfo updateWindow = new UpdateInfo(info.BuildInformation, Settings.Default.hb_version, Settings.Default.hb_build.ToString());
\r
2549 updateWindow.ShowDialog();
\r
2552 MessageBox.Show("There are no new updates at this time.", "Update Check", MessageBoxButtons.OK,
\r
2553 MessageBoxIcon.Information);
\r
2554 lbl_updateCheck.Visible = false;
\r
2557 catch (Exception ex)
\r
2559 if ((bool)result.AsyncState)
\r
2561 "Unable to check for updates, Please try again later.\n\nDetailed Error Information:\n" + ex,
\r
2562 "Error", MessageBoxButtons.OK, MessageBoxIcon.Error);
\r
2571 /// Handle GUI shortcuts
\r
2573 /// <param name="msg">Message</param>
\r
2574 /// <param name="keyData">Keys</param>
\r
2575 /// <returns>Bool</returns>
\r
2576 protected override bool ProcessCmdKey(ref Message msg, Keys keyData)
\r
2578 if (keyData == (Keys.Control | Keys.S))
\r
2580 btn_start_Click(this, new EventArgs());
\r
2584 if (keyData == (Keys.Control | Keys.Shift | Keys.A))
\r
2586 btn_add2Queue_Click(this, new EventArgs());
\r
2589 return base.ProcessCmdKey(ref msg, keyData);
\r
2593 /// If the queue is being processed, prompt the user to confirm application close.
\r
2595 /// <param name="e">FormClosingEventArgs</param>
\r
2596 protected override void OnFormClosing(FormClosingEventArgs e)
\r
2600 // If currently encoding, the queue isn't paused, and there are queue items to process, prompt to confirm close.
\r
2601 if (this.queueProcessor.EncodeService.IsEncoding)
\r
2603 DialogResult result =
\r
2605 "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
2606 "Close HandBrake?",
\r
2607 MessageBoxButtons.YesNo,
\r
2608 MessageBoxIcon.Question);
\r
2610 if (result == DialogResult.No)
\r
2616 this.queueProcessor.Pause();
\r
2617 this.queueProcessor.EncodeService.Stop();
\r
2620 if (SourceScan.IsScanning)
\r
2622 SourceScan.Stop();
\r
2625 SourceScan.ScanCompleted -= this.SourceScanScanCompleted;
\r
2626 SourceScan.ScanStatusChanged -= this.SourceScanScanStatusChanged;
\r
2628 catch (Exception exc)
\r
2630 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
2634 base.OnFormClosing(e);
\r
2640 // This is the END of the road ****************************************
\r