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