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