OSDN Git Service

WinGui:
[handbrake-jp/handbrake-jp-git.git] / win / C# / frmMain.cs
1 /*  frmMain.cs $\r
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
5 \r
6 namespace Handbrake\r
7 {\r
8     using System;\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
14     using System.IO;\r
15     using System.Reflection;\r
16     using System.Threading;\r
17     using System.Windows.Forms;\r
18     using Functions;\r
19 \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
24 \r
25     using Model;\r
26     using Presets;\r
27     using Properties;\r
28 \r
29     /// <summary>\r
30     /// The Main Window\r
31     /// </summary>\r
32     public partial class frmMain : Form\r
33     {\r
34         // Objects which may be used by one or more other objects *************\r
35         private IQueue encodeQueue = new Queue();\r
36         private PresetsHandler presetHandler = new PresetsHandler();\r
37 \r
38         // Windows ************************************************************\r
39         private frmQueue queueWindow;\r
40         private frmPreview qtpreview;\r
41         private frmActivityWindow activityWindow;\r
42 \r
43         // Globals: Mainly used for tracking. *********************************\r
44         public Title selectedTitle;\r
45         public string sourcePath;\r
46         private SourceType selectedSourceType;\r
47         private string dvdDrivePath;\r
48         private string dvdDriveLabel;\r
49         private Preset currentlySelectedPreset;\r
50         private DVD currentSource;\r
51         private IScan SourceScan = new ScanService();\r
52         private List<DriveInformation> drives;\r
53 \r
54         // Delegates **********************************************************\r
55         private delegate void UpdateWindowHandler();\r
56 \r
57         // Applicaiton Startup ************************************************\r
58 \r
59         #region Properties\r
60 \r
61         /// <summary>\r
62         /// Gets SourceName.\r
63         /// </summary>\r
64         public string SourceName\r
65         {\r
66             get\r
67             {\r
68                 if (this.selectedSourceType == SourceType.DvdDrive)\r
69                 {\r
70                     return this.dvdDriveLabel;\r
71                 }\r
72 \r
73                 if (Path.GetFileNameWithoutExtension(this.sourcePath) != "VIDEO_TS")\r
74                     return Path.GetFileNameWithoutExtension(this.sourcePath);\r
75 \r
76                 return Path.GetFileNameWithoutExtension(Path.GetDirectoryName(this.sourcePath));\r
77             }\r
78         }\r
79 \r
80         #endregion\r
81 \r
82         #region Application Startup\r
83 \r
84         /// <summary>\r
85         /// Initializes a new instance of the <see cref="frmMain"/> class.\r
86         /// </summary>\r
87         /// <param name="args">\r
88         /// The arguments passed in on application startup.\r
89         /// </param>\r
90         public frmMain(string[] args)\r
91         {\r
92             InitializeComponent();\r
93 \r
94             // Update the users config file with the CLI version data.\r
95             Main.SetCliVersionData();\r
96             Main.CheckForValidCliVersion();\r
97 \r
98             if (Settings.Default.hb_version.Contains("svn"))\r
99             {\r
100                 Version v = Assembly.GetExecutingAssembly().GetName().Version;\r
101                 this.Text += " " + v.ToString(4);\r
102             }\r
103 \r
104             // Check for new versions, if update checking is enabled\r
105             if (Settings.Default.updateStatus)\r
106             {\r
107                 if (DateTime.Now.Subtract(Settings.Default.lastUpdateCheckDate).TotalDays > Properties.Settings.Default.daysBetweenUpdateCheck)\r
108                 {\r
109                     Main.BeginCheckForUpdates(new AsyncCallback(UpdateCheckDone), false);\r
110                 }\r
111             }\r
112 \r
113             // Clear the log files in the background\r
114             if (Settings.Default.clearOldLogs)\r
115             {\r
116                 Thread clearLog = new Thread(Main.ClearOldLogs);\r
117                 clearLog.Start();\r
118             }\r
119 \r
120             // Setup the GUI components\r
121             LoadPresetPanel(); // Load the Preset Panel\r
122             treeView_presets.ExpandAll();\r
123             lbl_encode.Text = string.Empty;\r
124             drop_mode.SelectedIndex = 0;\r
125             queueWindow = new frmQueue(encodeQueue, this); // Prepare the Queue\r
126             if (!Settings.Default.QueryEditorTab)\r
127                 tabs_panel.TabPages.RemoveAt(7); // Remove the query editor tab if the user does not want it enabled.\r
128             if (Settings.Default.tooltipEnable)\r
129                 ToolTip.Active = true;\r
130 \r
131             // Load the user's default settings or Normal Preset\r
132             if (Settings.Default.defaultPreset != string.Empty && presetHandler.GetPreset(Properties.Settings.Default.defaultPreset) != null)\r
133             {\r
134                 string query = presetHandler.GetPreset(Settings.Default.defaultPreset).Query;\r
135                 if (query != null)\r
136                 {\r
137                     x264Panel.Reset2Defaults();\r
138 \r
139                     QueryParser presetQuery = QueryParser.Parse(query);\r
140                     PresetLoader.LoadPreset(this, presetQuery, Settings.Default.defaultPreset);\r
141 \r
142                     x264Panel.StandardizeOptString();\r
143                     x264Panel.SetCurrentSettingsInPanel();\r
144                 }\r
145             }\r
146             else\r
147                 loadNormalPreset();\r
148 \r
149             // Register with Growl (if not using Growl for the encoding completion action, this wont hurt anything)\r
150             GrowlCommunicator.Register();\r
151 \r
152             // Event Handlers and Queue Recovery\r
153             events();\r
154             Main.RecoverQueue(encodeQueue);\r
155 \r
156             // If have a file passed in via command arguemtents, check it's a file and try scanning it.\r
157             if (args.Length >= 1 && (File.Exists(args[0]) || Directory.Exists(args[0])))\r
158             {\r
159                 this.StartScan(args[0], 0);\r
160             }\r
161         }\r
162 \r
163         /// <summary>\r
164         /// When the update check is done, process the results.\r
165         /// </summary>\r
166         /// <param name="result">IAsyncResult result</param>\r
167         private void UpdateCheckDone(IAsyncResult result)\r
168         {\r
169             if (InvokeRequired)\r
170             {\r
171                 Invoke(new MethodInvoker(() => UpdateCheckDone(result)));\r
172                 return;\r
173             }\r
174 \r
175             UpdateCheckInformation info;\r
176 \r
177             try\r
178             {\r
179                 info = Main.EndCheckForUpdates(result);\r
180 \r
181                 if (info.NewVersionAvailable)\r
182                 {\r
183                     frmUpdater updateWindow = new frmUpdater(info.BuildInformation);\r
184                     updateWindow.ShowDialog();\r
185                 }\r
186             }\r
187             catch (Exception ex)\r
188             {\r
189                 if ((bool)result.AsyncState)\r
190                     Main.ShowExceptiowWindow("Unable to check for updates, Please try again later.", ex.ToString());\r
191             }\r
192         }\r
193 \r
194         #endregion\r
195 \r
196         #region Events\r
197 \r
198         // Encoding Events for setting up the GUI\r
199         private void events()\r
200         {\r
201             // Handle Widget changes when preset is selected.\r
202             RegisterPresetEventHandler();\r
203 \r
204             // Handle Window Resize\r
205             if (Properties.Settings.Default.MainWindowMinimize)\r
206                 this.Resize += new EventHandler(frmMain_Resize);\r
207 \r
208             // Handle Encode Start / Finish / Pause\r
209             encodeQueue.EncodeStarted += new EventHandler(encodeStarted);\r
210             encodeQueue.EncodeEnded += new EventHandler(encodeEnded);\r
211 \r
212             // Handle a file being draged onto the GUI.\r
213             this.DragEnter += new DragEventHandler(frmMain_DragEnter);\r
214             this.DragDrop += new DragEventHandler(frmMain_DragDrop);\r
215         }\r
216 \r
217         // 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
218         private void RegisterPresetEventHandler()\r
219         {\r
220             // Output Settings\r
221             drop_format.SelectedIndexChanged += new EventHandler(changePresetLabel);\r
222             check_largeFile.CheckedChanged += new EventHandler(changePresetLabel);\r
223             check_iPodAtom.CheckedChanged += new EventHandler(changePresetLabel);\r
224             check_optimiseMP4.CheckedChanged += new EventHandler(changePresetLabel);\r
225 \r
226             // Picture Settings\r
227             PictureSettings.PictureSettingsChanged += new EventHandler(changePresetLabel);\r
228 \r
229             // Filter Settings\r
230             Filters.FilterSettingsChanged += new EventHandler(changePresetLabel);\r
231 \r
232             // Video Tab\r
233             drp_videoEncoder.SelectedIndexChanged += new EventHandler(changePresetLabel);\r
234             check_2PassEncode.CheckedChanged += new EventHandler(changePresetLabel);\r
235             check_turbo.CheckedChanged += new EventHandler(changePresetLabel);\r
236             text_filesize.TextChanged += new EventHandler(changePresetLabel);\r
237             text_bitrate.TextChanged += new EventHandler(changePresetLabel);\r
238             slider_videoQuality.ValueChanged += new EventHandler(changePresetLabel);\r
239 \r
240             // Audio Panel\r
241             AudioSettings.AudioListChanged += new EventHandler(changePresetLabel);\r
242 \r
243             // Advanced Tab\r
244             x264Panel.rtf_x264Query.TextChanged += new EventHandler(changePresetLabel);\r
245         }\r
246 \r
247         private void UnRegisterPresetEventHandler()\r
248         {\r
249             // Output Settings \r
250             drop_format.SelectedIndexChanged -= new EventHandler(changePresetLabel);\r
251             check_largeFile.CheckedChanged -= new EventHandler(changePresetLabel);\r
252             check_iPodAtom.CheckedChanged -= new EventHandler(changePresetLabel);\r
253             check_optimiseMP4.CheckedChanged -= new EventHandler(changePresetLabel);\r
254 \r
255             // Picture Settings\r
256             PictureSettings.PictureSettingsChanged -= new EventHandler(changePresetLabel);\r
257 \r
258             // Filter Settings\r
259             Filters.FilterSettingsChanged -= new EventHandler(changePresetLabel);\r
260 \r
261             // Video Tab\r
262             drp_videoEncoder.SelectedIndexChanged -= new EventHandler(changePresetLabel);\r
263             check_2PassEncode.CheckedChanged -= new EventHandler(changePresetLabel);\r
264             check_turbo.CheckedChanged -= new EventHandler(changePresetLabel);\r
265             text_filesize.TextChanged -= new EventHandler(changePresetLabel);\r
266             text_bitrate.TextChanged -= new EventHandler(changePresetLabel);\r
267             slider_videoQuality.ValueChanged -= new EventHandler(changePresetLabel);\r
268 \r
269             // Audio Panel\r
270             AudioSettings.AudioListChanged -= new EventHandler(changePresetLabel);\r
271 \r
272             // Advanced Tab\r
273             x264Panel.rtf_x264Query.TextChanged -= new EventHandler(changePresetLabel);\r
274         }\r
275 \r
276         private void changePresetLabel(object sender, EventArgs e)\r
277         {\r
278             labelPreset.Text = "Output Settings (Preset: Custom)";\r
279             this.currentlySelectedPreset = null;\r
280         }\r
281 \r
282         private static void frmMain_DragEnter(object sender, DragEventArgs e)\r
283         {\r
284             if (e.Data.GetDataPresent(DataFormats.FileDrop, false))\r
285                 e.Effect = DragDropEffects.All;\r
286         }\r
287 \r
288         private void frmMain_DragDrop(object sender, DragEventArgs e)\r
289         {\r
290             string[] fileList = e.Data.GetData(DataFormats.FileDrop) as string[];\r
291             sourcePath = string.Empty;\r
292 \r
293             if (fileList != null)\r
294             {\r
295                 if (!string.IsNullOrEmpty(fileList[0]))\r
296                 {\r
297                     this.selectedSourceType = SourceType.VideoFile;\r
298                     StartScan(fileList[0], 0);\r
299                 }\r
300                 else\r
301                     UpdateSourceLabel();\r
302             }\r
303             else\r
304                 UpdateSourceLabel();\r
305         }\r
306 \r
307         private void encodeStarted(object sender, EventArgs e)\r
308         {\r
309             SetEncodeStarted();\r
310             encodeQueue.EncodeStatusChanged += EncodeQueue_EncodeStatusChanged;\r
311         }\r
312 \r
313         private void encodeEnded(object sender, EventArgs e)\r
314         {\r
315             encodeQueue.EncodeStatusChanged -= EncodeQueue_EncodeStatusChanged;\r
316             SetEncodeFinished();\r
317         }\r
318         #endregion\r
319 \r
320         // User Interface Menus / Tool Strips *********************************\r
321 \r
322         #region File Menu\r
323 \r
324         /// <summary>\r
325         /// Kill The scan menu Item\r
326         /// </summary>\r
327         /// <param name="sender">\r
328         /// The sender.\r
329         /// </param>\r
330         /// <param name="e">\r
331         /// The e.\r
332         /// </param>\r
333         private void mnu_killCLI_Click(object sender, EventArgs e)\r
334         {\r
335             KillScan();\r
336         }\r
337 \r
338         /// <summary>\r
339         /// Exit the Application Menu Item\r
340         /// </summary>\r
341         /// <param name="sender">\r
342         /// The sender.\r
343         /// </param>\r
344         /// <param name="e">\r
345         /// The e.\r
346         /// </param>\r
347         private void mnu_exit_Click(object sender, EventArgs e)\r
348         {\r
349             Application.Exit();\r
350         }\r
351 \r
352         #endregion\r
353 \r
354         #region Tools Menu\r
355 \r
356         /// <summary>\r
357         /// Menu - Start Button\r
358         /// </summary>\r
359         /// <param name="sender">\r
360         /// The sender.\r
361         /// </param>\r
362         /// <param name="e">\r
363         /// The e.\r
364         /// </param>\r
365         private void mnu_encode_Click(object sender, EventArgs e)\r
366         {\r
367             queueWindow.Show();\r
368         }\r
369 \r
370         /// <summary>\r
371         /// Menu - Display the Log Window\r
372         /// </summary>\r
373         /// <param name="sender">\r
374         /// The sender.\r
375         /// </param>\r
376         /// <param name="e">\r
377         /// The e.\r
378         /// </param>\r
379         private void mnu_encodeLog_Click(object sender, EventArgs e)\r
380         {\r
381             this.btn_ActivityWindow_Click(this, null);\r
382         }\r
383 \r
384         /// <summary>\r
385         /// Menu - Display the Options Window\r
386         /// </summary>\r
387         /// <param name="sender">\r
388         /// The sender.\r
389         /// </param>\r
390         /// <param name="e">\r
391         /// The e.\r
392         /// </param>\r
393         private void mnu_options_Click(object sender, EventArgs e)\r
394         {\r
395             Form options = new frmOptions(this);\r
396             options.ShowDialog();\r
397         }\r
398 \r
399         #endregion\r
400 \r
401         #region Presets Menu\r
402 \r
403         /// <summary>\r
404         /// Reset the Built in Presets\r
405         /// </summary>\r
406         /// <param name="sender">\r
407         /// The sender.\r
408         /// </param>\r
409         /// <param name="e">\r
410         /// The e.\r
411         /// </param>\r
412         private void mnu_presetReset_Click(object sender, EventArgs e)\r
413         {\r
414             presetHandler.UpdateBuiltInPresets();\r
415             LoadPresetPanel();\r
416             if (treeView_presets.Nodes.Count == 0)\r
417                 MessageBox.Show(\r
418                     "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
419                     "Error", MessageBoxButtons.OK, MessageBoxIcon.Error);\r
420             else\r
421                 MessageBox.Show("Presets have been updated!", "Alert", MessageBoxButtons.OK, MessageBoxIcon.Information);\r
422 \r
423             treeView_presets.ExpandAll();\r
424         }\r
425 \r
426         /// <summary>\r
427         /// Delete the selected preset\r
428         /// </summary>\r
429         /// <param name="sender">\r
430         /// The sender.\r
431         /// </param>\r
432         /// <param name="e">\r
433         /// The e.\r
434         /// </param>\r
435         private void mnu_delete_preset_Click(object sender, EventArgs e)\r
436         {\r
437             presetHandler.RemoveBuiltInPresets();\r
438             LoadPresetPanel(); // Reload the preset panel\r
439         }\r
440 \r
441         /// <summary>\r
442         /// Select the Normal preset\r
443         /// </summary>\r
444         /// <param name="sender">\r
445         /// The sender.\r
446         /// </param>\r
447         /// <param name="e">\r
448         /// The e.\r
449         /// </param>\r
450         private void mnu_SelectDefault_Click(object sender, EventArgs e)\r
451         {\r
452             loadNormalPreset();\r
453         }\r
454 \r
455         /// <summary>\r
456         /// Import a plist Preset\r
457         /// </summary>\r
458         /// <param name="sender">\r
459         /// The sender.\r
460         /// </param>\r
461         /// <param name="e">\r
462         /// The e.\r
463         /// </param>\r
464         private void mnu_importMacPreset_Click(object sender, EventArgs e)\r
465         {\r
466             ImportPreset();\r
467         }\r
468 \r
469         /// <summary>\r
470         /// Export a Plist Preset\r
471         /// </summary>\r
472         /// <param name="sender">\r
473         /// The sender.\r
474         /// </param>\r
475         /// <param name="e">\r
476         /// The e.\r
477         /// </param>\r
478         private void mnu_exportMacPreset_Click(object sender, EventArgs e)\r
479         {\r
480             ExportPreset();\r
481         }\r
482 \r
483         /// <summary>\r
484         /// Create a new Preset\r
485         /// </summary>\r
486         /// <param name="sender">\r
487         /// The sender.\r
488         /// </param>\r
489         /// <param name="e">\r
490         /// The e.\r
491         /// </param>\r
492         private void btn_new_preset_Click(object sender, EventArgs e)\r
493         {\r
494             Form preset = new frmAddPreset(this, presetHandler);\r
495             if (preset.ShowDialog() == DialogResult.OK)\r
496             {\r
497                 TreeNode presetTreeview = new TreeNode(presetHandler.LastPresetAdded.Name) { ForeColor = Color.Black };\r
498                 treeView_presets.Nodes.Add(presetTreeview);\r
499                 presetHandler.LastPresetAdded = null;\r
500             }\r
501         }\r
502 \r
503         #endregion\r
504 \r
505         #region Help Menu\r
506 \r
507         /// <summary>\r
508         /// Menu - Display the User Guide Web Page\r
509         /// </summary>\r
510         /// <param name="sender">\r
511         /// The sender.\r
512         /// </param>\r
513         /// <param name="e">\r
514         /// The e.\r
515         /// </param>\r
516         private void mnu_user_guide_Click(object sender, EventArgs e)\r
517         {\r
518             Process.Start("http://trac.handbrake.fr/wiki/HandBrakeGuide");\r
519         }\r
520 \r
521         /// <summary>\r
522         /// Menu - Check for Updates\r
523         /// </summary>\r
524         /// <param name="sender">\r
525         /// The sender.\r
526         /// </param>\r
527         /// <param name="e">\r
528         /// The e.\r
529         /// </param>\r
530         private void mnu_UpdateCheck_Click(object sender, EventArgs e)\r
531         {\r
532             lbl_updateCheck.Visible = true;\r
533             Main.BeginCheckForUpdates(new AsyncCallback(this.UpdateCheckDoneMenu), false);\r
534         }\r
535 \r
536         /// <summary>\r
537         /// Menu - Display the About Window\r
538         /// </summary>\r
539         /// <param name="sender">\r
540         /// The sender.\r
541         /// </param>\r
542         /// <param name="e">\r
543         /// The e.\r
544         /// </param>\r
545         private void mnu_about_Click(object sender, EventArgs e)\r
546         {\r
547             using (frmAbout About = new frmAbout())\r
548             {\r
549                 About.ShowDialog();\r
550             }\r
551         }\r
552 \r
553         #endregion\r
554 \r
555         #region Preset Bar\r
556 \r
557         /// <summary>\r
558         /// RMenu - Expand All\r
559         /// </summary>\r
560         /// <param name="sender">\r
561         /// The sender.\r
562         /// </param>\r
563         /// <param name="e">\r
564         /// The e.\r
565         /// </param>\r
566         private void pmnu_expandAll_Click(object sender, EventArgs e)\r
567         {\r
568             treeView_presets.ExpandAll();\r
569         }\r
570 \r
571         /// <summary>\r
572         /// RMenu - Collaspe All\r
573         /// </summary>\r
574         /// <param name="sender">\r
575         /// The sender.\r
576         /// </param>\r
577         /// <param name="e">\r
578         /// The e.\r
579         /// </param>\r
580         private void pmnu_collapse_Click(object sender, EventArgs e)\r
581         {\r
582             treeView_presets.CollapseAll();\r
583         }\r
584 \r
585         /// <summary>\r
586         /// Menu - Import Preset\r
587         /// </summary>\r
588         /// <param name="sender">\r
589         /// The sender.\r
590         /// </param>\r
591         /// <param name="e">\r
592         /// The e.\r
593         /// </param>\r
594         private void pmnu_import_Click(object sender, EventArgs e)\r
595         {\r
596             ImportPreset();\r
597         }\r
598 \r
599         /// <summary>\r
600         /// RMenu - Save Changes to Preset\r
601         /// </summary>\r
602         /// <param name="sender">\r
603         /// The sender.\r
604         /// </param>\r
605         /// <param name="e">\r
606         /// The e.\r
607         /// </param>\r
608         private void pmnu_saveChanges_Click(object sender, EventArgs e)\r
609         {\r
610             // TODO this requires a re-think since the Query Editor has changed.\r
611             DialogResult result =\r
612                 MessageBox.Show(\r
613                     "Do you wish to include picture settings when updating the preset: " +\r
614                     treeView_presets.SelectedNode.Text, "Update Preset", MessageBoxButtons.YesNoCancel,\r
615                     MessageBoxIcon.Question);\r
616             if (result == DialogResult.Yes)\r
617                 presetHandler.Update(treeView_presets.SelectedNode.Text,\r
618                                      QueryGenerator.GenerateQueryForPreset(this, QueryPictureSettingsMode.SourceMaximum, true, 0, 0), true);\r
619             else if (result == DialogResult.No)\r
620                 presetHandler.Update(treeView_presets.SelectedNode.Text,\r
621                                      QueryGenerator.GenerateQueryForPreset(this, QueryPictureSettingsMode.SourceMaximum, true, 0, 0), false);\r
622         }\r
623 \r
624         /// <summary>\r
625         /// RMenu - Delete Preset\r
626         /// </summary>\r
627         /// <param name="sender">\r
628         /// The sender.\r
629         /// </param>\r
630         /// <param name="e">\r
631         /// The e.\r
632         /// </param>\r
633         private void pmnu_delete_click(object sender, EventArgs e)\r
634         {\r
635             if (treeView_presets.SelectedNode != null)\r
636             {\r
637                 presetHandler.Remove(treeView_presets.SelectedNode.Text);\r
638                 treeView_presets.Nodes.Remove(treeView_presets.SelectedNode);\r
639             }\r
640             treeView_presets.Select();\r
641         }\r
642 \r
643         /// <summary>\r
644         /// Preset Menu Is Opening. Setup the Menu\r
645         /// </summary>\r
646         /// <param name="sender">\r
647         /// The sender.\r
648         /// </param>\r
649         /// <param name="e">\r
650         /// The e.\r
651         /// </param>\r
652         private void presets_menu_Opening(object sender, CancelEventArgs e)\r
653         {\r
654             // Make sure that the save menu is always disabled by default\r
655             pmnu_saveChanges.Enabled = false;\r
656 \r
657             // Now enable the save menu if the selected preset is a user preset\r
658             if (treeView_presets.SelectedNode != null)\r
659                 if (presetHandler.CheckIfUserPresetExists(treeView_presets.SelectedNode.Text))\r
660                     pmnu_saveChanges.Enabled = true;\r
661 \r
662             treeView_presets.Select();\r
663         }\r
664 \r
665         // Presets Management\r
666 \r
667         /// <summary>\r
668         /// Button - Add a preset\r
669         /// </summary>\r
670         /// <param name="sender">\r
671         /// The sender.\r
672         /// </param>\r
673         /// <param name="e">\r
674         /// The e.\r
675         /// </param>\r
676         private void btn_addPreset_Click(object sender, EventArgs e)\r
677         {\r
678             Form preset = new frmAddPreset(this, presetHandler);\r
679             if (preset.ShowDialog() == DialogResult.OK)\r
680             {\r
681                 TreeNode presetTreeview = new TreeNode(presetHandler.LastPresetAdded.Name) { ForeColor = Color.Black };\r
682                 treeView_presets.Nodes.Add(presetTreeview);\r
683                 presetHandler.LastPresetAdded = null;\r
684             }\r
685         }\r
686 \r
687         /// <summary>\r
688         /// Button - remove a Preset\r
689         /// </summary>\r
690         /// <param name="sender">\r
691         /// The sender.\r
692         /// </param>\r
693         /// <param name="e">\r
694         /// The e.\r
695         /// </param>\r
696         private void btn_removePreset_Click(object sender, EventArgs e)\r
697         {\r
698             DialogResult result = MessageBox.Show("Are you sure you wish to delete the selected preset?", "Preset",\r
699                                                   MessageBoxButtons.YesNo, MessageBoxIcon.Question);\r
700             if (result == DialogResult.Yes)\r
701             {\r
702                 if (treeView_presets.SelectedNode != null)\r
703                 {\r
704                     presetHandler.Remove(treeView_presets.SelectedNode.Text);\r
705                     treeView_presets.Nodes.Remove(treeView_presets.SelectedNode);\r
706                 }\r
707             }\r
708             treeView_presets.Select();\r
709         }\r
710 \r
711         /// <summary>\r
712         /// Button - Set the selected preset as the default\r
713         /// </summary>\r
714         /// <param name="sender">\r
715         /// The sender.\r
716         /// </param>\r
717         /// <param name="e">\r
718         /// The e.\r
719         /// </param>\r
720         private void btn_setDefault_Click(object sender, EventArgs e)\r
721         {\r
722             if (treeView_presets.SelectedNode != null)\r
723             {\r
724                 DialogResult result = MessageBox.Show("Are you sure you wish to set this preset as the default?",\r
725                                                       "Preset", MessageBoxButtons.YesNo, MessageBoxIcon.Question);\r
726                 if (result == DialogResult.Yes)\r
727                 {\r
728                     Properties.Settings.Default.defaultPreset = treeView_presets.SelectedNode.Text;\r
729                     Properties.Settings.Default.Save();\r
730                     MessageBox.Show("New default preset set.", "Alert", MessageBoxButtons.OK, MessageBoxIcon.Information);\r
731                 }\r
732             }\r
733             else\r
734                 MessageBox.Show("Please select a preset first.", "Warning", MessageBoxButtons.OK, MessageBoxIcon.Warning);\r
735         }\r
736 \r
737         /// <summary>\r
738         /// PresetBar Mouse Down event\r
739         /// </summary>\r
740         /// <param name="sender">\r
741         /// The sender.\r
742         /// </param>\r
743         /// <param name="e">\r
744         /// The e.\r
745         /// </param>\r
746         private void treeview_presets_mouseUp(object sender, MouseEventArgs e)\r
747         {\r
748             if (e.Button == MouseButtons.Right)\r
749                 treeView_presets.SelectedNode = treeView_presets.GetNodeAt(e.Location);\r
750             else if (e.Button == MouseButtons.Left)\r
751             {\r
752                 if (treeView_presets.GetNodeAt(e.Location) != null)\r
753                 {\r
754                     if (labelPreset.Text.Contains(treeView_presets.GetNodeAt(e.Location).Text))\r
755                         selectPreset();\r
756                 }\r
757             }\r
758 \r
759             treeView_presets.Select();\r
760         }\r
761 \r
762         /// <summary>\r
763         /// Preset Bar after selecting the preset\r
764         /// </summary>\r
765         /// <param name="sender">\r
766         /// The sender.\r
767         /// </param>\r
768         /// <param name="e">\r
769         /// The e.\r
770         /// </param>\r
771         private void treeView_presets_AfterSelect(object sender, TreeViewEventArgs e)\r
772         {\r
773             selectPreset();\r
774         }\r
775 \r
776         /// <summary>\r
777         /// Preset Bar - Handle the Delete Key\r
778         /// </summary>\r
779         /// <param name="sender">\r
780         /// The sender.\r
781         /// </param>\r
782         /// <param name="e">\r
783         /// The e.\r
784         /// </param>\r
785         private void treeView_presets_deleteKey(object sender, KeyEventArgs e)\r
786         {\r
787             if (e.KeyCode == Keys.Delete)\r
788             {\r
789                 DialogResult result = MessageBox.Show("Are you sure you wish to delete the selected preset?", "Preset",\r
790                                                       MessageBoxButtons.YesNo, MessageBoxIcon.Question);\r
791                 if (result == DialogResult.Yes)\r
792                 {\r
793                     if (treeView_presets.SelectedNode != null)\r
794                         presetHandler.Remove(treeView_presets.SelectedNode.Text);\r
795 \r
796                     // Remember each nodes expanded status so we can reload it\r
797                     List<bool> nodeStatus = new List<bool>();\r
798                     foreach (TreeNode node in treeView_presets.Nodes)\r
799                         nodeStatus.Add(node.IsExpanded);\r
800 \r
801                     // Now reload the preset panel\r
802                     LoadPresetPanel();\r
803 \r
804                     // And finally, re-expand any of the nodes if required\r
805                     int i = 0;\r
806                     foreach (TreeNode node in treeView_presets.Nodes)\r
807                     {\r
808                         if (nodeStatus[i])\r
809                             node.Expand();\r
810 \r
811                         i++;\r
812                     }\r
813                 }\r
814             }\r
815         }\r
816 \r
817         /// <summary>\r
818         /// Select the selected preset and setup the GUI\r
819         /// </summary>\r
820         private void selectPreset()\r
821         {\r
822             if (treeView_presets.SelectedNode != null)\r
823             {\r
824                 // Ok, so, we've selected a preset. Now we want to load it.\r
825                 string presetName = treeView_presets.SelectedNode.Text;\r
826                 Preset preset = presetHandler.GetPreset(presetName);\r
827                 if (preset != null)\r
828                 {\r
829                     string query = presetHandler.GetPreset(presetName).Query;\r
830 \r
831                     if (query != null)\r
832                     {\r
833                         // Ok, Reset all the H264 widgets before changing the preset\r
834                         x264Panel.Reset2Defaults();\r
835 \r
836                         // Send the query from the file to the Query Parser class\r
837                         QueryParser presetQuery = QueryParser.Parse(query);\r
838 \r
839                         // Now load the preset\r
840                         PresetLoader.LoadPreset(this, presetQuery, presetName);\r
841 \r
842                         // The x264 widgets will need updated, so do this now:\r
843                         x264Panel.StandardizeOptString();\r
844                         x264Panel.SetCurrentSettingsInPanel();\r
845 \r
846                         // Finally, let this window have a copy of the preset settings.\r
847                         this.currentlySelectedPreset = preset;\r
848                         PictureSettings.SetPresetCropWarningLabel(preset);\r
849                     }\r
850                 }\r
851             }\r
852         }\r
853 \r
854         /// <summary>\r
855         /// Load the Normal Preset\r
856         /// </summary>\r
857         private void loadNormalPreset()\r
858         {\r
859             foreach (TreeNode treenode in treeView_presets.Nodes)\r
860             {\r
861                 foreach (TreeNode node in treenode.Nodes)\r
862                 {\r
863                     if (node.Text.Equals("Normal"))\r
864                         treeView_presets.SelectedNode = treeView_presets.Nodes[treenode.Index].Nodes[0];\r
865                 }\r
866             }\r
867         }\r
868 \r
869         /// <summary>\r
870         /// Import a plist preset\r
871         /// </summary>\r
872         private void ImportPreset()\r
873         {\r
874             if (openPreset.ShowDialog() == DialogResult.OK)\r
875             {\r
876                 QueryParser parsed = PlistPresetHandler.Import(openPreset.FileName);\r
877                 if (presetHandler.CheckIfUserPresetExists(parsed.PresetName + " (Imported)"))\r
878                 {\r
879                     DialogResult result =\r
880                         MessageBox.Show("This preset appears to already exist. Would you like to overwrite it?",\r
881                                         "Overwrite preset?",\r
882                                         MessageBoxButtons.YesNo, MessageBoxIcon.Warning);\r
883                     if (result == DialogResult.Yes)\r
884                     {\r
885                         PresetLoader.LoadPreset(this, parsed, parsed.PresetName);\r
886                         presetHandler.Update(parsed.PresetName + " (Imported)",\r
887                                              QueryGenerator.GenerateFullQuery(this),\r
888                                              parsed.UsesPictureSettings);\r
889                     }\r
890                 }\r
891                 else\r
892                 {\r
893                     PresetLoader.LoadPreset(this, parsed, parsed.PresetName);\r
894                     if (presetHandler.Add(parsed.PresetName + " (Imported)",\r
895                                           QueryGenerator.GenerateFullQuery(this),\r
896                                           parsed.UsesPictureSettings))\r
897                     {\r
898                         TreeNode preset_treeview = new TreeNode(parsed.PresetName + " (Imported)")\r
899                                                        {\r
900                                                            ForeColor = Color.Black\r
901                                                        };\r
902                         treeView_presets.Nodes.Add(preset_treeview);\r
903                     }\r
904                 }\r
905             }\r
906         }\r
907 \r
908         /// <summary>\r
909         /// Export a plist Preset\r
910         /// </summary>\r
911         private void ExportPreset()\r
912         {\r
913             MessageBox.Show("This feature has not been implimented yet.", "Not Implimented", MessageBoxButtons.OK, MessageBoxIcon.Warning);\r
914             return;\r
915 \r
916             SaveFileDialog savefiledialog = new SaveFileDialog();\r
917             savefiledialog.Filter = "plist|*.plist";\r
918 \r
919             if (treeView_presets.SelectedNode != null)\r
920             {\r
921                 if (savefiledialog.ShowDialog() == DialogResult.OK)\r
922                 {\r
923                     Preset preset = presetHandler.GetPreset(treeView_presets.SelectedNode.Text);\r
924                     PlistPresetHandler.Export(savefiledialog.FileName, preset);\r
925                 }\r
926             }\r
927         }\r
928 \r
929         #endregion\r
930 \r
931         #region ToolStrip\r
932 \r
933         /// <summary>\r
934         /// 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
935         /// </summary>\r
936         /// <param name="sender">\r
937         /// The sender.\r
938         /// </param>\r
939         /// <param name="e">\r
940         /// The e.\r
941         /// </param>\r
942         private void btn_source_Click(object sender, EventArgs e)\r
943         {\r
944             // Remove old Drive Menu Items.\r
945             List<ToolStripMenuItem> itemsToRemove = new List<ToolStripMenuItem>();\r
946             foreach (var item in btn_source.DropDownItems)\r
947             {\r
948                 if (item.GetType() == typeof(ToolStripMenuItem))\r
949                 {\r
950                     ToolStripMenuItem menuItem = (ToolStripMenuItem)item;\r
951                     if (menuItem.Name.StartsWith("Drive"))\r
952                     {\r
953                         itemsToRemove.Add(menuItem);\r
954                     }\r
955                 }\r
956             }\r
957 \r
958             foreach (ToolStripMenuItem item in itemsToRemove)\r
959                 btn_source.DropDownItems.Remove(item);\r
960 \r
961             Thread driveInfoThread = new Thread(SetDriveSelectionMenuItem);\r
962             driveInfoThread.Start();\r
963         }\r
964 \r
965         /// <summary>\r
966         /// Toolbar - Start The Encode\r
967         /// </summary>\r
968         /// <param name="sender">\r
969         /// The sender.\r
970         /// </param>\r
971         /// <param name="e">\r
972         /// The e.\r
973         /// </param>\r
974         private void btn_start_Click(object sender, EventArgs e)\r
975         {\r
976             if (btn_start.Text == "Stop")\r
977             {\r
978                 DialogResult result = !Properties.Settings.Default.showCliForInGuiEncodeStatus\r
979                              ? MessageBox.Show(\r
980                                  "Are you sure you wish to cancel the encode?\n\nPlease note: Stopping this encode will render the file unplayable. ",\r
981                                  "Cancel Encode?",\r
982                                  MessageBoxButtons.YesNo,\r
983                                  MessageBoxIcon.Question)\r
984                              : MessageBox.Show(\r
985                                  "Are you sure you wish to cancel the encode?",\r
986                                  "Cancel Encode?",\r
987                                  MessageBoxButtons.YesNo,\r
988                                  MessageBoxIcon.Question);\r
989 \r
990                 if (result == DialogResult.Yes)\r
991                 {\r
992                     // Pause The Queue\r
993                     encodeQueue.Pause();\r
994 \r
995                     if (Settings.Default.showCliForInGuiEncodeStatus)\r
996                         encodeQueue.SafelyClose();\r
997                     else\r
998                         encodeQueue.Stop();\r
999                 }\r
1000             }\r
1001             else\r
1002             {\r
1003                 // 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
1004                 string jobSourcePath = !string.IsNullOrEmpty(rtf_query.Text) ? Main.GetSourceFromQuery(rtf_query.Text) : sourcePath;\r
1005                 string jobDestination = !string.IsNullOrEmpty(rtf_query.Text) ? Main.GetDestinationFromQuery(rtf_query.Text) : text_destination.Text;\r
1006 \r
1007                 if (encodeQueue.Count != 0 || (!string.IsNullOrEmpty(jobSourcePath) && !string.IsNullOrEmpty(jobDestination)))\r
1008                 {\r
1009                     string generatedQuery = QueryGenerator.GenerateFullQuery(this);\r
1010                     string specifiedQuery = rtf_query.Text != string.Empty\r
1011                                                 ? rtf_query.Text\r
1012                                                 : QueryGenerator.GenerateFullQuery(this);\r
1013                     string query = string.Empty;\r
1014 \r
1015                     // Check to make sure the generated query matches the GUI settings\r
1016                     if (Properties.Settings.Default.PromptOnUnmatchingQueries && !string.IsNullOrEmpty(specifiedQuery) &&\r
1017                         generatedQuery != specifiedQuery)\r
1018                     {\r
1019                         DialogResult result = MessageBox.Show("The query under the \"Query Editor\" tab " +\r
1020                                                               "does not match the current GUI settings.\n\nBecause the manual query takes " +\r
1021                                                               "priority over the GUI, your recently updated settings will not be taken " +\r
1022                                                               "into account when encoding this job." +\r
1023                                                               Environment.NewLine + Environment.NewLine +\r
1024                                                               "Do you want to replace the manual query with the updated GUI-generated query?",\r
1025                                                               "Manual Query does not Match GUI",\r
1026                                                               MessageBoxButtons.YesNoCancel, MessageBoxIcon.Asterisk,\r
1027                                                               MessageBoxDefaultButton.Button3);\r
1028 \r
1029                         switch (result)\r
1030                         {\r
1031                             case DialogResult.Yes:\r
1032                                 // Replace the manual query with the generated one\r
1033                                 query = generatedQuery;\r
1034                                 rtf_query.Text = generatedQuery;\r
1035                                 break;\r
1036                             case DialogResult.No:\r
1037                                 // Use the manual query\r
1038                                 query = specifiedQuery;\r
1039                                 break;\r
1040                             case DialogResult.Cancel:\r
1041                                 // Don't start the encode\r
1042                                 return;\r
1043                         }\r
1044                     }\r
1045                     else\r
1046                     {\r
1047                         query = specifiedQuery;\r
1048                     }\r
1049 \r
1050                     DialogResult overwrite = DialogResult.Yes;\r
1051                     if (!string.IsNullOrEmpty(jobDestination) && File.Exists(jobDestination))\r
1052                     {\r
1053                         overwrite = MessageBox.Show(\r
1054                                 "The destination file already exists. Are you sure you want to overwrite it?",\r
1055                                 "Overwrite File?",\r
1056                                 MessageBoxButtons.YesNo,\r
1057                                 MessageBoxIcon.Question);\r
1058                     }\r
1059 \r
1060                     if (overwrite == DialogResult.Yes)\r
1061                     {\r
1062                         if (encodeQueue.Count == 0)\r
1063                             encodeQueue.Add(query, this.GetTitle(), jobSourcePath, jobDestination, (rtf_query.Text != string.Empty));\r
1064 \r
1065                         queueWindow.SetQueue();\r
1066                         if (encodeQueue.Count > 1)\r
1067                             queueWindow.Show(false);\r
1068 \r
1069                         SetEncodeStarted(); // Encode is running, so setup the GUI appropriately\r
1070                         encodeQueue.Start(); // Start The Queue Encoding Process\r
1071                     }\r
1072 \r
1073                     this.Focus();\r
1074                 }\r
1075                 else if (string.IsNullOrEmpty(sourcePath) || string.IsNullOrEmpty(text_destination.Text))\r
1076                     MessageBox.Show("No source or destination selected.", "Warning", MessageBoxButtons.OK,\r
1077                                     MessageBoxIcon.Warning);\r
1078             }\r
1079         }\r
1080 \r
1081         /// <summary>\r
1082         /// Toolbar - Add the current job to the Queue\r
1083         /// </summary>\r
1084         /// <param name="sender">\r
1085         /// The sender.\r
1086         /// </param>\r
1087         /// <param name="e">\r
1088         /// The e.\r
1089         /// </param>\r
1090         private void btn_add2Queue_Click(object sender, EventArgs e)\r
1091         {\r
1092             // Get the CLI query or use the query editor if it's not empty.\r
1093             string query = QueryGenerator.GenerateFullQuery(this);\r
1094             if (!string.IsNullOrEmpty(rtf_query.Text))\r
1095                 query = rtf_query.Text;\r
1096 \r
1097             // 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
1098             string jobSourcePath = !string.IsNullOrEmpty(rtf_query.Text) ? Main.GetSourceFromQuery(rtf_query.Text) : sourcePath;\r
1099             string jobDestination = !string.IsNullOrEmpty(rtf_query.Text) ? Main.GetDestinationFromQuery(rtf_query.Text) : text_destination.Text;\r
1100 \r
1101             // Make sure we have a Source and Destination.\r
1102             if (string.IsNullOrEmpty(jobSourcePath) || string.IsNullOrEmpty(jobDestination))\r
1103             {\r
1104                 MessageBox.Show("No source or destination selected.", "Warning", MessageBoxButtons.OK, MessageBoxIcon.Warning);\r
1105                 return;\r
1106             }\r
1107 \r
1108             // Make sure the destination path exists.\r
1109             if (!Directory.Exists(Path.GetDirectoryName(jobDestination)))\r
1110             {\r
1111                 MessageBox.Show("Destination Path does not exist.", "Warning", MessageBoxButtons.OK, MessageBoxIcon.Warning);\r
1112                 return;\r
1113             }\r
1114 \r
1115             // Make sure we don't have a duplciate on the queue.\r
1116             if (encodeQueue.CheckForDestinationDuplicate(jobDestination))\r
1117             {\r
1118                 DialogResult result =\r
1119                     MessageBox.Show(\r
1120                         "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
1121                         "Warning", MessageBoxButtons.YesNo, MessageBoxIcon.Warning);\r
1122                 if (result == DialogResult.Yes)\r
1123                     encodeQueue.Add(query, this.GetTitle(), jobSourcePath, jobDestination, (rtf_query.Text != string.Empty));\r
1124             }\r
1125             else\r
1126                 encodeQueue.Add(query, this.GetTitle(), jobSourcePath, jobDestination, (rtf_query.Text != string.Empty));\r
1127 \r
1128             lbl_encode.Text = encodeQueue.Count + " encode(s) pending in the queue";\r
1129 \r
1130             queueWindow.Show();\r
1131         }\r
1132 \r
1133         /// <summary>\r
1134         /// Toolbar - Show the Queue\r
1135         /// </summary>\r
1136         /// <param name="sender">\r
1137         /// The sender.\r
1138         /// </param>\r
1139         /// <param name="e">\r
1140         /// The e.\r
1141         /// </param>\r
1142         private void btn_showQueue_Click(object sender, EventArgs e)\r
1143         {\r
1144             queueWindow.Show();\r
1145             queueWindow.Activate();\r
1146         }\r
1147 \r
1148         /// <summary>\r
1149         /// Toolbar - Show the Preview Window\r
1150         /// </summary>\r
1151         /// <param name="sender">\r
1152         /// The sender.\r
1153         /// </param>\r
1154         /// <param name="e">\r
1155         /// The e.\r
1156         /// </param>\r
1157         private void tb_preview_Click(object sender, EventArgs e)\r
1158         {\r
1159             if (string.IsNullOrEmpty(sourcePath) || string.IsNullOrEmpty(text_destination.Text))\r
1160                 MessageBox.Show("No source or destination selected.", "Warning", MessageBoxButtons.OK,\r
1161                                 MessageBoxIcon.Warning);\r
1162             else\r
1163             {\r
1164                 if (qtpreview == null)\r
1165                 {\r
1166                     qtpreview = new frmPreview(this);\r
1167                     qtpreview.Show();\r
1168                 }\r
1169                 else if (qtpreview.IsDisposed)\r
1170                 {\r
1171                     qtpreview = new frmPreview(this);\r
1172                     qtpreview.Show();\r
1173                 }\r
1174                 else\r
1175                     MessageBox.Show(qtpreview, "The preview window is already open!", "Warning", MessageBoxButtons.OK,\r
1176                                     MessageBoxIcon.Warning);\r
1177             }\r
1178         }\r
1179 \r
1180         /// <summary>\r
1181         /// Toolbar - Show the Activity log Window\r
1182         /// </summary>\r
1183         /// <param name="sender">\r
1184         /// The sender.\r
1185         /// </param>\r
1186         /// <param name="e">\r
1187         /// The e.\r
1188         /// </param>\r
1189         private void btn_ActivityWindow_Click(object sender, EventArgs e)\r
1190         {\r
1191             if (this.activityWindow == null || !this.activityWindow.IsHandleCreated)\r
1192                 this.activityWindow = new frmActivityWindow(encodeQueue, SourceScan);\r
1193 \r
1194             this.activityWindow.Show();\r
1195             this.activityWindow.Activate();\r
1196         }\r
1197 \r
1198         #endregion\r
1199 \r
1200         #region System Tray Icon\r
1201 \r
1202         /// <summary>\r
1203         /// Handle Resizing of the main window when deaing with the Notify Icon\r
1204         /// </summary>\r
1205         /// <param name="sender">\r
1206         /// The sender.\r
1207         /// </param>\r
1208         /// <param name="e">\r
1209         /// The e.\r
1210         /// </param>\r
1211         private void frmMain_Resize(object sender, EventArgs e)\r
1212         {\r
1213             if (FormWindowState.Minimized == this.WindowState)\r
1214             {\r
1215                 notifyIcon.Visible = true;\r
1216                 this.Hide();\r
1217             }\r
1218             else if (FormWindowState.Normal == this.WindowState)\r
1219                 notifyIcon.Visible = false;\r
1220         }\r
1221 \r
1222         /// <summary>\r
1223         /// Double Click the Tray Icon\r
1224         /// </summary>\r
1225         /// <param name="sender">\r
1226         /// The sender.\r
1227         /// </param>\r
1228         /// <param name="e">\r
1229         /// The e.\r
1230         /// </param>\r
1231         private void notifyIcon_MouseDoubleClick(object sender, MouseEventArgs e)\r
1232         {\r
1233             this.Visible = true;\r
1234             this.Activate();\r
1235             this.WindowState = FormWindowState.Normal;\r
1236             notifyIcon.Visible = false;\r
1237         }\r
1238 \r
1239         /// <summary>\r
1240         /// Tray Icon - Restore Menu Item - Resture the Window\r
1241         /// </summary>\r
1242         /// <param name="sender">\r
1243         /// The sender.\r
1244         /// </param>\r
1245         /// <param name="e">\r
1246         /// The e.\r
1247         /// </param>\r
1248         private void btn_restore_Click(object sender, EventArgs e)\r
1249         {\r
1250             this.Visible = true;\r
1251             this.Activate();\r
1252             this.WindowState = FormWindowState.Normal;\r
1253             notifyIcon.Visible = false;\r
1254         }\r
1255 \r
1256         #endregion\r
1257 \r
1258         #region Main Window and Tab Control\r
1259 \r
1260         // Source\r
1261         private void btn_dvd_source_Click(object sender, EventArgs e)\r
1262         {\r
1263             if (DVD_Open.ShowDialog() == DialogResult.OK)\r
1264             {\r
1265                 this.selectedSourceType = SourceType.Folder;\r
1266                 SelectSource(DVD_Open.SelectedPath);\r
1267             }\r
1268             else\r
1269                 UpdateSourceLabel();\r
1270         }\r
1271 \r
1272         private void btn_file_source_Click(object sender, EventArgs e)\r
1273         {\r
1274             if (ISO_Open.ShowDialog() == DialogResult.OK)\r
1275             {\r
1276                 this.selectedSourceType = SourceType.VideoFile;\r
1277                 SelectSource(ISO_Open.FileName);\r
1278             }\r
1279             else\r
1280                 UpdateSourceLabel();\r
1281         }\r
1282 \r
1283         private void mnu_dvd_drive_Click(object sender, EventArgs e)\r
1284         {\r
1285             ToolStripMenuItem item = sender as ToolStripMenuItem;\r
1286             if (item != null)\r
1287             {\r
1288                 string driveId = item.Name.Replace("Drive", string.Empty);\r
1289                 int id;\r
1290                 if (int.TryParse(driveId, out id))\r
1291                 {\r
1292                     this.dvdDrivePath = drives[id].RootDirectory;\r
1293                     this.dvdDriveLabel = drives[id].VolumeLabel;\r
1294 \r
1295                     if (this.dvdDrivePath == null) return;\r
1296                     this.selectedSourceType = SourceType.DvdDrive;\r
1297                     SelectSource(this.dvdDrivePath);\r
1298                 }\r
1299             }\r
1300         }\r
1301 \r
1302         private void SelectSource(string file)\r
1303         {\r
1304             Check_ChapterMarkers.Enabled = true;\r
1305             sourcePath = string.Empty;\r
1306 \r
1307             if (file == string.Empty) // Must have a file or path\r
1308             {\r
1309                 UpdateSourceLabel();\r
1310                 return;\r
1311             }\r
1312 \r
1313             sourcePath = Path.GetFileName(file);\r
1314             StartScan(file, 0);\r
1315         }\r
1316 \r
1317         private void drp_dvdtitle_Click(object sender, EventArgs e)\r
1318         {\r
1319             if ((drp_dvdtitle.Items.Count == 1) && (drp_dvdtitle.Items[0].ToString() == "Automatic"))\r
1320                 MessageBox.Show(\r
1321                     "There are no titles to select. Please load a source file by clicking the 'Source' button above before trying to select a title.",\r
1322                     "Alert", MessageBoxButtons.OK, MessageBoxIcon.Asterisk);\r
1323         }\r
1324 \r
1325         private void drp_dvdtitle_SelectedIndexChanged(object sender, EventArgs e)\r
1326         {\r
1327             UnRegisterPresetEventHandler();\r
1328             drop_mode.SelectedIndex = 0;\r
1329 \r
1330             drop_chapterStart.Items.Clear();\r
1331             drop_chapterFinish.Items.Clear();\r
1332 \r
1333             // If the dropdown is set to automatic nothing else needs to be done.\r
1334             // Otheriwse if its not, title data has to be loaded from parsing.\r
1335             if (drp_dvdtitle.Text != "Automatic")\r
1336             {\r
1337                 selectedTitle = drp_dvdtitle.SelectedItem as Title;\r
1338                 lbl_duration.Text = selectedTitle.Duration.ToString();\r
1339                 PictureSettings.CurrentlySelectedPreset = this.currentlySelectedPreset;\r
1340                 PictureSettings.Source = selectedTitle; // Setup Picture Settings Tab Control\r
1341 \r
1342                 // Populate the Angles dropdown\r
1343                 drop_angle.Items.Clear();\r
1344                 if (!Settings.Default.noDvdNav)\r
1345                 {\r
1346                     drop_angle.Visible = true;\r
1347                     lbl_angle.Visible = true;\r
1348 \r
1349                     for (int i = 1; i <= selectedTitle.AngleCount; i++)\r
1350                         drop_angle.Items.Add(i.ToString());\r
1351 \r
1352                     if (drop_angle.Items.Count != 0)\r
1353                         drop_angle.SelectedIndex = 0;\r
1354                 }\r
1355                 else\r
1356                 {\r
1357                     drop_angle.Visible = false;\r
1358                     lbl_angle.Visible = false;\r
1359                 }\r
1360 \r
1361                 // Populate the Start chapter Dropdown\r
1362                 drop_chapterStart.Items.Clear();\r
1363                 drop_chapterStart.Items.AddRange(selectedTitle.Chapters.ToArray());\r
1364                 if (drop_chapterStart.Items.Count > 0)\r
1365                     drop_chapterStart.Text = drop_chapterStart.Items[0].ToString();\r
1366 \r
1367                 // Populate the Final Chapter Dropdown\r
1368                 drop_chapterFinish.Items.Clear();\r
1369                 drop_chapterFinish.Items.AddRange(selectedTitle.Chapters.ToArray());\r
1370                 if (drop_chapterFinish.Items.Count > 0)\r
1371                     drop_chapterFinish.Text = drop_chapterFinish.Items[drop_chapterFinish.Items.Count - 1].ToString();\r
1372 \r
1373                 // Populate the Audio Channels Dropdown\r
1374                 AudioSettings.SetTrackList(selectedTitle, this.currentlySelectedPreset);\r
1375 \r
1376                 // Populate the Subtitles dropdown\r
1377                 Subtitles.SetSubtitleTrackAuto(selectedTitle.Subtitles.ToArray());\r
1378             }\r
1379             // Update the source label if we have multiple streams\r
1380             if (selectedTitle != null)\r
1381                 if (!string.IsNullOrEmpty(selectedTitle.SourceName))\r
1382                     labelSource.Text = labelSource.Text = Path.GetFileName(selectedTitle.SourceName);\r
1383 \r
1384             // Run the AutoName & ChapterNaming functions\r
1385             if (Settings.Default.autoNaming)\r
1386             {\r
1387                 string autoPath = Main.AutoName(this);\r
1388                 if (autoPath != null)\r
1389                     text_destination.Text = autoPath;\r
1390                 else\r
1391                     MessageBox.Show(\r
1392                         "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
1393                         "Warning", MessageBoxButtons.OK, MessageBoxIcon.Warning);\r
1394             }\r
1395 \r
1396             data_chpt.Rows.Clear();\r
1397             if (selectedTitle.Chapters.Count != 1)\r
1398             {\r
1399                 DataGridView chapterGridView = Main.ChapterNaming(data_chpt, drop_chapterFinish.Text);\r
1400                 if (chapterGridView != null)\r
1401                     data_chpt = chapterGridView;\r
1402             }\r
1403             else\r
1404             {\r
1405                 Check_ChapterMarkers.Checked = false;\r
1406                 Check_ChapterMarkers.Enabled = false;\r
1407             }\r
1408 \r
1409             // Hack to force the redraw of the scrollbars which don't resize properly when the control is disabled.\r
1410             data_chpt.Columns[0].Width = 166;\r
1411             data_chpt.Columns[0].Width = 165;\r
1412 \r
1413             RegisterPresetEventHandler();\r
1414         }\r
1415 \r
1416         private void chapersChanged(object sender, EventArgs e)\r
1417         {\r
1418             if (drop_mode.SelectedIndex != 0) // Function is not used if we are not in chapters mode.\r
1419                 return;\r
1420 \r
1421             Control ctl = (Control)sender;\r
1422             int chapterStart, chapterEnd;\r
1423             int.TryParse(drop_chapterStart.Text, out chapterStart);\r
1424             int.TryParse(drop_chapterFinish.Text, out chapterEnd);\r
1425 \r
1426             switch (ctl.Name)\r
1427             {\r
1428                 case "drop_chapterStart":\r
1429                     if (drop_chapterFinish.SelectedIndex == -1 && drop_chapterFinish.Items.Count != 0)\r
1430                         drop_chapterFinish.SelectedIndex = drop_chapterFinish.Items.Count - 1;\r
1431 \r
1432                     if (chapterEnd != 0)\r
1433                         if (chapterStart > chapterEnd)\r
1434                             drop_chapterFinish.Text = chapterStart.ToString();\r
1435                     break;\r
1436                 case "drop_chapterFinish":\r
1437                     if (drop_chapterStart.Items.Count >= 1 && drop_chapterStart.SelectedIndex == -1)\r
1438                         drop_chapterStart.SelectedIndex = 0;\r
1439 \r
1440                     if (chapterStart != 0)\r
1441                         if (chapterEnd < chapterStart)\r
1442                             drop_chapterFinish.Text = chapterStart.ToString();\r
1443 \r
1444                     // Add more rows to the Chapter menu if needed.\r
1445                     if (Check_ChapterMarkers.Checked)\r
1446                     {\r
1447                         int i = data_chpt.Rows.Count, finish;\r
1448                         int.TryParse(drop_chapterFinish.Text, out finish);\r
1449 \r
1450                         while (i < finish)\r
1451                         {\r
1452                             int n = data_chpt.Rows.Add();\r
1453                             data_chpt.Rows[n].Cells[0].Value = (i + 1);\r
1454                             data_chpt.Rows[n].Cells[1].Value = "Chapter " + (i + 1);\r
1455                             data_chpt.Rows[n].Cells[0].ValueType = typeof(int);\r
1456                             data_chpt.Rows[n].Cells[1].ValueType = typeof(string);\r
1457                             i++;\r
1458                         }\r
1459                     }\r
1460                     break;\r
1461             }\r
1462 \r
1463             // Update the Duration\r
1464             lbl_duration.Text =\r
1465                 Main.CalculateDuration(drop_chapterStart.SelectedIndex, drop_chapterFinish.SelectedIndex, selectedTitle)\r
1466                     .ToString();\r
1467 \r
1468             // Run the Autonaming function\r
1469             if (Settings.Default.autoNaming)\r
1470                 text_destination.Text = Main.AutoName(this);\r
1471 \r
1472             // Disable chapter markers if only 1 chapter is selected.\r
1473             if (chapterStart == chapterEnd)\r
1474             {\r
1475                 Check_ChapterMarkers.Enabled = false;\r
1476                 btn_importChapters.Enabled = false;\r
1477                 data_chpt.Enabled = false;\r
1478             }\r
1479             else\r
1480             {\r
1481                 Check_ChapterMarkers.Enabled = true;\r
1482                 if (Check_ChapterMarkers.Checked)\r
1483                 {\r
1484                     btn_importChapters.Enabled = true;\r
1485                     data_chpt.Enabled = true;\r
1486                 }\r
1487             }\r
1488         }\r
1489 \r
1490         private void SecondsOrFramesChanged(object sender, EventArgs e)\r
1491         {\r
1492             int start, end;\r
1493             int.TryParse(drop_chapterStart.Text, out start);\r
1494             int.TryParse(drop_chapterFinish.Text, out end);\r
1495             double duration = end - start;\r
1496 \r
1497             switch (drop_mode.SelectedIndex)\r
1498             {\r
1499                 case 1:\r
1500                     lbl_duration.Text = TimeSpan.FromSeconds(duration).ToString();\r
1501                     return;\r
1502                 case 2:\r
1503                     if (selectedTitle != null)\r
1504                     {\r
1505                         duration = duration / selectedTitle.Fps;\r
1506                         lbl_duration.Text = TimeSpan.FromSeconds(duration).ToString();\r
1507                     }\r
1508                     else\r
1509                         lbl_duration.Text = "--:--:--";\r
1510 \r
1511                     return;\r
1512             }\r
1513         }\r
1514 \r
1515         private void drop_mode_SelectedIndexChanged(object sender, EventArgs e)\r
1516         {\r
1517             // Reset\r
1518             this.drop_chapterFinish.TextChanged -= this.SecondsOrFramesChanged;\r
1519             this.drop_chapterStart.TextChanged -= this.SecondsOrFramesChanged;\r
1520 \r
1521             // Do Work\r
1522             switch (drop_mode.SelectedIndex)\r
1523             {\r
1524                 case 0:\r
1525                     drop_chapterStart.DropDownStyle = ComboBoxStyle.DropDownList;\r
1526                     drop_chapterFinish.DropDownStyle = ComboBoxStyle.DropDownList;\r
1527                     if (drop_chapterStart.Items.Count != 0)\r
1528                     {\r
1529                         drop_chapterStart.SelectedIndex = 0;\r
1530                         drop_chapterFinish.SelectedIndex = drop_chapterFinish.Items.Count - 1;\r
1531                     }\r
1532                     else\r
1533                         lbl_duration.Text = "--:--:--";\r
1534                     return;\r
1535                 case 1:\r
1536                     this.drop_chapterStart.TextChanged += this.SecondsOrFramesChanged;\r
1537                     this.drop_chapterFinish.TextChanged += this.SecondsOrFramesChanged;\r
1538                     drop_chapterStart.DropDownStyle = ComboBoxStyle.Simple;\r
1539                     drop_chapterFinish.DropDownStyle = ComboBoxStyle.Simple;\r
1540                     if (selectedTitle != null)\r
1541                     {\r
1542                         drop_chapterStart.Text = "0";\r
1543                         drop_chapterFinish.Text = selectedTitle.Duration.TotalSeconds.ToString();\r
1544                     }\r
1545                     return;\r
1546                 case 2:\r
1547                     this.drop_chapterStart.TextChanged += this.SecondsOrFramesChanged;\r
1548                     this.drop_chapterFinish.TextChanged += this.SecondsOrFramesChanged;\r
1549                     drop_chapterStart.DropDownStyle = ComboBoxStyle.Simple;\r
1550                     drop_chapterFinish.DropDownStyle = ComboBoxStyle.Simple;\r
1551                     if (selectedTitle != null)\r
1552                     {\r
1553                         drop_chapterStart.Text = "0";\r
1554                         drop_chapterFinish.Text = (selectedTitle.Fps * selectedTitle.Duration.TotalSeconds).ToString();\r
1555                     }\r
1556                     return;\r
1557             }\r
1558         }\r
1559 \r
1560         // Destination\r
1561         private void btn_destBrowse_Click(object sender, EventArgs e)\r
1562         {\r
1563             // This removes the file extension from the filename box on the save file dialog.\r
1564             // It's daft but some users don't realise that typing an extension overrides the dropdown extension selected.\r
1565             DVD_Save.FileName = Path.GetFileNameWithoutExtension(text_destination.Text);\r
1566 \r
1567             if (Path.IsPathRooted(text_destination.Text))\r
1568                 DVD_Save.InitialDirectory = Path.GetDirectoryName(text_destination.Text);\r
1569 \r
1570             // Show the dialog and set the main form file path\r
1571             if (drop_format.SelectedIndex.Equals(0))\r
1572                 DVD_Save.FilterIndex = 1;\r
1573             else if (drop_format.SelectedIndex.Equals(1))\r
1574                 DVD_Save.FilterIndex = 2;\r
1575 \r
1576             if (DVD_Save.ShowDialog() == DialogResult.OK && !string.IsNullOrEmpty(DVD_Save.FileName))\r
1577             {\r
1578                 // Add a file extension manually, as FileDialog.AddExtension has issues with dots in filenames\r
1579                 switch (DVD_Save.FilterIndex)\r
1580                 {\r
1581                     case 1:\r
1582                         if (!Path.GetExtension(DVD_Save.FileName).Equals(".mp4", StringComparison.InvariantCultureIgnoreCase))\r
1583                             DVD_Save.FileName = Settings.Default.useM4v ? DVD_Save.FileName.Replace(".mp4", ".m4v").Replace(".mkv", ".m4v") : DVD_Save.FileName.Replace(".m4v", ".mp4").Replace(".mkv", ".mp4");\r
1584                         break;\r
1585                     case 2:\r
1586                         if (!Path.GetExtension(DVD_Save.FileName).Equals(".mkv", StringComparison.InvariantCultureIgnoreCase))\r
1587                             DVD_Save.FileName = DVD_Save.FileName.Replace(".mp4", ".mkv").Replace(".m4v", ".mkv");\r
1588                         break;\r
1589                     default:\r
1590                         // do nothing  \r
1591                         break;\r
1592                 }\r
1593                 text_destination.Text = DVD_Save.FileName;\r
1594 \r
1595                 // Quicktime requires .m4v file for chapter markers to work. If checked, change the extension to .m4v (mp4 and m4v are the same thing)\r
1596                 if (Check_ChapterMarkers.Checked && DVD_Save.FilterIndex != 2)\r
1597                     SetExtension(".m4v");\r
1598             }\r
1599         }\r
1600 \r
1601         private void text_destination_TextChanged(object sender, EventArgs e)\r
1602         {\r
1603             string path = text_destination.Text;\r
1604             if (path.EndsWith(".mp4") || path.EndsWith(".m4v"))\r
1605                 drop_format.SelectedIndex = 0;\r
1606             else if (path.EndsWith(".mkv"))\r
1607                 drop_format.SelectedIndex = 1;\r
1608         }\r
1609 \r
1610         // Output Settings\r
1611         private void drop_format_SelectedIndexChanged(object sender, EventArgs e)\r
1612         {\r
1613             switch (drop_format.SelectedIndex)\r
1614             {\r
1615                 case 0:\r
1616                     if (Settings.Default.useM4v || Check_ChapterMarkers.Checked ||\r
1617                         AudioSettings.RequiresM4V() || Subtitles.RequiresM4V())\r
1618                         SetExtension(".m4v");\r
1619                     else\r
1620                         SetExtension(".mp4");\r
1621                     break;\r
1622                 case 1:\r
1623                     SetExtension(".mkv");\r
1624                     break;\r
1625             }\r
1626 \r
1627             AudioSettings.SetContainer(drop_format.Text);\r
1628 \r
1629             if (drop_format.Text.Contains("MP4"))\r
1630             {\r
1631                 if (drp_videoEncoder.Items.Contains("VP3 (Theora)"))\r
1632                 {\r
1633                     drp_videoEncoder.Items.Remove("VP3 (Theora)");\r
1634                     drp_videoEncoder.SelectedIndex = 1;\r
1635                 }\r
1636             }\r
1637             else if (drop_format.Text.Contains("MKV"))\r
1638                 drp_videoEncoder.Items.Add("VP3 (Theora)");\r
1639         }\r
1640 \r
1641         public void SetExtension(string newExtension)\r
1642         {\r
1643             if (newExtension == ".mp4" || newExtension == ".m4v")\r
1644                 if (Settings.Default.useM4v || Check_ChapterMarkers.Checked || AudioSettings.RequiresM4V() ||\r
1645                     Subtitles.RequiresM4V())\r
1646                     newExtension = ".m4v";\r
1647                 else\r
1648                     newExtension = ".mp4";\r
1649 \r
1650             if (Path.HasExtension(newExtension))\r
1651                 text_destination.Text = Path.ChangeExtension(text_destination.Text, newExtension);\r
1652         }\r
1653 \r
1654         // Video Tab\r
1655         private void drp_videoEncoder_SelectedIndexChanged(object sender, EventArgs e)\r
1656         {\r
1657             setContainerOpts();\r
1658 \r
1659             // Turn off some options which are H.264 only when the user selects a non h.264 encoder\r
1660             if (drp_videoEncoder.Text.Contains("H.264"))\r
1661             {\r
1662                 if (check_2PassEncode.CheckState == CheckState.Checked)\r
1663                     check_turbo.Enabled = true;\r
1664 \r
1665                 tab_advanced.Enabled = true;\r
1666                 if ((drop_format.Text.Contains("MP4")) || (drop_format.Text.Contains("M4V")))\r
1667                     check_iPodAtom.Enabled = true;\r
1668                 else\r
1669                     check_iPodAtom.Enabled = false;\r
1670             }\r
1671             else\r
1672             {\r
1673                 check_turbo.CheckState = CheckState.Unchecked;\r
1674                 check_turbo.Enabled = false;\r
1675                 tab_advanced.Enabled = false;\r
1676                 x264Panel.X264Query = string.Empty;\r
1677                 check_iPodAtom.Enabled = false;\r
1678                 check_iPodAtom.Checked = false;\r
1679             }\r
1680 \r
1681             // Setup the CQ Slider\r
1682             switch (drp_videoEncoder.Text)\r
1683             {\r
1684                 case "MPEG-4 (FFmpeg)":\r
1685                     if (slider_videoQuality.Value > 31)\r
1686                         slider_videoQuality.Value = 20; // Just reset to 70% QP 10 on encode change.\r
1687                     slider_videoQuality.Minimum = 1;\r
1688                     slider_videoQuality.Maximum = 31;\r
1689                     break;\r
1690                 case "H.264 (x264)":\r
1691                     slider_videoQuality.Minimum = 0;\r
1692                     slider_videoQuality.TickFrequency = 1;\r
1693 \r
1694                     double cqStep = Settings.Default.x264cqstep;\r
1695                     double multiplier = 1.0 / cqStep;\r
1696                     double value = slider_videoQuality.Value * multiplier;\r
1697 \r
1698                     slider_videoQuality.Maximum = (int)(51 / Settings.Default.x264cqstep);\r
1699 \r
1700                     if (value < slider_videoQuality.Maximum)\r
1701                         slider_videoQuality.Value = slider_videoQuality.Maximum - (int)value;\r
1702 \r
1703                     break;\r
1704                 case "VP3 (Theora)":\r
1705                     if (slider_videoQuality.Value > 63)\r
1706                         slider_videoQuality.Value = 45; // Just reset to 70% QP 45 on encode change.\r
1707                     slider_videoQuality.Minimum = 0;\r
1708                     slider_videoQuality.Maximum = 63;\r
1709                     break;\r
1710             }\r
1711         }\r
1712 \r
1713         /// <summary>\r
1714         /// When the FrameRate is not Same As Source, show the Max/Constant Mode dropdown\r
1715         /// </summary>\r
1716         /// <param name="sender">\r
1717         /// The sender.\r
1718         /// </param>\r
1719         /// <param name="e">\r
1720         /// The e.\r
1721         /// </param>\r
1722         private void drp_videoFramerate_SelectedIndexChanged(object sender, EventArgs e)\r
1723         {\r
1724             if (this.drp_videoFramerate.SelectedIndex == 0)\r
1725             {\r
1726                 this.checkMaximumFramerate.Visible = false;\r
1727                 this.checkMaximumFramerate.CheckState = CheckState.Unchecked;\r
1728             }\r
1729             else\r
1730             {\r
1731                 this.checkMaximumFramerate.Visible = true;\r
1732             }\r
1733         }\r
1734 \r
1735         /// <summary>\r
1736         /// Set the container format options\r
1737         /// </summary>\r
1738         public void setContainerOpts()\r
1739         {\r
1740             if ((drop_format.Text.Contains("MP4")) || (drop_format.Text.Contains("M4V")))\r
1741             {\r
1742                 check_largeFile.Enabled = true;\r
1743                 check_optimiseMP4.Enabled = true;\r
1744                 check_iPodAtom.Enabled = true;\r
1745             }\r
1746             else\r
1747             {\r
1748                 check_largeFile.Enabled = false;\r
1749                 check_optimiseMP4.Enabled = false;\r
1750                 check_iPodAtom.Enabled = false;\r
1751                 check_largeFile.Checked = false;\r
1752                 check_optimiseMP4.Checked = false;\r
1753                 check_iPodAtom.Checked = false;\r
1754             }\r
1755         }\r
1756 \r
1757         private double cachedCqStep = Settings.Default.x264cqstep;\r
1758 \r
1759         /// <summary>\r
1760         /// Update the CQ slider for x264 for a new CQ step. This is set from option\r
1761         /// </summary>\r
1762         public void setQualityFromSlider()\r
1763         {\r
1764             // Work out the current RF value.\r
1765             double cqStep = cachedCqStep;\r
1766             double rfValue = 51.0 - slider_videoQuality.Value * cqStep;\r
1767 \r
1768             // Change the maximum value for the slider\r
1769             slider_videoQuality.Maximum = (int)(51 / Settings.Default.x264cqstep);\r
1770 \r
1771             // Reset the CQ slider to RF0\r
1772             slider_videoQuality.Value = slider_videoQuality.Maximum;\r
1773 \r
1774             // Reset the CQ slider back to the previous value as close as possible\r
1775             double cqStepNew = Settings.Default.x264cqstep;\r
1776             double rfValueCurrent = 51.0 - slider_videoQuality.Value * cqStepNew;\r
1777             while (rfValueCurrent < rfValue)\r
1778             {\r
1779                 slider_videoQuality.Value--;\r
1780                 rfValueCurrent = 51.0 - slider_videoQuality.Value * cqStepNew;\r
1781             }\r
1782 \r
1783             // Cache the CQ step for the next calculation\r
1784             cachedCqStep = Settings.Default.x264cqstep;\r
1785         }\r
1786 \r
1787         private void slider_videoQuality_Scroll(object sender, EventArgs e)\r
1788         {\r
1789             double cqStep = Settings.Default.x264cqstep;\r
1790             switch (drp_videoEncoder.Text)\r
1791             {\r
1792                 case "MPEG-4 (FFmpeg)":\r
1793                     lbl_SliderValue.Text = "QP:" + (32 - slider_videoQuality.Value);\r
1794                     break;\r
1795                 case "H.264 (x264)":\r
1796                     double rfValue = 51.0 - slider_videoQuality.Value * cqStep;\r
1797                     rfValue = Math.Round(rfValue, 2);\r
1798                     lbl_SliderValue.Text = "RF:" + rfValue.ToString(new CultureInfo("en-US"));\r
1799                     break;\r
1800                 case "VP3 (Theora)":\r
1801                     lbl_SliderValue.Text = "QP:" + slider_videoQuality.Value;\r
1802                     break;\r
1803             }\r
1804         }\r
1805 \r
1806         private void radio_targetFilesize_CheckedChanged(object sender, EventArgs e)\r
1807         {\r
1808             text_bitrate.Enabled = false;\r
1809             text_filesize.Enabled = true;\r
1810             slider_videoQuality.Enabled = false;\r
1811 \r
1812             check_2PassEncode.Enabled = true;\r
1813         }\r
1814 \r
1815         private void radio_avgBitrate_CheckedChanged(object sender, EventArgs e)\r
1816         {\r
1817             text_bitrate.Enabled = true;\r
1818             text_filesize.Enabled = false;\r
1819             slider_videoQuality.Enabled = false;\r
1820 \r
1821             check_2PassEncode.Enabled = true;\r
1822         }\r
1823 \r
1824         private void radio_cq_CheckedChanged(object sender, EventArgs e)\r
1825         {\r
1826             text_bitrate.Enabled = false;\r
1827             text_filesize.Enabled = false;\r
1828             slider_videoQuality.Enabled = true;\r
1829 \r
1830             check_2PassEncode.Enabled = false;\r
1831             check_2PassEncode.CheckState = CheckState.Unchecked;\r
1832         }\r
1833 \r
1834         private void check_2PassEncode_CheckedChanged(object sender, EventArgs e)\r
1835         {\r
1836             if (check_2PassEncode.CheckState.ToString() == "Checked")\r
1837             {\r
1838                 if (drp_videoEncoder.Text.Contains("H.264"))\r
1839                     check_turbo.Enabled = true;\r
1840             }\r
1841             else\r
1842             {\r
1843                 check_turbo.Enabled = false;\r
1844                 check_turbo.CheckState = CheckState.Unchecked;\r
1845             }\r
1846         }\r
1847 \r
1848         // Chapter Marker Tab\r
1849         private void Check_ChapterMarkers_CheckedChanged(object sender, EventArgs e)\r
1850         {\r
1851             if (Check_ChapterMarkers.Checked)\r
1852             {\r
1853                 if (drop_format.SelectedIndex != 1)\r
1854                     SetExtension(".m4v");\r
1855                 data_chpt.Enabled = true;\r
1856                 btn_importChapters.Enabled = true;\r
1857             }\r
1858             else\r
1859             {\r
1860                 if (drop_format.SelectedIndex != 1 && !Settings.Default.useM4v)\r
1861                     SetExtension(".mp4");\r
1862                 data_chpt.Enabled = false;\r
1863                 btn_importChapters.Enabled = false;\r
1864             }\r
1865         }\r
1866 \r
1867         private void btn_importChapters_Click(object sender, EventArgs e)\r
1868         {\r
1869             if (File_ChapterImport.ShowDialog() == DialogResult.OK)\r
1870             {\r
1871                 string filename = File_ChapterImport.FileName;\r
1872                 DataGridView imported = Main.ImportChapterNames(data_chpt, filename);\r
1873                 if (imported != null)\r
1874                     data_chpt = imported;\r
1875             }\r
1876         }\r
1877 \r
1878         private void btn_export_Click(object sender, EventArgs e)\r
1879         {\r
1880             SaveFileDialog saveFileDialog = new SaveFileDialog { Filter = "Csv File|*.csv", DefaultExt = "csv" };\r
1881             if (saveFileDialog.ShowDialog() == DialogResult.OK)\r
1882             {\r
1883                 string filename = saveFileDialog.FileName;\r
1884 \r
1885                 Main.SaveChapterMarkersToCsv(this, filename);\r
1886             }\r
1887         }\r
1888 \r
1889         private void mnu_resetChapters_Click(object sender, EventArgs e)\r
1890         {\r
1891             data_chpt.Rows.Clear();\r
1892             DataGridView chapterGridView = Main.ChapterNaming(data_chpt, drop_chapterFinish.Text);\r
1893             if (chapterGridView != null)\r
1894             {\r
1895                 data_chpt = chapterGridView;\r
1896             }\r
1897         }\r
1898 \r
1899         // Query Editor Tab\r
1900         private void btn_generate_Query_Click(object sender, EventArgs e)\r
1901         {\r
1902             rtf_query.Text = QueryGenerator.GenerateFullQuery(this);\r
1903         }\r
1904 \r
1905         private void btn_clear_Click(object sender, EventArgs e)\r
1906         {\r
1907             rtf_query.Clear();\r
1908         }\r
1909 \r
1910         #endregion\r
1911 \r
1912         // MainWindow Components, Actions and Functions ***********************\r
1913 \r
1914         #region Source Scan\r
1915 \r
1916         /// <summary>\r
1917         /// Start the Scan Process\r
1918         /// </summary>\r
1919         /// <param name="filename">\r
1920         /// The filename.\r
1921         /// </param>\r
1922         /// <param name="title">\r
1923         /// The title.\r
1924         /// </param>\r
1925         private void StartScan(string filename, int title)\r
1926         {\r
1927             // Setup the GUI components for the scan.\r
1928             sourcePath = filename;\r
1929 \r
1930             this.DisableGUI();\r
1931 \r
1932             // Start the Scan\r
1933             try\r
1934             {\r
1935                 SourceScan.Scan(sourcePath, title);\r
1936                 SourceScan.ScanStatusChanged += SourceScan_ScanStatusChanged;\r
1937                 SourceScan.ScanCompleted += SourceScan_ScanCompleted;\r
1938             }\r
1939             catch (Exception exc)\r
1940             {\r
1941                 MessageBox.Show("frmMain.cs - StartScan " + exc, "Error", MessageBoxButtons.OK, MessageBoxIcon.Error);\r
1942             }\r
1943         }\r
1944 \r
1945         /// <summary>\r
1946         /// Update the Status label for the scan\r
1947         /// </summary>\r
1948         /// <param name="sender">\r
1949         /// The sender.\r
1950         /// </param>\r
1951         /// <param name="e">\r
1952         /// The e.\r
1953         /// </param>\r
1954         private void SourceScan_ScanStatusChanged(object sender, HandBrake.ApplicationServices.ScanProgressEventArgs e)\r
1955         {\r
1956             UpdateScanStatusLabel(sender, e);\r
1957         }\r
1958 \r
1959         /// <summary>\r
1960         /// Update the UI after the scan has completed\r
1961         /// </summary>\r
1962         /// <param name="sender">\r
1963         /// The sender.\r
1964         /// </param>\r
1965         /// <param name="e">\r
1966         /// The e.\r
1967         /// </param>\r
1968         private void SourceScan_ScanCompleted(object sender, EventArgs e)\r
1969         {\r
1970             UpdateGuiAfterScan();\r
1971         }\r
1972 \r
1973         /// <summary>\r
1974         /// Update the Scan Status Label\r
1975         /// </summary>\r
1976         /// <param name="sender"> The Sender </param>\r
1977         /// <param name="e">Scan Progress Event Args</param>\r
1978         private void UpdateScanStatusLabel(object sender, HandBrake.ApplicationServices.ScanProgressEventArgs e)\r
1979         {\r
1980             if (InvokeRequired)\r
1981             {\r
1982                 BeginInvoke(new ScanService.ScanProgessStatus(UpdateScanStatusLabel), new[] { e });\r
1983                 return;\r
1984             }\r
1985 \r
1986             lbl_encode.Text = "Scanning Title" + e.CurrentTitle + " of " + e.TotalTitles;\r
1987         }\r
1988 \r
1989         /// <summary>\r
1990         /// Reset the GUI when the scan has completed\r
1991         /// </summary>\r
1992         private void UpdateGuiAfterScan()\r
1993         {\r
1994             if (InvokeRequired)\r
1995             {\r
1996                 BeginInvoke(new UpdateWindowHandler(UpdateGuiAfterScan));\r
1997                 return;\r
1998             }\r
1999 \r
2000             try\r
2001             {\r
2002                 currentSource = SourceScan.SouceData;\r
2003 \r
2004                 // Setup some GUI components\r
2005                 drp_dvdtitle.Items.Clear();\r
2006                 if (currentSource.Titles.Count != 0)\r
2007                     drp_dvdtitle.Items.AddRange(currentSource.Titles.ToArray());\r
2008 \r
2009                 foreach (Title title in currentSource.Titles)\r
2010                 {\r
2011                     if (title.MainTitle)\r
2012                     {\r
2013                         drp_dvdtitle.SelectedItem = title;\r
2014                     }\r
2015                 }\r
2016 \r
2017                 if (drp_dvdtitle.SelectedItem == null && drp_dvdtitle.Items.Count > 0)\r
2018                 {\r
2019                     drp_dvdtitle.SelectedIndex = 0;\r
2020                 }\r
2021 \r
2022                 // Enable the creation of chapter markers if the file is an image of a dvd\r
2023                 if (drop_chapterStart.Items.Count > 0)\r
2024                 {\r
2025                     int start, end;\r
2026                     int.TryParse(drop_chapterStart.Items[0].ToString(), out start);\r
2027                     int.TryParse(drop_chapterFinish.Items[drop_chapterFinish.Items.Count - 1].ToString(), out end);\r
2028                     if (end > start) Check_ChapterMarkers.Enabled = true;\r
2029                     else\r
2030                     {\r
2031                         Check_ChapterMarkers.Enabled = false;\r
2032                         Check_ChapterMarkers.Checked = false;\r
2033                         data_chpt.Rows.Clear();\r
2034                     }\r
2035                 }\r
2036 \r
2037                 // If no titles were found, Display an error message\r
2038                 if (drp_dvdtitle.Items.Count == 0)\r
2039                 {\r
2040                     MessageBox.Show(\r
2041                         "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
2042                         "Error", MessageBoxButtons.OK, MessageBoxIcon.Hand);\r
2043                     sourcePath = string.Empty;\r
2044                 }\r
2045                 UpdateSourceLabel();\r
2046 \r
2047                 // Enable the GUI components and enable any disabled components\r
2048                 EnableGUI();\r
2049             }\r
2050             catch (Exception exc)\r
2051             {\r
2052                 MessageBox.Show("frmMain.cs - updateUIafterScan " + exc, "Error", MessageBoxButtons.OK,\r
2053                                 MessageBoxIcon.Error);\r
2054                 EnableGUI();\r
2055             }\r
2056         }\r
2057 \r
2058         /// <summary>\r
2059         /// Enable the GUI\r
2060         /// </summary>\r
2061         private void EnableGUI()\r
2062         {\r
2063             try\r
2064             {\r
2065                 if (InvokeRequired)\r
2066                     BeginInvoke(new UpdateWindowHandler(EnableGUI));\r
2067                 lbl_encode.Text = "Scan Completed";\r
2068                 foreach (Control ctrl in Controls)\r
2069                     ctrl.Enabled = true;\r
2070                 btn_start.Enabled = true;\r
2071                 btn_showQueue.Enabled = true;\r
2072                 btn_add2Queue.Enabled = true;\r
2073                 tb_preview.Enabled = true;\r
2074                 btn_source.Enabled = true;\r
2075                 mnu_killCLI.Visible = false;\r
2076             }\r
2077             catch (Exception exc)\r
2078             {\r
2079                 MessageBox.Show("frmMain.cs - EnableGUI() " + exc, "Error", MessageBoxButtons.OK, MessageBoxIcon.Error);\r
2080             }\r
2081         }\r
2082 \r
2083         /// <summary>\r
2084         /// Disable the GUI\r
2085         /// </summary>\r
2086         private void DisableGUI()\r
2087         {\r
2088             foreach (Control ctrl in Controls)\r
2089                 if (!(ctrl is StatusStrip || ctrl is MenuStrip || ctrl is ToolStrip))\r
2090                     ctrl.Enabled = false;\r
2091 \r
2092             lbl_encode.Visible = true;\r
2093             lbl_encode.Text = "Scanning ...";\r
2094             btn_source.Enabled = false;\r
2095             btn_start.Enabled = false;\r
2096             btn_showQueue.Enabled = false;\r
2097             btn_add2Queue.Enabled = false;\r
2098             tb_preview.Enabled = false;\r
2099             mnu_killCLI.Visible = true;\r
2100         }\r
2101 \r
2102         /// <summary>\r
2103         /// Kill the Scan\r
2104         /// </summary>\r
2105         private void KillScan()\r
2106         {\r
2107             SourceScan.ScanCompleted -= SourceScan_ScanCompleted;\r
2108             EnableGUI();\r
2109             ResetGUI();\r
2110 \r
2111             SourceScan.Stop();\r
2112 \r
2113             lbl_encode.Text = "Scan Cancelled!";\r
2114         }\r
2115 \r
2116         /// <summary>\r
2117         /// Reset the GUI\r
2118         /// </summary>\r
2119         private void ResetGUI()\r
2120         {\r
2121             drp_dvdtitle.Items.Clear();\r
2122             drop_chapterStart.Items.Clear();\r
2123             drop_chapterFinish.Items.Clear();\r
2124             lbl_duration.Text = "Select a Title";\r
2125             PictureSettings.lbl_src_res.Text = "Select a Title";\r
2126             sourcePath = String.Empty;\r
2127             text_destination.Text = String.Empty;\r
2128             selectedTitle = null;\r
2129         }\r
2130 \r
2131         /// <summary>\r
2132         /// Update the Source Label\r
2133         /// </summary>\r
2134         private void UpdateSourceLabel()\r
2135         {\r
2136             labelSource.Text = string.IsNullOrEmpty(sourcePath) ? "Select \"Source\" to continue." : this.SourceName;\r
2137 \r
2138             if (selectedTitle != null)\r
2139                 if (!string.IsNullOrEmpty(selectedTitle.SourceName))\r
2140                     // If it's one of multiple source files, make sure we don't use the folder name\r
2141                     labelSource.Text = Path.GetFileName(selectedTitle.SourceName);\r
2142         }\r
2143 \r
2144         /// <summary>\r
2145         /// Take a job from the Queue, rescan it, and reload the GUI for that job.\r
2146         /// </summary>\r
2147         /// <param name="job">\r
2148         /// The job.\r
2149         /// </param>\r
2150         public void RecievingJob(Job job)\r
2151         {\r
2152             string query = job.Query;\r
2153             StartScan(job.Source, job.Title);\r
2154 \r
2155             if (query != null)\r
2156             {\r
2157                 // Ok, Reset all the H264 widgets before changing the preset\r
2158                 x264Panel.Reset2Defaults();\r
2159 \r
2160                 // Send the query from the file to the Query Parser class\r
2161                 QueryParser presetQuery = QueryParser.Parse(query);\r
2162 \r
2163                 // Now load the preset\r
2164                 PresetLoader.LoadPreset(this, presetQuery, "Load Back From Queue");\r
2165 \r
2166                 // The x264 widgets will need updated, so do this now:\r
2167                 x264Panel.StandardizeOptString();\r
2168                 x264Panel.SetCurrentSettingsInPanel();\r
2169 \r
2170                 // Finally, let this window have a copy of the preset settings.\r
2171                 this.currentlySelectedPreset = null;\r
2172                 PictureSettings.SetPresetCropWarningLabel(null);\r
2173             }\r
2174         }\r
2175 \r
2176         #endregion\r
2177 \r
2178         #region GUI Functions and Actions\r
2179 \r
2180         /// <summary>\r
2181         /// Set the GUI to it's finished encoding state.\r
2182         /// </summary>\r
2183         private void SetEncodeFinished()\r
2184         {\r
2185             try\r
2186             {\r
2187                 if (InvokeRequired)\r
2188                 {\r
2189                     BeginInvoke(new UpdateWindowHandler(SetEncodeFinished));\r
2190                     return;\r
2191                 }\r
2192 \r
2193                 lbl_encode.Text = "Encoding Finished";\r
2194                 ProgressBarStatus.Visible = false;\r
2195                 btn_start.Text = "Start";\r
2196                 btn_start.ToolTipText = "Start the encoding process";\r
2197                 btn_start.Image = Resources.Play;\r
2198 \r
2199                 // If the window is minimized, display the notification in a popup.\r
2200                 if (Settings.Default.trayIconAlerts)\r
2201                     if (FormWindowState.Minimized == this.WindowState)\r
2202                     {\r
2203                         notifyIcon.BalloonTipText = lbl_encode.Text;\r
2204                         notifyIcon.ShowBalloonTip(500);\r
2205                     }\r
2206             }\r
2207             catch (Exception exc)\r
2208             {\r
2209                 MessageBox.Show(exc.ToString());\r
2210             }\r
2211         }\r
2212 \r
2213         /// <summary>\r
2214         /// Set the GUI to it's started encoding state.\r
2215         /// </summary>\r
2216         private void SetEncodeStarted()\r
2217         {\r
2218             try\r
2219             {\r
2220                 if (InvokeRequired)\r
2221                 {\r
2222                     BeginInvoke(new UpdateWindowHandler(SetEncodeStarted));\r
2223                     return;\r
2224                 }\r
2225                 lbl_encode.Visible = true;\r
2226                 ProgressBarStatus.Value = 0;\r
2227                 ProgressBarStatus.Visible = true;\r
2228                 lbl_encode.Text = "Encoding with " + encodeQueue.Count + " encode(s) pending";\r
2229                 btn_start.Text = "Stop";\r
2230                 btn_start.ToolTipText = "Stop the encoding process.";\r
2231                 btn_start.Image = Resources.stop;\r
2232             }\r
2233             catch (Exception exc)\r
2234             {\r
2235                 MessageBox.Show(exc.ToString());\r
2236             }\r
2237         }\r
2238 \r
2239         /// <summary>\r
2240         /// Display the Encode Status\r
2241         /// </summary>\r
2242         /// <param name="sender">\r
2243         /// The sender.\r
2244         /// </param>\r
2245         /// <param name="e">\r
2246         /// The e.\r
2247         /// </param>\r
2248         private void EncodeQueue_EncodeStatusChanged(object sender, HandBrake.ApplicationServices.EncodeProgressEventArgs e)\r
2249         {\r
2250             if (this.InvokeRequired)\r
2251             {\r
2252                 this.BeginInvoke(new Encode.EncodeProgessStatus(EncodeQueue_EncodeStatusChanged), new[] { sender, e });\r
2253                 return;\r
2254             }\r
2255 \r
2256             lbl_encode.Text =\r
2257                 string.Format(\r
2258                 "{0:00.00}%,  FPS: {1:000.0},  Avg FPS: {2:000.0},  Time Remaining: {3},  Encode(s) Pending {4}",\r
2259                 e.PercentComplete,\r
2260                 e.CurrentFrameRate,\r
2261                 e.AverageFrameRate,\r
2262                 e.EstimatedTimeLeft,\r
2263                 encodeQueue.Count);\r
2264 \r
2265             ProgressBarStatus.Value = (int)Math.Round(e.PercentComplete);\r
2266         }\r
2267 \r
2268         /// <summary>\r
2269         /// Set the DVD Drive selection in the "Source" Menu\r
2270         /// </summary>\r
2271         private void SetDriveSelectionMenuItem()\r
2272         {\r
2273             try\r
2274             {\r
2275                 if (InvokeRequired)\r
2276                 {\r
2277                     BeginInvoke(new UpdateWindowHandler(SetDriveSelectionMenuItem));\r
2278                     return;\r
2279                 }\r
2280 \r
2281                 drives = Main.GetDrives();\r
2282 \r
2283                 List<ToolStripMenuItem> menuItems = new List<ToolStripMenuItem>();\r
2284                 foreach (DriveInformation drive in drives)\r
2285                 {\r
2286                     ToolStripMenuItem menuItem = new ToolStripMenuItem\r
2287                         {\r
2288                             Name = drive.ToString(),\r
2289                             Text = drive.RootDirectory + " (" + drive.VolumeLabel + ")",\r
2290                             Image = Resources.disc_small\r
2291                         };\r
2292                     menuItem.Click += mnu_dvd_drive_Click;\r
2293                     menuItems.Add(menuItem);\r
2294                 }\r
2295 \r
2296                 foreach (ToolStripMenuItem item in menuItems)\r
2297                     btn_source.DropDownItems.Add(item);\r
2298             }\r
2299             catch (Exception exc)\r
2300             {\r
2301                 MessageBox.Show("Error in SetDriveSelectionMenuItem" + exc);\r
2302             }\r
2303         }\r
2304 \r
2305         /// <summary>\r
2306         /// Access the preset Handler and setup the preset panel.\r
2307         /// </summary>\r
2308         private void LoadPresetPanel()\r
2309         {\r
2310             if (presetHandler.CheckIfPresetsAreOutOfDate())\r
2311                 if (!Settings.Default.presetNotification)\r
2312                     MessageBox.Show(this,\r
2313                                     "HandBrake has determined your built-in presets are out of date... These presets will now be updated.",\r
2314                                     "Preset Update", MessageBoxButtons.OK, MessageBoxIcon.Information);\r
2315 \r
2316             presetHandler.GetPresetPanel(ref treeView_presets);\r
2317             treeView_presets.Update();\r
2318         }\r
2319 \r
2320         /// <summary>\r
2321         /// Get the title from the selected item in the title dropdown.\r
2322         /// </summary>\r
2323         /// <returns>\r
2324         /// The title.\r
2325         /// </returns>\r
2326         private int GetTitle()\r
2327         {\r
2328             int title = 0;\r
2329             if (drp_dvdtitle.SelectedItem != null)\r
2330             {\r
2331                 string[] titleInfo = drp_dvdtitle.SelectedItem.ToString().Split(' ');\r
2332                 int.TryParse(titleInfo[0], out title);\r
2333             }\r
2334 \r
2335             return title;\r
2336         }\r
2337 \r
2338         /// <summary>\r
2339         /// Handle the Update Check Finishing.\r
2340         /// </summary>\r
2341         /// <param name="result">\r
2342         /// The result.\r
2343         /// </param>\r
2344         private void UpdateCheckDoneMenu(IAsyncResult result)\r
2345         {\r
2346             // Make sure it's running on the calling thread\r
2347             if (InvokeRequired)\r
2348             {\r
2349                 Invoke(new MethodInvoker(() => this.UpdateCheckDoneMenu(result)));\r
2350                 return;\r
2351             }\r
2352             UpdateCheckInformation info;\r
2353             try\r
2354             {\r
2355                 // Get the information about the new build, if any, and close the window\r
2356                 info = Main.EndCheckForUpdates(result);\r
2357 \r
2358                 if (info.NewVersionAvailable && info.BuildInformation != null)\r
2359                 {\r
2360                     frmUpdater updateWindow = new frmUpdater(info.BuildInformation);\r
2361                     updateWindow.ShowDialog();\r
2362                 }\r
2363                 else\r
2364                     MessageBox.Show("There are no new updates at this time.", "Update Check", MessageBoxButtons.OK,\r
2365                                     MessageBoxIcon.Information);\r
2366                 lbl_updateCheck.Visible = false;\r
2367                 return;\r
2368             }\r
2369             catch (Exception ex)\r
2370             {\r
2371                 if ((bool)result.AsyncState)\r
2372                     MessageBox.Show(\r
2373                         "Unable to check for updates, Please try again later.\n\nDetailed Error Information:\n" + ex,\r
2374                         "Error", MessageBoxButtons.OK, MessageBoxIcon.Error);\r
2375             }\r
2376         }\r
2377 \r
2378         #endregion\r
2379 \r
2380         #region Overrides\r
2381 \r
2382         /// <summary>\r
2383         /// Handle GUI shortcuts\r
2384         /// </summary>\r
2385         /// <param name="msg">Message</param>\r
2386         /// <param name="keyData">Keys</param>\r
2387         /// <returns>Bool</returns>\r
2388         protected override bool ProcessCmdKey(ref Message msg, Keys keyData)\r
2389         {\r
2390             if (keyData == (Keys.Control | Keys.S))\r
2391             {\r
2392                 btn_start_Click(this, new EventArgs());\r
2393                 return true;\r
2394             }\r
2395 \r
2396             if (keyData == (Keys.Control | Keys.A))\r
2397             {\r
2398                 btn_add2Queue_Click(this, new EventArgs());\r
2399                 return true;\r
2400             }\r
2401             return base.ProcessCmdKey(ref msg, keyData);\r
2402         }\r
2403 \r
2404         /// <summary>\r
2405         /// If the queue is being processed, prompt the user to confirm application close.\r
2406         /// </summary>\r
2407         /// <param name="e">FormClosingEventArgs</param>\r
2408         protected override void OnFormClosing(FormClosingEventArgs e)\r
2409         {\r
2410             try\r
2411             {\r
2412                 // If currently encoding, the queue isn't paused, and there are queue items to process, prompt to confirm close.\r
2413                 if (encodeQueue.IsEncoding)\r
2414                 {\r
2415                     DialogResult result =\r
2416                         MessageBox.Show(\r
2417                             "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
2418                             "Close HandBrake?",\r
2419                             MessageBoxButtons.YesNo,\r
2420                             MessageBoxIcon.Question);\r
2421 \r
2422                     if (result == DialogResult.No)\r
2423                     {\r
2424                         e.Cancel = true;\r
2425                         return;\r
2426                     }\r
2427 \r
2428                     encodeQueue.Stop();\r
2429                 }\r
2430 \r
2431                 if (SourceScan.IsScanning)\r
2432                 {\r
2433                     SourceScan.ScanCompleted -= SourceScan_ScanCompleted;\r
2434                     SourceScan.Stop();\r
2435                 }\r
2436             }\r
2437             catch (Exception exc)\r
2438             {\r
2439                 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
2440             }\r
2441             finally\r
2442             {\r
2443                 base.OnFormClosing(e);\r
2444             }\r
2445         }\r
2446 \r
2447         #endregion\r
2448 \r
2449         // This is the END of the road ****************************************\r
2450     }\r
2451 }