2 This file is part of the HandBrake source code.
\r
3 Homepage: <http://handbrake.fr/>.
\r
4 It may be used under the terms of the GNU General Public License. */
\r
9 using System.Collections.Generic;
\r
10 using System.ComponentModel;
\r
11 using System.Diagnostics;
\r
12 using System.Drawing;
\r
13 using System.Globalization;
\r
15 using System.Threading;
\r
16 using System.Windows.Forms;
\r
19 using HandBrake.Framework.Model;
\r
20 using HandBrake.Framework.Services;
\r
21 using HandBrake.Framework.Views;
\r
22 using HandBrake.ApplicationServices.Functions;
\r
23 using HandBrake.ApplicationServices.Model;
\r
24 using HandBrake.ApplicationServices.Parsing;
\r
25 using HandBrake.ApplicationServices.Services;
\r
26 using HandBrake.ApplicationServices.Services.Interfaces;
\r
28 using Handbrake.ToolWindows;
\r
34 using Main = Handbrake.Functions.Main;
\r
39 public partial class frmMain : Form
\r
41 // Objects which may be used by one or more other objects *************
\r
42 private IQueue encodeQueue = new Queue();
\r
43 private PresetsHandler presetHandler = new PresetsHandler();
\r
45 // Windows ************************************************************
\r
46 private frmQueue queueWindow;
\r
47 private frmPreview qtpreview;
\r
48 private frmActivityWindow activityWindow;
\r
50 // Globals: Mainly used for tracking. *********************************
\r
51 public Title selectedTitle;
\r
52 public string sourcePath;
\r
53 private SourceType selectedSourceType;
\r
54 private string dvdDrivePath;
\r
55 private string dvdDriveLabel;
\r
56 private Preset currentlySelectedPreset;
\r
57 private DVD currentSource;
\r
58 private IScan SourceScan = new ScanService();
\r
59 private List<DriveInformation> drives;
\r
60 private Job queueEdit;
\r
62 // Delegates **********************************************************
\r
63 private delegate void UpdateWindowHandler();
\r
65 // Applicaiton Startup ************************************************
\r
70 /// Gets SourceName.
\r
72 public string SourceName
\r
76 if (this.selectedSourceType == SourceType.DvdDrive)
\r
78 return this.dvdDriveLabel;
\r
81 if (selectedTitle != null && !string.IsNullOrEmpty(selectedTitle.SourceName))
\r
83 return Path.GetFileName(selectedTitle.SourceName);
\r
86 if (Path.GetFileNameWithoutExtension(this.sourcePath) != "VIDEO_TS")
\r
87 return Path.GetFileNameWithoutExtension(this.sourcePath);
\r
89 return Path.GetFileNameWithoutExtension(Path.GetDirectoryName(this.sourcePath));
\r
95 #region Application Startup
\r
98 /// Initializes a new instance of the <see cref="frmMain"/> class.
\r
100 /// <param name="args">
\r
101 /// The arguments passed in on application startup.
\r
103 public frmMain(string[] args)
\r
105 InitializeComponent();
\r
107 // Update the users config file with the CLI version data.
\r
108 Main.SetCliVersionData();
\r
110 if (Settings.Default.hb_version.Contains("svn"))
\r
112 this.Text += " " + Settings.Default.hb_version;
\r
115 // Check for new versions, if update checking is enabled
\r
116 if (Settings.Default.updateStatus)
\r
118 if (DateTime.Now.Subtract(Settings.Default.lastUpdateCheckDate).TotalDays > Properties.Settings.Default.daysBetweenUpdateCheck)
\r
120 // Set when the last update was
\r
121 Settings.Default.lastUpdateCheckDate = DateTime.Now;
\r
122 Settings.Default.Save();
\r
123 string url = Settings.Default.hb_build.ToString().EndsWith("1")
\r
124 ? Settings.Default.appcast_unstable
\r
125 : Settings.Default.appcast;
\r
126 UpdateService.BeginCheckForUpdates(new AsyncCallback(UpdateCheckDone), false, url, Settings.Default.hb_build, Settings.Default.skipversion, Settings.Default.hb_version);
\r
130 // Clear the log files in the background
\r
131 if (Settings.Default.clearOldLogs)
\r
133 Thread clearLog = new Thread(Main.ClearOldLogs);
\r
137 // Setup the GUI components
\r
138 LoadPresetPanel(); // Load the Preset Panel
\r
139 treeView_presets.ExpandAll();
\r
140 lbl_encode.Text = string.Empty;
\r
141 drop_mode.SelectedIndex = 0;
\r
142 queueWindow = new frmQueue(encodeQueue, this); // Prepare the Queue
\r
143 if (!Settings.Default.QueryEditorTab)
\r
144 tabs_panel.TabPages.RemoveAt(7); // Remove the query editor tab if the user does not want it enabled.
\r
145 if (Settings.Default.tooltipEnable)
\r
146 ToolTip.Active = true;
\r
148 // Load the user's default settings or Normal Preset
\r
149 if (Settings.Default.defaultPreset != string.Empty && presetHandler.GetPreset(Properties.Settings.Default.defaultPreset) != null)
\r
151 string query = presetHandler.GetPreset(Settings.Default.defaultPreset).Query;
\r
154 x264Panel.Reset2Defaults();
\r
156 QueryParser presetQuery = QueryParser.Parse(query);
\r
157 PresetLoader.LoadPreset(this, presetQuery, Settings.Default.defaultPreset);
\r
159 x264Panel.StandardizeOptString();
\r
160 x264Panel.SetCurrentSettingsInPanel();
\r
164 loadNormalPreset();
\r
166 // Register with Growl (if not using Growl for the encoding completion action, this wont hurt anything)
\r
167 GrowlCommunicator.Register();
\r
169 // Event Handlers and Queue Recovery
\r
171 Main.RecoverQueue(encodeQueue);
\r
173 // If have a file passed in via command arguemtents, check it's a file and try scanning it.
\r
174 if (args.Length >= 1 && (File.Exists(args[0]) || Directory.Exists(args[0])))
\r
176 this.StartScan(args[0], 0);
\r
181 /// When the update check is done, process the results.
\r
183 /// <param name="result">IAsyncResult result</param>
\r
184 private void UpdateCheckDone(IAsyncResult result)
\r
186 if (InvokeRequired)
\r
188 Invoke(new MethodInvoker(() => UpdateCheckDone(result)));
\r
194 UpdateCheckInformation info = UpdateService.EndCheckForUpdates(result);
\r
196 if (info.NewVersionAvailable)
\r
198 UpdateInfo updateWindow = new UpdateInfo(info.BuildInformation, Settings.Default.hb_version, Settings.Default.hb_build.ToString());
\r
199 updateWindow.ShowDialog();
\r
202 catch (Exception ex)
\r
204 if ((bool)result.AsyncState)
\r
205 Main.ShowExceptiowWindow("Unable to check for updates, Please try again later.", ex.ToString());
\r
213 // Encoding Events for setting up the GUI
\r
214 private void events()
\r
216 // Handle Widget changes when preset is selected.
\r
217 RegisterPresetEventHandler();
\r
219 // Handle Window Resize
\r
220 if (Properties.Settings.Default.MainWindowMinimize)
\r
221 this.Resize += new EventHandler(frmMain_Resize);
\r
223 // Handle Encode Start / Finish / Pause
\r
224 encodeQueue.EncodeStarted += new EventHandler(encodeStarted);
\r
225 encodeQueue.EncodeEnded += new EventHandler(encodeEnded);
\r
227 // Scan Started and Completed Events
\r
228 SourceScan.ScanStatusChanged += new EventHandler(SourceScan_ScanStatusChanged);
\r
229 SourceScan.ScanCompleted += new EventHandler(SourceScan_ScanCompleted);
\r
231 // Handle a file being draged onto the GUI.
\r
232 this.DragEnter += new DragEventHandler(frmMain_DragEnter);
\r
233 this.DragDrop += new DragEventHandler(frmMain_DragDrop);
\r
236 // 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
237 private void RegisterPresetEventHandler()
\r
240 drop_format.SelectedIndexChanged += new EventHandler(changePresetLabel);
\r
241 check_largeFile.CheckedChanged += new EventHandler(changePresetLabel);
\r
242 check_iPodAtom.CheckedChanged += new EventHandler(changePresetLabel);
\r
243 check_optimiseMP4.CheckedChanged += new EventHandler(changePresetLabel);
\r
245 // Picture Settings
\r
246 PictureSettings.PictureSettingsChanged += new EventHandler(changePresetLabel);
\r
249 Filters.FilterSettingsChanged += new EventHandler(changePresetLabel);
\r
252 drp_videoEncoder.SelectedIndexChanged += new EventHandler(changePresetLabel);
\r
253 check_2PassEncode.CheckedChanged += new EventHandler(changePresetLabel);
\r
254 check_turbo.CheckedChanged += new EventHandler(changePresetLabel);
\r
255 text_filesize.TextChanged += new EventHandler(changePresetLabel);
\r
256 text_bitrate.TextChanged += new EventHandler(changePresetLabel);
\r
257 slider_videoQuality.ValueChanged += new EventHandler(changePresetLabel);
\r
260 AudioSettings.AudioListChanged += new EventHandler(changePresetLabel);
\r
263 x264Panel.rtf_x264Query.TextChanged += new EventHandler(changePresetLabel);
\r
266 private void UnRegisterPresetEventHandler()
\r
268 // Output Settings
\r
269 drop_format.SelectedIndexChanged -= new EventHandler(changePresetLabel);
\r
270 check_largeFile.CheckedChanged -= new EventHandler(changePresetLabel);
\r
271 check_iPodAtom.CheckedChanged -= new EventHandler(changePresetLabel);
\r
272 check_optimiseMP4.CheckedChanged -= new EventHandler(changePresetLabel);
\r
274 // Picture Settings
\r
275 PictureSettings.PictureSettingsChanged -= new EventHandler(changePresetLabel);
\r
278 Filters.FilterSettingsChanged -= new EventHandler(changePresetLabel);
\r
281 drp_videoEncoder.SelectedIndexChanged -= new EventHandler(changePresetLabel);
\r
282 check_2PassEncode.CheckedChanged -= new EventHandler(changePresetLabel);
\r
283 check_turbo.CheckedChanged -= new EventHandler(changePresetLabel);
\r
284 text_filesize.TextChanged -= new EventHandler(changePresetLabel);
\r
285 text_bitrate.TextChanged -= new EventHandler(changePresetLabel);
\r
286 slider_videoQuality.ValueChanged -= new EventHandler(changePresetLabel);
\r
289 AudioSettings.AudioListChanged -= new EventHandler(changePresetLabel);
\r
292 x264Panel.rtf_x264Query.TextChanged -= new EventHandler(changePresetLabel);
\r
295 private void changePresetLabel(object sender, EventArgs e)
\r
297 labelPreset.Text = "Output Settings (Preset: Custom)";
\r
298 this.currentlySelectedPreset = null;
\r
301 private static void frmMain_DragEnter(object sender, DragEventArgs e)
\r
303 if (e.Data.GetDataPresent(DataFormats.FileDrop, false))
\r
304 e.Effect = DragDropEffects.All;
\r
307 private void frmMain_DragDrop(object sender, DragEventArgs e)
\r
309 string[] fileList = e.Data.GetData(DataFormats.FileDrop) as string[];
\r
310 sourcePath = string.Empty;
\r
312 if (fileList != null)
\r
314 if (!string.IsNullOrEmpty(fileList[0]))
\r
316 this.selectedSourceType = SourceType.VideoFile;
\r
317 StartScan(fileList[0], 0);
\r
320 UpdateSourceLabel();
\r
323 UpdateSourceLabel();
\r
326 private void encodeStarted(object sender, EventArgs e)
\r
328 SetEncodeStarted();
\r
329 encodeQueue.EncodeStatusChanged += EncodeQueue_EncodeStatusChanged;
\r
332 private void encodeEnded(object sender, EventArgs e)
\r
334 encodeQueue.EncodeStatusChanged -= EncodeQueue_EncodeStatusChanged;
\r
335 SetEncodeFinished();
\r
339 // User Interface Menus / Tool Strips *********************************
\r
344 /// Kill The scan menu Item
\r
346 /// <param name="sender">
\r
349 /// <param name="e">
\r
352 private void mnu_killCLI_Click(object sender, EventArgs e)
\r
358 /// Exit the Application Menu Item
\r
360 /// <param name="sender">
\r
363 /// <param name="e">
\r
366 private void mnu_exit_Click(object sender, EventArgs e)
\r
368 Application.Exit();
\r
376 /// Menu - Start Button
\r
378 /// <param name="sender">
\r
381 /// <param name="e">
\r
384 private void mnu_encode_Click(object sender, EventArgs e)
\r
386 queueWindow.Show();
\r
390 /// Menu - Display the Log Window
\r
392 /// <param name="sender">
\r
395 /// <param name="e">
\r
398 private void mnu_encodeLog_Click(object sender, EventArgs e)
\r
400 this.btn_ActivityWindow_Click(this, null);
\r
404 /// Menu - Display the Options Window
\r
406 /// <param name="sender">
\r
409 /// <param name="e">
\r
412 private void mnu_options_Click(object sender, EventArgs e)
\r
414 Form options = new frmOptions(this);
\r
415 options.ShowDialog();
\r
420 #region Presets Menu
\r
423 /// Reset the Built in Presets
\r
425 /// <param name="sender">
\r
428 /// <param name="e">
\r
431 private void mnu_presetReset_Click(object sender, EventArgs e)
\r
433 presetHandler.UpdateBuiltInPresets();
\r
435 if (treeView_presets.Nodes.Count == 0)
\r
437 "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
438 "Error", MessageBoxButtons.OK, MessageBoxIcon.Error);
\r
440 MessageBox.Show("Presets have been updated!", "Alert", MessageBoxButtons.OK, MessageBoxIcon.Information);
\r
442 treeView_presets.ExpandAll();
\r
446 /// Delete the selected preset
\r
448 /// <param name="sender">
\r
451 /// <param name="e">
\r
454 private void mnu_delete_preset_Click(object sender, EventArgs e)
\r
456 presetHandler.RemoveBuiltInPresets();
\r
457 LoadPresetPanel(); // Reload the preset panel
\r
461 /// Select the Normal preset
\r
463 /// <param name="sender">
\r
466 /// <param name="e">
\r
469 private void mnu_SelectDefault_Click(object sender, EventArgs e)
\r
471 loadNormalPreset();
\r
475 /// Import a plist Preset
\r
477 /// <param name="sender">
\r
480 /// <param name="e">
\r
483 private void mnu_importMacPreset_Click(object sender, EventArgs e)
\r
489 /// Export a Plist Preset
\r
491 /// <param name="sender">
\r
494 /// <param name="e">
\r
497 private void mnu_exportMacPreset_Click(object sender, EventArgs e)
\r
503 /// Create a new Preset
\r
505 /// <param name="sender">
\r
508 /// <param name="e">
\r
511 private void btn_new_preset_Click(object sender, EventArgs e)
\r
513 Form preset = new frmAddPreset(this, presetHandler);
\r
514 if (preset.ShowDialog() == DialogResult.OK)
\r
516 TreeNode presetTreeview = new TreeNode(presetHandler.LastPresetAdded.Name) { ForeColor = Color.Black };
\r
517 treeView_presets.Nodes.Add(presetTreeview);
\r
518 presetHandler.LastPresetAdded = null;
\r
527 /// Menu - Display the User Guide Web Page
\r
529 /// <param name="sender">
\r
532 /// <param name="e">
\r
535 private void mnu_user_guide_Click(object sender, EventArgs e)
\r
537 Process.Start("http://trac.handbrake.fr/wiki/HandBrakeGuide");
\r
541 /// Menu - Check for Updates
\r
543 /// <param name="sender">
\r
546 /// <param name="e">
\r
549 private void mnu_UpdateCheck_Click(object sender, EventArgs e)
\r
551 lbl_updateCheck.Visible = true;
\r
552 Settings.Default.lastUpdateCheckDate = DateTime.Now;
\r
553 Settings.Default.Save();
\r
554 string url = Settings.Default.hb_build.ToString().EndsWith("1")
\r
555 ? Settings.Default.appcast_unstable
\r
556 : Settings.Default.appcast;
\r
557 UpdateService.BeginCheckForUpdates(new AsyncCallback(UpdateCheckDoneMenu), false, url, Settings.Default.hb_build, Settings.Default.skipversion, Settings.Default.hb_version);
\r
561 /// Menu - Display the About Window
\r
563 /// <param name="sender">
\r
566 /// <param name="e">
\r
569 private void mnu_about_Click(object sender, EventArgs e)
\r
571 using (frmAbout About = new frmAbout())
\r
573 About.ShowDialog();
\r
582 /// RMenu - Expand All
\r
584 /// <param name="sender">
\r
587 /// <param name="e">
\r
590 private void pmnu_expandAll_Click(object sender, EventArgs e)
\r
592 treeView_presets.ExpandAll();
\r
596 /// RMenu - Collaspe All
\r
598 /// <param name="sender">
\r
601 /// <param name="e">
\r
604 private void pmnu_collapse_Click(object sender, EventArgs e)
\r
606 treeView_presets.CollapseAll();
\r
610 /// Menu - Import Preset
\r
612 /// <param name="sender">
\r
615 /// <param name="e">
\r
618 private void pmnu_import_Click(object sender, EventArgs e)
\r
624 /// RMenu - Save Changes to Preset
\r
626 /// <param name="sender">
\r
629 /// <param name="e">
\r
632 private void pmnu_saveChanges_Click(object sender, EventArgs e)
\r
634 // TODO this requires a re-think since the Query Editor has changed.
\r
635 DialogResult result =
\r
637 "Do you wish to include picture settings when updating the preset: " +
\r
638 treeView_presets.SelectedNode.Text, "Update Preset", MessageBoxButtons.YesNoCancel,
\r
639 MessageBoxIcon.Question);
\r
640 if (result == DialogResult.Yes)
\r
641 presetHandler.Update(treeView_presets.SelectedNode.Text,
\r
642 QueryGenerator.GenerateQueryForPreset(this, QueryPictureSettingsMode.SourceMaximum, true, 0, 0), true);
\r
643 else if (result == DialogResult.No)
\r
644 presetHandler.Update(treeView_presets.SelectedNode.Text,
\r
645 QueryGenerator.GenerateQueryForPreset(this, QueryPictureSettingsMode.SourceMaximum, true, 0, 0), false);
\r
649 /// RMenu - Delete Preset
\r
651 /// <param name="sender">
\r
654 /// <param name="e">
\r
657 private void pmnu_delete_click(object sender, EventArgs e)
\r
659 if (treeView_presets.SelectedNode != null)
\r
661 presetHandler.Remove(treeView_presets.SelectedNode.Text);
\r
662 treeView_presets.Nodes.Remove(treeView_presets.SelectedNode);
\r
664 treeView_presets.Select();
\r
668 /// Preset Menu Is Opening. Setup the Menu
\r
670 /// <param name="sender">
\r
673 /// <param name="e">
\r
676 private void presets_menu_Opening(object sender, CancelEventArgs e)
\r
678 // Make sure that the save menu is always disabled by default
\r
679 pmnu_saveChanges.Enabled = false;
\r
681 // Now enable the save menu if the selected preset is a user preset
\r
682 if (treeView_presets.SelectedNode != null)
\r
683 if (presetHandler.CheckIfUserPresetExists(treeView_presets.SelectedNode.Text))
\r
684 pmnu_saveChanges.Enabled = true;
\r
686 treeView_presets.Select();
\r
689 // Presets Management
\r
692 /// Button - Add a preset
\r
694 /// <param name="sender">
\r
697 /// <param name="e">
\r
700 private void btn_addPreset_Click(object sender, EventArgs e)
\r
702 Form preset = new frmAddPreset(this, presetHandler);
\r
703 if (preset.ShowDialog() == DialogResult.OK)
\r
705 TreeNode presetTreeview = new TreeNode(presetHandler.LastPresetAdded.Name) { ForeColor = Color.Black };
\r
706 treeView_presets.Nodes.Add(presetTreeview);
\r
707 presetHandler.LastPresetAdded = null;
\r
712 /// Button - remove a Preset
\r
714 /// <param name="sender">
\r
717 /// <param name="e">
\r
720 private void btn_removePreset_Click(object sender, EventArgs e)
\r
722 DialogResult result = MessageBox.Show("Are you sure you wish to delete the selected preset?", "Preset",
\r
723 MessageBoxButtons.YesNo, MessageBoxIcon.Question);
\r
724 if (result == DialogResult.Yes)
\r
726 if (treeView_presets.SelectedNode != null)
\r
728 presetHandler.Remove(treeView_presets.SelectedNode.Text);
\r
729 treeView_presets.Nodes.Remove(treeView_presets.SelectedNode);
\r
732 treeView_presets.Select();
\r
736 /// Button - Set the selected preset as the default
\r
738 /// <param name="sender">
\r
741 /// <param name="e">
\r
744 private void btn_setDefault_Click(object sender, EventArgs e)
\r
746 if (treeView_presets.SelectedNode != null)
\r
748 DialogResult result = MessageBox.Show("Are you sure you wish to set this preset as the default?",
\r
749 "Preset", MessageBoxButtons.YesNo, MessageBoxIcon.Question);
\r
750 if (result == DialogResult.Yes)
\r
752 Properties.Settings.Default.defaultPreset = treeView_presets.SelectedNode.Text;
\r
753 Properties.Settings.Default.Save();
\r
754 MessageBox.Show("New default preset set.", "Alert", MessageBoxButtons.OK, MessageBoxIcon.Information);
\r
758 MessageBox.Show("Please select a preset first.", "Warning", MessageBoxButtons.OK, MessageBoxIcon.Warning);
\r
762 /// PresetBar Mouse Down event
\r
764 /// <param name="sender">
\r
767 /// <param name="e">
\r
770 private void treeview_presets_mouseUp(object sender, MouseEventArgs e)
\r
772 if (e.Button == MouseButtons.Right)
\r
773 treeView_presets.SelectedNode = treeView_presets.GetNodeAt(e.Location);
\r
774 else if (e.Button == MouseButtons.Left)
\r
776 if (treeView_presets.GetNodeAt(e.Location) != null)
\r
778 if (labelPreset.Text.Contains(treeView_presets.GetNodeAt(e.Location).Text))
\r
783 treeView_presets.Select();
\r
787 /// Preset Bar after selecting the preset
\r
789 /// <param name="sender">
\r
792 /// <param name="e">
\r
795 private void treeView_presets_AfterSelect(object sender, TreeViewEventArgs e)
\r
801 /// When the mouse moves, display a preset
\r
803 /// <param name="sender">The Sender</param>
\r
804 /// <param name="e">the MouseEventArgs</param>
\r
805 private void TreeViewPresetsMouseMove(object sender, MouseEventArgs e)
\r
807 TreeNode theNode = this.treeView_presets.GetNodeAt(e.X, e.Y);
\r
809 if ((theNode != null))
\r
811 // Change the ToolTip only if the pointer moved to a new node.
\r
812 if (theNode.ToolTipText != this.ToolTip.GetToolTip(this.treeView_presets))
\r
814 this.ToolTip.SetToolTip(this.treeView_presets, theNode.ToolTipText);
\r
817 else // Pointer is not over a node so clear the ToolTip.
\r
819 this.ToolTip.SetToolTip(this.treeView_presets, string.Empty);
\r
824 /// Preset Bar - Handle the Delete Key
\r
826 /// <param name="sender">
\r
829 /// <param name="e">
\r
832 private void treeView_presets_deleteKey(object sender, KeyEventArgs e)
\r
834 if (e.KeyCode == Keys.Delete)
\r
836 DialogResult result = MessageBox.Show("Are you sure you wish to delete the selected preset?", "Preset",
\r
837 MessageBoxButtons.YesNo, MessageBoxIcon.Question);
\r
838 if (result == DialogResult.Yes)
\r
840 if (treeView_presets.SelectedNode != null)
\r
841 presetHandler.Remove(treeView_presets.SelectedNode.Text);
\r
843 // Remember each nodes expanded status so we can reload it
\r
844 List<bool> nodeStatus = new List<bool>();
\r
845 foreach (TreeNode node in treeView_presets.Nodes)
\r
846 nodeStatus.Add(node.IsExpanded);
\r
848 // Now reload the preset panel
\r
851 // And finally, re-expand any of the nodes if required
\r
853 foreach (TreeNode node in treeView_presets.Nodes)
\r
865 /// Select the selected preset and setup the GUI
\r
867 private void selectPreset()
\r
869 if (treeView_presets.SelectedNode != null)
\r
871 // Ok, so, we've selected a preset. Now we want to load it.
\r
872 string presetName = treeView_presets.SelectedNode.Text;
\r
873 Preset preset = presetHandler.GetPreset(presetName);
\r
874 if (preset != null)
\r
876 string query = presetHandler.GetPreset(presetName).Query;
\r
880 // Ok, Reset all the H264 widgets before changing the preset
\r
881 x264Panel.Reset2Defaults();
\r
883 // Send the query from the file to the Query Parser class
\r
884 QueryParser presetQuery = QueryParser.Parse(query);
\r
886 // Now load the preset
\r
887 PresetLoader.LoadPreset(this, presetQuery, presetName);
\r
889 // The x264 widgets will need updated, so do this now:
\r
890 x264Panel.StandardizeOptString();
\r
891 x264Panel.SetCurrentSettingsInPanel();
\r
893 // Finally, let this window have a copy of the preset settings.
\r
894 this.currentlySelectedPreset = preset;
\r
895 PictureSettings.SetPresetCropWarningLabel(preset);
\r
902 /// Load the Normal Preset
\r
904 private void loadNormalPreset()
\r
906 foreach (TreeNode treenode in treeView_presets.Nodes)
\r
908 foreach (TreeNode node in treenode.Nodes)
\r
910 if (node.Text.Equals("Normal"))
\r
911 treeView_presets.SelectedNode = treeView_presets.Nodes[treenode.Index].Nodes[0];
\r
917 /// Import a plist preset
\r
919 private void ImportPreset()
\r
921 if (openPreset.ShowDialog() == DialogResult.OK)
\r
923 QueryParser parsed = PlistPresetHandler.Import(openPreset.FileName);
\r
924 if (presetHandler.CheckIfUserPresetExists(parsed.PresetName + " (Imported)"))
\r
926 DialogResult result =
\r
927 MessageBox.Show("This preset appears to already exist. Would you like to overwrite it?",
\r
928 "Overwrite preset?",
\r
929 MessageBoxButtons.YesNo, MessageBoxIcon.Warning);
\r
930 if (result == DialogResult.Yes)
\r
932 PresetLoader.LoadPreset(this, parsed, parsed.PresetName);
\r
933 presetHandler.Update(parsed.PresetName + " (Imported)",
\r
934 QueryGenerator.GenerateFullQuery(this),
\r
935 parsed.UsesPictureSettings);
\r
940 PresetLoader.LoadPreset(this, parsed, parsed.PresetName);
\r
941 if (presetHandler.Add(parsed.PresetName + " (Imported)",
\r
942 QueryGenerator.GenerateFullQuery(this),
\r
943 parsed.UsesPictureSettings, string.Empty))
\r
945 TreeNode preset_treeview = new TreeNode(parsed.PresetName + " (Imported)")
\r
947 ForeColor = Color.Black
\r
949 treeView_presets.Nodes.Add(preset_treeview);
\r
956 /// Export a plist Preset
\r
958 private void ExportPreset()
\r
960 SaveFileDialog savefiledialog = new SaveFileDialog { Filter = "plist|*.plist" };
\r
962 if (treeView_presets.SelectedNode != null)
\r
964 if (savefiledialog.ShowDialog() == DialogResult.OK)
\r
966 Preset preset = presetHandler.GetPreset(treeView_presets.SelectedNode.Text);
\r
967 PlistPresetHandler.Export(savefiledialog.FileName, preset);
\r
977 /// 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
979 /// <param name="sender">
\r
982 /// <param name="e">
\r
985 private void btn_source_Click(object sender, EventArgs e)
\r
987 // Remove old Drive Menu Items.
\r
988 List<ToolStripMenuItem> itemsToRemove = new List<ToolStripMenuItem>();
\r
989 foreach (var item in btn_source.DropDownItems)
\r
991 if (item.GetType() == typeof(ToolStripMenuItem))
\r
993 ToolStripMenuItem menuItem = (ToolStripMenuItem)item;
\r
994 if (menuItem.Name.StartsWith("Drive"))
\r
996 itemsToRemove.Add(menuItem);
\r
1001 foreach (ToolStripMenuItem item in itemsToRemove)
\r
1002 btn_source.DropDownItems.Remove(item);
\r
1004 Thread driveInfoThread = new Thread(SetDriveSelectionMenuItem);
\r
1005 driveInfoThread.Start();
\r
1009 /// Toolbar - Start The Encode
\r
1011 /// <param name="sender">
\r
1014 /// <param name="e">
\r
1017 private void btn_start_Click(object sender, EventArgs e)
\r
1019 if (btn_start.Text == "Stop")
\r
1021 DialogResult result = !Properties.Settings.Default.showCliForInGuiEncodeStatus
\r
1022 ? MessageBox.Show(
\r
1023 "Are you sure you wish to cancel the encode?\n\nPlease note: Stopping this encode will render the file unplayable. ",
\r
1025 MessageBoxButtons.YesNo,
\r
1026 MessageBoxIcon.Question)
\r
1027 : MessageBox.Show(
\r
1028 "Are you sure you wish to cancel the encode?",
\r
1030 MessageBoxButtons.YesNo,
\r
1031 MessageBoxIcon.Question);
\r
1033 if (result == DialogResult.Yes)
\r
1035 // Pause The Queue
\r
1036 encodeQueue.Pause();
\r
1038 if (Settings.Default.showCliForInGuiEncodeStatus)
\r
1039 encodeQueue.SafelyClose();
\r
1041 encodeQueue.Stop();
\r
1046 // 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
1047 string jobSourcePath = !string.IsNullOrEmpty(rtf_query.Text) ? Main.GetSourceFromQuery(rtf_query.Text) : sourcePath;
\r
1048 string jobDestination = !string.IsNullOrEmpty(rtf_query.Text) ? Main.GetDestinationFromQuery(rtf_query.Text) : text_destination.Text;
\r
1050 if (encodeQueue.Count != 0 || (!string.IsNullOrEmpty(jobSourcePath) && !string.IsNullOrEmpty(jobDestination)))
\r
1052 string generatedQuery = QueryGenerator.GenerateFullQuery(this);
\r
1053 string specifiedQuery = rtf_query.Text != string.Empty
\r
1055 : QueryGenerator.GenerateFullQuery(this);
\r
1056 string query = string.Empty;
\r
1058 // Check to make sure the generated query matches the GUI settings
\r
1059 if (Properties.Settings.Default.PromptOnUnmatchingQueries && !string.IsNullOrEmpty(specifiedQuery) &&
\r
1060 generatedQuery != specifiedQuery)
\r
1062 DialogResult result = MessageBox.Show("The query under the \"Query Editor\" tab " +
\r
1063 "does not match the current GUI settings.\n\nBecause the manual query takes " +
\r
1064 "priority over the GUI, your recently updated settings will not be taken " +
\r
1065 "into account when encoding this job." +
\r
1066 Environment.NewLine + Environment.NewLine +
\r
1067 "Do you want to replace the manual query with the updated GUI-generated query?",
\r
1068 "Manual Query does not Match GUI",
\r
1069 MessageBoxButtons.YesNoCancel, MessageBoxIcon.Asterisk,
\r
1070 MessageBoxDefaultButton.Button3);
\r
1074 case DialogResult.Yes:
\r
1075 // Replace the manual query with the generated one
\r
1076 query = generatedQuery;
\r
1077 rtf_query.Text = generatedQuery;
\r
1079 case DialogResult.No:
\r
1080 // Use the manual query
\r
1081 query = specifiedQuery;
\r
1083 case DialogResult.Cancel:
\r
1084 // Don't start the encode
\r
1090 query = specifiedQuery;
\r
1093 DialogResult overwrite = DialogResult.Yes;
\r
1094 if (!string.IsNullOrEmpty(jobDestination) && File.Exists(jobDestination))
\r
1096 overwrite = MessageBox.Show(
\r
1097 "The destination file already exists. Are you sure you want to overwrite it?",
\r
1098 "Overwrite File?",
\r
1099 MessageBoxButtons.YesNo,
\r
1100 MessageBoxIcon.Question);
\r
1103 if (overwrite == DialogResult.Yes)
\r
1105 if (encodeQueue.Count == 0)
\r
1106 encodeQueue.Add(query, this.GetTitle(), jobSourcePath, jobDestination, (rtf_query.Text != string.Empty));
\r
1108 queueWindow.SetQueue();
\r
1109 if (encodeQueue.Count > 1)
\r
1110 queueWindow.Show(false);
\r
1112 SetEncodeStarted(); // Encode is running, so setup the GUI appropriately
\r
1113 encodeQueue.Start(); // Start The Queue Encoding Process
\r
1118 else if (string.IsNullOrEmpty(sourcePath) || string.IsNullOrEmpty(text_destination.Text))
\r
1119 MessageBox.Show("No source or destination selected.", "Warning", MessageBoxButtons.OK,
\r
1120 MessageBoxIcon.Warning);
\r
1125 /// Toolbar - Add the current job to the Queue
\r
1127 /// <param name="sender">
\r
1130 /// <param name="e">
\r
1133 private void btn_add2Queue_Click(object sender, EventArgs e)
\r
1135 // Add the item to the queue.
\r
1136 AddItemToQueue(true);
\r
1137 queueWindow.Show();
\r
1141 /// Add Multiple Items to the Queue at once.
\r
1143 /// <param name="sender">The Sender</param>
\r
1144 /// <param name="e">The EventArgs</param>
\r
1145 private void MnuAddMultiToQueueClick(object sender, EventArgs e)
\r
1147 if (!Settings.Default.autoNaming)
\r
1149 MessageBox.Show("Destination Auto Naming must be enabled in preferences for this feature to work.", "Error", MessageBoxButtons.OK, MessageBoxIcon.Error);
\r
1153 if (this.SourceScan.SouceData == null)
\r
1155 MessageBox.Show("You must first scan a source or collection of source to use this feature.", "Error", MessageBoxButtons.OK, MessageBoxIcon.Error);
\r
1159 BatchAdd batchAdd = new BatchAdd();
\r
1160 if (batchAdd.ShowDialog() == DialogResult.OK)
\r
1162 int min = batchAdd.Min;
\r
1163 int max = batchAdd.Max;
\r
1164 bool errors = false;
\r
1166 foreach (Title title in this.SourceScan.SouceData.Titles)
\r
1168 if (title.Duration.TotalMinutes > min && title.Duration.TotalMinutes < max)
\r
1171 this.drp_dvdtitle.SelectedItem = title;
\r
1173 if (!this.AddItemToQueue(false))
\r
1183 "One or more items could not be added to the queue. You should check your queue and manually add any missing jobs.",
\r
1185 MessageBoxButtons.OK,
\r
1186 MessageBoxIcon.Warning);
\r
1191 private bool AddItemToQueue(bool showError)
\r
1193 string query = QueryGenerator.GenerateFullQuery(this);
\r
1194 if (!string.IsNullOrEmpty(rtf_query.Text))
\r
1195 query = rtf_query.Text;
\r
1197 // 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
1198 string jobSourcePath = !string.IsNullOrEmpty(rtf_query.Text) ? Main.GetSourceFromQuery(rtf_query.Text) : sourcePath;
\r
1199 string jobDestination = !string.IsNullOrEmpty(rtf_query.Text) ? Main.GetDestinationFromQuery(rtf_query.Text) : text_destination.Text;
\r
1201 // Make sure we have a Source and Destination.
\r
1202 if (string.IsNullOrEmpty(jobSourcePath) || string.IsNullOrEmpty(jobDestination))
\r
1205 MessageBox.Show("No source or destination selected.", "Warning", MessageBoxButtons.OK, MessageBoxIcon.Warning);
\r
1209 // Make sure the destination path exists.
\r
1210 if (!Directory.Exists(Path.GetDirectoryName(jobDestination)))
\r
1213 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
1217 // Make sure we don't have a duplciate on the queue.
\r
1218 if (encodeQueue.CheckForDestinationDuplicate(jobDestination))
\r
1222 DialogResult result;
\r
1226 "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
1229 MessageBoxButtons.YesNo,
\r
1230 MessageBoxIcon.Warning);
\r
1232 if (result != DialogResult.Yes) return false;
\r
1241 encodeQueue.Add(query, this.GetTitle(), jobSourcePath, jobDestination, (rtf_query.Text != string.Empty));
\r
1243 lbl_encode.Text = encodeQueue.Count + " encode(s) pending in the queue";
\r
1249 /// Toolbar - Show the Queue
\r
1251 /// <param name="sender">
\r
1254 /// <param name="e">
\r
1257 private void btn_showQueue_Click(object sender, EventArgs e)
\r
1259 queueWindow.Show();
\r
1260 queueWindow.Activate();
\r
1264 /// Toolbar - Show the Preview Window
\r
1266 /// <param name="sender">
\r
1269 /// <param name="e">
\r
1272 private void tb_preview_Click(object sender, EventArgs e)
\r
1274 if (string.IsNullOrEmpty(sourcePath) || string.IsNullOrEmpty(text_destination.Text))
\r
1275 MessageBox.Show("No source or destination selected.", "Warning", MessageBoxButtons.OK,
\r
1276 MessageBoxIcon.Warning);
\r
1279 if (qtpreview == null)
\r
1281 qtpreview = new frmPreview(this);
\r
1284 else if (qtpreview.IsDisposed)
\r
1286 qtpreview = new frmPreview(this);
\r
1290 MessageBox.Show(qtpreview, "The preview window is already open!", "Warning", MessageBoxButtons.OK,
\r
1291 MessageBoxIcon.Warning);
\r
1296 /// Toolbar - Show the Activity log Window
\r
1298 /// <param name="sender">
\r
1301 /// <param name="e">
\r
1304 private void btn_ActivityWindow_Click(object sender, EventArgs e)
\r
1306 if (this.activityWindow == null || !this.activityWindow.IsHandleCreated)
\r
1307 this.activityWindow = new frmActivityWindow(encodeQueue, SourceScan);
\r
1309 this.activityWindow.Show();
\r
1310 this.activityWindow.Activate();
\r
1315 #region System Tray Icon
\r
1318 /// Handle Resizing of the main window when deaing with the Notify Icon
\r
1320 /// <param name="sender">
\r
1323 /// <param name="e">
\r
1326 private void frmMain_Resize(object sender, EventArgs e)
\r
1328 if (FormWindowState.Minimized == this.WindowState)
\r
1330 notifyIcon.Visible = true;
\r
1333 else if (FormWindowState.Normal == this.WindowState)
\r
1334 notifyIcon.Visible = false;
\r
1338 /// Double Click the Tray Icon
\r
1340 /// <param name="sender">
\r
1343 /// <param name="e">
\r
1346 private void notifyIcon_MouseDoubleClick(object sender, MouseEventArgs e)
\r
1348 this.Visible = true;
\r
1350 this.WindowState = FormWindowState.Normal;
\r
1351 notifyIcon.Visible = false;
\r
1355 /// Tray Icon - Restore Menu Item - Resture the Window
\r
1357 /// <param name="sender">
\r
1360 /// <param name="e">
\r
1363 private void btn_restore_Click(object sender, EventArgs e)
\r
1365 this.Visible = true;
\r
1367 this.WindowState = FormWindowState.Normal;
\r
1368 notifyIcon.Visible = false;
\r
1373 #region Main Window and Tab Control
\r
1376 private void BtnFolderScanClicked(object sender, EventArgs e)
\r
1378 this.btn_source.HideDropDown();
\r
1379 if (DVD_Open.ShowDialog() == DialogResult.OK)
\r
1381 this.selectedSourceType = SourceType.Folder;
\r
1382 SelectSource(DVD_Open.SelectedPath, 0);
\r
1385 UpdateSourceLabel();
\r
1388 private void BtnFileScanClicked(object sender, EventArgs e)
\r
1390 this.btn_source.HideDropDown();
\r
1391 if (ISO_Open.ShowDialog() == DialogResult.OK)
\r
1393 this.selectedSourceType = SourceType.VideoFile;
\r
1394 SelectSource(ISO_Open.FileName, 0);
\r
1397 UpdateSourceLabel();
\r
1400 private void MnuDvdDriveClick(object sender, EventArgs e)
\r
1402 ToolStripMenuItem item = sender as ToolStripMenuItem;
\r
1405 string driveId = item.Name.Replace("Drive", string.Empty);
\r
1407 if (int.TryParse(driveId, out id))
\r
1409 this.dvdDrivePath = drives[id].RootDirectory;
\r
1410 this.dvdDriveLabel = drives[id].VolumeLabel;
\r
1412 if (this.dvdDrivePath == null) return;
\r
1413 this.selectedSourceType = SourceType.DvdDrive;
\r
1414 SelectSource(this.dvdDrivePath, 0);
\r
1419 private void VideoTitleSpecificScanClick(object sender, EventArgs e)
\r
1421 this.btn_source.HideDropDown();
\r
1422 if (ISO_Open.ShowDialog() == DialogResult.OK)
\r
1424 this.selectedSourceType = SourceType.VideoFile;
\r
1426 int sourceTitle = 0;
\r
1427 TitleSpecificScan title = new TitleSpecificScan();
\r
1428 if (title.ShowDialog() == DialogResult.OK)
\r
1430 sourceTitle = title.Title;
\r
1431 SelectSource(ISO_Open.FileName, sourceTitle);
\r
1435 UpdateSourceLabel();
\r
1438 private void FolderTitleSpecificScanClick(object sender, EventArgs e)
\r
1440 this.btn_source.HideDropDown();
\r
1441 if (DVD_Open.ShowDialog() == DialogResult.OK)
\r
1443 this.selectedSourceType = SourceType.Folder;
\r
1445 int sourceTitle = 0;
\r
1446 TitleSpecificScan title = new TitleSpecificScan();
\r
1447 if (title.ShowDialog() == DialogResult.OK)
\r
1449 sourceTitle = title.Title;
\r
1450 SelectSource(DVD_Open.SelectedPath, sourceTitle);
\r
1454 UpdateSourceLabel();
\r
1457 private void SelectSource(string file, int titleSpecific)
\r
1459 Check_ChapterMarkers.Enabled = true;
\r
1460 sourcePath = string.Empty;
\r
1462 if (file == string.Empty) // Must have a file or path
\r
1464 UpdateSourceLabel();
\r
1468 sourcePath = Path.GetFileName(file);
\r
1469 StartScan(file, titleSpecific);
\r
1472 private void drp_dvdtitle_Click(object sender, EventArgs e)
\r
1474 if ((drp_dvdtitle.Items.Count == 1) && (drp_dvdtitle.Items[0].ToString() == "Automatic"))
\r
1476 "There are no titles to select. Please load a source file by clicking the 'Source' button above before trying to select a title.",
\r
1477 "Alert", MessageBoxButtons.OK, MessageBoxIcon.Asterisk);
\r
1480 private void drp_dvdtitle_SelectedIndexChanged(object sender, EventArgs e)
\r
1482 UnRegisterPresetEventHandler();
\r
1483 drop_mode.SelectedIndex = 0;
\r
1485 drop_chapterStart.Items.Clear();
\r
1486 drop_chapterFinish.Items.Clear();
\r
1488 // If the dropdown is set to automatic nothing else needs to be done.
\r
1489 // Otheriwse if its not, title data has to be loaded from parsing.
\r
1490 if (drp_dvdtitle.Text != "Automatic")
\r
1492 selectedTitle = drp_dvdtitle.SelectedItem as Title;
\r
1493 lbl_duration.Text = selectedTitle.Duration.ToString();
\r
1494 PictureSettings.CurrentlySelectedPreset = this.currentlySelectedPreset;
\r
1495 PictureSettings.Source = selectedTitle; // Setup Picture Settings Tab Control
\r
1497 // Populate the Angles dropdown
\r
1498 drop_angle.Items.Clear();
\r
1499 if (!Properties.Settings.Default.noDvdNav)
\r
1501 drop_angle.Visible = true;
\r
1502 lbl_angle.Visible = true;
\r
1504 for (int i = 1; i <= selectedTitle.AngleCount; i++)
\r
1505 drop_angle.Items.Add(i.ToString());
\r
1507 if (drop_angle.Items.Count == 0)
\r
1509 drop_angle.Visible = false;
\r
1510 lbl_angle.Visible = false;
\r
1513 if (drop_angle.Items.Count != 0)
\r
1514 drop_angle.SelectedIndex = 0;
\r
1518 drop_angle.Visible = false;
\r
1519 lbl_angle.Visible = false;
\r
1522 // Populate the Start chapter Dropdown
\r
1523 drop_chapterStart.Items.Clear();
\r
1524 drop_chapterStart.Items.AddRange(selectedTitle.Chapters.ToArray());
\r
1525 if (drop_chapterStart.Items.Count > 0)
\r
1526 drop_chapterStart.Text = drop_chapterStart.Items[0].ToString();
\r
1528 // Populate the Final Chapter Dropdown
\r
1529 drop_chapterFinish.Items.Clear();
\r
1530 drop_chapterFinish.Items.AddRange(selectedTitle.Chapters.ToArray());
\r
1531 if (drop_chapterFinish.Items.Count > 0)
\r
1532 drop_chapterFinish.Text = drop_chapterFinish.Items[drop_chapterFinish.Items.Count - 1].ToString();
\r
1534 // Populate the Audio Channels Dropdown
\r
1535 AudioSettings.SetTrackListFromPreset(selectedTitle, this.currentlySelectedPreset);
\r
1537 // Populate the Subtitles dropdown
\r
1538 Subtitles.SetSubtitleTrackAuto(selectedTitle.Subtitles.ToArray());
\r
1540 // Update the source label if we have multiple streams
\r
1541 if (selectedTitle != null)
\r
1542 if (!string.IsNullOrEmpty(selectedTitle.SourceName))
\r
1543 labelSource.Text = Path.GetFileName(selectedTitle.SourceName);
\r
1545 // Run the AutoName & ChapterNaming functions
\r
1546 if (Properties.Settings.Default.autoNaming)
\r
1548 string autoPath = Main.AutoName(this);
\r
1549 if (autoPath != null)
\r
1550 text_destination.Text = autoPath;
\r
1553 "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
1554 "Warning", MessageBoxButtons.OK, MessageBoxIcon.Warning);
\r
1557 data_chpt.Rows.Clear();
\r
1558 if (selectedTitle.Chapters.Count != 1)
\r
1560 DataGridView chapterGridView = Main.ChapterNaming(selectedTitle, data_chpt, drop_chapterFinish.Text);
\r
1561 if (chapterGridView != null)
\r
1562 data_chpt = chapterGridView;
\r
1566 Check_ChapterMarkers.Checked = false;
\r
1567 Check_ChapterMarkers.Enabled = false;
\r
1570 // Hack to force the redraw of the scrollbars which don't resize properly when the control is disabled.
\r
1571 data_chpt.Columns[0].Width = 166;
\r
1572 data_chpt.Columns[0].Width = 165;
\r
1574 RegisterPresetEventHandler();
\r
1577 private void chapersChanged(object sender, EventArgs e)
\r
1579 if (drop_mode.SelectedIndex != 0) // Function is not used if we are not in chapters mode.
\r
1582 Control ctl = (Control)sender;
\r
1583 int chapterStart, chapterEnd;
\r
1584 int.TryParse(drop_chapterStart.Text, out chapterStart);
\r
1585 int.TryParse(drop_chapterFinish.Text, out chapterEnd);
\r
1589 case "drop_chapterStart":
\r
1590 if (drop_chapterFinish.SelectedIndex == -1 && drop_chapterFinish.Items.Count != 0)
\r
1591 drop_chapterFinish.SelectedIndex = drop_chapterFinish.Items.Count - 1;
\r
1593 if (chapterEnd != 0)
\r
1594 if (chapterStart > chapterEnd)
\r
1595 drop_chapterFinish.Text = chapterStart.ToString();
\r
1597 case "drop_chapterFinish":
\r
1598 if (drop_chapterStart.Items.Count >= 1 && drop_chapterStart.SelectedIndex == -1)
\r
1599 drop_chapterStart.SelectedIndex = 0;
\r
1601 if (chapterStart != 0)
\r
1602 if (chapterEnd < chapterStart)
\r
1603 drop_chapterFinish.Text = chapterStart.ToString();
\r
1605 // Add more rows to the Chapter menu if needed.
\r
1606 if (Check_ChapterMarkers.Checked)
\r
1608 int i = data_chpt.Rows.Count, finish = 0;
\r
1609 int.TryParse(drop_chapterFinish.Text, out finish);
\r
1611 while (i < finish)
\r
1613 int n = data_chpt.Rows.Add();
\r
1614 data_chpt.Rows[n].Cells[0].Value = (i + 1);
\r
1615 data_chpt.Rows[n].Cells[1].Value = "Chapter " + (i + 1);
\r
1616 data_chpt.Rows[n].Cells[0].ValueType = typeof(int);
\r
1617 data_chpt.Rows[n].Cells[1].ValueType = typeof(string);
\r
1624 // Update the Duration
\r
1625 lbl_duration.Text =
\r
1626 Main.CalculateDuration(drop_chapterStart.SelectedIndex, drop_chapterFinish.SelectedIndex, selectedTitle)
\r
1629 // Run the Autonaming function
\r
1630 if (Properties.Settings.Default.autoNaming)
\r
1631 text_destination.Text = Main.AutoName(this);
\r
1633 // Disable chapter markers if only 1 chapter is selected.
\r
1634 if (chapterStart == chapterEnd)
\r
1636 Check_ChapterMarkers.Enabled = false;
\r
1637 btn_importChapters.Enabled = false;
\r
1638 data_chpt.Enabled = false;
\r
1642 Check_ChapterMarkers.Enabled = true;
\r
1643 if (Check_ChapterMarkers.Checked)
\r
1645 btn_importChapters.Enabled = true;
\r
1646 data_chpt.Enabled = true;
\r
1651 private void SecondsOrFramesChanged(object sender, EventArgs e)
\r
1654 int.TryParse(drop_chapterStart.Text, out start);
\r
1655 int.TryParse(drop_chapterFinish.Text, out end);
\r
1656 double duration = end - start;
\r
1658 switch (drop_mode.SelectedIndex)
\r
1661 lbl_duration.Text = TimeSpan.FromSeconds(duration).ToString();
\r
1664 if (selectedTitle != null)
\r
1666 duration = duration / selectedTitle.Fps;
\r
1667 lbl_duration.Text = TimeSpan.FromSeconds(duration).ToString();
\r
1670 lbl_duration.Text = "--:--:--";
\r
1676 private void drop_mode_SelectedIndexChanged(object sender, EventArgs e)
\r
1679 this.drop_chapterFinish.TextChanged -= new EventHandler(this.SecondsOrFramesChanged);
\r
1680 this.drop_chapterStart.TextChanged -= new EventHandler(this.SecondsOrFramesChanged);
\r
1683 switch (drop_mode.SelectedIndex)
\r
1686 drop_chapterStart.DropDownStyle = ComboBoxStyle.DropDownList;
\r
1687 drop_chapterFinish.DropDownStyle = ComboBoxStyle.DropDownList;
\r
1688 if (drop_chapterStart.Items.Count != 0)
\r
1690 drop_chapterStart.SelectedIndex = 0;
\r
1691 drop_chapterFinish.SelectedIndex = drop_chapterFinish.Items.Count - 1;
\r
1694 lbl_duration.Text = "--:--:--";
\r
1697 this.drop_chapterStart.TextChanged += new EventHandler(this.SecondsOrFramesChanged);
\r
1698 this.drop_chapterFinish.TextChanged += new EventHandler(this.SecondsOrFramesChanged);
\r
1699 drop_chapterStart.DropDownStyle = ComboBoxStyle.Simple;
\r
1700 drop_chapterFinish.DropDownStyle = ComboBoxStyle.Simple;
\r
1701 if (selectedTitle != null)
\r
1703 drop_chapterStart.Text = "0";
\r
1704 drop_chapterFinish.Text = selectedTitle.Duration.TotalSeconds.ToString();
\r
1708 this.drop_chapterStart.TextChanged += new EventHandler(this.SecondsOrFramesChanged);
\r
1709 this.drop_chapterFinish.TextChanged += new EventHandler(this.SecondsOrFramesChanged);
\r
1710 drop_chapterStart.DropDownStyle = ComboBoxStyle.Simple;
\r
1711 drop_chapterFinish.DropDownStyle = ComboBoxStyle.Simple;
\r
1712 if (selectedTitle != null)
\r
1714 drop_chapterStart.Text = "0";
\r
1715 drop_chapterFinish.Text = (selectedTitle.Fps * selectedTitle.Duration.TotalSeconds).ToString();
\r
1722 private void btn_destBrowse_Click(object sender, EventArgs e)
\r
1724 // This removes the file extension from the filename box on the save file dialog.
\r
1725 // It's daft but some users don't realise that typing an extension overrides the dropdown extension selected.
\r
1726 DVD_Save.FileName = Path.GetFileNameWithoutExtension(text_destination.Text);
\r
1728 if (Path.IsPathRooted(text_destination.Text))
\r
1729 DVD_Save.InitialDirectory = Path.GetDirectoryName(text_destination.Text);
\r
1731 // Show the dialog and set the main form file path
\r
1732 if (drop_format.SelectedIndex.Equals(0))
\r
1733 DVD_Save.FilterIndex = 1;
\r
1734 else if (drop_format.SelectedIndex.Equals(1))
\r
1735 DVD_Save.FilterIndex = 2;
\r
1737 if (DVD_Save.ShowDialog() == DialogResult.OK)
\r
1739 // Add a file extension manually, as FileDialog.AddExtension has issues with dots in filenames
\r
1740 switch (DVD_Save.FilterIndex)
\r
1744 !Path.GetExtension(DVD_Save.FileName).Equals(".mp4",
\r
1745 StringComparison.InvariantCultureIgnoreCase))
\r
1746 if (Properties.Settings.Default.useM4v)
\r
1747 DVD_Save.FileName = DVD_Save.FileName.Replace(".mp4", ".m4v").Replace(".mkv", ".m4v");
\r
1749 DVD_Save.FileName = DVD_Save.FileName.Replace(".m4v", ".mp4").Replace(".mkv", ".mp4");
\r
1753 !Path.GetExtension(DVD_Save.FileName).Equals(".mkv", StringComparison.InvariantCultureIgnoreCase))
\r
1754 DVD_Save.FileName = DVD_Save.FileName.Replace(".mp4", ".mkv").Replace(".m4v", ".mkv");
\r
1760 text_destination.Text = DVD_Save.FileName;
\r
1762 // Quicktime requires .m4v file for chapter markers to work. If checked, change the extension to .m4v (mp4 and m4v are the same thing)
\r
1763 if (Check_ChapterMarkers.Checked && DVD_Save.FilterIndex != 2)
\r
1764 SetExtension(".m4v");
\r
1768 private void text_destination_TextChanged(object sender, EventArgs e)
\r
1770 string path = text_destination.Text;
\r
1771 if (path.EndsWith(".mp4") || path.EndsWith(".m4v"))
\r
1772 drop_format.SelectedIndex = 0;
\r
1773 else if (path.EndsWith(".mkv"))
\r
1774 drop_format.SelectedIndex = 1;
\r
1777 // Output Settings
\r
1778 private void drop_format_SelectedIndexChanged(object sender, EventArgs e)
\r
1780 switch (drop_format.SelectedIndex)
\r
1783 if (Properties.Settings.Default.useM4v || Check_ChapterMarkers.Checked ||
\r
1784 AudioSettings.RequiresM4V() || Subtitles.RequiresM4V())
\r
1785 SetExtension(".m4v");
\r
1787 SetExtension(".mp4");
\r
1790 SetExtension(".mkv");
\r
1794 AudioSettings.SetContainer(drop_format.Text);
\r
1796 if (drop_format.Text.Contains("MP4"))
\r
1798 if (drp_videoEncoder.Items.Contains("VP3 (Theora)"))
\r
1800 drp_videoEncoder.Items.Remove("VP3 (Theora)");
\r
1801 drp_videoEncoder.SelectedIndex = 1;
\r
1804 else if (drop_format.Text.Contains("MKV"))
\r
1805 drp_videoEncoder.Items.Add("VP3 (Theora)");
\r
1808 public void SetExtension(string newExtension)
\r
1810 if (newExtension == ".mp4" || newExtension == ".m4v")
\r
1811 if (Properties.Settings.Default.useM4v || Check_ChapterMarkers.Checked || AudioSettings.RequiresM4V() ||
\r
1812 Subtitles.RequiresM4V())
\r
1813 newExtension = ".m4v";
\r
1815 newExtension = ".mp4";
\r
1817 if (Path.HasExtension(newExtension))
\r
1818 text_destination.Text = Path.ChangeExtension(text_destination.Text, newExtension);
\r
1822 private void drp_videoEncoder_SelectedIndexChanged(object sender, EventArgs e)
\r
1824 setContainerOpts();
\r
1826 // Turn off some options which are H.264 only when the user selects a non h.264 encoder
\r
1827 if (drp_videoEncoder.Text.Contains("H.264"))
\r
1829 if (check_2PassEncode.CheckState == CheckState.Checked)
\r
1830 check_turbo.Enabled = true;
\r
1832 tab_advanced.Enabled = true;
\r
1833 if ((drop_format.Text.Contains("MP4")) || (drop_format.Text.Contains("M4V")))
\r
1834 check_iPodAtom.Enabled = true;
\r
1836 check_iPodAtom.Enabled = false;
\r
1840 check_turbo.CheckState = CheckState.Unchecked;
\r
1841 check_turbo.Enabled = false;
\r
1842 tab_advanced.Enabled = false;
\r
1843 x264Panel.X264Query = string.Empty;
\r
1844 check_iPodAtom.Enabled = false;
\r
1845 check_iPodAtom.Checked = false;
\r
1848 // Setup the CQ Slider
\r
1849 switch (drp_videoEncoder.Text)
\r
1851 case "MPEG-4 (FFmpeg)":
\r
1852 if (slider_videoQuality.Value > 31)
\r
1853 slider_videoQuality.Value = 20; // Just reset to 70% QP 10 on encode change.
\r
1854 slider_videoQuality.Minimum = 1;
\r
1855 slider_videoQuality.Maximum = 31;
\r
1857 case "H.264 (x264)":
\r
1858 slider_videoQuality.Minimum = 0;
\r
1859 slider_videoQuality.TickFrequency = 1;
\r
1861 CultureInfo culture = CultureInfo.CreateSpecificCulture("en-US");
\r
1862 double cqStep = Properties.Settings.Default.x264cqstep;
\r
1863 double multiplier = 1.0 / cqStep;
\r
1864 double value = slider_videoQuality.Value * multiplier;
\r
1866 slider_videoQuality.Maximum = (int)(51 / Properties.Settings.Default.x264cqstep);
\r
1868 if (value < slider_videoQuality.Maximum)
\r
1869 slider_videoQuality.Value = slider_videoQuality.Maximum - (int)value;
\r
1872 case "VP3 (Theora)":
\r
1873 if (slider_videoQuality.Value > 63)
\r
1874 slider_videoQuality.Value = 45; // Just reset to 70% QP 45 on encode change.
\r
1875 slider_videoQuality.Minimum = 0;
\r
1876 slider_videoQuality.Maximum = 63;
\r
1882 /// When the FrameRate is not Same As Source, show the Max/Constant Mode dropdown
\r
1884 /// <param name="sender">
\r
1887 /// <param name="e">
\r
1890 private void drp_videoFramerate_SelectedIndexChanged(object sender, EventArgs e)
\r
1892 if (this.drp_videoFramerate.SelectedIndex == 0)
\r
1894 this.checkMaximumFramerate.Visible = false;
\r
1895 this.checkMaximumFramerate.CheckState = CheckState.Unchecked;
\r
1899 this.checkMaximumFramerate.Visible = true;
\r
1904 /// Set the container format options
\r
1906 public void setContainerOpts()
\r
1908 if ((drop_format.Text.Contains("MP4")) || (drop_format.Text.Contains("M4V")))
\r
1910 check_largeFile.Enabled = true;
\r
1911 check_optimiseMP4.Enabled = true;
\r
1912 check_iPodAtom.Enabled = true;
\r
1916 check_largeFile.Enabled = false;
\r
1917 check_optimiseMP4.Enabled = false;
\r
1918 check_iPodAtom.Enabled = false;
\r
1919 check_largeFile.Checked = false;
\r
1920 check_optimiseMP4.Checked = false;
\r
1921 check_iPodAtom.Checked = false;
\r
1925 private double cachedCqStep = Properties.Settings.Default.x264cqstep;
\r
1928 /// Update the CQ slider for x264 for a new CQ step. This is set from option
\r
1930 public void setQualityFromSlider()
\r
1932 // Work out the current RF value.
\r
1933 double cqStep = this.cachedCqStep;
\r
1934 double rfValue = 51.0 - slider_videoQuality.Value * cqStep;
\r
1936 // Change the maximum value for the slider
\r
1937 slider_videoQuality.Maximum = (int)(51 / Properties.Settings.Default.x264cqstep);
\r
1939 // Reset the CQ slider to RF0
\r
1940 slider_videoQuality.Value = slider_videoQuality.Maximum;
\r
1942 // Reset the CQ slider back to the previous value as close as possible
\r
1943 double cqStepNew = Properties.Settings.Default.x264cqstep;
\r
1944 double rfValueCurrent = 51.0 - slider_videoQuality.Value * cqStepNew;
\r
1945 while (rfValueCurrent < rfValue)
\r
1947 slider_videoQuality.Value--;
\r
1948 rfValueCurrent = 51.0 - slider_videoQuality.Value * cqStepNew;
\r
1951 // Cache the CQ step for the next calculation
\r
1952 this.cachedCqStep = Properties.Settings.Default.x264cqstep;
\r
1955 private void slider_videoQuality_Scroll(object sender, EventArgs e)
\r
1957 double cqStep = Properties.Settings.Default.x264cqstep;
\r
1958 switch (drp_videoEncoder.Text)
\r
1960 case "MPEG-4 (FFmpeg)":
\r
1961 lbl_SliderValue.Text = "QP:" + (32 - slider_videoQuality.Value);
\r
1963 case "H.264 (x264)":
\r
1964 double rfValue = 51.0 - slider_videoQuality.Value * cqStep;
\r
1965 rfValue = Math.Round(rfValue, 2);
\r
1966 lbl_SliderValue.Text = "RF:" + rfValue.ToString(new CultureInfo("en-US"));
\r
1968 case "VP3 (Theora)":
\r
1969 lbl_SliderValue.Text = "QP:" + slider_videoQuality.Value;
\r
1974 private void radio_targetFilesize_CheckedChanged(object sender, EventArgs e)
\r
1976 text_bitrate.Enabled = false;
\r
1977 text_filesize.Enabled = true;
\r
1978 slider_videoQuality.Enabled = false;
\r
1980 check_2PassEncode.Enabled = true;
\r
1983 private void radio_avgBitrate_CheckedChanged(object sender, EventArgs e)
\r
1985 text_bitrate.Enabled = true;
\r
1986 text_filesize.Enabled = false;
\r
1987 slider_videoQuality.Enabled = false;
\r
1989 check_2PassEncode.Enabled = true;
\r
1992 private void radio_cq_CheckedChanged(object sender, EventArgs e)
\r
1994 text_bitrate.Enabled = false;
\r
1995 text_filesize.Enabled = false;
\r
1996 slider_videoQuality.Enabled = true;
\r
1998 check_2PassEncode.Enabled = false;
\r
1999 check_2PassEncode.CheckState = CheckState.Unchecked;
\r
2002 private void check_2PassEncode_CheckedChanged(object sender, EventArgs e)
\r
2004 if (check_2PassEncode.CheckState.ToString() == "Checked")
\r
2006 if (drp_videoEncoder.Text.Contains("H.264"))
\r
2007 check_turbo.Enabled = true;
\r
2011 check_turbo.Enabled = false;
\r
2012 check_turbo.CheckState = CheckState.Unchecked;
\r
2016 // Chapter Marker Tab
\r
2017 private void Check_ChapterMarkers_CheckedChanged(object sender, EventArgs e)
\r
2019 if (Check_ChapterMarkers.Checked)
\r
2021 if (drop_format.SelectedIndex != 1)
\r
2022 SetExtension(".m4v");
\r
2023 data_chpt.Enabled = true;
\r
2024 btn_importChapters.Enabled = true;
\r
2028 if (drop_format.SelectedIndex != 1 && !Properties.Settings.Default.useM4v)
\r
2029 SetExtension(".mp4");
\r
2030 data_chpt.Enabled = false;
\r
2031 btn_importChapters.Enabled = false;
\r
2035 private void btn_importChapters_Click(object sender, EventArgs e)
\r
2037 if (File_ChapterImport.ShowDialog() == DialogResult.OK)
\r
2039 string filename = File_ChapterImport.FileName;
\r
2040 DataGridView imported = Main.ImportChapterNames(data_chpt, filename);
\r
2041 if (imported != null)
\r
2042 data_chpt = imported;
\r
2046 private void btn_export_Click(object sender, EventArgs e)
\r
2048 SaveFileDialog saveFileDialog = new SaveFileDialog();
\r
2049 saveFileDialog.Filter = "Csv File|*.csv";
\r
2050 saveFileDialog.DefaultExt = "csv";
\r
2051 if (saveFileDialog.ShowDialog() == DialogResult.OK)
\r
2053 string filename = saveFileDialog.FileName;
\r
2055 Main.SaveChapterMarkersToCsv(this, filename);
\r
2059 private void mnu_resetChapters_Click(object sender, EventArgs e)
\r
2061 data_chpt.Rows.Clear();
\r
2062 DataGridView chapterGridView = Main.ChapterNaming(selectedTitle, data_chpt, drop_chapterFinish.Text);
\r
2063 if (chapterGridView != null)
\r
2065 data_chpt = chapterGridView;
\r
2069 // Query Editor Tab
\r
2070 private void btn_generate_Query_Click(object sender, EventArgs e)
\r
2072 rtf_query.Text = QueryGenerator.GenerateFullQuery(this);
\r
2075 private void btn_clear_Click(object sender, EventArgs e)
\r
2077 rtf_query.Clear();
\r
2082 // MainWindow Components, Actions and Functions ***********************
\r
2084 #region Source Scan
\r
2087 /// Start the Scan Process
\r
2089 /// <param name="filename">
\r
2092 /// <param name="title">
\r
2095 private void StartScan(string filename, int title)
\r
2097 // Setup the GUI components for the scan.
\r
2098 sourcePath = filename;
\r
2100 this.DisableGUI();
\r
2105 SourceScan.Scan(sourcePath, title);
\r
2107 catch (Exception exc)
\r
2109 MessageBox.Show("frmMain.cs - StartScan " + exc, "Error", MessageBoxButtons.OK, MessageBoxIcon.Error);
\r
2114 /// Update the Status label for the scan
\r
2116 /// <param name="sender">
\r
2119 /// <param name="e">
\r
2122 private void SourceScan_ScanStatusChanged(object sender, EventArgs e)
\r
2124 UpdateScanStatusLabel();
\r
2128 /// Update the UI after the scan has completed
\r
2130 /// <param name="sender">
\r
2133 /// <param name="e">
\r
2136 private void SourceScan_ScanCompleted(object sender, EventArgs e)
\r
2138 UpdateGuiAfterScan();
\r
2142 /// Update the Scan Status Label
\r
2144 private void UpdateScanStatusLabel()
\r
2146 if (InvokeRequired)
\r
2148 BeginInvoke(new UpdateWindowHandler(UpdateScanStatusLabel));
\r
2151 labelSource.Text = SourceScan.ScanStatus;
\r
2155 /// Reset the GUI when the scan has completed
\r
2157 private void UpdateGuiAfterScan()
\r
2159 if (InvokeRequired)
\r
2161 BeginInvoke(new UpdateWindowHandler(UpdateGuiAfterScan));
\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 -= new EventHandler(SourceScan_ScanCompleted);
\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(Job 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, HandBrake.ApplicationServices.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.ScanCompleted -= new EventHandler(SourceScan_ScanCompleted);
\r
2607 SourceScan.Stop();
\r
2610 catch (Exception exc)
\r
2612 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
2616 base.OnFormClosing(e);
\r
2622 // This is the END of the road ****************************************
\r