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.Reflection;
\r
16 using System.Threading;
\r
17 using System.Windows.Forms;
\r
20 using HandBrake.ApplicationServices.Model;
\r
21 using HandBrake.ApplicationServices.Parsing;
\r
22 using HandBrake.ApplicationServices.Services;
\r
23 using HandBrake.ApplicationServices.Services.Interfaces;
\r
29 public partial class frmMain : Form
\r
31 // Objects which may be used by one or more other objects *************
\r
32 private IQueue encodeQueue = new Queue();
\r
33 private PresetsHandler presetHandler = new PresetsHandler();
\r
35 // Windows ************************************************************
\r
36 private frmQueue queueWindow;
\r
37 private frmPreview qtpreview;
\r
38 private frmActivityWindow activityWindow;
\r
39 private frmSplashScreen splash = new frmSplashScreen();
\r
41 // Globals: Mainly used for tracking. *********************************
\r
42 public Title selectedTitle;
\r
43 public string sourcePath;
\r
44 private SourceType selectedSourceType;
\r
45 private string dvdDrivePath;
\r
46 private string dvdDriveLabel;
\r
47 private Preset currentlySelectedPreset;
\r
48 private DVD currentSource;
\r
49 private IScan SourceScan = new ScanService();
\r
50 private List<DriveInformation> drives;
\r
52 // Delegates **********************************************************
\r
53 private delegate void UpdateWindowHandler();
\r
55 // Applicaiton Startup ************************************************
\r
60 /// Gets SourceName.
\r
62 public string SourceName
\r
66 if (this.selectedSourceType == SourceType.DvdDrive)
\r
68 return this.dvdDriveLabel;
\r
71 if (Path.GetFileNameWithoutExtension(this.sourcePath) != "VIDEO_TS")
\r
72 return Path.GetFileNameWithoutExtension(this.sourcePath);
\r
74 return Path.GetFileNameWithoutExtension(Path.GetDirectoryName(this.sourcePath));
\r
80 #region Application Startup
\r
83 /// Initializes a new instance of the <see cref="frmMain"/> class.
\r
85 /// <param name="args">
\r
86 /// The arguments passed in on application startup.
\r
88 public frmMain(string[] args)
\r
90 // Load and setup the splash screen in this thread
\r
92 Label lblStatus = new Label { Size = new Size(150, 20), Location = new Point(182, 102) };
\r
93 splash.Controls.Add(lblStatus);
\r
95 InitializeComponent();
\r
97 // Update the users config file with the CLI version data.
\r
98 UpdateSplashStatus(lblStatus, "Checking CLI Version Data ...");
\r
99 Main.SetCliVersionData();
\r
100 Main.CheckForValidCliVersion();
\r
102 if (Settings.Default.hb_version.Contains("svn"))
\r
104 Version v = Assembly.GetExecutingAssembly().GetName().Version;
\r
105 this.Text += " " + v.ToString(4);
\r
108 // Show the form, but leave disabled until preloading is complete then show the main form)
\r
109 this.Enabled = false;
\r
111 Application.DoEvents(); // Forces frmMain to draw
\r
113 // Check for new versions, if update checking is enabled
\r
114 if (Properties.Settings.Default.updateStatus)
\r
116 DateTime now = DateTime.Now;
\r
117 DateTime lastCheck = Properties.Settings.Default.lastUpdateCheckDate;
\r
118 TimeSpan elapsed = now.Subtract(lastCheck);
\r
119 if (elapsed.TotalDays > Properties.Settings.Default.daysBetweenUpdateCheck)
\r
121 UpdateSplashStatus(lblStatus, "Checking for updates ...");
\r
122 Main.BeginCheckForUpdates(new AsyncCallback(UpdateCheckDone), false);
\r
126 // Clear the log files in the background
\r
127 if (Properties.Settings.Default.clearOldLogs)
\r
129 UpdateSplashStatus(lblStatus, "Clearing Old Log Files ..");
\r
130 Thread clearLog = new Thread(Main.ClearOldLogs);
\r
134 // Setup the GUI components
\r
135 UpdateSplashStatus(lblStatus, "Setting up the GUI ...");
\r
136 LoadPresetPanel(); // Load the Preset Panel
\r
137 treeView_presets.ExpandAll();
\r
138 lbl_encode.Text = string.Empty;
\r
139 drop_mode.SelectedIndex = 0;
\r
140 queueWindow = new frmQueue(encodeQueue, this); // Prepare the Queue
\r
141 if (!Properties.Settings.Default.QueryEditorTab)
\r
142 tabs_panel.TabPages.RemoveAt(7); // Remove the query editor tab if the user does not want it enabled.
\r
143 if (Properties.Settings.Default.tooltipEnable)
\r
144 ToolTip.Active = true;
\r
146 // Load the user's default settings or Normal Preset
\r
147 if (Properties.Settings.Default.defaultPreset != string.Empty && presetHandler.GetPreset(Properties.Settings.Default.defaultPreset) != null)
\r
149 string query = presetHandler.GetPreset(Properties.Settings.Default.defaultPreset).Query;
\r
152 x264Panel.Reset2Defaults();
\r
154 QueryParser presetQuery = QueryParser.Parse(query);
\r
155 PresetLoader.LoadPreset(this, presetQuery, Properties.Settings.Default.defaultPreset);
\r
157 x264Panel.StandardizeOptString();
\r
158 x264Panel.SetCurrentSettingsInPanel();
\r
162 loadNormalPreset();
\r
164 // Register with Growl (if not using Growl for the encoding completion action, this wont hurt anything)
\r
165 GrowlCommunicator.Register();
\r
167 // Finished Loading
\r
168 UpdateSplashStatus(lblStatus, "Loading Complete.");
\r
171 this.Enabled = true;
\r
173 // Event Handlers and Queue Recovery
\r
177 // If have a file passed in via command arguemtents, check it's a file and try scanning it.
\r
178 if (args.Length >= 1 && (File.Exists(args[0]) || Directory.Exists(args[0])))
\r
180 this.StartScan(args[0], 0);
\r
184 private void UpdateCheckDone(IAsyncResult result)
\r
186 if (InvokeRequired)
\r
188 Invoke(new MethodInvoker(() => UpdateCheckDone(result)));
\r
192 UpdateCheckInformation info;
\r
196 info = Main.EndCheckForUpdates(result);
\r
198 if (info.NewVersionAvailable)
\r
200 frmUpdater updateWindow = new frmUpdater(info.BuildInformation);
\r
201 updateWindow.ShowDialog();
\r
204 catch (Exception ex)
\r
206 if ((bool)result.AsyncState)
\r
207 Main.ShowExceptiowWindow("Unable to check for updates, Please try again later.", ex.ToString());
\r
211 // Startup Functions
\r
212 private void queueRecovery()
\r
214 DialogResult result = DialogResult.None;
\r
215 List<string> queueFiles = Main.CheckQueueRecovery();
\r
216 if (queueFiles.Count == 1)
\r
218 result = MessageBox.Show(
\r
219 "HandBrake has detected unfinished items on the queue from the last time the application was launched. Would you like to recover these?",
\r
220 "Queue Recovery Possible", MessageBoxButtons.YesNo, MessageBoxIcon.Question);
\r
222 else if (queueFiles.Count > 1)
\r
224 result = MessageBox.Show(
\r
225 "HandBrake has detected multiple unfinished queue files. These will be from multiple instances of HandBrake running. Would you like to recover all unfinished jobs?",
\r
226 "Queue Recovery Possible", MessageBoxButtons.YesNo, MessageBoxIcon.Question);
\r
229 if (result == DialogResult.Yes)
\r
231 foreach (string file in queueFiles)
\r
233 encodeQueue.LoadQueueFromFile(file); // Start Recovery
\r
238 if (Main.IsMultiInstance) return; // Don't tamper with the files if we are multi instance
\r
240 string tempPath = Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.ApplicationData), @"HandBrake\");
\r
241 foreach (string file in queueFiles)
\r
243 if (File.Exists(Path.Combine(tempPath, file)))
\r
244 File.Delete(Path.Combine(tempPath, file));
\r
249 private void UpdateSplashStatus(Label status, string text)
\r
251 status.Text = text;
\r
252 Application.DoEvents();
\r
259 // Encoding Events for setting up the GUI
\r
260 private void events()
\r
262 // Handle Widget changes when preset is selected.
\r
263 RegisterPresetEventHandler();
\r
265 // Handle Window Resize
\r
266 if (Properties.Settings.Default.MainWindowMinimize)
\r
267 this.Resize += new EventHandler(frmMain_Resize);
\r
269 // Handle Encode Start / Finish / Pause
\r
270 encodeQueue.EncodeStarted += new EventHandler(encodeStarted);
\r
271 encodeQueue.EncodeEnded += new EventHandler(encodeEnded);
\r
273 // Handle a file being draged onto the GUI.
\r
274 this.DragEnter += new DragEventHandler(frmMain_DragEnter);
\r
275 this.DragDrop += new DragEventHandler(frmMain_DragDrop);
\r
278 // 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
279 private void RegisterPresetEventHandler()
\r
282 drop_format.SelectedIndexChanged += new EventHandler(changePresetLabel);
\r
283 check_largeFile.CheckedChanged += new EventHandler(changePresetLabel);
\r
284 check_iPodAtom.CheckedChanged += new EventHandler(changePresetLabel);
\r
285 check_optimiseMP4.CheckedChanged += new EventHandler(changePresetLabel);
\r
287 // Picture Settings
\r
288 PictureSettings.PictureSettingsChanged += new EventHandler(changePresetLabel);
\r
291 Filters.FilterSettingsChanged += new EventHandler(changePresetLabel);
\r
294 drp_videoEncoder.SelectedIndexChanged += new EventHandler(changePresetLabel);
\r
295 check_2PassEncode.CheckedChanged += new EventHandler(changePresetLabel);
\r
296 check_turbo.CheckedChanged += new EventHandler(changePresetLabel);
\r
297 text_filesize.TextChanged += new EventHandler(changePresetLabel);
\r
298 text_bitrate.TextChanged += new EventHandler(changePresetLabel);
\r
299 slider_videoQuality.ValueChanged += new EventHandler(changePresetLabel);
\r
302 AudioSettings.AudioListChanged += new EventHandler(changePresetLabel);
\r
305 x264Panel.rtf_x264Query.TextChanged += new EventHandler(changePresetLabel);
\r
308 private void UnRegisterPresetEventHandler()
\r
310 // Output Settings
\r
311 drop_format.SelectedIndexChanged -= new EventHandler(changePresetLabel);
\r
312 check_largeFile.CheckedChanged -= new EventHandler(changePresetLabel);
\r
313 check_iPodAtom.CheckedChanged -= new EventHandler(changePresetLabel);
\r
314 check_optimiseMP4.CheckedChanged -= new EventHandler(changePresetLabel);
\r
316 // Picture Settings
\r
317 PictureSettings.PictureSettingsChanged -= new EventHandler(changePresetLabel);
\r
320 Filters.FilterSettingsChanged -= new EventHandler(changePresetLabel);
\r
323 drp_videoEncoder.SelectedIndexChanged -= new EventHandler(changePresetLabel);
\r
324 check_2PassEncode.CheckedChanged -= new EventHandler(changePresetLabel);
\r
325 check_turbo.CheckedChanged -= new EventHandler(changePresetLabel);
\r
326 text_filesize.TextChanged -= new EventHandler(changePresetLabel);
\r
327 text_bitrate.TextChanged -= new EventHandler(changePresetLabel);
\r
328 slider_videoQuality.ValueChanged -= new EventHandler(changePresetLabel);
\r
331 AudioSettings.AudioListChanged -= new EventHandler(changePresetLabel);
\r
334 x264Panel.rtf_x264Query.TextChanged -= new EventHandler(changePresetLabel);
\r
337 private void changePresetLabel(object sender, EventArgs e)
\r
339 labelPreset.Text = "Output Settings (Preset: Custom)";
\r
340 this.currentlySelectedPreset = null;
\r
343 private static void frmMain_DragEnter(object sender, DragEventArgs e)
\r
345 if (e.Data.GetDataPresent(DataFormats.FileDrop, false))
\r
346 e.Effect = DragDropEffects.All;
\r
349 private void frmMain_DragDrop(object sender, DragEventArgs e)
\r
351 string[] fileList = e.Data.GetData(DataFormats.FileDrop) as string[];
\r
352 sourcePath = string.Empty;
\r
354 if (fileList != null)
\r
356 if (!string.IsNullOrEmpty(fileList[0]))
\r
358 this.selectedSourceType = SourceType.VideoFile;
\r
359 StartScan(fileList[0], 0);
\r
362 UpdateSourceLabel();
\r
365 UpdateSourceLabel();
\r
368 private void encodeStarted(object sender, EventArgs e)
\r
370 SetEncodeStarted();
\r
371 encodeQueue.EncodeStatusChanged += EncodeQueue_EncodeStatusChanged;
\r
374 private void encodeEnded(object sender, EventArgs e)
\r
376 encodeQueue.EncodeStatusChanged -= EncodeQueue_EncodeStatusChanged;
\r
377 SetEncodeFinished();
\r
381 // User Interface Menus / Tool Strips *********************************
\r
386 /// Kill The scan menu Item
\r
388 /// <param name="sender">
\r
391 /// <param name="e">
\r
394 private void mnu_killCLI_Click(object sender, EventArgs e)
\r
400 /// Exit the Application Menu Item
\r
402 /// <param name="sender">
\r
405 /// <param name="e">
\r
408 private void mnu_exit_Click(object sender, EventArgs e)
\r
410 Application.Exit();
\r
418 /// Menu - Start Button
\r
420 /// <param name="sender">
\r
423 /// <param name="e">
\r
426 private void mnu_encode_Click(object sender, EventArgs e)
\r
428 queueWindow.Show();
\r
432 /// Menu - Display the Log Window
\r
434 /// <param name="sender">
\r
437 /// <param name="e">
\r
440 private void mnu_encodeLog_Click(object sender, EventArgs e)
\r
442 frmActivityWindow dvdInfoWindow = new frmActivityWindow(encodeQueue, SourceScan);
\r
443 dvdInfoWindow.Show();
\r
447 /// Menu - Display the Options Window
\r
449 /// <param name="sender">
\r
452 /// <param name="e">
\r
455 private void mnu_options_Click(object sender, EventArgs e)
\r
457 Form options = new frmOptions(this);
\r
458 options.ShowDialog();
\r
463 #region Presets Menu
\r
466 /// Reset the Built in Presets
\r
468 /// <param name="sender">
\r
471 /// <param name="e">
\r
474 private void mnu_presetReset_Click(object sender, EventArgs e)
\r
476 presetHandler.UpdateBuiltInPresets();
\r
478 if (treeView_presets.Nodes.Count == 0)
\r
480 "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
481 "Error", MessageBoxButtons.OK, MessageBoxIcon.Error);
\r
483 MessageBox.Show("Presets have been updated!", "Alert", MessageBoxButtons.OK, MessageBoxIcon.Information);
\r
485 treeView_presets.ExpandAll();
\r
489 /// Delete the selected preset
\r
491 /// <param name="sender">
\r
494 /// <param name="e">
\r
497 private void mnu_delete_preset_Click(object sender, EventArgs e)
\r
499 presetHandler.RemoveBuiltInPresets();
\r
500 LoadPresetPanel(); // Reload the preset panel
\r
504 /// Select the Normal preset
\r
506 /// <param name="sender">
\r
509 /// <param name="e">
\r
512 private void mnu_SelectDefault_Click(object sender, EventArgs e)
\r
514 loadNormalPreset();
\r
518 /// Import a plist Preset
\r
520 /// <param name="sender">
\r
523 /// <param name="e">
\r
526 private void mnu_importMacPreset_Click(object sender, EventArgs e)
\r
532 /// Export a Plist Preset
\r
534 /// <param name="sender">
\r
537 /// <param name="e">
\r
540 private void mnu_exportMacPreset_Click(object sender, EventArgs e)
\r
546 /// Create a new Preset
\r
548 /// <param name="sender">
\r
551 /// <param name="e">
\r
554 private void btn_new_preset_Click(object sender, EventArgs e)
\r
556 Form preset = new frmAddPreset(this, presetHandler);
\r
557 if (preset.ShowDialog() == DialogResult.OK)
\r
559 TreeNode presetTreeview = new TreeNode(presetHandler.LastPresetAdded.Name) { ForeColor = Color.Black };
\r
560 treeView_presets.Nodes.Add(presetTreeview);
\r
561 presetHandler.LastPresetAdded = null;
\r
570 /// Menu - Display the User Guide Web Page
\r
572 /// <param name="sender">
\r
575 /// <param name="e">
\r
578 private void mnu_user_guide_Click(object sender, EventArgs e)
\r
580 Process.Start("http://trac.handbrake.fr/wiki/HandBrakeGuide");
\r
584 /// Menu - Check for Updates
\r
586 /// <param name="sender">
\r
589 /// <param name="e">
\r
592 private void mnu_UpdateCheck_Click(object sender, EventArgs e)
\r
594 lbl_updateCheck.Visible = true;
\r
595 Main.BeginCheckForUpdates(new AsyncCallback(this.UpdateCheckDoneMenu), false);
\r
599 /// Menu - Display the About Window
\r
601 /// <param name="sender">
\r
604 /// <param name="e">
\r
607 private void mnu_about_Click(object sender, EventArgs e)
\r
609 using (frmAbout About = new frmAbout())
\r
611 About.ShowDialog();
\r
620 /// RMenu - Expand All
\r
622 /// <param name="sender">
\r
625 /// <param name="e">
\r
628 private void pmnu_expandAll_Click(object sender, EventArgs e)
\r
630 treeView_presets.ExpandAll();
\r
634 /// RMenu - Collaspe All
\r
636 /// <param name="sender">
\r
639 /// <param name="e">
\r
642 private void pmnu_collapse_Click(object sender, EventArgs e)
\r
644 treeView_presets.CollapseAll();
\r
648 /// Menu - Import Preset
\r
650 /// <param name="sender">
\r
653 /// <param name="e">
\r
656 private void pmnu_import_Click(object sender, EventArgs e)
\r
662 /// RMenu - Save Changes to Preset
\r
664 /// <param name="sender">
\r
667 /// <param name="e">
\r
670 private void pmnu_saveChanges_Click(object sender, EventArgs e)
\r
672 // TODO this requires a re-think since the Query Editor has changed.
\r
673 DialogResult result =
\r
675 "Do you wish to include picture settings when updating the preset: " +
\r
676 treeView_presets.SelectedNode.Text, "Update Preset", MessageBoxButtons.YesNoCancel,
\r
677 MessageBoxIcon.Question);
\r
678 if (result == DialogResult.Yes)
\r
679 presetHandler.Update(treeView_presets.SelectedNode.Text,
\r
680 QueryGenerator.GenerateQueryForPreset(this, QueryPictureSettingsMode.SourceMaximum, true, 0, 0), true);
\r
681 else if (result == DialogResult.No)
\r
682 presetHandler.Update(treeView_presets.SelectedNode.Text,
\r
683 QueryGenerator.GenerateQueryForPreset(this, QueryPictureSettingsMode.SourceMaximum, true, 0, 0), false);
\r
687 /// RMenu - Delete Preset
\r
689 /// <param name="sender">
\r
692 /// <param name="e">
\r
695 private void pmnu_delete_click(object sender, EventArgs e)
\r
697 if (treeView_presets.SelectedNode != null)
\r
699 presetHandler.Remove(treeView_presets.SelectedNode.Text);
\r
700 treeView_presets.Nodes.Remove(treeView_presets.SelectedNode);
\r
702 treeView_presets.Select();
\r
706 /// Preset Menu Is Opening. Setup the Menu
\r
708 /// <param name="sender">
\r
711 /// <param name="e">
\r
714 private void presets_menu_Opening(object sender, CancelEventArgs e)
\r
716 // Make sure that the save menu is always disabled by default
\r
717 pmnu_saveChanges.Enabled = false;
\r
719 // Now enable the save menu if the selected preset is a user preset
\r
720 if (treeView_presets.SelectedNode != null)
\r
721 if (presetHandler.CheckIfUserPresetExists(treeView_presets.SelectedNode.Text))
\r
722 pmnu_saveChanges.Enabled = true;
\r
724 treeView_presets.Select();
\r
727 // Presets Management
\r
730 /// Button - Add a preset
\r
732 /// <param name="sender">
\r
735 /// <param name="e">
\r
738 private void btn_addPreset_Click(object sender, EventArgs e)
\r
740 Form preset = new frmAddPreset(this, presetHandler);
\r
741 if (preset.ShowDialog() == DialogResult.OK)
\r
743 TreeNode presetTreeview = new TreeNode(presetHandler.LastPresetAdded.Name) { ForeColor = Color.Black };
\r
744 treeView_presets.Nodes.Add(presetTreeview);
\r
745 presetHandler.LastPresetAdded = null;
\r
750 /// Button - remove a Preset
\r
752 /// <param name="sender">
\r
755 /// <param name="e">
\r
758 private void btn_removePreset_Click(object sender, EventArgs e)
\r
760 DialogResult result = MessageBox.Show("Are you sure you wish to delete the selected preset?", "Preset",
\r
761 MessageBoxButtons.YesNo, MessageBoxIcon.Question);
\r
762 if (result == DialogResult.Yes)
\r
764 if (treeView_presets.SelectedNode != null)
\r
766 presetHandler.Remove(treeView_presets.SelectedNode.Text);
\r
767 treeView_presets.Nodes.Remove(treeView_presets.SelectedNode);
\r
770 treeView_presets.Select();
\r
774 /// Button - Set the selected preset as the default
\r
776 /// <param name="sender">
\r
779 /// <param name="e">
\r
782 private void btn_setDefault_Click(object sender, EventArgs e)
\r
784 if (treeView_presets.SelectedNode != null)
\r
786 DialogResult result = MessageBox.Show("Are you sure you wish to set this preset as the default?",
\r
787 "Preset", MessageBoxButtons.YesNo, MessageBoxIcon.Question);
\r
788 if (result == DialogResult.Yes)
\r
790 Properties.Settings.Default.defaultPreset = treeView_presets.SelectedNode.Text;
\r
791 Properties.Settings.Default.Save();
\r
792 MessageBox.Show("New default preset set.", "Alert", MessageBoxButtons.OK, MessageBoxIcon.Information);
\r
796 MessageBox.Show("Please select a preset first.", "Warning", MessageBoxButtons.OK, MessageBoxIcon.Warning);
\r
800 /// PresetBar Mouse Down event
\r
802 /// <param name="sender">
\r
805 /// <param name="e">
\r
808 private void treeview_presets_mouseUp(object sender, MouseEventArgs e)
\r
810 if (e.Button == MouseButtons.Right)
\r
811 treeView_presets.SelectedNode = treeView_presets.GetNodeAt(e.Location);
\r
812 else if (e.Button == MouseButtons.Left)
\r
814 if (treeView_presets.GetNodeAt(e.Location) != null)
\r
816 if (labelPreset.Text.Contains(treeView_presets.GetNodeAt(e.Location).Text))
\r
821 treeView_presets.Select();
\r
825 /// Preset Bar after selecting the preset
\r
827 /// <param name="sender">
\r
830 /// <param name="e">
\r
833 private void treeView_presets_AfterSelect(object sender, TreeViewEventArgs e)
\r
839 /// Preset Bar - Handle the Delete Key
\r
841 /// <param name="sender">
\r
844 /// <param name="e">
\r
847 private void treeView_presets_deleteKey(object sender, KeyEventArgs e)
\r
849 if (e.KeyCode == Keys.Delete)
\r
851 DialogResult result = MessageBox.Show("Are you sure you wish to delete the selected preset?", "Preset",
\r
852 MessageBoxButtons.YesNo, MessageBoxIcon.Question);
\r
853 if (result == DialogResult.Yes)
\r
855 if (treeView_presets.SelectedNode != null)
\r
856 presetHandler.Remove(treeView_presets.SelectedNode.Text);
\r
858 // Remember each nodes expanded status so we can reload it
\r
859 List<bool> nodeStatus = new List<bool>();
\r
860 foreach (TreeNode node in treeView_presets.Nodes)
\r
861 nodeStatus.Add(node.IsExpanded);
\r
863 // Now reload the preset panel
\r
866 // And finally, re-expand any of the nodes if required
\r
868 foreach (TreeNode node in treeView_presets.Nodes)
\r
880 /// Select the selected preset and setup the GUI
\r
882 private void selectPreset()
\r
884 if (treeView_presets.SelectedNode != null)
\r
886 // Ok, so, we've selected a preset. Now we want to load it.
\r
887 string presetName = treeView_presets.SelectedNode.Text;
\r
888 Preset preset = presetHandler.GetPreset(presetName);
\r
889 if (preset != null)
\r
891 string query = presetHandler.GetPreset(presetName).Query;
\r
895 // Ok, Reset all the H264 widgets before changing the preset
\r
896 x264Panel.Reset2Defaults();
\r
898 // Send the query from the file to the Query Parser class
\r
899 QueryParser presetQuery = QueryParser.Parse(query);
\r
901 // Now load the preset
\r
902 PresetLoader.LoadPreset(this, presetQuery, presetName);
\r
904 // The x264 widgets will need updated, so do this now:
\r
905 x264Panel.StandardizeOptString();
\r
906 x264Panel.SetCurrentSettingsInPanel();
\r
908 // Finally, let this window have a copy of the preset settings.
\r
909 this.currentlySelectedPreset = preset;
\r
910 PictureSettings.SetPresetCropWarningLabel(preset);
\r
917 /// Load the Normal Preset
\r
919 private void loadNormalPreset()
\r
921 foreach (TreeNode treenode in treeView_presets.Nodes)
\r
923 foreach (TreeNode node in treenode.Nodes)
\r
925 if (node.Text.Equals("Normal"))
\r
926 treeView_presets.SelectedNode = treeView_presets.Nodes[treenode.Index].Nodes[0];
\r
932 /// Import a plist preset
\r
934 private void ImportPreset()
\r
936 if (openPreset.ShowDialog() == DialogResult.OK)
\r
938 QueryParser parsed = PlistPresetHandler.Import(openPreset.FileName);
\r
939 if (presetHandler.CheckIfUserPresetExists(parsed.PresetName + " (Imported)"))
\r
941 DialogResult result =
\r
942 MessageBox.Show("This preset appears to already exist. Would you like to overwrite it?",
\r
943 "Overwrite preset?",
\r
944 MessageBoxButtons.YesNo, MessageBoxIcon.Warning);
\r
945 if (result == DialogResult.Yes)
\r
947 PresetLoader.LoadPreset(this, parsed, parsed.PresetName);
\r
948 presetHandler.Update(parsed.PresetName + " (Imported)",
\r
949 QueryGenerator.GenerateFullQuery(this),
\r
950 parsed.UsesPictureSettings);
\r
955 PresetLoader.LoadPreset(this, parsed, parsed.PresetName);
\r
956 if (presetHandler.Add(parsed.PresetName + " (Imported)",
\r
957 QueryGenerator.GenerateFullQuery(this),
\r
958 parsed.UsesPictureSettings))
\r
960 TreeNode preset_treeview = new TreeNode(parsed.PresetName + " (Imported)")
\r
962 ForeColor = Color.Black
\r
964 treeView_presets.Nodes.Add(preset_treeview);
\r
971 /// Export a plist Preset
\r
973 private void ExportPreset()
\r
975 MessageBox.Show("This feature has not been implimented yet.", "Not Implimented", MessageBoxButtons.OK, MessageBoxIcon.Warning);
\r
978 SaveFileDialog savefiledialog = new SaveFileDialog();
\r
979 savefiledialog.Filter = "plist|*.plist";
\r
981 if (treeView_presets.SelectedNode != null)
\r
984 if (savefiledialog.ShowDialog() == DialogResult.OK)
\r
986 Preset preset = presetHandler.GetPreset(treeView_presets.SelectedNode.Text);
\r
987 PlistPresetHandler.Export(savefiledialog.FileName, preset);
\r
997 /// 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
999 /// <param name="sender">
\r
1002 /// <param name="e">
\r
1005 private void btn_source_Click(object sender, EventArgs e)
\r
1007 // Remove old Drive Menu Items.
\r
1008 List<ToolStripMenuItem> itemsToRemove = new List<ToolStripMenuItem>();
\r
1009 foreach (var item in btn_source.DropDownItems)
\r
1011 if (item.GetType() == typeof(ToolStripMenuItem))
\r
1013 ToolStripMenuItem menuItem = (ToolStripMenuItem)item;
\r
1014 if (menuItem.Name.StartsWith("Drive"))
\r
1016 itemsToRemove.Add(menuItem);
\r
1021 foreach (ToolStripMenuItem item in itemsToRemove)
\r
1022 btn_source.DropDownItems.Remove(item);
\r
1024 Thread driveInfoThread = new Thread(SetDriveSelectionMenuItem);
\r
1025 driveInfoThread.Start();
\r
1029 /// Toolbar - Start The Encode
\r
1031 /// <param name="sender">
\r
1034 /// <param name="e">
\r
1037 private void btn_start_Click(object sender, EventArgs e)
\r
1039 if (btn_start.Text == "Stop")
\r
1041 DialogResult result = !Properties.Settings.Default.showCliForInGuiEncodeStatus
\r
1042 ? MessageBox.Show(
\r
1043 "Are you sure you wish to cancel the encode?\n\nPlease note: Stopping this encode will render the file unplayable. ",
\r
1045 MessageBoxButtons.YesNo,
\r
1046 MessageBoxIcon.Question)
\r
1047 : MessageBox.Show(
\r
1048 "Are you sure you wish to cancel the encode?",
\r
1050 MessageBoxButtons.YesNo,
\r
1051 MessageBoxIcon.Question);
\r
1053 if (result == DialogResult.Yes)
\r
1055 // Pause The Queue
\r
1056 encodeQueue.Pause();
\r
1058 if (Settings.Default.showCliForInGuiEncodeStatus)
\r
1059 encodeQueue.SafelyClose();
\r
1061 encodeQueue.Stop();
\r
1066 // 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
1067 string jobSourcePath = !string.IsNullOrEmpty(rtf_query.Text) ? Main.GetSourceFromQuery(rtf_query.Text) : sourcePath;
\r
1068 string jobDestination = !string.IsNullOrEmpty(rtf_query.Text) ? Main.GetDestinationFromQuery(rtf_query.Text) : text_destination.Text;
\r
1070 if (encodeQueue.Count != 0 || (!string.IsNullOrEmpty(jobSourcePath) && !string.IsNullOrEmpty(jobDestination)))
\r
1072 string generatedQuery = QueryGenerator.GenerateFullQuery(this);
\r
1073 string specifiedQuery = rtf_query.Text != string.Empty
\r
1075 : QueryGenerator.GenerateFullQuery(this);
\r
1076 string query = string.Empty;
\r
1078 // Check to make sure the generated query matches the GUI settings
\r
1079 if (Properties.Settings.Default.PromptOnUnmatchingQueries && !string.IsNullOrEmpty(specifiedQuery) &&
\r
1080 generatedQuery != specifiedQuery)
\r
1082 DialogResult result = MessageBox.Show("The query under the \"Query Editor\" tab " +
\r
1083 "does not match the current GUI settings.\n\nBecause the manual query takes " +
\r
1084 "priority over the GUI, your recently updated settings will not be taken " +
\r
1085 "into account when encoding this job." +
\r
1086 Environment.NewLine + Environment.NewLine +
\r
1087 "Do you want to replace the manual query with the updated GUI-generated query?",
\r
1088 "Manual Query does not Match GUI",
\r
1089 MessageBoxButtons.YesNoCancel, MessageBoxIcon.Asterisk,
\r
1090 MessageBoxDefaultButton.Button3);
\r
1094 case DialogResult.Yes:
\r
1095 // Replace the manual query with the generated one
\r
1096 query = generatedQuery;
\r
1097 rtf_query.Text = generatedQuery;
\r
1099 case DialogResult.No:
\r
1100 // Use the manual query
\r
1101 query = specifiedQuery;
\r
1103 case DialogResult.Cancel:
\r
1104 // Don't start the encode
\r
1110 query = specifiedQuery;
\r
1113 DialogResult overwrite = DialogResult.Yes;
\r
1114 if (!string.IsNullOrEmpty(jobDestination) && File.Exists(jobDestination))
\r
1116 overwrite = MessageBox.Show(
\r
1117 "The destination file already exists. Are you sure you want to overwrite it?",
\r
1118 "Overwrite File?",
\r
1119 MessageBoxButtons.YesNo,
\r
1120 MessageBoxIcon.Question);
\r
1123 if (overwrite == DialogResult.Yes)
\r
1125 if (encodeQueue.Count == 0)
\r
1126 encodeQueue.Add(query, this.GetTitle(), jobSourcePath, jobDestination, (rtf_query.Text != string.Empty));
\r
1128 queueWindow.SetQueue();
\r
1129 if (encodeQueue.Count > 1)
\r
1130 queueWindow.Show(false);
\r
1132 SetEncodeStarted(); // Encode is running, so setup the GUI appropriately
\r
1133 encodeQueue.Start(); // Start The Queue Encoding Process
\r
1138 else if (string.IsNullOrEmpty(sourcePath) || string.IsNullOrEmpty(text_destination.Text))
\r
1139 MessageBox.Show("No source or destination selected.", "Warning", MessageBoxButtons.OK,
\r
1140 MessageBoxIcon.Warning);
\r
1145 /// Toolbar - Add the current job to the Queue
\r
1147 /// <param name="sender">
\r
1150 /// <param name="e">
\r
1153 private void btn_add2Queue_Click(object sender, EventArgs e)
\r
1155 // Get the CLI query or use the query editor if it's not empty.
\r
1156 string query = QueryGenerator.GenerateFullQuery(this);
\r
1157 if (!string.IsNullOrEmpty(rtf_query.Text))
\r
1158 query = rtf_query.Text;
\r
1160 // 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
1161 string jobSourcePath = !string.IsNullOrEmpty(rtf_query.Text) ? Main.GetSourceFromQuery(rtf_query.Text) : sourcePath;
\r
1162 string jobDestination = !string.IsNullOrEmpty(rtf_query.Text) ? Main.GetDestinationFromQuery(rtf_query.Text) : text_destination.Text;
\r
1164 // Make sure we have a Source and Destination.
\r
1165 if (string.IsNullOrEmpty(jobSourcePath) || string.IsNullOrEmpty(jobDestination))
\r
1167 MessageBox.Show("No source or destination selected.", "Warning", MessageBoxButtons.OK, MessageBoxIcon.Warning);
\r
1171 // Make sure the destination path exists.
\r
1172 if (!Directory.Exists(Path.GetDirectoryName(jobDestination)))
\r
1174 MessageBox.Show("Destination Path does not exist.", "Warning", MessageBoxButtons.OK, MessageBoxIcon.Warning);
\r
1178 // Make sure we don't have a duplciate on the queue.
\r
1179 if (encodeQueue.CheckForDestinationDuplicate(jobDestination))
\r
1181 DialogResult result =
\r
1183 "There is already a queue item for this destination path. \n\n If you continue, the encode will be overwritten. Do you wish to continue?",
\r
1184 "Warning", MessageBoxButtons.YesNo, MessageBoxIcon.Warning);
\r
1185 if (result == DialogResult.Yes)
\r
1186 encodeQueue.Add(query, this.GetTitle(), jobSourcePath, jobDestination, (rtf_query.Text != string.Empty));
\r
1189 encodeQueue.Add(query, this.GetTitle(), jobSourcePath, jobDestination, (rtf_query.Text != string.Empty));
\r
1191 lbl_encode.Text = encodeQueue.Count + " encode(s) pending in the queue";
\r
1193 queueWindow.Show();
\r
1198 /// Toolbar - Show the Queue
\r
1200 /// <param name="sender">
\r
1203 /// <param name="e">
\r
1206 private void btn_showQueue_Click(object sender, EventArgs e)
\r
1208 queueWindow.Show();
\r
1209 queueWindow.Activate();
\r
1213 /// Toolbar - Show the Preview Window
\r
1215 /// <param name="sender">
\r
1218 /// <param name="e">
\r
1221 private void tb_preview_Click(object sender, EventArgs e)
\r
1223 if (string.IsNullOrEmpty(sourcePath) || string.IsNullOrEmpty(text_destination.Text))
\r
1224 MessageBox.Show("No source or destination selected.", "Warning", MessageBoxButtons.OK,
\r
1225 MessageBoxIcon.Warning);
\r
1228 if (qtpreview == null)
\r
1230 qtpreview = new frmPreview(this);
\r
1233 else if (qtpreview.IsDisposed)
\r
1235 qtpreview = new frmPreview(this);
\r
1239 MessageBox.Show(qtpreview, "The preview window is already open!", "Warning", MessageBoxButtons.OK,
\r
1240 MessageBoxIcon.Warning);
\r
1245 /// Toolbar - Show the Activity log Window
\r
1247 /// <param name="sender">
\r
1250 /// <param name="e">
\r
1253 private void btn_ActivityWindow_Click(object sender, EventArgs e)
\r
1255 if (this.activityWindow == null || !this.activityWindow.IsHandleCreated)
\r
1256 this.activityWindow = new frmActivityWindow(encodeQueue, SourceScan);
\r
1258 this.activityWindow.Show();
\r
1259 this.activityWindow.Activate();
\r
1264 #region System Tray Icon
\r
1267 /// Handle Resizing of the main window when deaing with the Notify Icon
\r
1269 /// <param name="sender">
\r
1272 /// <param name="e">
\r
1275 private void frmMain_Resize(object sender, EventArgs e)
\r
1277 if (FormWindowState.Minimized == this.WindowState)
\r
1279 notifyIcon.Visible = true;
\r
1282 else if (FormWindowState.Normal == this.WindowState)
\r
1283 notifyIcon.Visible = false;
\r
1287 /// Double Click the Tray Icon
\r
1289 /// <param name="sender">
\r
1292 /// <param name="e">
\r
1295 private void notifyIcon_MouseDoubleClick(object sender, MouseEventArgs e)
\r
1297 this.Visible = true;
\r
1299 this.WindowState = FormWindowState.Normal;
\r
1300 notifyIcon.Visible = false;
\r
1304 /// Tray Icon - Restore Menu Item - Resture the Window
\r
1306 /// <param name="sender">
\r
1309 /// <param name="e">
\r
1312 private void btn_restore_Click(object sender, EventArgs e)
\r
1314 this.Visible = true;
\r
1316 this.WindowState = FormWindowState.Normal;
\r
1317 notifyIcon.Visible = false;
\r
1322 #region Main Window and Tab Control
\r
1325 private void btn_dvd_source_Click(object sender, EventArgs e)
\r
1327 if (DVD_Open.ShowDialog() == DialogResult.OK)
\r
1329 this.selectedSourceType = SourceType.Folder;
\r
1330 SelectSource(DVD_Open.SelectedPath);
\r
1333 UpdateSourceLabel();
\r
1336 private void btn_file_source_Click(object sender, EventArgs e)
\r
1338 if (ISO_Open.ShowDialog() == DialogResult.OK)
\r
1340 this.selectedSourceType = SourceType.VideoFile;
\r
1341 SelectSource(ISO_Open.FileName);
\r
1344 UpdateSourceLabel();
\r
1347 private void mnu_dvd_drive_Click(object sender, EventArgs e)
\r
1349 ToolStripMenuItem item = sender as ToolStripMenuItem;
\r
1352 string driveId = item.Name.Replace("Drive", string.Empty);
\r
1354 if (int.TryParse(driveId, out id))
\r
1357 this.dvdDrivePath = drives[id].RootDirectory;
\r
1358 this.dvdDriveLabel = drives[id].VolumeLabel;
\r
1360 if (this.dvdDrivePath == null) return;
\r
1361 this.selectedSourceType = SourceType.DvdDrive;
\r
1362 SelectSource(this.dvdDrivePath);
\r
1367 private void SelectSource(string file)
\r
1369 Check_ChapterMarkers.Enabled = true;
\r
1370 sourcePath = string.Empty;
\r
1372 if (file == string.Empty) // Must have a file or path
\r
1374 UpdateSourceLabel();
\r
1378 sourcePath = Path.GetFileName(file);
\r
1379 StartScan(file, 0);
\r
1382 private void drp_dvdtitle_Click(object sender, EventArgs e)
\r
1384 if ((drp_dvdtitle.Items.Count == 1) && (drp_dvdtitle.Items[0].ToString() == "Automatic"))
\r
1386 "There are no titles to select. Please load a source file by clicking the 'Source' button above before trying to select a title.",
\r
1387 "Alert", MessageBoxButtons.OK, MessageBoxIcon.Asterisk);
\r
1390 private void drp_dvdtitle_SelectedIndexChanged(object sender, EventArgs e)
\r
1392 UnRegisterPresetEventHandler();
\r
1393 drop_mode.SelectedIndex = 0;
\r
1395 drop_chapterStart.Items.Clear();
\r
1396 drop_chapterFinish.Items.Clear();
\r
1398 // If the dropdown is set to automatic nothing else needs to be done.
\r
1399 // Otheriwse if its not, title data has to be loaded from parsing.
\r
1400 if (drp_dvdtitle.Text != "Automatic")
\r
1402 selectedTitle = drp_dvdtitle.SelectedItem as Title;
\r
1403 lbl_duration.Text = selectedTitle.Duration.ToString();
\r
1404 PictureSettings.CurrentlySelectedPreset = this.currentlySelectedPreset;
\r
1405 PictureSettings.Source = selectedTitle; // Setup Picture Settings Tab Control
\r
1407 // Populate the Angles dropdown
\r
1408 drop_angle.Items.Clear();
\r
1409 if (!Properties.Settings.Default.noDvdNav)
\r
1411 drop_angle.Visible = true;
\r
1412 lbl_angle.Visible = true;
\r
1414 for (int i = 1; i <= selectedTitle.AngleCount; i++)
\r
1415 drop_angle.Items.Add(i.ToString());
\r
1417 if (drop_angle.Items.Count != 0)
\r
1418 drop_angle.SelectedIndex = 0;
\r
1422 drop_angle.Visible = false;
\r
1423 lbl_angle.Visible = false;
\r
1426 // Populate the Start chapter Dropdown
\r
1427 drop_chapterStart.Items.Clear();
\r
1428 drop_chapterStart.Items.AddRange(selectedTitle.Chapters.ToArray());
\r
1429 if (drop_chapterStart.Items.Count > 0)
\r
1430 drop_chapterStart.Text = drop_chapterStart.Items[0].ToString();
\r
1432 // Populate the Final Chapter Dropdown
\r
1433 drop_chapterFinish.Items.Clear();
\r
1434 drop_chapterFinish.Items.AddRange(selectedTitle.Chapters.ToArray());
\r
1435 if (drop_chapterFinish.Items.Count > 0)
\r
1436 drop_chapterFinish.Text = drop_chapterFinish.Items[drop_chapterFinish.Items.Count - 1].ToString();
\r
1438 // Populate the Audio Channels Dropdown
\r
1439 AudioSettings.SetTrackList(selectedTitle, this.currentlySelectedPreset);
\r
1441 // Populate the Subtitles dropdown
\r
1442 Subtitles.SetSubtitleTrackAuto(selectedTitle.Subtitles.ToArray());
\r
1444 // Update the source label if we have multiple streams
\r
1445 if (selectedTitle != null)
\r
1446 if (!string.IsNullOrEmpty(selectedTitle.SourceName))
\r
1447 labelSource.Text = labelSource.Text = Path.GetFileName(selectedTitle.SourceName);
\r
1449 // Run the AutoName & ChapterNaming functions
\r
1450 if (Properties.Settings.Default.autoNaming)
\r
1452 string autoPath = Main.AutoName(this);
\r
1453 if (autoPath != null)
\r
1454 text_destination.Text = autoPath;
\r
1457 "You currently have \"Automatically name output files\" enabled for the destination file box, but you do not have a default directory set.\n\nYou should set a \"Default Path\" in HandBrakes preferences. (See 'Tools' menu -> 'Options' -> 'General' Tab -> 'Default Path')",
\r
1458 "Warning", MessageBoxButtons.OK, MessageBoxIcon.Warning);
\r
1461 data_chpt.Rows.Clear();
\r
1462 if (selectedTitle.Chapters.Count != 1)
\r
1464 DataGridView chapterGridView = Main.ChapterNaming(data_chpt, drop_chapterFinish.Text);
\r
1465 if (chapterGridView != null)
\r
1466 data_chpt = chapterGridView;
\r
1470 Check_ChapterMarkers.Checked = false;
\r
1471 Check_ChapterMarkers.Enabled = false;
\r
1474 // Hack to force the redraw of the scrollbars which don't resize properly when the control is disabled.
\r
1475 data_chpt.Columns[0].Width = 166;
\r
1476 data_chpt.Columns[0].Width = 165;
\r
1478 RegisterPresetEventHandler();
\r
1481 private void chapersChanged(object sender, EventArgs e)
\r
1483 if (drop_mode.SelectedIndex != 0) // Function is not used if we are not in chapters mode.
\r
1486 Control ctl = (Control)sender;
\r
1487 int chapterStart, chapterEnd;
\r
1488 int.TryParse(drop_chapterStart.Text, out chapterStart);
\r
1489 int.TryParse(drop_chapterFinish.Text, out chapterEnd);
\r
1493 case "drop_chapterStart":
\r
1494 if (drop_chapterFinish.SelectedIndex == -1 && drop_chapterFinish.Items.Count != 0)
\r
1495 drop_chapterFinish.SelectedIndex = drop_chapterFinish.Items.Count - 1;
\r
1497 if (chapterEnd != 0)
\r
1498 if (chapterStart > chapterEnd)
\r
1499 drop_chapterFinish.Text = chapterStart.ToString();
\r
1501 case "drop_chapterFinish":
\r
1502 if (drop_chapterStart.Items.Count >= 1 && drop_chapterStart.SelectedIndex == -1)
\r
1503 drop_chapterStart.SelectedIndex = 0;
\r
1505 if (chapterStart != 0)
\r
1506 if (chapterEnd < chapterStart)
\r
1507 drop_chapterFinish.Text = chapterStart.ToString();
\r
1509 // Add more rows to the Chapter menu if needed.
\r
1510 if (Check_ChapterMarkers.Checked)
\r
1512 int i = data_chpt.Rows.Count, finish = 0;
\r
1513 int.TryParse(drop_chapterFinish.Text, out finish);
\r
1515 while (i < finish)
\r
1517 int n = data_chpt.Rows.Add();
\r
1518 data_chpt.Rows[n].Cells[0].Value = (i + 1);
\r
1519 data_chpt.Rows[n].Cells[1].Value = "Chapter " + (i + 1);
\r
1520 data_chpt.Rows[n].Cells[0].ValueType = typeof(int);
\r
1521 data_chpt.Rows[n].Cells[1].ValueType = typeof(string);
\r
1528 // Update the Duration
\r
1529 lbl_duration.Text =
\r
1530 Main.CalculateDuration(drop_chapterStart.SelectedIndex, drop_chapterFinish.SelectedIndex, selectedTitle)
\r
1533 // Run the Autonaming function
\r
1534 if (Properties.Settings.Default.autoNaming)
\r
1535 text_destination.Text = Main.AutoName(this);
\r
1537 // Disable chapter markers if only 1 chapter is selected.
\r
1538 if (chapterStart == chapterEnd)
\r
1540 Check_ChapterMarkers.Enabled = false;
\r
1541 btn_importChapters.Enabled = false;
\r
1542 data_chpt.Enabled = false;
\r
1546 Check_ChapterMarkers.Enabled = true;
\r
1547 if (Check_ChapterMarkers.Checked)
\r
1549 btn_importChapters.Enabled = true;
\r
1550 data_chpt.Enabled = true;
\r
1555 private void SecondsOrFramesChanged(object sender, EventArgs e)
\r
1558 int.TryParse(drop_chapterStart.Text, out start);
\r
1559 int.TryParse(drop_chapterFinish.Text, out end);
\r
1560 double duration = end - start;
\r
1562 switch (drop_mode.SelectedIndex)
\r
1565 lbl_duration.Text = TimeSpan.FromSeconds(duration).ToString();
\r
1568 if (selectedTitle != null)
\r
1570 duration = duration / selectedTitle.Fps;
\r
1571 lbl_duration.Text = TimeSpan.FromSeconds(duration).ToString();
\r
1574 lbl_duration.Text = "--:--:--";
\r
1580 private void drop_mode_SelectedIndexChanged(object sender, EventArgs e)
\r
1583 this.drop_chapterFinish.TextChanged -= new EventHandler(this.SecondsOrFramesChanged);
\r
1584 this.drop_chapterStart.TextChanged -= new EventHandler(this.SecondsOrFramesChanged);
\r
1587 switch (drop_mode.SelectedIndex)
\r
1590 drop_chapterStart.DropDownStyle = ComboBoxStyle.DropDownList;
\r
1591 drop_chapterFinish.DropDownStyle = ComboBoxStyle.DropDownList;
\r
1592 if (drop_chapterStart.Items.Count != 0)
\r
1594 drop_chapterStart.SelectedIndex = 0;
\r
1595 drop_chapterFinish.SelectedIndex = drop_chapterFinish.Items.Count - 1;
\r
1598 lbl_duration.Text = "--:--:--";
\r
1601 this.drop_chapterStart.TextChanged += new EventHandler(this.SecondsOrFramesChanged);
\r
1602 this.drop_chapterFinish.TextChanged += new EventHandler(this.SecondsOrFramesChanged);
\r
1603 drop_chapterStart.DropDownStyle = ComboBoxStyle.Simple;
\r
1604 drop_chapterFinish.DropDownStyle = ComboBoxStyle.Simple;
\r
1605 if (selectedTitle != null)
\r
1607 drop_chapterStart.Text = "0";
\r
1608 drop_chapterFinish.Text = selectedTitle.Duration.TotalSeconds.ToString();
\r
1612 this.drop_chapterStart.TextChanged += new EventHandler(this.SecondsOrFramesChanged);
\r
1613 this.drop_chapterFinish.TextChanged += new EventHandler(this.SecondsOrFramesChanged);
\r
1614 drop_chapterStart.DropDownStyle = ComboBoxStyle.Simple;
\r
1615 drop_chapterFinish.DropDownStyle = ComboBoxStyle.Simple;
\r
1616 if (selectedTitle != null)
\r
1618 drop_chapterStart.Text = "0";
\r
1619 drop_chapterFinish.Text = (selectedTitle.Fps * selectedTitle.Duration.TotalSeconds).ToString();
\r
1626 private void btn_destBrowse_Click(object sender, EventArgs e)
\r
1628 // This removes the file extension from the filename box on the save file dialog.
\r
1629 // It's daft but some users don't realise that typing an extension overrides the dropdown extension selected.
\r
1630 DVD_Save.FileName = Path.GetFileNameWithoutExtension(text_destination.Text);
\r
1632 if (Path.IsPathRooted(text_destination.Text))
\r
1633 DVD_Save.InitialDirectory = Path.GetDirectoryName(text_destination.Text);
\r
1635 // Show the dialog and set the main form file path
\r
1636 if (drop_format.SelectedIndex.Equals(0))
\r
1637 DVD_Save.FilterIndex = 1;
\r
1638 else if (drop_format.SelectedIndex.Equals(1))
\r
1639 DVD_Save.FilterIndex = 2;
\r
1641 if (DVD_Save.ShowDialog() == DialogResult.OK)
\r
1643 // Add a file extension manually, as FileDialog.AddExtension has issues with dots in filenames
\r
1644 switch (DVD_Save.FilterIndex)
\r
1648 !Path.GetExtension(DVD_Save.FileName).Equals(".mp4",
\r
1649 StringComparison.InvariantCultureIgnoreCase))
\r
1650 if (Properties.Settings.Default.useM4v)
\r
1651 DVD_Save.FileName = DVD_Save.FileName.Replace(".mp4", ".m4v").Replace(".mkv", ".m4v");
\r
1653 DVD_Save.FileName = DVD_Save.FileName.Replace(".m4v", ".mp4").Replace(".mkv", ".mp4");
\r
1657 !Path.GetExtension(DVD_Save.FileName).Equals(".mkv", StringComparison.InvariantCultureIgnoreCase))
\r
1658 DVD_Save.FileName = DVD_Save.FileName.Replace(".mp4", ".mkv").Replace(".m4v", ".mkv");
\r
1664 text_destination.Text = DVD_Save.FileName;
\r
1666 // Quicktime requires .m4v file for chapter markers to work. If checked, change the extension to .m4v (mp4 and m4v are the same thing)
\r
1667 if (Check_ChapterMarkers.Checked && DVD_Save.FilterIndex != 2)
\r
1668 SetExtension(".m4v");
\r
1672 private void text_destination_TextChanged(object sender, EventArgs e)
\r
1674 string path = text_destination.Text;
\r
1675 if (path.EndsWith(".mp4") || path.EndsWith(".m4v"))
\r
1676 drop_format.SelectedIndex = 0;
\r
1677 else if (path.EndsWith(".mkv"))
\r
1678 drop_format.SelectedIndex = 1;
\r
1681 // Output Settings
\r
1682 private void drop_format_SelectedIndexChanged(object sender, EventArgs e)
\r
1684 switch (drop_format.SelectedIndex)
\r
1687 if (Properties.Settings.Default.useM4v || Check_ChapterMarkers.Checked ||
\r
1688 AudioSettings.RequiresM4V() || Subtitles.RequiresM4V())
\r
1689 SetExtension(".m4v");
\r
1691 SetExtension(".mp4");
\r
1694 SetExtension(".mkv");
\r
1698 AudioSettings.SetContainer(drop_format.Text);
\r
1700 if (drop_format.Text.Contains("MP4"))
\r
1702 if (drp_videoEncoder.Items.Contains("VP3 (Theora)"))
\r
1704 drp_videoEncoder.Items.Remove("VP3 (Theora)");
\r
1705 drp_videoEncoder.SelectedIndex = 1;
\r
1708 else if (drop_format.Text.Contains("MKV"))
\r
1709 drp_videoEncoder.Items.Add("VP3 (Theora)");
\r
1712 public void SetExtension(string newExtension)
\r
1714 if (newExtension == ".mp4" || newExtension == ".m4v")
\r
1715 if (Properties.Settings.Default.useM4v || Check_ChapterMarkers.Checked || AudioSettings.RequiresM4V() ||
\r
1716 Subtitles.RequiresM4V())
\r
1717 newExtension = ".m4v";
\r
1719 newExtension = ".mp4";
\r
1721 if (Path.HasExtension(newExtension))
\r
1722 text_destination.Text = Path.ChangeExtension(text_destination.Text, newExtension);
\r
1726 private void drp_videoEncoder_SelectedIndexChanged(object sender, EventArgs e)
\r
1728 setContainerOpts();
\r
1730 // Turn off some options which are H.264 only when the user selects a non h.264 encoder
\r
1731 if (drp_videoEncoder.Text.Contains("H.264"))
\r
1733 if (check_2PassEncode.CheckState == CheckState.Checked)
\r
1734 check_turbo.Enabled = true;
\r
1736 tab_advanced.Enabled = true;
\r
1737 if ((drop_format.Text.Contains("MP4")) || (drop_format.Text.Contains("M4V")))
\r
1738 check_iPodAtom.Enabled = true;
\r
1740 check_iPodAtom.Enabled = false;
\r
1744 check_turbo.CheckState = CheckState.Unchecked;
\r
1745 check_turbo.Enabled = false;
\r
1746 tab_advanced.Enabled = false;
\r
1747 x264Panel.X264Query = string.Empty;
\r
1748 check_iPodAtom.Enabled = false;
\r
1749 check_iPodAtom.Checked = false;
\r
1752 // Setup the CQ Slider
\r
1753 switch (drp_videoEncoder.Text)
\r
1755 case "MPEG-4 (FFmpeg)":
\r
1756 if (slider_videoQuality.Value > 31)
\r
1757 slider_videoQuality.Value = 20; // Just reset to 70% QP 10 on encode change.
\r
1758 slider_videoQuality.Minimum = 1;
\r
1759 slider_videoQuality.Maximum = 31;
\r
1761 case "H.264 (x264)":
\r
1762 slider_videoQuality.Minimum = 0;
\r
1763 slider_videoQuality.TickFrequency = 1;
\r
1765 CultureInfo culture = CultureInfo.CreateSpecificCulture("en-US");
\r
1766 double cqStep = Properties.Settings.Default.x264cqstep;
\r
1767 double multiplier = 1.0 / cqStep;
\r
1768 double value = slider_videoQuality.Value * multiplier;
\r
1770 slider_videoQuality.Maximum = (int)(51 / Properties.Settings.Default.x264cqstep);
\r
1772 if (value < slider_videoQuality.Maximum)
\r
1773 slider_videoQuality.Value = slider_videoQuality.Maximum - (int)value;
\r
1776 case "VP3 (Theora)":
\r
1777 if (slider_videoQuality.Value > 63)
\r
1778 slider_videoQuality.Value = 45; // Just reset to 70% QP 45 on encode change.
\r
1779 slider_videoQuality.Minimum = 0;
\r
1780 slider_videoQuality.Maximum = 63;
\r
1786 /// When the FrameRate is not Same As Source, show the Max/Constant Mode dropdown
\r
1788 /// <param name="sender">
\r
1791 /// <param name="e">
\r
1794 private void drp_videoFramerate_SelectedIndexChanged(object sender, EventArgs e)
\r
1796 if (this.drp_videoFramerate.SelectedIndex == 0)
\r
1798 this.checkMaximumFramerate.Visible = false;
\r
1799 this.checkMaximumFramerate.CheckState = CheckState.Unchecked;
\r
1803 this.checkMaximumFramerate.Visible = true;
\r
1808 /// Set the container format options
\r
1810 public void setContainerOpts()
\r
1812 if ((drop_format.Text.Contains("MP4")) || (drop_format.Text.Contains("M4V")))
\r
1814 check_largeFile.Enabled = true;
\r
1815 check_optimiseMP4.Enabled = true;
\r
1816 check_iPodAtom.Enabled = true;
\r
1820 check_largeFile.Enabled = false;
\r
1821 check_optimiseMP4.Enabled = false;
\r
1822 check_iPodAtom.Enabled = false;
\r
1823 check_largeFile.Checked = false;
\r
1824 check_optimiseMP4.Checked = false;
\r
1825 check_iPodAtom.Checked = false;
\r
1829 private double _cachedCqStep = Properties.Settings.Default.x264cqstep;
\r
1832 /// Update the CQ slider for x264 for a new CQ step. This is set from option
\r
1834 public void setQualityFromSlider()
\r
1836 // Work out the current RF value.
\r
1837 double cqStep = _cachedCqStep;
\r
1838 double rfValue = 51.0 - slider_videoQuality.Value * cqStep;
\r
1840 // Change the maximum value for the slider
\r
1841 slider_videoQuality.Maximum = (int)(51 / Properties.Settings.Default.x264cqstep);
\r
1843 // Reset the CQ slider to RF0
\r
1844 slider_videoQuality.Value = slider_videoQuality.Maximum;
\r
1846 // Reset the CQ slider back to the previous value as close as possible
\r
1847 double cqStepNew = Properties.Settings.Default.x264cqstep;
\r
1848 double rfValueCurrent = 51.0 - slider_videoQuality.Value * cqStepNew;
\r
1849 while (rfValueCurrent < rfValue)
\r
1851 slider_videoQuality.Value--;
\r
1852 rfValueCurrent = 51.0 - slider_videoQuality.Value * cqStepNew;
\r
1855 // Cache the CQ step for the next calculation
\r
1856 _cachedCqStep = Properties.Settings.Default.x264cqstep;
\r
1859 private void slider_videoQuality_Scroll(object sender, EventArgs e)
\r
1861 double cqStep = Properties.Settings.Default.x264cqstep;
\r
1862 switch (drp_videoEncoder.Text)
\r
1864 case "MPEG-4 (FFmpeg)":
\r
1865 lbl_SliderValue.Text = "QP:" + (32 - slider_videoQuality.Value);
\r
1867 case "H.264 (x264)":
\r
1868 double rfValue = 51.0 - slider_videoQuality.Value * cqStep;
\r
1869 rfValue = Math.Round(rfValue, 2);
\r
1870 lbl_SliderValue.Text = "RF:" + rfValue.ToString(new CultureInfo("en-US"));
\r
1872 case "VP3 (Theora)":
\r
1873 lbl_SliderValue.Text = "QP:" + slider_videoQuality.Value;
\r
1878 private void radio_targetFilesize_CheckedChanged(object sender, EventArgs e)
\r
1880 text_bitrate.Enabled = false;
\r
1881 text_filesize.Enabled = true;
\r
1882 slider_videoQuality.Enabled = false;
\r
1884 check_2PassEncode.Enabled = true;
\r
1887 private void radio_avgBitrate_CheckedChanged(object sender, EventArgs e)
\r
1889 text_bitrate.Enabled = true;
\r
1890 text_filesize.Enabled = false;
\r
1891 slider_videoQuality.Enabled = false;
\r
1893 check_2PassEncode.Enabled = true;
\r
1896 private void radio_cq_CheckedChanged(object sender, EventArgs e)
\r
1898 text_bitrate.Enabled = false;
\r
1899 text_filesize.Enabled = false;
\r
1900 slider_videoQuality.Enabled = true;
\r
1902 check_2PassEncode.Enabled = false;
\r
1903 check_2PassEncode.CheckState = CheckState.Unchecked;
\r
1906 private void check_2PassEncode_CheckedChanged(object sender, EventArgs e)
\r
1908 if (check_2PassEncode.CheckState.ToString() == "Checked")
\r
1910 if (drp_videoEncoder.Text.Contains("H.264"))
\r
1911 check_turbo.Enabled = true;
\r
1915 check_turbo.Enabled = false;
\r
1916 check_turbo.CheckState = CheckState.Unchecked;
\r
1920 // Chapter Marker Tab
\r
1921 private void Check_ChapterMarkers_CheckedChanged(object sender, EventArgs e)
\r
1923 if (Check_ChapterMarkers.Checked)
\r
1925 if (drop_format.SelectedIndex != 1)
\r
1926 SetExtension(".m4v");
\r
1927 data_chpt.Enabled = true;
\r
1928 btn_importChapters.Enabled = true;
\r
1932 if (drop_format.SelectedIndex != 1 && !Properties.Settings.Default.useM4v)
\r
1933 SetExtension(".mp4");
\r
1934 data_chpt.Enabled = false;
\r
1935 btn_importChapters.Enabled = false;
\r
1939 private void btn_importChapters_Click(object sender, EventArgs e)
\r
1941 if (File_ChapterImport.ShowDialog() == DialogResult.OK)
\r
1943 string filename = File_ChapterImport.FileName;
\r
1944 DataGridView imported = Main.ImportChapterNames(data_chpt, filename);
\r
1945 if (imported != null)
\r
1946 data_chpt = imported;
\r
1950 private void btn_export_Click(object sender, EventArgs e)
\r
1952 SaveFileDialog saveFileDialog = new SaveFileDialog();
\r
1953 saveFileDialog.Filter = "Csv File|*.csv";
\r
1954 saveFileDialog.DefaultExt = "csv";
\r
1955 if (saveFileDialog.ShowDialog() == DialogResult.OK)
\r
1957 string filename = saveFileDialog.FileName;
\r
1959 Main.SaveChapterMarkersToCsv(this, filename);
\r
1963 private void mnu_resetChapters_Click(object sender, EventArgs e)
\r
1965 data_chpt.Rows.Clear();
\r
1966 DataGridView chapterGridView = Main.ChapterNaming(data_chpt, drop_chapterFinish.Text);
\r
1967 if (chapterGridView != null)
\r
1969 data_chpt = chapterGridView;
\r
1973 // Query Editor Tab
\r
1974 private void btn_generate_Query_Click(object sender, EventArgs e)
\r
1976 rtf_query.Text = QueryGenerator.GenerateFullQuery(this);
\r
1979 private void btn_clear_Click(object sender, EventArgs e)
\r
1981 rtf_query.Clear();
\r
1986 // MainWindow Components, Actions and Functions ***********************
\r
1988 #region Source Scan
\r
1991 /// Start the Scan Process
\r
1993 /// <param name="filename">
\r
1996 /// <param name="title">
\r
1999 private void StartScan(string filename, int title)
\r
2001 // Setup the GUI components for the scan.
\r
2002 sourcePath = filename;
\r
2004 this.DisableGUI();
\r
2009 SourceScan.Scan(sourcePath, title);
\r
2010 SourceScan.ScanStatusChanged += new EventHandler(SourceScan_ScanStatusChanged);
\r
2011 SourceScan.ScanCompleted += new EventHandler(SourceScan_ScanCompleted);
\r
2013 catch (Exception exc)
\r
2015 MessageBox.Show("frmMain.cs - StartScan " + exc, "Error", MessageBoxButtons.OK, MessageBoxIcon.Error);
\r
2020 /// Update the Status label for the scan
\r
2022 /// <param name="sender">
\r
2025 /// <param name="e">
\r
2028 private void SourceScan_ScanStatusChanged(object sender, EventArgs e)
\r
2030 UpdateScanStatusLabel();
\r
2034 /// Update the UI after the scan has completed
\r
2036 /// <param name="sender">
\r
2039 /// <param name="e">
\r
2042 private void SourceScan_ScanCompleted(object sender, EventArgs e)
\r
2044 UpdateGuiAfterScan();
\r
2048 /// Update the Scan Status Label
\r
2050 private void UpdateScanStatusLabel()
\r
2052 if (InvokeRequired)
\r
2054 BeginInvoke(new UpdateWindowHandler(UpdateScanStatusLabel));
\r
2057 lbl_encode.Text = SourceScan.ScanStatus;
\r
2061 /// Reset the GUI when the scan has completed
\r
2063 private void UpdateGuiAfterScan()
\r
2065 if (InvokeRequired)
\r
2067 BeginInvoke(new UpdateWindowHandler(UpdateGuiAfterScan));
\r
2073 currentSource = SourceScan.SouceData;
\r
2075 // Setup some GUI components
\r
2076 drp_dvdtitle.Items.Clear();
\r
2077 if (currentSource.Titles.Count != 0)
\r
2078 drp_dvdtitle.Items.AddRange(currentSource.Titles.ToArray());
\r
2080 foreach (Title title in currentSource.Titles)
\r
2082 if (title.MainTitle)
\r
2084 drp_dvdtitle.SelectedItem = title;
\r
2088 if (drp_dvdtitle.SelectedItem == null && drp_dvdtitle.Items.Count > 0)
\r
2090 drp_dvdtitle.SelectedIndex = 0;
\r
2093 // Enable the creation of chapter markers if the file is an image of a dvd
\r
2094 if (drop_chapterStart.Items.Count > 0)
\r
2097 int.TryParse(drop_chapterStart.Items[0].ToString(), out start);
\r
2098 int.TryParse(drop_chapterFinish.Items[drop_chapterFinish.Items.Count - 1].ToString(), out end);
\r
2099 if (end > start) Check_ChapterMarkers.Enabled = true;
\r
2102 Check_ChapterMarkers.Enabled = false;
\r
2103 Check_ChapterMarkers.Checked = false;
\r
2104 data_chpt.Rows.Clear();
\r
2108 // If no titles were found, Display an error message
\r
2109 if (drp_dvdtitle.Items.Count == 0)
\r
2112 "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
2113 "Error", MessageBoxButtons.OK, MessageBoxIcon.Hand);
\r
2114 sourcePath = string.Empty;
\r
2116 UpdateSourceLabel();
\r
2118 // Enable the GUI components and enable any disabled components
\r
2121 catch (Exception exc)
\r
2123 MessageBox.Show("frmMain.cs - updateUIafterScan " + exc, "Error", MessageBoxButtons.OK,
\r
2124 MessageBoxIcon.Error);
\r
2130 /// Enable the GUI
\r
2132 private void EnableGUI()
\r
2136 if (InvokeRequired)
\r
2137 BeginInvoke(new UpdateWindowHandler(EnableGUI));
\r
2138 lbl_encode.Text = "Scan Completed";
\r
2139 foreach (Control ctrl in Controls)
\r
2140 ctrl.Enabled = true;
\r
2141 btn_start.Enabled = true;
\r
2142 btn_showQueue.Enabled = true;
\r
2143 btn_add2Queue.Enabled = true;
\r
2144 tb_preview.Enabled = true;
\r
2145 btn_source.Enabled = true;
\r
2146 mnu_killCLI.Visible = false;
\r
2148 catch (Exception exc)
\r
2150 MessageBox.Show("frmMain.cs - EnableGUI() " + exc, "Error", MessageBoxButtons.OK, MessageBoxIcon.Error);
\r
2155 /// Disable the GUI
\r
2157 private void DisableGUI()
\r
2159 foreach (Control ctrl in Controls)
\r
2160 if (!(ctrl is StatusStrip || ctrl is MenuStrip || ctrl is ToolStrip))
\r
2161 ctrl.Enabled = false;
\r
2163 lbl_encode.Visible = true;
\r
2164 lbl_encode.Text = "Scanning ...";
\r
2165 btn_source.Enabled = false;
\r
2166 btn_start.Enabled = false;
\r
2167 btn_showQueue.Enabled = false;
\r
2168 btn_add2Queue.Enabled = false;
\r
2169 tb_preview.Enabled = false;
\r
2170 mnu_killCLI.Visible = true;
\r
2176 private void KillScan()
\r
2178 SourceScan.ScanCompleted -= new EventHandler(SourceScan_ScanCompleted);
\r
2182 SourceScan.Stop();
\r
2184 lbl_encode.Text = "Scan Cancelled!";
\r
2190 private void ResetGUI()
\r
2192 drp_dvdtitle.Items.Clear();
\r
2193 drop_chapterStart.Items.Clear();
\r
2194 drop_chapterFinish.Items.Clear();
\r
2195 lbl_duration.Text = "Select a Title";
\r
2196 PictureSettings.lbl_src_res.Text = "Select a Title";
\r
2197 sourcePath = String.Empty;
\r
2198 text_destination.Text = String.Empty;
\r
2199 selectedTitle = null;
\r
2203 /// Update the Source Label
\r
2205 private void UpdateSourceLabel()
\r
2207 labelSource.Text = string.IsNullOrEmpty(sourcePath) ? "Select \"Source\" to continue." : this.SourceName;
\r
2209 if (selectedTitle != null)
\r
2210 if (!string.IsNullOrEmpty(selectedTitle.SourceName))
\r
2211 // If it's one of multiple source files, make sure we don't use the folder name
\r
2212 labelSource.Text = Path.GetFileName(selectedTitle.SourceName);
\r
2216 /// Take a job from the Queue, rescan it, and reload the GUI for that job.
\r
2218 /// <param name="job">
\r
2221 public void RecievingJob(Job job)
\r
2223 string query = job.Query;
\r
2224 StartScan(job.Source, job.Title);
\r
2226 if (query != null)
\r
2228 // Ok, Reset all the H264 widgets before changing the preset
\r
2229 x264Panel.Reset2Defaults();
\r
2231 // Send the query from the file to the Query Parser class
\r
2232 QueryParser presetQuery = QueryParser.Parse(query);
\r
2234 // Now load the preset
\r
2235 PresetLoader.LoadPreset(this, presetQuery, "Load Back From Queue");
\r
2237 // The x264 widgets will need updated, so do this now:
\r
2238 x264Panel.StandardizeOptString();
\r
2239 x264Panel.SetCurrentSettingsInPanel();
\r
2241 // Finally, let this window have a copy of the preset settings.
\r
2242 this.currentlySelectedPreset = null;
\r
2243 PictureSettings.SetPresetCropWarningLabel(null);
\r
2249 #region GUI Functions and Actions
\r
2252 /// Set the GUI to it's finished encoding state.
\r
2254 private void SetEncodeFinished()
\r
2258 if (InvokeRequired)
\r
2260 BeginInvoke(new UpdateWindowHandler(SetEncodeFinished));
\r
2264 lbl_encode.Text = "Encoding Finished";
\r
2265 ProgressBarStatus.Visible = false;
\r
2266 btn_start.Text = "Start";
\r
2267 btn_start.ToolTipText = "Start the encoding process";
\r
2268 btn_start.Image = Properties.Resources.Play;
\r
2270 // If the window is minimized, display the notification in a popup.
\r
2271 if (Properties.Settings.Default.trayIconAlerts)
\r
2272 if (FormWindowState.Minimized == this.WindowState)
\r
2274 notifyIcon.BalloonTipText = lbl_encode.Text;
\r
2275 notifyIcon.ShowBalloonTip(500);
\r
2278 catch (Exception exc)
\r
2280 MessageBox.Show(exc.ToString());
\r
2285 /// Set the GUI to it's started encoding state.
\r
2287 private void SetEncodeStarted()
\r
2291 if (InvokeRequired)
\r
2293 BeginInvoke(new UpdateWindowHandler(SetEncodeStarted));
\r
2296 lbl_encode.Visible = true;
\r
2297 ProgressBarStatus.Value = 0;
\r
2298 ProgressBarStatus.Visible = true;
\r
2299 lbl_encode.Text = "Encoding with " + encodeQueue.Count + " encode(s) pending";
\r
2300 btn_start.Text = "Stop";
\r
2301 btn_start.ToolTipText = "Stop the encoding process.";
\r
2302 btn_start.Image = Properties.Resources.stop;
\r
2304 catch (Exception exc)
\r
2306 MessageBox.Show(exc.ToString());
\r
2311 /// Display the Encode Status
\r
2313 /// <param name="sender">
\r
2316 /// <param name="e">
\r
2319 private void EncodeQueue_EncodeStatusChanged(object sender, HandBrake.ApplicationServices.EncodeProgressEventArgs e)
\r
2321 if (this.InvokeRequired)
\r
2323 this.BeginInvoke(new Encode.EncodeProgessStatus(EncodeQueue_EncodeStatusChanged), new[] { sender, e });
\r
2329 "{0:00.00}%, FPS: {1:000.0}, Avg FPS: {2:000.0}, Time Remaining: {3}",
\r
2330 e.PercentComplete,
\r
2331 e.CurrentFrameRate,
\r
2332 e.AverageFrameRate,
\r
2333 e.EstimatedTimeLeft);
\r
2335 ProgressBarStatus.Value = (int)Math.Round(e.PercentComplete);
\r
2339 /// Set the DVD Drive selection in the "Source" Menu
\r
2341 private void SetDriveSelectionMenuItem()
\r
2345 if (InvokeRequired)
\r
2347 BeginInvoke(new UpdateWindowHandler(SetDriveSelectionMenuItem));
\r
2351 drives = Main.GetDrives();
\r
2353 List<ToolStripMenuItem> menuItems = new List<ToolStripMenuItem>();
\r
2354 foreach (DriveInformation drive in drives)
\r
2356 ToolStripMenuItem menuItem = new ToolStripMenuItem
\r
2358 Name = drive.ToString(),
\r
2359 Text = drive.RootDirectory + " (" + drive.VolumeLabel + ")",
\r
2360 Image = Resources.disc_small
\r
2362 menuItem.Click += new EventHandler(mnu_dvd_drive_Click);
\r
2363 menuItems.Add(menuItem);
\r
2366 foreach (ToolStripMenuItem item in menuItems)
\r
2367 btn_source.DropDownItems.Add(item);
\r
2369 catch (Exception exc)
\r
2371 MessageBox.Show("Error in SetDriveSelectionMenuItem" + exc);
\r
2376 /// Access the preset Handler and setup the preset panel.
\r
2378 private void LoadPresetPanel()
\r
2380 if (presetHandler.CheckIfPresetsAreOutOfDate())
\r
2381 if (!Properties.Settings.Default.presetNotification)
\r
2382 MessageBox.Show(splash,
\r
2383 "HandBrake has determined your built-in presets are out of date... These presets will now be updated.",
\r
2384 "Preset Update", MessageBoxButtons.OK, MessageBoxIcon.Information);
\r
2386 presetHandler.GetPresetPanel(ref treeView_presets);
\r
2387 treeView_presets.Update();
\r
2391 /// Get the title from the selected item in the title dropdown.
\r
2396 private int GetTitle()
\r
2399 if (drp_dvdtitle.SelectedItem != null)
\r
2401 string[] titleInfo = drp_dvdtitle.SelectedItem.ToString().Split(' ');
\r
2402 int.TryParse(titleInfo[0], out title);
\r
2409 /// Handle the Update Check Finishing.
\r
2411 /// <param name="result">
\r
2414 private void UpdateCheckDoneMenu(IAsyncResult result)
\r
2416 // Make sure it's running on the calling thread
\r
2417 if (InvokeRequired)
\r
2419 Invoke(new MethodInvoker(() => this.UpdateCheckDoneMenu(result)));
\r
2422 UpdateCheckInformation info;
\r
2425 // Get the information about the new build, if any, and close the window
\r
2426 info = Main.EndCheckForUpdates(result);
\r
2428 if (info.NewVersionAvailable && info.BuildInformation != null)
\r
2430 frmUpdater updateWindow = new frmUpdater(info.BuildInformation);
\r
2431 updateWindow.ShowDialog();
\r
2434 MessageBox.Show("There are no new updates at this time.", "Update Check", MessageBoxButtons.OK,
\r
2435 MessageBoxIcon.Information);
\r
2436 lbl_updateCheck.Visible = false;
\r
2439 catch (Exception ex)
\r
2441 if ((bool)result.AsyncState)
\r
2443 "Unable to check for updates, Please try again later.\n\nDetailed Error Information:\n" + ex,
\r
2444 "Error", MessageBoxButtons.OK, MessageBoxIcon.Error);
\r
2453 /// Handle GUI shortcuts
\r
2455 /// <param name="msg">Message</param>
\r
2456 /// <param name="keyData">Keys</param>
\r
2457 /// <returns>Bool</returns>
\r
2458 protected override bool ProcessCmdKey(ref Message msg, Keys keyData)
\r
2460 if (keyData == (Keys.Control | Keys.S))
\r
2462 btn_start_Click(this, new EventArgs());
\r
2466 if (keyData == (Keys.Control | Keys.A))
\r
2468 btn_add2Queue_Click(this, new EventArgs());
\r
2471 return base.ProcessCmdKey(ref msg, keyData);
\r
2475 /// If the queue is being processed, prompt the user to confirm application close.
\r
2477 /// <param name="e">FormClosingEventArgs</param>
\r
2478 protected override void OnFormClosing(FormClosingEventArgs e)
\r
2480 // If currently encoding, the queue isn't paused, and there are queue items to process, prompt to confirm close.
\r
2481 if (encodeQueue.IsEncoding)
\r
2483 DialogResult result =
\r
2485 "HandBrake has queue items to process. Closing HandBrake will stop the current encoding.\n\nDo you want to close HandBrake?",
\r
2486 "Close HandBrake?", MessageBoxButtons.YesNo, MessageBoxIcon.Question);
\r
2488 if (result == DialogResult.No)
\r
2494 // Try to safely close out if we can, or kill the cli if using in-gui status
\r
2495 if (!Settings.Default.showCliForInGuiEncodeStatus)
\r
2496 encodeQueue.Stop();
\r
2498 encodeQueue.SafelyClose();
\r
2501 if (SourceScan.IsScanning)
\r
2503 SourceScan.ScanCompleted -= new EventHandler(SourceScan_ScanCompleted);
\r
2504 SourceScan.Stop();
\r
2506 base.OnFormClosing(e);
\r
2511 // This is the END of the road ****************************************
\r