2 This file is part of the HandBrake source code.
\r
3 Homepage: <http://handbrake.fr/>.
\r
4 It may be used under the terms of the GNU General Public License. */
\r
9 using System.Collections.Generic;
\r
10 using System.ComponentModel;
\r
11 using System.Diagnostics;
\r
12 using System.Drawing;
\r
13 using System.Globalization;
\r
16 using System.Threading;
\r
17 using System.Windows.Forms;
\r
20 using HandBrake.ApplicationServices.EventArgs;
\r
21 using HandBrake.ApplicationServices.Utilities;
\r
22 using HandBrake.Framework.Model;
\r
23 using HandBrake.Framework.Services;
\r
24 using HandBrake.Framework.Views;
\r
25 using HandBrake.ApplicationServices.Functions;
\r
26 using HandBrake.ApplicationServices.Model;
\r
27 using HandBrake.ApplicationServices.Parsing;
\r
28 using HandBrake.ApplicationServices.Services;
\r
29 using HandBrake.ApplicationServices.Services.Interfaces;
\r
31 using Handbrake.ToolWindows;
\r
36 using Main = Handbrake.Functions.Main;
\r
41 public partial class frmMain : Form
\r
43 // Objects which may be used by one or more other objects *************
\r
44 private IQueueProcessor queueProcessor = new QueueProcessor(Program.InstanceId);
\r
45 private PresetService presetHandler = new PresetService();
\r
47 // Windows ************************************************************
\r
48 private frmQueue queueWindow;
\r
49 private frmPreview qtpreview;
\r
50 private frmActivityWindow activityWindow;
\r
52 // Globals: Mainly used for tracking. *********************************
\r
53 public Title selectedTitle;
\r
54 public string sourcePath;
\r
55 private SourceType selectedSourceType;
\r
56 private string dvdDrivePath;
\r
57 private string dvdDriveLabel;
\r
58 private Preset currentlySelectedPreset;
\r
59 private Source currentSource;
\r
61 private IScan SourceScan;
\r
62 private List<DriveInformation> drives;
\r
63 private QueueTask queueEdit;
\r
65 // Delegates **********************************************************
\r
66 private delegate void UpdateWindowHandler();
\r
68 // Applicaiton Startup ************************************************
\r
73 /// Gets SourceName.
\r
75 public string SourceName
\r
79 if (this.selectedSourceType == SourceType.DvdDrive)
\r
81 return this.dvdDriveLabel;
\r
84 if (selectedTitle != null && !string.IsNullOrEmpty(selectedTitle.SourceName))
\r
86 return Path.GetFileName(selectedTitle.SourceName);
\r
89 // We have a drive, selected as a folder.
\r
90 if (this.sourcePath.EndsWith("\\"))
\r
92 drives = UtilityService.GetDrives();
\r
93 foreach (DriveInformation item in drives)
\r
95 if (item.RootDirectory.Contains(this.sourcePath))
\r
97 return item.VolumeLabel;
\r
102 if (Path.GetFileNameWithoutExtension(this.sourcePath) != "VIDEO_TS")
\r
103 return Path.GetFileNameWithoutExtension(this.sourcePath);
\r
105 return Path.GetFileNameWithoutExtension(Path.GetDirectoryName(this.sourcePath));
\r
111 #region Application Startup
\r
114 /// Initializes a new instance of the <see cref="frmMain"/> class.
\r
116 /// <param name="args">
\r
117 /// The arguments passed in on application startup.
\r
119 public frmMain(string[] args)
\r
121 InitializeComponent();
\r
123 // We can use LibHB, if the library hb.dll exists.
\r
124 this.SourceScan = File.Exists("hb.dll") ? (IScan)new LibScan() : new ScanService();
\r
126 // Update the users config file with the CLI version data.
\r
127 Main.SetCliVersionData();
\r
129 if (Settings.Default.hb_version.Contains("svn"))
\r
131 this.Text += " " + Settings.Default.hb_version;
\r
134 // Check for new versions, if update checking is enabled
\r
135 if (Settings.Default.updateStatus)
\r
137 if (DateTime.Now.Subtract(Settings.Default.lastUpdateCheckDate).TotalDays > Properties.Settings.Default.daysBetweenUpdateCheck)
\r
139 // Set when the last update was
\r
140 Settings.Default.lastUpdateCheckDate = DateTime.Now;
\r
141 Settings.Default.Save();
\r
142 string url = Settings.Default.hb_build.ToString().EndsWith("1")
\r
143 ? Settings.Default.appcast_unstable
\r
144 : Settings.Default.appcast;
\r
145 UpdateService.BeginCheckForUpdates(new AsyncCallback(UpdateCheckDone), false, url, Settings.Default.hb_build, Settings.Default.skipversion, Settings.Default.hb_version);
\r
149 // Clear the log files in the background
\r
150 if (Settings.Default.clearOldLogs)
\r
152 Thread clearLog = new Thread(() => UtilityService.ClearLogFiles(30));
\r
156 // Setup the GUI components
\r
157 LoadPresetPanel(); // Load the Preset Panel
\r
158 treeView_presets.ExpandAll();
\r
159 lbl_encode.Text = string.Empty;
\r
160 drop_mode.SelectedIndex = 0;
\r
161 queueWindow = new frmQueue(this.queueProcessor, this); // Prepare the Queue
\r
162 if (!Settings.Default.QueryEditorTab)
\r
163 tabs_panel.TabPages.RemoveAt(7); // Remove the query editor tab if the user does not want it enabled.
\r
164 if (Settings.Default.tooltipEnable)
\r
165 ToolTip.Active = true;
\r
167 // Load the user's default settings or Normal Preset
\r
168 if (Settings.Default.defaultPreset != string.Empty && presetHandler.GetPreset(Properties.Settings.Default.defaultPreset) != null)
\r
170 string query = presetHandler.GetPreset(Settings.Default.defaultPreset).Query;
\r
173 x264Panel.Reset2Defaults();
\r
175 EncodeTask presetQuery = QueryParserUtility.Parse(query);
\r
176 PresetLoader.LoadPreset(this, presetQuery, Settings.Default.defaultPreset);
\r
178 x264Panel.StandardizeOptString();
\r
179 x264Panel.SetCurrentSettingsInPanel();
\r
183 loadNormalPreset();
\r
185 // Register with Growl (if not using Growl for the encoding completion action, this wont hurt anything)
\r
186 GrowlCommunicator.Register();
\r
188 // Event Handlers and Queue Recovery
\r
190 Main.RecoverQueue(this.queueProcessor);
\r
192 // If have a file passed in via command arguemtents, check it's a file and try scanning it.
\r
193 if (args.Length >= 1 && (File.Exists(args[0]) || Directory.Exists(args[0])))
\r
195 this.StartScan(args[0], 0);
\r
200 /// When the update check is done, process the results.
\r
202 /// <param name="result">IAsyncResult result</param>
\r
203 private void UpdateCheckDone(IAsyncResult result)
\r
205 if (InvokeRequired)
\r
207 Invoke(new MethodInvoker(() => UpdateCheckDone(result)));
\r
213 UpdateCheckInformation info = UpdateService.EndCheckForUpdates(result);
\r
215 if (info.NewVersionAvailable)
\r
217 UpdateInfo updateWindow = new UpdateInfo(info.BuildInformation, Settings.Default.hb_version, Settings.Default.hb_build.ToString());
\r
218 updateWindow.ShowDialog();
\r
221 catch (Exception ex)
\r
223 if ((bool)result.AsyncState)
\r
224 Main.ShowExceptiowWindow("Unable to check for updates, Please try again later.", ex.ToString());
\r
232 // Encoding Events for setting up the GUI
\r
233 private void events()
\r
235 // Handle Widget changes when preset is selected.
\r
236 RegisterPresetEventHandler();
\r
238 // Handle Window Resize
\r
239 if (Settings.Default.MainWindowMinimize)
\r
240 this.Resize += this.frmMain_Resize;
\r
242 // Handle Encode Start / Finish / Pause
\r
243 this.queueProcessor.EncodeService.EncodeStarted += this.encodeStarted;
\r
244 this.queueProcessor.EncodeService.EncodeCompleted += encodeEnded;
\r
246 // Scan Started and Completed Events
\r
247 SourceScan.ScanStatusChanged += this.SourceScanScanStatusChanged;
\r
248 SourceScan.ScanCompleted += this.SourceScanScanCompleted;
\r
250 // Handle a file being draged onto the GUI.
\r
251 this.DragEnter += frmMain_DragEnter;
\r
252 this.DragDrop += this.frmMain_DragDrop;
\r
255 // 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
256 private void RegisterPresetEventHandler()
\r
259 drop_format.SelectedIndexChanged += this.changePresetLabel;
\r
260 check_largeFile.CheckedChanged += this.changePresetLabel;
\r
261 check_iPodAtom.CheckedChanged += this.changePresetLabel;
\r
262 check_optimiseMP4.CheckedChanged += this.changePresetLabel;
\r
264 // Picture Settings
\r
265 PictureSettings.PictureSettingsChanged += this.changePresetLabel;
\r
268 Filters.FilterSettingsChanged += this.changePresetLabel;
\r
271 drp_videoEncoder.SelectedIndexChanged += this.changePresetLabel;
\r
272 check_2PassEncode.CheckedChanged += this.changePresetLabel;
\r
273 check_turbo.CheckedChanged += this.changePresetLabel;
\r
274 text_bitrate.TextChanged += this.changePresetLabel;
\r
275 slider_videoQuality.ValueChanged += this.changePresetLabel;
\r
278 AudioSettings.AudioListChanged += this.changePresetLabel;
\r
281 x264Panel.rtf_x264Query.TextChanged += this.changePresetLabel;
\r
284 private void UnRegisterPresetEventHandler()
\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
292 // Picture Settings
\r
293 PictureSettings.PictureSettingsChanged -= this.changePresetLabel;
\r
296 Filters.FilterSettingsChanged -= this.changePresetLabel;
\r
299 drp_videoEncoder.SelectedIndexChanged -= this.changePresetLabel;
\r
300 check_2PassEncode.CheckedChanged -= this.changePresetLabel;
\r
301 check_turbo.CheckedChanged -= this.changePresetLabel;
\r
302 text_bitrate.TextChanged -= this.changePresetLabel;
\r
303 slider_videoQuality.ValueChanged -= this.changePresetLabel;
\r
306 AudioSettings.AudioListChanged -= this.changePresetLabel;
\r
309 x264Panel.rtf_x264Query.TextChanged -= this.changePresetLabel;
\r
312 private void changePresetLabel(object sender, EventArgs e)
\r
314 labelPreset.Text = "Output Settings (Preset: Custom)";
\r
315 this.currentlySelectedPreset = null;
\r
318 private static void frmMain_DragEnter(object sender, DragEventArgs e)
\r
320 if (e.Data.GetDataPresent(DataFormats.FileDrop, false))
\r
321 e.Effect = DragDropEffects.All;
\r
324 private void frmMain_DragDrop(object sender, DragEventArgs e)
\r
326 string[] fileList = e.Data.GetData(DataFormats.FileDrop) as string[];
\r
327 sourcePath = string.Empty;
\r
329 if (fileList != null)
\r
331 if (!string.IsNullOrEmpty(fileList[0]))
\r
333 this.selectedSourceType = SourceType.VideoFile;
\r
334 StartScan(fileList[0], 0);
\r
337 UpdateSourceLabel();
\r
340 UpdateSourceLabel();
\r
343 private void encodeStarted(object sender, EventArgs e)
\r
345 SetEncodeStarted();
\r
346 this.queueProcessor.EncodeService.EncodeStatusChanged += EncodeQueue_EncodeStatusChanged;
\r
349 private void encodeEnded(object sender, EventArgs e)
\r
351 this.queueProcessor.EncodeService.EncodeStatusChanged -= EncodeQueue_EncodeStatusChanged;
\r
352 SetEncodeFinished();
\r
356 // User Interface Menus / Tool Strips *********************************
\r
361 /// Kill The scan menu Item
\r
363 /// <param name="sender">
\r
366 /// <param name="e">
\r
369 private void mnu_killCLI_Click(object sender, EventArgs e)
\r
375 /// Exit the Application Menu Item
\r
377 /// <param name="sender">
\r
380 /// <param name="e">
\r
383 private void mnu_exit_Click(object sender, EventArgs e)
\r
385 Application.Exit();
\r
393 /// Menu - Start Button
\r
395 /// <param name="sender">
\r
398 /// <param name="e">
\r
401 private void mnu_encode_Click(object sender, EventArgs e)
\r
403 queueWindow.Show();
\r
407 /// Menu - Display the Log Window
\r
409 /// <param name="sender">
\r
412 /// <param name="e">
\r
415 private void mnu_encodeLog_Click(object sender, EventArgs e)
\r
417 this.btn_ActivityWindow_Click(this, null);
\r
421 /// Menu - Display the Options Window
\r
423 /// <param name="sender">
\r
426 /// <param name="e">
\r
429 private void mnu_options_Click(object sender, EventArgs e)
\r
431 Form options = new frmOptions(this);
\r
432 options.ShowDialog();
\r
437 #region Presets Menu
\r
440 /// Reset the Built in Presets
\r
442 /// <param name="sender">
\r
445 /// <param name="e">
\r
448 private void mnu_presetReset_Click(object sender, EventArgs e)
\r
450 presetHandler.UpdateBuiltInPresets(string.Empty);
\r
452 if (treeView_presets.Nodes.Count == 0)
\r
454 "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
455 "Error", MessageBoxButtons.OK, MessageBoxIcon.Error);
\r
457 MessageBox.Show("Presets have been updated!", "Alert", MessageBoxButtons.OK, MessageBoxIcon.Information);
\r
459 treeView_presets.ExpandAll();
\r
463 /// Delete the selected preset
\r
465 /// <param name="sender">
\r
468 /// <param name="e">
\r
471 private void mnu_delete_preset_Click(object sender, EventArgs e)
\r
473 presetHandler.ClearBuiltIn();
\r
474 LoadPresetPanel(); // Reload the preset panel
\r
478 /// Select the Normal preset
\r
480 /// <param name="sender">
\r
483 /// <param name="e">
\r
486 private void mnu_SelectDefault_Click(object sender, EventArgs e)
\r
488 loadNormalPreset();
\r
492 /// Import a plist Preset
\r
494 /// <param name="sender">
\r
497 /// <param name="e">
\r
500 private void mnu_importMacPreset_Click(object sender, EventArgs e)
\r
506 /// Export a Plist Preset
\r
508 /// <param name="sender">
\r
511 /// <param name="e">
\r
514 private void mnu_exportMacPreset_Click(object sender, EventArgs e)
\r
520 /// Create a new Preset
\r
522 /// <param name="sender">
\r
525 /// <param name="e">
\r
528 private void btn_new_preset_Click(object sender, EventArgs e)
\r
530 Form preset = new frmAddPreset(this, presetHandler);
\r
531 if (preset.ShowDialog() == DialogResult.OK)
\r
533 TreeNode presetTreeview = new TreeNode(presetHandler.LastPresetAdded.Name) { ForeColor = Color.Black };
\r
534 treeView_presets.Nodes.Add(presetTreeview);
\r
535 presetHandler.LastPresetAdded = null;
\r
544 /// Menu - Display the User Guide Web Page
\r
546 /// <param name="sender">
\r
549 /// <param name="e">
\r
552 private void mnu_user_guide_Click(object sender, EventArgs e)
\r
554 Process.Start("http://trac.handbrake.fr/wiki/HandBrakeGuide");
\r
558 /// Menu - Check for Updates
\r
560 /// <param name="sender">
\r
563 /// <param name="e">
\r
566 private void mnu_UpdateCheck_Click(object sender, EventArgs e)
\r
568 lbl_updateCheck.Visible = true;
\r
569 Settings.Default.lastUpdateCheckDate = DateTime.Now;
\r
570 Settings.Default.Save();
\r
571 string url = Settings.Default.hb_build.ToString().EndsWith("1")
\r
572 ? Settings.Default.appcast_unstable
\r
573 : Settings.Default.appcast;
\r
574 UpdateService.BeginCheckForUpdates(new AsyncCallback(UpdateCheckDoneMenu), false, url, Settings.Default.hb_build, Settings.Default.skipversion, Settings.Default.hb_version);
\r
578 /// Menu - Display the About Window
\r
580 /// <param name="sender">
\r
583 /// <param name="e">
\r
586 private void mnu_about_Click(object sender, EventArgs e)
\r
588 using (frmAbout About = new frmAbout())
\r
590 About.ShowDialog();
\r
599 /// RMenu - Expand All
\r
601 /// <param name="sender">
\r
604 /// <param name="e">
\r
607 private void pmnu_expandAll_Click(object sender, EventArgs e)
\r
609 treeView_presets.ExpandAll();
\r
613 /// RMenu - Collaspe All
\r
615 /// <param name="sender">
\r
618 /// <param name="e">
\r
621 private void pmnu_collapse_Click(object sender, EventArgs e)
\r
623 treeView_presets.CollapseAll();
\r
627 /// Menu - Import Preset
\r
629 /// <param name="sender">
\r
632 /// <param name="e">
\r
635 private void pmnu_import_Click(object sender, EventArgs e)
\r
641 /// RMenu - Save Changes to Preset
\r
643 /// <param name="sender">
\r
646 /// <param name="e">
\r
649 private void pmnu_saveChanges_Click(object sender, EventArgs e)
\r
651 DialogResult result =
\r
653 "Do you wish to include picture settings when updating the preset: " +
\r
654 treeView_presets.SelectedNode.Text, "Update Preset", MessageBoxButtons.YesNoCancel,
\r
655 MessageBoxIcon.Question);
\r
657 Preset preset = new Preset
\r
659 Name = this.treeView_presets.SelectedNode.Text,
\r
661 QueryGenerator.GenerateQueryForPreset(this, QueryPictureSettingsMode.SourceMaximum, true, 0, 0),
\r
662 CropSettings = (result == DialogResult.Yes)
\r
665 presetHandler.Update(preset);
\r
669 /// RMenu - Delete Preset
\r
671 /// <param name="sender">
\r
674 /// <param name="e">
\r
677 private void pmnu_delete_click(object sender, EventArgs e)
\r
679 if (treeView_presets.SelectedNode != null)
\r
681 presetHandler.Remove((Preset)treeView_presets.SelectedNode.Tag);
\r
682 treeView_presets.Nodes.Remove(treeView_presets.SelectedNode);
\r
684 treeView_presets.Select();
\r
688 /// Preset Menu Is Opening. Setup the Menu
\r
690 /// <param name="sender">
\r
693 /// <param name="e">
\r
696 private void presets_menu_Opening(object sender, CancelEventArgs e)
\r
698 // Make sure that the save menu is always disabled by default
\r
699 pmnu_saveChanges.Enabled = false;
\r
701 // Now enable the save menu if the selected preset is a user preset
\r
702 if (treeView_presets.SelectedNode != null)
\r
703 if (presetHandler.CheckIfPresetExists(treeView_presets.SelectedNode.Text))
\r
704 pmnu_saveChanges.Enabled = true;
\r
706 treeView_presets.Select();
\r
709 // Presets Management
\r
712 /// Button - Add a preset
\r
714 /// <param name="sender">
\r
717 /// <param name="e">
\r
720 private void btn_addPreset_Click(object sender, EventArgs e)
\r
722 Form preset = new frmAddPreset(this, presetHandler);
\r
723 if (preset.ShowDialog() == DialogResult.OK)
\r
725 TreeNode presetTreeview = new TreeNode(presetHandler.LastPresetAdded.Name) { ForeColor = Color.Black };
\r
726 treeView_presets.Nodes.Add(presetTreeview);
\r
727 presetHandler.LastPresetAdded = null;
\r
732 /// Button - remove a Preset
\r
734 /// <param name="sender">
\r
737 /// <param name="e">
\r
740 private void btn_removePreset_Click(object sender, EventArgs e)
\r
742 DialogResult result = MessageBox.Show("Are you sure you wish to delete the selected preset?", "Preset",
\r
743 MessageBoxButtons.YesNo, MessageBoxIcon.Question);
\r
744 if (result == DialogResult.Yes)
\r
746 if (treeView_presets.SelectedNode != null)
\r
748 presetHandler.Remove((Preset)treeView_presets.SelectedNode.Tag);
\r
749 treeView_presets.Nodes.Remove(treeView_presets.SelectedNode);
\r
752 treeView_presets.Select();
\r
756 /// Button - Set the selected preset as the default
\r
758 /// <param name="sender">
\r
761 /// <param name="e">
\r
764 private void btn_setDefault_Click(object sender, EventArgs e)
\r
766 if (treeView_presets.SelectedNode != null)
\r
768 DialogResult result = MessageBox.Show("Are you sure you wish to set this preset as the default?",
\r
769 "Preset", MessageBoxButtons.YesNo, MessageBoxIcon.Question);
\r
770 if (result == DialogResult.Yes)
\r
772 Properties.Settings.Default.defaultPreset = treeView_presets.SelectedNode.Text;
\r
773 Properties.Settings.Default.Save();
\r
774 MessageBox.Show("New default preset set.", "Alert", MessageBoxButtons.OK, MessageBoxIcon.Information);
\r
778 MessageBox.Show("Please select a preset first.", "Warning", MessageBoxButtons.OK, MessageBoxIcon.Warning);
\r
782 /// PresetBar Mouse Down event
\r
784 /// <param name="sender">
\r
787 /// <param name="e">
\r
790 private void treeview_presets_mouseUp(object sender, MouseEventArgs e)
\r
792 if (e.Button == MouseButtons.Right)
\r
793 treeView_presets.SelectedNode = treeView_presets.GetNodeAt(e.Location);
\r
794 else if (e.Button == MouseButtons.Left)
\r
796 if (treeView_presets.GetNodeAt(e.Location) != null)
\r
798 if (labelPreset.Text.Contains(treeView_presets.GetNodeAt(e.Location).Text))
\r
803 treeView_presets.Select();
\r
807 /// Preset Bar after selecting the preset
\r
809 /// <param name="sender">
\r
812 /// <param name="e">
\r
815 private void treeView_presets_AfterSelect(object sender, TreeViewEventArgs e)
\r
821 /// When the mouse moves, display a preset
\r
823 /// <param name="sender">The Sender</param>
\r
824 /// <param name="e">the MouseEventArgs</param>
\r
825 private void TreeViewPresetsMouseMove(object sender, MouseEventArgs e)
\r
827 TreeNode theNode = this.treeView_presets.GetNodeAt(e.X, e.Y);
\r
829 if ((theNode != null))
\r
831 // Change the ToolTip only if the pointer moved to a new node.
\r
832 if (theNode.ToolTipText != this.ToolTip.GetToolTip(this.treeView_presets))
\r
834 this.ToolTip.SetToolTip(this.treeView_presets, theNode.ToolTipText);
\r
837 else // Pointer is not over a node so clear the ToolTip.
\r
839 this.ToolTip.SetToolTip(this.treeView_presets, string.Empty);
\r
844 /// Preset Bar - Handle the Delete Key
\r
846 /// <param name="sender">
\r
849 /// <param name="e">
\r
852 private void treeView_presets_deleteKey(object sender, KeyEventArgs e)
\r
854 if (e.KeyCode == Keys.Delete)
\r
856 DialogResult result = MessageBox.Show("Are you sure you wish to delete the selected preset?", "Preset",
\r
857 MessageBoxButtons.YesNo, MessageBoxIcon.Question);
\r
858 if (result == DialogResult.Yes)
\r
860 if (treeView_presets.SelectedNode != null)
\r
861 presetHandler.Remove((Preset)treeView_presets.SelectedNode.Tag);
\r
863 // Remember each nodes expanded status so we can reload it
\r
864 List<bool> nodeStatus = new List<bool>();
\r
865 foreach (TreeNode node in treeView_presets.Nodes)
\r
866 nodeStatus.Add(node.IsExpanded);
\r
868 // Now reload the preset panel
\r
871 // And finally, re-expand any of the nodes if required
\r
873 foreach (TreeNode node in treeView_presets.Nodes)
\r
885 /// Select the selected preset and setup the GUI
\r
887 private void selectPreset()
\r
889 if (treeView_presets.SelectedNode != null)
\r
891 // Ok, so, we've selected a preset. Now we want to load it.
\r
892 string presetName = treeView_presets.SelectedNode.Text;
\r
893 Preset preset = presetHandler.GetPreset(presetName);
\r
894 if (preset != null)
\r
896 string query = presetHandler.GetPreset(presetName).Query;
\r
900 // Ok, Reset all the H264 widgets before changing the preset
\r
901 x264Panel.Reset2Defaults();
\r
903 // Send the query from the file to the Query Parser class
\r
904 EncodeTask presetQuery = QueryParserUtility.Parse(query);
\r
906 // Now load the preset
\r
907 PresetLoader.LoadPreset(this, presetQuery, presetName);
\r
909 // The x264 widgets will need updated, so do this now:
\r
910 x264Panel.StandardizeOptString();
\r
911 x264Panel.SetCurrentSettingsInPanel();
\r
913 // Finally, let this window have a copy of the preset settings.
\r
914 this.currentlySelectedPreset = preset;
\r
915 PictureSettings.SetPresetCropWarningLabel(preset);
\r
922 /// Load the Normal Preset
\r
924 private void loadNormalPreset()
\r
926 foreach (TreeNode treenode in treeView_presets.Nodes)
\r
928 foreach (TreeNode node in treenode.Nodes)
\r
930 if (node.Text.Equals("Normal"))
\r
931 treeView_presets.SelectedNode = treeView_presets.Nodes[treenode.Index].Nodes[0];
\r
937 /// Import a plist preset
\r
939 private void ImportPreset()
\r
941 if (openPreset.ShowDialog() == DialogResult.OK)
\r
943 EncodeTask parsed = PlistPresetHandler.Import(openPreset.FileName);
\r
944 if (presetHandler.CheckIfPresetExists(parsed.PresetName + " (Imported)"))
\r
946 DialogResult result =
\r
947 MessageBox.Show("This preset appears to already exist. Would you like to overwrite it?",
\r
948 "Overwrite preset?",
\r
949 MessageBoxButtons.YesNo, MessageBoxIcon.Warning);
\r
950 if (result == DialogResult.Yes)
\r
952 PresetLoader.LoadPreset(this, parsed, parsed.PresetName);
\r
954 Preset preset = new Preset
\r
956 Name = parsed.PresetName + " (Imported)",
\r
957 Query = QueryGenerator.GenerateFullQuery(this),
\r
958 CropSettings = parsed.UsesPictureSettings
\r
961 presetHandler.Update(preset);
\r
966 PresetLoader.LoadPreset(this, parsed, parsed.PresetName);
\r
968 Preset preset = new Preset
\r
970 Name = parsed.PresetName + " (Imported)",
\r
971 Query = QueryGenerator.GenerateFullQuery(this),
\r
972 CropSettings = parsed.UsesPictureSettings
\r
975 if (presetHandler.Add(preset))
\r
977 TreeNode preset_treeview = new TreeNode(parsed.PresetName + " (Imported)")
\r
979 ForeColor = Color.Black
\r
981 treeView_presets.Nodes.Add(preset_treeview);
\r
988 /// Export a plist Preset
\r
990 private void ExportPreset()
\r
992 SaveFileDialog savefiledialog = new SaveFileDialog { Filter = "plist|*.plist" };
\r
994 if (treeView_presets.SelectedNode != null)
\r
996 if (savefiledialog.ShowDialog() == DialogResult.OK)
\r
998 Preset preset = presetHandler.GetPreset(treeView_presets.SelectedNode.Text);
\r
999 PlistPresetHandler.Export(savefiledialog.FileName, preset);
\r
1009 /// 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
1011 /// <param name="sender">
\r
1014 /// <param name="e">
\r
1017 private void btn_source_Click(object sender, EventArgs e)
\r
1019 // Remove old Drive Menu Items.
\r
1020 List<ToolStripMenuItem> itemsToRemove = new List<ToolStripMenuItem>();
\r
1021 foreach (var item in btn_source.DropDownItems)
\r
1023 if (item.GetType() == typeof(ToolStripMenuItem))
\r
1025 ToolStripMenuItem menuItem = (ToolStripMenuItem)item;
\r
1026 if (menuItem.Name.StartsWith("Drive"))
\r
1028 itemsToRemove.Add(menuItem);
\r
1033 foreach (ToolStripMenuItem item in itemsToRemove)
\r
1034 btn_source.DropDownItems.Remove(item);
\r
1036 Thread driveInfoThread = new Thread(SetDriveSelectionMenuItem);
\r
1037 driveInfoThread.Start();
\r
1041 /// Toolbar - Start The Encode
\r
1043 /// <param name="sender">
\r
1046 /// <param name="e">
\r
1049 private void btn_start_Click(object sender, EventArgs e)
\r
1051 if (btn_start.Text == "Stop")
\r
1053 DialogResult result = !Properties.Settings.Default.showCliForInGuiEncodeStatus
\r
1054 ? MessageBox.Show(
\r
1055 "Are you sure you wish to cancel the encode?\n\nPlease note: Stopping this encode will render the file unplayable. ",
\r
1057 MessageBoxButtons.YesNo,
\r
1058 MessageBoxIcon.Question)
\r
1059 : MessageBox.Show(
\r
1060 "Are you sure you wish to cancel the encode?",
\r
1062 MessageBoxButtons.YesNo,
\r
1063 MessageBoxIcon.Question);
\r
1065 if (result == DialogResult.Yes)
\r
1067 // Pause The Queue
\r
1068 this.queueProcessor.Pause();
\r
1070 if (Settings.Default.showCliForInGuiEncodeStatus)
\r
1071 this.queueProcessor.EncodeService.SafelyStop();
\r
1073 this.queueProcessor.EncodeService.Stop();
\r
1078 // 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
1079 string jobSourcePath = !string.IsNullOrEmpty(rtf_query.Text) ? Main.GetSourceFromQuery(rtf_query.Text) : sourcePath;
\r
1080 string jobDestination = !string.IsNullOrEmpty(rtf_query.Text) ? Main.GetDestinationFromQuery(rtf_query.Text) : text_destination.Text;
\r
1082 if (this.queueProcessor.QueueManager.Count != 0 || (!string.IsNullOrEmpty(jobSourcePath) && !string.IsNullOrEmpty(jobDestination)))
\r
1084 string generatedQuery = QueryGenerator.GenerateFullQuery(this);
\r
1085 string specifiedQuery = rtf_query.Text != string.Empty
\r
1087 : QueryGenerator.GenerateFullQuery(this);
\r
1088 string query = string.Empty;
\r
1090 // Check to make sure the generated query matches the GUI settings
\r
1091 if (Properties.Settings.Default.PromptOnUnmatchingQueries && !string.IsNullOrEmpty(specifiedQuery) &&
\r
1092 generatedQuery != specifiedQuery)
\r
1094 DialogResult result = MessageBox.Show("The query under the \"Query Editor\" tab " +
\r
1095 "does not match the current GUI settings.\n\nBecause the manual query takes " +
\r
1096 "priority over the GUI, your recently updated settings will not be taken " +
\r
1097 "into account when encoding this job." +
\r
1098 Environment.NewLine + Environment.NewLine +
\r
1099 "Do you want to replace the manual query with the updated GUI-generated query?",
\r
1100 "Manual Query does not Match GUI",
\r
1101 MessageBoxButtons.YesNoCancel, MessageBoxIcon.Asterisk,
\r
1102 MessageBoxDefaultButton.Button3);
\r
1106 case DialogResult.Yes:
\r
1107 // Replace the manual query with the generated one
\r
1108 query = generatedQuery;
\r
1109 rtf_query.Text = generatedQuery;
\r
1111 case DialogResult.No:
\r
1112 // Use the manual query
\r
1113 query = specifiedQuery;
\r
1115 case DialogResult.Cancel:
\r
1116 // Don't start the encode
\r
1122 query = specifiedQuery;
\r
1125 DialogResult overwrite = DialogResult.Yes;
\r
1126 if (!string.IsNullOrEmpty(jobDestination) && File.Exists(jobDestination))
\r
1128 overwrite = MessageBox.Show(
\r
1129 "The destination file already exists. Are you sure you want to overwrite it?",
\r
1130 "Overwrite File?",
\r
1131 MessageBoxButtons.YesNo,
\r
1132 MessageBoxIcon.Question);
\r
1135 if (overwrite == DialogResult.Yes)
\r
1137 QueueTask task = new QueueTask(query)
\r
1139 Title = this.GetTitle(),
\r
1140 Source = jobSourcePath,
\r
1141 Destination = jobDestination,
\r
1142 CustomQuery = (this.rtf_query.Text != string.Empty)
\r
1145 if (this.queueProcessor.QueueManager.Count == 0)
\r
1146 this.queueProcessor.QueueManager.Add(task);
\r
1148 queueWindow.SetQueue();
\r
1149 if (this.queueProcessor.QueueManager.Count > 1)
\r
1150 queueWindow.Show(false);
\r
1152 SetEncodeStarted(); // Encode is running, so setup the GUI appropriately
\r
1153 this.queueProcessor.Start(); // Start The Queue Encoding Process
\r
1158 else if (string.IsNullOrEmpty(sourcePath) || string.IsNullOrEmpty(text_destination.Text))
\r
1159 MessageBox.Show("No source or destination selected.", "Warning", MessageBoxButtons.OK,
\r
1160 MessageBoxIcon.Warning);
\r
1165 /// Toolbar - Add the current job to the Queue
\r
1167 /// <param name="sender">
\r
1170 /// <param name="e">
\r
1173 private void btn_add2Queue_Click(object sender, EventArgs e)
\r
1175 // Add the item to the queue.
\r
1176 AddItemToQueue(true);
\r
1177 queueWindow.Show();
\r
1181 /// Add Multiple Items to the Queue at once.
\r
1183 /// <param name="sender">The Sender</param>
\r
1184 /// <param name="e">The EventArgs</param>
\r
1185 private void MnuAddMultiToQueueClick(object sender, EventArgs e)
\r
1187 if (!Settings.Default.autoNaming)
\r
1189 MessageBox.Show("Destination Auto Naming must be enabled in preferences for this feature to work.", "Error", MessageBoxButtons.OK, MessageBoxIcon.Error);
\r
1193 if (this.SourceScan.SouceData == null)
\r
1195 MessageBox.Show("You must first scan a source or collection of source to use this feature.", "Error", MessageBoxButtons.OK, MessageBoxIcon.Error);
\r
1199 BatchAdd batchAdd = new BatchAdd();
\r
1200 if (batchAdd.ShowDialog() == DialogResult.OK)
\r
1202 int min = batchAdd.Min;
\r
1203 int max = batchAdd.Max;
\r
1204 bool errors = false;
\r
1206 foreach (Title title in this.SourceScan.SouceData.Titles)
\r
1208 if (title.Duration.TotalMinutes > min && title.Duration.TotalMinutes < max)
\r
1211 this.drp_dvdtitle.SelectedItem = title;
\r
1213 if (!this.AddItemToQueue(false))
\r
1223 "One or more items could not be added to the queue. You should check your queue and manually add any missing jobs.",
\r
1225 MessageBoxButtons.OK,
\r
1226 MessageBoxIcon.Warning);
\r
1231 private bool AddItemToQueue(bool showError)
\r
1233 string query = QueryGenerator.GenerateFullQuery(this);
\r
1234 if (!string.IsNullOrEmpty(rtf_query.Text))
\r
1235 query = rtf_query.Text;
\r
1237 // 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
1238 string jobSourcePath = !string.IsNullOrEmpty(rtf_query.Text) ? Main.GetSourceFromQuery(rtf_query.Text) : sourcePath;
\r
1239 string jobDestination = !string.IsNullOrEmpty(rtf_query.Text) ? Main.GetDestinationFromQuery(rtf_query.Text) : text_destination.Text;
\r
1241 // Make sure we have a Source and Destination.
\r
1242 if (string.IsNullOrEmpty(jobSourcePath) || string.IsNullOrEmpty(jobDestination))
\r
1245 MessageBox.Show("No source or destination selected.", "Warning", MessageBoxButtons.OK, MessageBoxIcon.Warning);
\r
1249 // Make sure the destination path exists.
\r
1250 if (!Directory.Exists(Path.GetDirectoryName(jobDestination)))
\r
1253 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
1257 // Make sure we don't have a duplciate on the queue.
\r
1258 if (this.queueProcessor.QueueManager.CheckForDestinationPathDuplicates(jobDestination))
\r
1262 DialogResult result;
\r
1266 "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
1269 MessageBoxButtons.YesNo,
\r
1270 MessageBoxIcon.Warning);
\r
1272 if (result != DialogResult.Yes) return false;
\r
1281 QueueTask task = new QueueTask(query)
\r
1283 Title = this.GetTitle(),
\r
1284 Source = jobSourcePath,
\r
1285 Destination = jobDestination,
\r
1286 CustomQuery = (this.rtf_query.Text != string.Empty)
\r
1288 this.queueProcessor.QueueManager.Add(task);
\r
1290 lbl_encode.Text = this.queueProcessor.QueueManager.Count + " encode(s) pending in the queue";
\r
1296 /// Toolbar - Show the Queue
\r
1298 /// <param name="sender">
\r
1301 /// <param name="e">
\r
1304 private void btn_showQueue_Click(object sender, EventArgs e)
\r
1306 queueWindow.Show();
\r
1307 queueWindow.Activate();
\r
1311 /// Toolbar - Show the Preview Window
\r
1313 /// <param name="sender">
\r
1316 /// <param name="e">
\r
1319 private void tb_preview_Click(object sender, EventArgs e)
\r
1321 if (string.IsNullOrEmpty(sourcePath) || string.IsNullOrEmpty(text_destination.Text))
\r
1322 MessageBox.Show("No source or destination selected.", "Warning", MessageBoxButtons.OK,
\r
1323 MessageBoxIcon.Warning);
\r
1326 if (qtpreview == null)
\r
1328 qtpreview = new frmPreview(this);
\r
1331 else if (qtpreview.IsDisposed)
\r
1333 qtpreview = new frmPreview(this);
\r
1337 MessageBox.Show(qtpreview, "The preview window is already open!", "Warning", MessageBoxButtons.OK,
\r
1338 MessageBoxIcon.Warning);
\r
1343 /// Toolbar - Show the Activity log Window
\r
1345 /// <param name="sender">
\r
1348 /// <param name="e">
\r
1351 private void btn_ActivityWindow_Click(object sender, EventArgs e)
\r
1353 if (this.activityWindow == null || !this.activityWindow.IsHandleCreated)
\r
1354 this.activityWindow = new frmActivityWindow(this.queueProcessor.EncodeService, SourceScan);
\r
1356 this.activityWindow.Show();
\r
1357 this.activityWindow.Activate();
\r
1362 #region System Tray Icon
\r
1365 /// Handle Resizing of the main window when deaing with the Notify Icon
\r
1367 /// <param name="sender">
\r
1370 /// <param name="e">
\r
1373 private void frmMain_Resize(object sender, EventArgs e)
\r
1375 if (FormWindowState.Minimized == this.WindowState)
\r
1377 notifyIcon.Visible = true;
\r
1380 else if (FormWindowState.Normal == this.WindowState)
\r
1381 notifyIcon.Visible = false;
\r
1385 /// Double Click the Tray Icon
\r
1387 /// <param name="sender">
\r
1390 /// <param name="e">
\r
1393 private void notifyIcon_MouseDoubleClick(object sender, MouseEventArgs e)
\r
1395 this.Visible = true;
\r
1397 this.WindowState = FormWindowState.Normal;
\r
1398 notifyIcon.Visible = false;
\r
1402 /// Tray Icon - Restore Menu Item - Resture the Window
\r
1404 /// <param name="sender">
\r
1407 /// <param name="e">
\r
1410 private void btn_restore_Click(object sender, EventArgs e)
\r
1412 this.Visible = true;
\r
1414 this.WindowState = FormWindowState.Normal;
\r
1415 notifyIcon.Visible = false;
\r
1420 #region Main Window and Tab Control
\r
1423 private void BtnFolderScanClicked(object sender, EventArgs e)
\r
1425 this.btn_source.HideDropDown();
\r
1426 if (DVD_Open.ShowDialog() == DialogResult.OK)
\r
1428 this.selectedSourceType = SourceType.Folder;
\r
1429 SelectSource(DVD_Open.SelectedPath, 0);
\r
1432 UpdateSourceLabel();
\r
1435 private void BtnFileScanClicked(object sender, EventArgs e)
\r
1437 this.btn_source.HideDropDown();
\r
1438 if (ISO_Open.ShowDialog() == DialogResult.OK)
\r
1440 this.selectedSourceType = SourceType.VideoFile;
\r
1441 SelectSource(ISO_Open.FileName, 0);
\r
1444 UpdateSourceLabel();
\r
1447 private void MnuDvdDriveClick(object sender, EventArgs e)
\r
1449 ToolStripMenuItem item = sender as ToolStripMenuItem;
\r
1452 string driveId = item.Name.Replace("Drive", string.Empty);
\r
1454 if (int.TryParse(driveId, out id))
\r
1456 this.dvdDrivePath = drives[id].RootDirectory;
\r
1457 this.dvdDriveLabel = drives[id].VolumeLabel;
\r
1459 if (this.dvdDrivePath == null) return;
\r
1460 this.selectedSourceType = SourceType.DvdDrive;
\r
1461 SelectSource(this.dvdDrivePath, 0);
\r
1466 private void VideoTitleSpecificScanClick(object sender, EventArgs e)
\r
1468 this.btn_source.HideDropDown();
\r
1469 if (ISO_Open.ShowDialog() == DialogResult.OK)
\r
1471 this.selectedSourceType = SourceType.VideoFile;
\r
1473 int sourceTitle = 0;
\r
1474 TitleSpecificScan title = new TitleSpecificScan();
\r
1475 if (title.ShowDialog() == DialogResult.OK)
\r
1477 sourceTitle = title.Title;
\r
1478 SelectSource(ISO_Open.FileName, sourceTitle);
\r
1482 UpdateSourceLabel();
\r
1485 private void FolderTitleSpecificScanClick(object sender, EventArgs e)
\r
1487 this.btn_source.HideDropDown();
\r
1488 if (DVD_Open.ShowDialog() == DialogResult.OK)
\r
1490 this.selectedSourceType = SourceType.Folder;
\r
1492 int sourceTitle = 0;
\r
1493 TitleSpecificScan title = new TitleSpecificScan();
\r
1494 if (title.ShowDialog() == DialogResult.OK)
\r
1496 sourceTitle = title.Title;
\r
1497 SelectSource(DVD_Open.SelectedPath, sourceTitle);
\r
1501 UpdateSourceLabel();
\r
1504 private void SelectSource(string file, int titleSpecific)
\r
1506 Check_ChapterMarkers.Enabled = true;
\r
1507 sourcePath = string.Empty;
\r
1509 if (file == string.Empty) // Must have a file or path
\r
1511 UpdateSourceLabel();
\r
1515 sourcePath = Path.GetFileName(file);
\r
1516 StartScan(file, titleSpecific);
\r
1519 private void drp_dvdtitle_Click(object sender, EventArgs e)
\r
1521 if ((drp_dvdtitle.Items.Count == 1) && (drp_dvdtitle.Items[0].ToString() == "Automatic"))
\r
1523 "There are no titles to select. Please load a source file by clicking the 'Source' button above before trying to select a title.",
\r
1524 "Alert", MessageBoxButtons.OK, MessageBoxIcon.Asterisk);
\r
1527 private void drp_dvdtitle_SelectedIndexChanged(object sender, EventArgs e)
\r
1529 UnRegisterPresetEventHandler();
\r
1530 drop_mode.SelectedIndex = 0;
\r
1532 drop_chapterStart.Items.Clear();
\r
1533 drop_chapterFinish.Items.Clear();
\r
1535 // If the dropdown is set to automatic nothing else needs to be done.
\r
1536 // Otheriwse if its not, title data has to be loaded from parsing.
\r
1537 if (drp_dvdtitle.Text != "Automatic")
\r
1539 selectedTitle = drp_dvdtitle.SelectedItem as Title;
\r
1540 lbl_duration.Text = selectedTitle.Duration.ToString();
\r
1541 PictureSettings.CurrentlySelectedPreset = this.currentlySelectedPreset;
\r
1542 PictureSettings.Source = selectedTitle; // Setup Picture Settings Tab Control
\r
1544 // Populate the Angles dropdown
\r
1545 drop_angle.Items.Clear();
\r
1546 if (!Properties.Settings.Default.noDvdNav)
\r
1548 drop_angle.Visible = true;
\r
1549 lbl_angle.Visible = true;
\r
1551 for (int i = 1; i <= selectedTitle.AngleCount; i++)
\r
1552 drop_angle.Items.Add(i.ToString());
\r
1554 if (drop_angle.Items.Count == 0)
\r
1556 drop_angle.Visible = false;
\r
1557 lbl_angle.Visible = false;
\r
1560 if (drop_angle.Items.Count != 0)
\r
1561 drop_angle.SelectedIndex = 0;
\r
1565 drop_angle.Visible = false;
\r
1566 lbl_angle.Visible = false;
\r
1569 // Populate the Start chapter Dropdown
\r
1570 drop_chapterStart.Items.Clear();
\r
1571 drop_chapterStart.Items.AddRange(selectedTitle.Chapters.ToArray());
\r
1572 if (drop_chapterStart.Items.Count > 0)
\r
1573 drop_chapterStart.Text = drop_chapterStart.Items[0].ToString();
\r
1575 // Populate the Final Chapter Dropdown
\r
1576 drop_chapterFinish.Items.Clear();
\r
1577 drop_chapterFinish.Items.AddRange(selectedTitle.Chapters.ToArray());
\r
1578 if (drop_chapterFinish.Items.Count > 0)
\r
1579 drop_chapterFinish.Text = drop_chapterFinish.Items[drop_chapterFinish.Items.Count - 1].ToString();
\r
1581 // Populate the Audio Channels Dropdown
\r
1582 AudioSettings.SetTrackListFromPreset(selectedTitle, this.currentlySelectedPreset);
\r
1584 // Populate the Subtitles dropdown
\r
1585 Subtitles.SetSubtitleTrackAuto(selectedTitle.Subtitles.ToArray());
\r
1587 // Update the source label if we have multiple streams
\r
1588 if (selectedTitle != null)
\r
1589 if (!string.IsNullOrEmpty(selectedTitle.SourceName))
\r
1590 labelSource.Text = Path.GetFileName(selectedTitle.SourceName);
\r
1592 // Run the AutoName & ChapterNaming functions
\r
1593 if (Properties.Settings.Default.autoNaming)
\r
1595 string autoPath = Main.AutoName(this);
\r
1596 if (autoPath != null)
\r
1597 text_destination.Text = autoPath;
\r
1600 "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
1601 "Warning", MessageBoxButtons.OK, MessageBoxIcon.Warning);
\r
1604 data_chpt.Rows.Clear();
\r
1605 if (selectedTitle.Chapters.Count != 1)
\r
1607 DataGridView chapterGridView = Main.ChapterNaming(selectedTitle, data_chpt, drop_chapterFinish.Text);
\r
1608 if (chapterGridView != null)
\r
1609 data_chpt = chapterGridView;
\r
1613 Check_ChapterMarkers.Checked = false;
\r
1614 Check_ChapterMarkers.Enabled = false;
\r
1617 // Hack to force the redraw of the scrollbars which don't resize properly when the control is disabled.
\r
1618 data_chpt.Columns[0].Width = 166;
\r
1619 data_chpt.Columns[0].Width = 165;
\r
1621 RegisterPresetEventHandler();
\r
1624 private void chapersChanged(object sender, EventArgs e)
\r
1626 if (drop_mode.SelectedIndex != 0) // Function is not used if we are not in chapters mode.
\r
1629 Control ctl = (Control)sender;
\r
1630 int chapterStart, chapterEnd;
\r
1631 int.TryParse(drop_chapterStart.Text, out chapterStart);
\r
1632 int.TryParse(drop_chapterFinish.Text, out chapterEnd);
\r
1636 case "drop_chapterStart":
\r
1637 if (drop_chapterFinish.SelectedIndex == -1 && drop_chapterFinish.Items.Count != 0)
\r
1638 drop_chapterFinish.SelectedIndex = drop_chapterFinish.Items.Count - 1;
\r
1640 if (chapterEnd != 0)
\r
1641 if (chapterStart > chapterEnd)
\r
1642 drop_chapterFinish.Text = chapterStart.ToString();
\r
1644 case "drop_chapterFinish":
\r
1645 if (drop_chapterStart.Items.Count >= 1 && drop_chapterStart.SelectedIndex == -1)
\r
1646 drop_chapterStart.SelectedIndex = 0;
\r
1648 if (chapterStart != 0)
\r
1649 if (chapterEnd < chapterStart)
\r
1650 drop_chapterFinish.Text = chapterStart.ToString();
\r
1652 // Add more rows to the Chapter menu if needed.
\r
1653 if (Check_ChapterMarkers.Checked)
\r
1655 int i = data_chpt.Rows.Count, finish = 0;
\r
1656 int.TryParse(drop_chapterFinish.Text, out finish);
\r
1658 while (i < finish)
\r
1660 int n = data_chpt.Rows.Add();
\r
1661 data_chpt.Rows[n].Cells[0].Value = (i + 1);
\r
1662 data_chpt.Rows[n].Cells[1].Value = "Chapter " + (i + 1);
\r
1663 data_chpt.Rows[n].Cells[0].ValueType = typeof(int);
\r
1664 data_chpt.Rows[n].Cells[1].ValueType = typeof(string);
\r
1671 // Update the Duration
\r
1672 lbl_duration.Text =
\r
1673 Main.CalculateDuration(drop_chapterStart.SelectedIndex, drop_chapterFinish.SelectedIndex, selectedTitle)
\r
1676 // Run the Autonaming function
\r
1677 if (Properties.Settings.Default.autoNaming)
\r
1678 text_destination.Text = Main.AutoName(this);
\r
1680 // Disable chapter markers if only 1 chapter is selected.
\r
1681 if (chapterStart == chapterEnd)
\r
1683 Check_ChapterMarkers.Enabled = false;
\r
1684 btn_importChapters.Enabled = false;
\r
1685 data_chpt.Enabled = false;
\r
1689 Check_ChapterMarkers.Enabled = true;
\r
1690 if (Check_ChapterMarkers.Checked)
\r
1692 btn_importChapters.Enabled = true;
\r
1693 data_chpt.Enabled = true;
\r
1698 private void SecondsOrFramesChanged(object sender, EventArgs e)
\r
1701 int.TryParse(drop_chapterStart.Text, out start);
\r
1702 int.TryParse(drop_chapterFinish.Text, out end);
\r
1703 double duration = end - start;
\r
1705 switch (drop_mode.SelectedIndex)
\r
1708 lbl_duration.Text = TimeSpan.FromSeconds(duration).ToString();
\r
1711 if (selectedTitle != null)
\r
1713 duration = duration / selectedTitle.Fps;
\r
1714 lbl_duration.Text = TimeSpan.FromSeconds(duration).ToString();
\r
1717 lbl_duration.Text = "--:--:--";
\r
1723 private void drop_mode_SelectedIndexChanged(object sender, EventArgs e)
\r
1726 this.drop_chapterFinish.TextChanged -= new EventHandler(this.SecondsOrFramesChanged);
\r
1727 this.drop_chapterStart.TextChanged -= new EventHandler(this.SecondsOrFramesChanged);
\r
1730 switch (drop_mode.SelectedIndex)
\r
1733 drop_chapterStart.DropDownStyle = ComboBoxStyle.DropDownList;
\r
1734 drop_chapterFinish.DropDownStyle = ComboBoxStyle.DropDownList;
\r
1735 if (drop_chapterStart.Items.Count != 0)
\r
1737 drop_chapterStart.SelectedIndex = 0;
\r
1738 drop_chapterFinish.SelectedIndex = drop_chapterFinish.Items.Count - 1;
\r
1741 lbl_duration.Text = "--:--:--";
\r
1744 this.drop_chapterStart.TextChanged += new EventHandler(this.SecondsOrFramesChanged);
\r
1745 this.drop_chapterFinish.TextChanged += new EventHandler(this.SecondsOrFramesChanged);
\r
1746 drop_chapterStart.DropDownStyle = ComboBoxStyle.Simple;
\r
1747 drop_chapterFinish.DropDownStyle = ComboBoxStyle.Simple;
\r
1748 if (selectedTitle != null)
\r
1750 drop_chapterStart.Text = "0";
\r
1751 drop_chapterFinish.Text = selectedTitle.Duration.TotalSeconds.ToString();
\r
1755 this.drop_chapterStart.TextChanged += new EventHandler(this.SecondsOrFramesChanged);
\r
1756 this.drop_chapterFinish.TextChanged += new EventHandler(this.SecondsOrFramesChanged);
\r
1757 drop_chapterStart.DropDownStyle = ComboBoxStyle.Simple;
\r
1758 drop_chapterFinish.DropDownStyle = ComboBoxStyle.Simple;
\r
1759 if (selectedTitle != null)
\r
1761 drop_chapterStart.Text = "0";
\r
1762 drop_chapterFinish.Text = (selectedTitle.Fps * selectedTitle.Duration.TotalSeconds).ToString();
\r
1769 private void btn_destBrowse_Click(object sender, EventArgs e)
\r
1771 // This removes the file extension from the filename box on the save file dialog.
\r
1772 // It's daft but some users don't realise that typing an extension overrides the dropdown extension selected.
\r
1773 DVD_Save.FileName = Path.GetFileNameWithoutExtension(text_destination.Text);
\r
1775 if (Path.IsPathRooted(text_destination.Text))
\r
1776 DVD_Save.InitialDirectory = Path.GetDirectoryName(text_destination.Text);
\r
1778 // Show the dialog and set the main form file path
\r
1779 if (drop_format.SelectedIndex.Equals(0))
\r
1780 DVD_Save.FilterIndex = 1;
\r
1781 else if (drop_format.SelectedIndex.Equals(1))
\r
1782 DVD_Save.FilterIndex = 2;
\r
1784 if (DVD_Save.ShowDialog() == DialogResult.OK)
\r
1786 // Add a file extension manually, as FileDialog.AddExtension has issues with dots in filenames
\r
1787 switch (DVD_Save.FilterIndex)
\r
1791 !Path.GetExtension(DVD_Save.FileName).Equals(".mp4",
\r
1792 StringComparison.InvariantCultureIgnoreCase))
\r
1793 if (Properties.Settings.Default.useM4v)
\r
1794 DVD_Save.FileName = DVD_Save.FileName.Replace(".mp4", ".m4v").Replace(".mkv", ".m4v");
\r
1796 DVD_Save.FileName = DVD_Save.FileName.Replace(".m4v", ".mp4").Replace(".mkv", ".mp4");
\r
1800 !Path.GetExtension(DVD_Save.FileName).Equals(".mkv", StringComparison.InvariantCultureIgnoreCase))
\r
1801 DVD_Save.FileName = DVD_Save.FileName.Replace(".mp4", ".mkv").Replace(".m4v", ".mkv");
\r
1807 text_destination.Text = DVD_Save.FileName;
\r
1809 // Quicktime requires .m4v file for chapter markers to work. If checked, change the extension to .m4v (mp4 and m4v are the same thing)
\r
1810 if (Check_ChapterMarkers.Checked && DVD_Save.FilterIndex != 2)
\r
1811 SetExtension(".m4v");
\r
1815 private void text_destination_TextChanged(object sender, EventArgs e)
\r
1817 string path = text_destination.Text;
\r
1818 if (path.EndsWith(".mp4") || path.EndsWith(".m4v"))
\r
1819 drop_format.SelectedIndex = 0;
\r
1820 else if (path.EndsWith(".mkv"))
\r
1821 drop_format.SelectedIndex = 1;
\r
1824 // Output Settings
\r
1825 private void drop_format_SelectedIndexChanged(object sender, EventArgs e)
\r
1827 switch (drop_format.SelectedIndex)
\r
1830 if (Properties.Settings.Default.useM4v || Check_ChapterMarkers.Checked ||
\r
1831 AudioSettings.RequiresM4V() || Subtitles.RequiresM4V())
\r
1832 SetExtension(".m4v");
\r
1834 SetExtension(".mp4");
\r
1837 SetExtension(".mkv");
\r
1841 AudioSettings.SetContainer(drop_format.Text);
\r
1843 if (drop_format.Text.Contains("MP4"))
\r
1845 if (drp_videoEncoder.Items.Contains("VP3 (Theora)"))
\r
1847 drp_videoEncoder.Items.Remove("VP3 (Theora)");
\r
1848 drp_videoEncoder.SelectedIndex = 1;
\r
1851 else if (drop_format.Text.Contains("MKV"))
\r
1852 drp_videoEncoder.Items.Add("VP3 (Theora)");
\r
1855 public void SetExtension(string newExtension)
\r
1857 if (newExtension == ".mp4" || newExtension == ".m4v")
\r
1858 if (Properties.Settings.Default.useM4v || Check_ChapterMarkers.Checked || AudioSettings.RequiresM4V() ||
\r
1859 Subtitles.RequiresM4V())
\r
1860 newExtension = ".m4v";
\r
1862 newExtension = ".mp4";
\r
1864 if (Path.HasExtension(newExtension))
\r
1865 text_destination.Text = Path.ChangeExtension(text_destination.Text, newExtension);
\r
1869 private void drp_videoEncoder_SelectedIndexChanged(object sender, EventArgs e)
\r
1871 setContainerOpts();
\r
1873 // Turn off some options which are H.264 only when the user selects a non h.264 encoder
\r
1874 if (drp_videoEncoder.Text.Contains("H.264"))
\r
1876 if (check_2PassEncode.CheckState == CheckState.Checked)
\r
1877 check_turbo.Enabled = true;
\r
1879 tab_advanced.Enabled = true;
\r
1880 if ((drop_format.Text.Contains("MP4")) || (drop_format.Text.Contains("M4V")))
\r
1881 check_iPodAtom.Enabled = true;
\r
1883 check_iPodAtom.Enabled = false;
\r
1887 check_turbo.CheckState = CheckState.Unchecked;
\r
1888 check_turbo.Enabled = false;
\r
1889 tab_advanced.Enabled = false;
\r
1890 x264Panel.X264Query = string.Empty;
\r
1891 check_iPodAtom.Enabled = false;
\r
1892 check_iPodAtom.Checked = false;
\r
1895 // Setup the CQ Slider
\r
1896 switch (drp_videoEncoder.Text)
\r
1898 case "MPEG-4 (FFmpeg)":
\r
1899 if (slider_videoQuality.Value > 31)
\r
1900 slider_videoQuality.Value = 20; // Just reset to 70% QP 10 on encode change.
\r
1901 slider_videoQuality.Minimum = 1;
\r
1902 slider_videoQuality.Maximum = 31;
\r
1904 case "H.264 (x264)":
\r
1905 slider_videoQuality.Minimum = 0;
\r
1906 slider_videoQuality.TickFrequency = 1;
\r
1908 CultureInfo culture = CultureInfo.CreateSpecificCulture("en-US");
\r
1909 double cqStep = Properties.Settings.Default.x264cqstep;
\r
1910 double multiplier = 1.0 / cqStep;
\r
1911 double value = slider_videoQuality.Value * multiplier;
\r
1913 slider_videoQuality.Maximum = (int)(51 / Properties.Settings.Default.x264cqstep);
\r
1915 if (value < slider_videoQuality.Maximum)
\r
1916 slider_videoQuality.Value = slider_videoQuality.Maximum - (int)value;
\r
1919 case "VP3 (Theora)":
\r
1920 if (slider_videoQuality.Value > 63)
\r
1921 slider_videoQuality.Value = 45; // Just reset to 70% QP 45 on encode change.
\r
1922 slider_videoQuality.Minimum = 0;
\r
1923 slider_videoQuality.Maximum = 63;
\r
1929 /// When the FrameRate is not Same As Source, show the Max/Constant Mode dropdown
\r
1931 /// <param name="sender">
\r
1934 /// <param name="e">
\r
1937 private void drp_videoFramerate_SelectedIndexChanged(object sender, EventArgs e)
\r
1939 if (this.drp_videoFramerate.SelectedIndex == 0)
\r
1941 this.checkMaximumFramerate.Visible = false;
\r
1942 this.checkMaximumFramerate.CheckState = CheckState.Unchecked;
\r
1946 this.checkMaximumFramerate.Visible = true;
\r
1951 /// Set the container format options
\r
1953 public void setContainerOpts()
\r
1955 if ((drop_format.Text.Contains("MP4")) || (drop_format.Text.Contains("M4V")))
\r
1957 check_largeFile.Enabled = true;
\r
1958 check_optimiseMP4.Enabled = true;
\r
1959 check_iPodAtom.Enabled = true;
\r
1963 check_largeFile.Enabled = false;
\r
1964 check_optimiseMP4.Enabled = false;
\r
1965 check_iPodAtom.Enabled = false;
\r
1966 check_largeFile.Checked = false;
\r
1967 check_optimiseMP4.Checked = false;
\r
1968 check_iPodAtom.Checked = false;
\r
1972 private double cachedCqStep = Properties.Settings.Default.x264cqstep;
\r
1975 /// Update the CQ slider for x264 for a new CQ step. This is set from option
\r
1977 public void setQualityFromSlider()
\r
1979 // Work out the current RF value.
\r
1980 double cqStep = this.cachedCqStep;
\r
1981 double rfValue = 51.0 - slider_videoQuality.Value * cqStep;
\r
1983 // Change the maximum value for the slider
\r
1984 slider_videoQuality.Maximum = (int)(51 / Properties.Settings.Default.x264cqstep);
\r
1986 // Reset the CQ slider to RF0
\r
1987 slider_videoQuality.Value = slider_videoQuality.Maximum;
\r
1989 // Reset the CQ slider back to the previous value as close as possible
\r
1990 double cqStepNew = Properties.Settings.Default.x264cqstep;
\r
1991 double rfValueCurrent = 51.0 - slider_videoQuality.Value * cqStepNew;
\r
1992 while (rfValueCurrent < rfValue)
\r
1994 slider_videoQuality.Value--;
\r
1995 rfValueCurrent = 51.0 - slider_videoQuality.Value * cqStepNew;
\r
1998 // Cache the CQ step for the next calculation
\r
1999 this.cachedCqStep = Properties.Settings.Default.x264cqstep;
\r
2002 private void slider_videoQuality_Scroll(object sender, EventArgs e)
\r
2004 double cqStep = Properties.Settings.Default.x264cqstep;
\r
2005 switch (drp_videoEncoder.Text)
\r
2007 case "MPEG-4 (FFmpeg)":
\r
2008 lbl_SliderValue.Text = "QP:" + (32 - slider_videoQuality.Value);
\r
2010 case "H.264 (x264)":
\r
2011 double rfValue = 51.0 - slider_videoQuality.Value * cqStep;
\r
2012 rfValue = Math.Round(rfValue, 2);
\r
2013 lbl_SliderValue.Text = "RF:" + rfValue.ToString(new CultureInfo("en-US"));
\r
2014 this.lbl_rfwarn.Visible = rfValue == 0;
\r
2016 case "VP3 (Theora)":
\r
2017 lbl_SliderValue.Text = "QP:" + slider_videoQuality.Value;
\r
2022 private void radio_avgBitrate_CheckedChanged(object sender, EventArgs e)
\r
2024 text_bitrate.Enabled = true;
\r
2025 slider_videoQuality.Enabled = false;
\r
2027 check_2PassEncode.Enabled = true;
\r
2030 private void radio_cq_CheckedChanged(object sender, EventArgs e)
\r
2032 text_bitrate.Enabled = false;
\r
2033 slider_videoQuality.Enabled = true;
\r
2035 check_2PassEncode.Enabled = false;
\r
2036 check_2PassEncode.CheckState = CheckState.Unchecked;
\r
2039 private void check_2PassEncode_CheckedChanged(object sender, EventArgs e)
\r
2041 if (check_2PassEncode.CheckState.ToString() == "Checked")
\r
2043 if (drp_videoEncoder.Text.Contains("H.264"))
\r
2044 check_turbo.Enabled = true;
\r
2048 check_turbo.Enabled = false;
\r
2049 check_turbo.CheckState = CheckState.Unchecked;
\r
2053 // Chapter Marker Tab
\r
2054 private void Check_ChapterMarkers_CheckedChanged(object sender, EventArgs e)
\r
2056 if (Check_ChapterMarkers.Checked)
\r
2058 if (drop_format.SelectedIndex != 1)
\r
2059 SetExtension(".m4v");
\r
2060 data_chpt.Enabled = true;
\r
2061 btn_importChapters.Enabled = true;
\r
2065 if (drop_format.SelectedIndex != 1 && !Properties.Settings.Default.useM4v)
\r
2066 SetExtension(".mp4");
\r
2067 data_chpt.Enabled = false;
\r
2068 btn_importChapters.Enabled = false;
\r
2072 private void btn_importChapters_Click(object sender, EventArgs e)
\r
2074 if (File_ChapterImport.ShowDialog() == DialogResult.OK)
\r
2076 string filename = File_ChapterImport.FileName;
\r
2077 DataGridView imported = Main.ImportChapterNames(data_chpt, filename);
\r
2078 if (imported != null)
\r
2079 data_chpt = imported;
\r
2083 private void btn_export_Click(object sender, EventArgs e)
\r
2085 SaveFileDialog saveFileDialog = new SaveFileDialog();
\r
2086 saveFileDialog.Filter = "Csv File|*.csv";
\r
2087 saveFileDialog.DefaultExt = "csv";
\r
2088 if (saveFileDialog.ShowDialog() == DialogResult.OK)
\r
2090 string filename = saveFileDialog.FileName;
\r
2092 Main.SaveChapterMarkersToCsv(this, filename);
\r
2096 private void mnu_resetChapters_Click(object sender, EventArgs e)
\r
2098 data_chpt.Rows.Clear();
\r
2099 DataGridView chapterGridView = Main.ChapterNaming(selectedTitle, data_chpt, drop_chapterFinish.Text);
\r
2100 if (chapterGridView != null)
\r
2102 data_chpt = chapterGridView;
\r
2106 // Query Editor Tab
\r
2107 private void btn_generate_Query_Click(object sender, EventArgs e)
\r
2109 rtf_query.Text = QueryGenerator.GenerateFullQuery(this);
\r
2112 private void btn_clear_Click(object sender, EventArgs e)
\r
2114 rtf_query.Clear();
\r
2119 // MainWindow Components, Actions and Functions ***********************
\r
2121 #region Source Scan
\r
2124 /// Start the Scan Process
\r
2126 /// <param name="filename">
\r
2129 /// <param name="title">
\r
2132 private void StartScan(string filename, int title)
\r
2134 // Setup the GUI components for the scan.
\r
2135 sourcePath = filename;
\r
2137 this.DisableGUI();
\r
2142 SourceScan.Scan(sourcePath, title);
\r
2144 catch (Exception exc)
\r
2146 MessageBox.Show("frmMain.cs - StartScan " + exc, "Error", MessageBoxButtons.OK, MessageBoxIcon.Error);
\r
2151 /// Update the Status label for the scan
\r
2153 /// <param name="sender">
\r
2156 /// <param name="e">
\r
2159 private void SourceScanScanStatusChanged(object sender, ScanProgressEventArgs e)
\r
2161 if (this.InvokeRequired)
\r
2163 this.BeginInvoke(new ScanProgessStatus(this.SourceScanScanStatusChanged), new[] { sender, e });
\r
2167 labelSource.Text = string.Format("Processing Title: {0} of {1}", e.CurrentTitle, e.Titles);
\r
2171 /// Update the UI after the scan has completed
\r
2173 /// <param name="sender">
\r
2176 /// <param name="e">
\r
2179 private void SourceScanScanCompleted(object sender, EventArgs e)
\r
2181 if (this.InvokeRequired)
\r
2183 this.BeginInvoke(new ScanCompletedStatus(this.SourceScanScanCompleted), new[] { sender, e });
\r
2189 currentSource = SourceScan.SouceData;
\r
2191 // Setup some GUI components
\r
2192 drp_dvdtitle.Items.Clear();
\r
2193 if (currentSource.Titles.Count != 0)
\r
2194 drp_dvdtitle.Items.AddRange(currentSource.Titles.ToArray());
\r
2196 foreach (Title title in currentSource.Titles)
\r
2198 if (title.MainTitle)
\r
2200 drp_dvdtitle.SelectedItem = title;
\r
2204 if (drp_dvdtitle.SelectedItem == null && drp_dvdtitle.Items.Count > 0)
\r
2206 drp_dvdtitle.SelectedIndex = 0;
\r
2209 // Enable the creation of chapter markers if the file is an image of a dvd
\r
2210 if (drop_chapterStart.Items.Count > 0)
\r
2213 int.TryParse(drop_chapterStart.Items[0].ToString(), out start);
\r
2214 int.TryParse(drop_chapterFinish.Items[drop_chapterFinish.Items.Count - 1].ToString(), out end);
\r
2215 if (end > start) Check_ChapterMarkers.Enabled = true;
\r
2218 Check_ChapterMarkers.Enabled = false;
\r
2219 Check_ChapterMarkers.Checked = false;
\r
2220 data_chpt.Rows.Clear();
\r
2224 // If no titles were found, Display an error message
\r
2225 if (drp_dvdtitle.Items.Count == 0)
\r
2228 "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
2229 "Error", MessageBoxButtons.OK, MessageBoxIcon.Hand);
\r
2230 sourcePath = string.Empty;
\r
2232 UpdateSourceLabel();
\r
2234 // This is a bit of a hack to fix the queue editing.
\r
2235 // 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
2236 // When this occures, we want to repopulate their old settings.
\r
2237 if (queueEdit != null)
\r
2240 if (queueEdit.Query != null)
\r
2242 // Send the query from the file to the Query Parser class
\r
2243 EncodeTask presetQuery = QueryParserUtility.Parse(queueEdit.Query);
\r
2245 // Now load the preset
\r
2246 PresetLoader.LoadPreset(this, presetQuery, "Load Back From Queue");
\r
2248 // Set the destination path
\r
2249 this.text_destination.Text = queueEdit.Destination;
\r
2251 // The x264 widgets will need updated, so do this now:
\r
2252 x264Panel.StandardizeOptString();
\r
2253 x264Panel.SetCurrentSettingsInPanel();
\r
2255 // Set the crop label
\r
2256 PictureSettings.SetPresetCropWarningLabel(null);
\r
2262 // Enable the GUI components and enable any disabled components
\r
2265 catch (Exception exc)
\r
2267 MessageBox.Show("frmMain.cs - updateUIafterScan " + exc, "Error", MessageBoxButtons.OK,
\r
2268 MessageBoxIcon.Error);
\r
2274 /// Enable the GUI
\r
2276 private void EnableGUI()
\r
2280 if (InvokeRequired)
\r
2281 BeginInvoke(new UpdateWindowHandler(EnableGUI));
\r
2282 foreach (Control ctrl in Controls)
\r
2283 ctrl.Enabled = true;
\r
2284 btn_start.Enabled = true;
\r
2285 btn_showQueue.Enabled = true;
\r
2286 btn_add2Queue.Enabled = true;
\r
2287 tb_preview.Enabled = true;
\r
2288 btn_source.Enabled = true;
\r
2289 mnu_killCLI.Visible = false;
\r
2291 catch (Exception exc)
\r
2293 MessageBox.Show("frmMain.cs - EnableGUI() " + exc, "Error", MessageBoxButtons.OK, MessageBoxIcon.Error);
\r
2298 /// Disable the GUI
\r
2300 private void DisableGUI()
\r
2302 foreach (Control ctrl in Controls)
\r
2303 if (!(ctrl is StatusStrip || ctrl is MenuStrip || ctrl is ToolStrip))
\r
2304 ctrl.Enabled = false;
\r
2306 labelSource.Enabled = true;
\r
2307 labelStaticSource.Enabled = true;
\r
2308 SourceLayoutPanel.Enabled = true;
\r
2309 btn_source.Enabled = false;
\r
2310 btn_start.Enabled = false;
\r
2311 btn_showQueue.Enabled = false;
\r
2312 btn_add2Queue.Enabled = false;
\r
2313 tb_preview.Enabled = false;
\r
2314 mnu_killCLI.Visible = true;
\r
2320 private void KillScan()
\r
2322 SourceScan.ScanCompleted -= this.SourceScanScanCompleted;
\r
2326 SourceScan.Stop();
\r
2328 labelSource.Text = "Scan Cancelled";
\r
2334 private void ResetGUI()
\r
2336 drp_dvdtitle.Items.Clear();
\r
2337 drop_chapterStart.Items.Clear();
\r
2338 drop_chapterFinish.Items.Clear();
\r
2339 lbl_duration.Text = "Select a Title";
\r
2340 PictureSettings.lbl_src_res.Text = "Select a Title";
\r
2341 sourcePath = String.Empty;
\r
2342 text_destination.Text = String.Empty;
\r
2343 selectedTitle = null;
\r
2347 /// Update the Source Label
\r
2349 private void UpdateSourceLabel()
\r
2351 labelSource.Text = string.IsNullOrEmpty(sourcePath) ? "Select \"Source\" to continue." : this.SourceName;
\r
2355 /// Take a job from the Queue, rescan it, and reload the GUI for that job.
\r
2357 /// <param name="job">
\r
2360 public void RecievingJob(QueueTask job)
\r
2363 this.currentlySelectedPreset = null;
\r
2364 x264Panel.Reset2Defaults();
\r
2367 queueEdit = job; // Nasty but will do for now. TODO
\r
2368 StartScan(job.Source, job.Title);
\r
2373 #region GUI Functions and Actions
\r
2376 /// Set the GUI to it's finished encoding state.
\r
2378 private void SetEncodeFinished()
\r
2382 if (InvokeRequired)
\r
2384 BeginInvoke(new UpdateWindowHandler(SetEncodeFinished));
\r
2388 lbl_encode.Text = "Encoding Finished";
\r
2389 ProgressBarStatus.Visible = false;
\r
2390 btn_start.Text = "Start";
\r
2391 btn_start.ToolTipText = "Start the encoding process";
\r
2392 btn_start.Image = Properties.Resources.Play;
\r
2394 // If the window is minimized, display the notification in a popup.
\r
2395 if (Properties.Settings.Default.trayIconAlerts)
\r
2396 if (FormWindowState.Minimized == this.WindowState)
\r
2398 notifyIcon.BalloonTipText = lbl_encode.Text;
\r
2399 notifyIcon.ShowBalloonTip(500);
\r
2402 catch (Exception exc)
\r
2404 MessageBox.Show(exc.ToString());
\r
2409 /// Set the GUI to it's started encoding state.
\r
2411 private void SetEncodeStarted()
\r
2415 if (InvokeRequired)
\r
2417 BeginInvoke(new UpdateWindowHandler(SetEncodeStarted));
\r
2420 lbl_encode.Visible = true;
\r
2421 ProgressBarStatus.Value = 0;
\r
2422 ProgressBarStatus.Visible = true;
\r
2423 lbl_encode.Text = "Encoding with " + this.queueProcessor.QueueManager.Count + " encode(s) pending";
\r
2424 btn_start.Text = "Stop";
\r
2425 btn_start.ToolTipText = "Stop the encoding process.";
\r
2426 btn_start.Image = Properties.Resources.stop;
\r
2428 catch (Exception exc)
\r
2430 MessageBox.Show(exc.ToString());
\r
2435 /// Display the Encode Status
\r
2437 /// <param name="sender">
\r
2440 /// <param name="e">
\r
2443 private void EncodeQueue_EncodeStatusChanged(object sender, EncodeProgressEventArgs e)
\r
2445 if (this.InvokeRequired)
\r
2447 this.BeginInvoke(new EncodeProgessStatus(EncodeQueue_EncodeStatusChanged), new[] { sender, e });
\r
2453 "{0:00.00}%, FPS: {1:000.0}, Avg FPS: {2:000.0}, Time Remaining: {3}, Encode(s) Pending {4}",
\r
2454 e.PercentComplete,
\r
2455 e.CurrentFrameRate,
\r
2456 e.AverageFrameRate,
\r
2457 e.EstimatedTimeLeft,
\r
2458 this.queueProcessor.QueueManager.Count);
\r
2460 ProgressBarStatus.Value = (int)Math.Round(e.PercentComplete);
\r
2464 /// Set the DVD Drive selection in the "Source" Menu
\r
2466 private void SetDriveSelectionMenuItem()
\r
2470 if (InvokeRequired)
\r
2472 BeginInvoke(new UpdateWindowHandler(SetDriveSelectionMenuItem));
\r
2476 drives = UtilityService.GetDrives();
\r
2478 List<ToolStripMenuItem> menuItems = new List<ToolStripMenuItem>();
\r
2479 foreach (DriveInformation drive in drives)
\r
2481 ToolStripMenuItem menuItem = new ToolStripMenuItem
\r
2483 Name = drive.ToString(),
\r
2484 Text = drive.RootDirectory + " (" + drive.VolumeLabel + ")",
\r
2485 Image = Resources.disc_small
\r
2487 menuItem.Click += new EventHandler(MnuDvdDriveClick);
\r
2488 menuItems.Add(menuItem);
\r
2491 foreach (ToolStripMenuItem item in menuItems)
\r
2492 btn_source.DropDownItems.Add(item);
\r
2494 catch (Exception exc)
\r
2496 MessageBox.Show("Error in SetDriveSelectionMenuItem" + exc);
\r
2501 /// Access the preset Handler and setup the preset panel.
\r
2503 private void LoadPresetPanel()
\r
2505 if (presetHandler.CheckIfPresetsAreOutOfDate())
\r
2506 if (!Settings.Default.presetNotification)
\r
2507 MessageBox.Show(this,
\r
2508 "HandBrake has determined your built-in presets are out of date... These presets will now be updated.",
\r
2509 "Preset Update", MessageBoxButtons.OK, MessageBoxIcon.Information);
\r
2511 // Clear the old presets
\r
2512 treeView_presets.Nodes.Clear();
\r
2515 string category = string.Empty; // The category we are currnetly processing
\r
2516 TreeNode rootNode = null;
\r
2517 foreach (Preset preset in this.presetHandler.Presets.Where(p => p.IsBuildIn))
\r
2519 // If the category of this preset doesn't match the current category we are processing
\r
2520 // Then we need to create a new root node.
\r
2521 if (preset.Category != category)
\r
2523 rootNode = new TreeNode(preset.Category) { ForeColor = Color.DarkBlue };
\r
2524 treeView_presets.Nodes.Add(rootNode);
\r
2525 category = preset.Category;
\r
2528 if (preset.Category == category && rootNode != null)
\r
2529 rootNode.Nodes.Add(new TreeNode(preset.Name) { ToolTipText = preset.Description, ForeColor = Color.DarkBlue });
\r
2534 foreach (Preset preset in this.presetHandler.Presets.Where(p => !p.IsBuildIn)) // User Presets
\r
2536 if (preset.Category != category && preset.Category != string.Empty)
\r
2538 rootNode = new TreeNode(preset.Category) { ForeColor = Color.Black };
\r
2539 treeView_presets.Nodes.Add(rootNode);
\r
2540 category = preset.Category;
\r
2543 if (preset.Category == category && rootNode != null)
\r
2544 rootNode.Nodes.Add(new TreeNode(preset.Name) { ForeColor = Color.Black, ToolTipText = preset.Description });
\r
2546 treeView_presets.Nodes.Add(new TreeNode(preset.Name) { ForeColor = Color.Black, ToolTipText = preset.Description });
\r
2549 treeView_presets.Update();
\r
2553 /// Get the title from the selected item in the title dropdown.
\r
2558 private int GetTitle()
\r
2561 if (drp_dvdtitle.SelectedItem != null)
\r
2563 string[] titleInfo = drp_dvdtitle.SelectedItem.ToString().Split(' ');
\r
2564 int.TryParse(titleInfo[0], out title);
\r
2571 /// Handle the Update Check Finishing.
\r
2573 /// <param name="result">
\r
2576 private void UpdateCheckDoneMenu(IAsyncResult result)
\r
2578 // Make sure it's running on the calling thread
\r
2579 if (InvokeRequired)
\r
2581 Invoke(new MethodInvoker(() => this.UpdateCheckDoneMenu(result)));
\r
2584 UpdateCheckInformation info;
\r
2587 // Get the information about the new build, if any, and close the window
\r
2588 info = UpdateService.EndCheckForUpdates(result);
\r
2590 if (info.NewVersionAvailable && info.BuildInformation != null)
\r
2592 UpdateInfo updateWindow = new UpdateInfo(info.BuildInformation, Settings.Default.hb_version, Settings.Default.hb_build.ToString());
\r
2593 updateWindow.ShowDialog();
\r
2596 MessageBox.Show("There are no new updates at this time.", "Update Check", MessageBoxButtons.OK,
\r
2597 MessageBoxIcon.Information);
\r
2598 lbl_updateCheck.Visible = false;
\r
2601 catch (Exception ex)
\r
2603 if ((bool)result.AsyncState)
\r
2605 "Unable to check for updates, Please try again later.\n\nDetailed Error Information:\n" + ex,
\r
2606 "Error", MessageBoxButtons.OK, MessageBoxIcon.Error);
\r
2615 /// Handle GUI shortcuts
\r
2617 /// <param name="msg">Message</param>
\r
2618 /// <param name="keyData">Keys</param>
\r
2619 /// <returns>Bool</returns>
\r
2620 protected override bool ProcessCmdKey(ref Message msg, Keys keyData)
\r
2622 if (keyData == (Keys.Control | Keys.S))
\r
2624 btn_start_Click(this, new EventArgs());
\r
2628 if (keyData == (Keys.Control | Keys.Shift | Keys.A))
\r
2630 btn_add2Queue_Click(this, new EventArgs());
\r
2633 return base.ProcessCmdKey(ref msg, keyData);
\r
2637 /// If the queue is being processed, prompt the user to confirm application close.
\r
2639 /// <param name="e">FormClosingEventArgs</param>
\r
2640 protected override void OnFormClosing(FormClosingEventArgs e)
\r
2644 // If currently encoding, the queue isn't paused, and there are queue items to process, prompt to confirm close.
\r
2645 if (this.queueProcessor.EncodeService.IsEncoding)
\r
2647 DialogResult result =
\r
2649 "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
2650 "Close HandBrake?",
\r
2651 MessageBoxButtons.YesNo,
\r
2652 MessageBoxIcon.Question);
\r
2654 if (result == DialogResult.No)
\r
2660 this.queueProcessor.Pause();
\r
2661 this.queueProcessor.EncodeService.Stop();
\r
2664 if (SourceScan.IsScanning)
\r
2666 SourceScan.Stop();
\r
2669 SourceScan.ScanCompleted -= this.SourceScanScanCompleted;
\r
2670 SourceScan.ScanStatusChanged -= this.SourceScanScanStatusChanged;
\r
2672 catch (Exception exc)
\r
2674 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
2678 base.OnFormClosing(e);
\r
2684 // This is the END of the road ****************************************
\r