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
1790 if (!Path.GetExtension(DVD_Save.FileName).Equals(".mp4", StringComparison.InvariantCultureIgnoreCase))
\r
1791 if (Properties.Settings.Default.useM4v == 2 || Properties.Settings.Default.useM4v == 0)
\r
1792 DVD_Save.FileName = DVD_Save.FileName.Replace(".mp4", ".m4v").Replace(".mkv", ".m4v");
\r
1794 DVD_Save.FileName = DVD_Save.FileName.Replace(".m4v", ".mp4").Replace(".mkv", ".mp4");
\r
1797 if (!Path.GetExtension(DVD_Save.FileName).Equals(".mkv", StringComparison.InvariantCultureIgnoreCase))
\r
1798 DVD_Save.FileName = DVD_Save.FileName.Replace(".mp4", ".mkv").Replace(".m4v", ".mkv");
\r
1804 text_destination.Text = DVD_Save.FileName;
\r
1806 // Quicktime requires .m4v file for chapter markers to work. If checked, change the extension to .m4v (mp4 and m4v are the same thing)
\r
1807 if (Check_ChapterMarkers.Checked && DVD_Save.FilterIndex != 2)
\r
1808 SetExtension(".m4v");
\r
1812 private void text_destination_TextChanged(object sender, EventArgs e)
\r
1814 string path = text_destination.Text;
\r
1815 if (path.EndsWith(".mp4") || path.EndsWith(".m4v"))
\r
1816 drop_format.SelectedIndex = 0;
\r
1817 else if (path.EndsWith(".mkv"))
\r
1818 drop_format.SelectedIndex = 1;
\r
1821 // Output Settings
\r
1822 private void drop_format_SelectedIndexChanged(object sender, EventArgs e)
\r
1824 switch (drop_format.SelectedIndex)
\r
1827 SetExtension(".mp4");
\r
1830 SetExtension(".mkv");
\r
1834 AudioSettings.SetContainer(drop_format.Text);
\r
1836 if (drop_format.Text.Contains("MP4"))
\r
1838 if (drp_videoEncoder.Items.Contains("VP3 (Theora)"))
\r
1840 drp_videoEncoder.Items.Remove("VP3 (Theora)");
\r
1841 drp_videoEncoder.SelectedIndex = 1;
\r
1844 else if (drop_format.Text.Contains("MKV"))
\r
1845 drp_videoEncoder.Items.Add("VP3 (Theora)");
\r
1848 public void SetExtension(string newExtension)
\r
1850 if (newExtension == ".mp4" || newExtension == ".m4v")
\r
1851 if (Check_ChapterMarkers.Checked || AudioSettings.RequiresM4V() || Subtitles.RequiresM4V() || Properties.Settings.Default.useM4v == 2)
\r
1852 newExtension = Properties.Settings.Default.useM4v == 1 ? ".mp4" : ".m4v";
\r
1854 newExtension = ".mp4";
\r
1856 if (Path.HasExtension(newExtension))
\r
1857 text_destination.Text = Path.ChangeExtension(text_destination.Text, newExtension);
\r
1861 private void drp_videoEncoder_SelectedIndexChanged(object sender, EventArgs e)
\r
1863 setContainerOpts();
\r
1865 // Turn off some options which are H.264 only when the user selects a non h.264 encoder
\r
1866 if (drp_videoEncoder.Text.Contains("H.264"))
\r
1868 if (check_2PassEncode.CheckState == CheckState.Checked)
\r
1869 check_turbo.Enabled = true;
\r
1871 tab_advanced.Enabled = true;
\r
1872 if ((drop_format.Text.Contains("MP4")) || (drop_format.Text.Contains("M4V")))
\r
1873 check_iPodAtom.Enabled = true;
\r
1875 check_iPodAtom.Enabled = false;
\r
1879 check_turbo.CheckState = CheckState.Unchecked;
\r
1880 check_turbo.Enabled = false;
\r
1881 tab_advanced.Enabled = false;
\r
1882 x264Panel.X264Query = string.Empty;
\r
1883 check_iPodAtom.Enabled = false;
\r
1884 check_iPodAtom.Checked = false;
\r
1887 // Setup the CQ Slider
\r
1888 switch (drp_videoEncoder.Text)
\r
1890 case "MPEG-4 (FFmpeg)":
\r
1891 if (slider_videoQuality.Value > 31)
\r
1892 slider_videoQuality.Value = 20; // Just reset to 70% QP 10 on encode change.
\r
1893 slider_videoQuality.Minimum = 1;
\r
1894 slider_videoQuality.Maximum = 31;
\r
1896 case "H.264 (x264)":
\r
1897 slider_videoQuality.Minimum = 0;
\r
1898 slider_videoQuality.TickFrequency = 1;
\r
1900 CultureInfo culture = CultureInfo.CreateSpecificCulture("en-US");
\r
1901 double cqStep = Properties.Settings.Default.x264cqstep;
\r
1902 double multiplier = 1.0 / cqStep;
\r
1903 double value = slider_videoQuality.Value * multiplier;
\r
1905 slider_videoQuality.Maximum = (int)(51 / Properties.Settings.Default.x264cqstep);
\r
1907 if (value < slider_videoQuality.Maximum)
\r
1908 slider_videoQuality.Value = slider_videoQuality.Maximum - (int)value;
\r
1911 case "VP3 (Theora)":
\r
1912 if (slider_videoQuality.Value > 63)
\r
1913 slider_videoQuality.Value = 45; // Just reset to 70% QP 45 on encode change.
\r
1914 slider_videoQuality.Minimum = 0;
\r
1915 slider_videoQuality.Maximum = 63;
\r
1921 /// When the FrameRate is not Same As Source, show the Max/Constant Mode dropdown
\r
1923 /// <param name="sender">
\r
1926 /// <param name="e">
\r
1929 private void drp_videoFramerate_SelectedIndexChanged(object sender, EventArgs e)
\r
1931 if (this.drp_videoFramerate.SelectedIndex == 0)
\r
1933 this.checkMaximumFramerate.Visible = false;
\r
1934 this.checkMaximumFramerate.CheckState = CheckState.Unchecked;
\r
1938 this.checkMaximumFramerate.Visible = true;
\r
1943 /// Set the container format options
\r
1945 public void setContainerOpts()
\r
1947 if ((drop_format.Text.Contains("MP4")) || (drop_format.Text.Contains("M4V")))
\r
1949 check_largeFile.Enabled = true;
\r
1950 check_optimiseMP4.Enabled = true;
\r
1951 check_iPodAtom.Enabled = true;
\r
1955 check_largeFile.Enabled = false;
\r
1956 check_optimiseMP4.Enabled = false;
\r
1957 check_iPodAtom.Enabled = false;
\r
1958 check_largeFile.Checked = false;
\r
1959 check_optimiseMP4.Checked = false;
\r
1960 check_iPodAtom.Checked = false;
\r
1964 private double cachedCqStep = Properties.Settings.Default.x264cqstep;
\r
1967 /// Update the CQ slider for x264 for a new CQ step. This is set from option
\r
1969 public void setQualityFromSlider()
\r
1971 // Work out the current RF value.
\r
1972 double cqStep = this.cachedCqStep;
\r
1973 double rfValue = 51.0 - slider_videoQuality.Value * cqStep;
\r
1975 // Change the maximum value for the slider
\r
1976 slider_videoQuality.Maximum = (int)(51 / Properties.Settings.Default.x264cqstep);
\r
1978 // Reset the CQ slider to RF0
\r
1979 slider_videoQuality.Value = slider_videoQuality.Maximum;
\r
1981 // Reset the CQ slider back to the previous value as close as possible
\r
1982 double cqStepNew = Properties.Settings.Default.x264cqstep;
\r
1983 double rfValueCurrent = 51.0 - slider_videoQuality.Value * cqStepNew;
\r
1984 while (rfValueCurrent < rfValue)
\r
1986 slider_videoQuality.Value--;
\r
1987 rfValueCurrent = 51.0 - slider_videoQuality.Value * cqStepNew;
\r
1990 // Cache the CQ step for the next calculation
\r
1991 this.cachedCqStep = Properties.Settings.Default.x264cqstep;
\r
1994 private void slider_videoQuality_Scroll(object sender, EventArgs e)
\r
1996 double cqStep = Properties.Settings.Default.x264cqstep;
\r
1997 switch (drp_videoEncoder.Text)
\r
1999 case "MPEG-4 (FFmpeg)":
\r
2000 lbl_SliderValue.Text = "QP:" + (32 - slider_videoQuality.Value);
\r
2002 case "H.264 (x264)":
\r
2003 double rfValue = 51.0 - slider_videoQuality.Value * cqStep;
\r
2004 rfValue = Math.Round(rfValue, 2);
\r
2005 lbl_SliderValue.Text = "RF:" + rfValue.ToString(new CultureInfo("en-US"));
\r
2006 this.lbl_rfwarn.Visible = rfValue == 0;
\r
2008 case "VP3 (Theora)":
\r
2009 lbl_SliderValue.Text = "QP:" + slider_videoQuality.Value;
\r
2014 private void radio_avgBitrate_CheckedChanged(object sender, EventArgs e)
\r
2016 text_bitrate.Enabled = true;
\r
2017 slider_videoQuality.Enabled = false;
\r
2019 check_2PassEncode.Enabled = true;
\r
2022 private void radio_cq_CheckedChanged(object sender, EventArgs e)
\r
2024 text_bitrate.Enabled = false;
\r
2025 slider_videoQuality.Enabled = true;
\r
2027 check_2PassEncode.Enabled = false;
\r
2028 check_2PassEncode.CheckState = CheckState.Unchecked;
\r
2031 private void check_2PassEncode_CheckedChanged(object sender, EventArgs e)
\r
2033 if (check_2PassEncode.CheckState.ToString() == "Checked")
\r
2035 if (drp_videoEncoder.Text.Contains("H.264"))
\r
2036 check_turbo.Enabled = true;
\r
2040 check_turbo.Enabled = false;
\r
2041 check_turbo.CheckState = CheckState.Unchecked;
\r
2045 // Chapter Marker Tab
\r
2046 private void Check_ChapterMarkers_CheckedChanged(object sender, EventArgs e)
\r
2048 if (Check_ChapterMarkers.Checked)
\r
2050 if (drop_format.SelectedIndex != 1)
\r
2051 SetExtension(".m4v");
\r
2052 data_chpt.Enabled = true;
\r
2053 btn_importChapters.Enabled = true;
\r
2057 if (drop_format.SelectedIndex != 1)
\r
2058 SetExtension(".mp4");
\r
2059 data_chpt.Enabled = false;
\r
2060 btn_importChapters.Enabled = false;
\r
2064 private void btn_importChapters_Click(object sender, EventArgs e)
\r
2066 if (File_ChapterImport.ShowDialog() == DialogResult.OK)
\r
2068 string filename = File_ChapterImport.FileName;
\r
2069 DataGridView imported = Main.ImportChapterNames(data_chpt, filename);
\r
2070 if (imported != null)
\r
2071 data_chpt = imported;
\r
2075 private void btn_export_Click(object sender, EventArgs e)
\r
2077 SaveFileDialog saveFileDialog = new SaveFileDialog();
\r
2078 saveFileDialog.Filter = "Csv File|*.csv";
\r
2079 saveFileDialog.DefaultExt = "csv";
\r
2080 if (saveFileDialog.ShowDialog() == DialogResult.OK)
\r
2082 string filename = saveFileDialog.FileName;
\r
2084 Main.SaveChapterMarkersToCsv(this, filename);
\r
2088 private void mnu_resetChapters_Click(object sender, EventArgs e)
\r
2090 data_chpt.Rows.Clear();
\r
2091 DataGridView chapterGridView = Main.ChapterNaming(selectedTitle, data_chpt, drop_chapterFinish.Text);
\r
2092 if (chapterGridView != null)
\r
2094 data_chpt = chapterGridView;
\r
2098 // Query Editor Tab
\r
2099 private void btn_generate_Query_Click(object sender, EventArgs e)
\r
2101 rtf_query.Text = QueryGenerator.GenerateFullQuery(this);
\r
2104 private void btn_clear_Click(object sender, EventArgs e)
\r
2106 rtf_query.Clear();
\r
2111 // MainWindow Components, Actions and Functions ***********************
\r
2113 #region Source Scan
\r
2116 /// Start the Scan Process
\r
2118 /// <param name="filename">
\r
2121 /// <param name="title">
\r
2124 private void StartScan(string filename, int title)
\r
2126 // Setup the GUI components for the scan.
\r
2127 sourcePath = filename;
\r
2129 this.DisableGUI();
\r
2134 SourceScan.Scan(sourcePath, title);
\r
2136 catch (Exception exc)
\r
2138 MessageBox.Show("frmMain.cs - StartScan " + exc, "Error", MessageBoxButtons.OK, MessageBoxIcon.Error);
\r
2143 /// Update the Status label for the scan
\r
2145 /// <param name="sender">
\r
2148 /// <param name="e">
\r
2151 private void SourceScanScanStatusChanged(object sender, ScanProgressEventArgs e)
\r
2153 if (this.InvokeRequired)
\r
2155 this.BeginInvoke(new ScanProgessStatus(this.SourceScanScanStatusChanged), new[] { sender, e });
\r
2159 labelSource.Text = string.Format("Processing Title: {0} of {1}", e.CurrentTitle, e.Titles);
\r
2163 /// Update the UI after the scan has completed
\r
2165 /// <param name="sender">
\r
2168 /// <param name="e">
\r
2171 private void SourceScanScanCompleted(object sender, EventArgs e)
\r
2173 if (this.InvokeRequired)
\r
2175 this.BeginInvoke(new ScanCompletedStatus(this.SourceScanScanCompleted), new[] { sender, e });
\r
2181 currentSource = SourceScan.SouceData;
\r
2183 // Setup some GUI components
\r
2184 drp_dvdtitle.Items.Clear();
\r
2185 if (currentSource.Titles.Count != 0)
\r
2186 drp_dvdtitle.Items.AddRange(currentSource.Titles.ToArray());
\r
2188 foreach (Title title in currentSource.Titles)
\r
2190 if (title.MainTitle)
\r
2192 drp_dvdtitle.SelectedItem = title;
\r
2196 if (drp_dvdtitle.SelectedItem == null && drp_dvdtitle.Items.Count > 0)
\r
2198 drp_dvdtitle.SelectedIndex = 0;
\r
2201 // Enable the creation of chapter markers if the file is an image of a dvd
\r
2202 if (drop_chapterStart.Items.Count > 0)
\r
2205 int.TryParse(drop_chapterStart.Items[0].ToString(), out start);
\r
2206 int.TryParse(drop_chapterFinish.Items[drop_chapterFinish.Items.Count - 1].ToString(), out end);
\r
2207 if (end > start) Check_ChapterMarkers.Enabled = true;
\r
2210 Check_ChapterMarkers.Enabled = false;
\r
2211 Check_ChapterMarkers.Checked = false;
\r
2212 data_chpt.Rows.Clear();
\r
2216 // If no titles were found, Display an error message
\r
2217 if (drp_dvdtitle.Items.Count == 0)
\r
2220 "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
2221 "Error", MessageBoxButtons.OK, MessageBoxIcon.Hand);
\r
2222 sourcePath = string.Empty;
\r
2224 UpdateSourceLabel();
\r
2226 // This is a bit of a hack to fix the queue editing.
\r
2227 // 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
2228 // When this occures, we want to repopulate their old settings.
\r
2229 if (queueEdit != null)
\r
2232 if (queueEdit.Query != null)
\r
2234 // Send the query from the file to the Query Parser class
\r
2235 EncodeTask presetQuery = QueryParserUtility.Parse(queueEdit.Query);
\r
2237 // Now load the preset
\r
2238 PresetLoader.LoadPreset(this, presetQuery, "Load Back From Queue");
\r
2240 // Set the destination path
\r
2241 this.text_destination.Text = queueEdit.Destination;
\r
2243 // The x264 widgets will need updated, so do this now:
\r
2244 x264Panel.StandardizeOptString();
\r
2245 x264Panel.SetCurrentSettingsInPanel();
\r
2247 // Set the crop label
\r
2248 PictureSettings.SetPresetCropWarningLabel(null);
\r
2254 // Enable the GUI components and enable any disabled components
\r
2257 catch (Exception exc)
\r
2259 MessageBox.Show("frmMain.cs - updateUIafterScan " + exc, "Error", MessageBoxButtons.OK,
\r
2260 MessageBoxIcon.Error);
\r
2266 /// Enable the GUI
\r
2268 private void EnableGUI()
\r
2272 if (InvokeRequired)
\r
2273 BeginInvoke(new UpdateWindowHandler(EnableGUI));
\r
2274 foreach (Control ctrl in Controls)
\r
2275 ctrl.Enabled = true;
\r
2276 btn_start.Enabled = true;
\r
2277 btn_showQueue.Enabled = true;
\r
2278 btn_add2Queue.Enabled = true;
\r
2279 tb_preview.Enabled = true;
\r
2280 btn_source.Enabled = true;
\r
2281 mnu_killCLI.Visible = false;
\r
2283 catch (Exception exc)
\r
2285 MessageBox.Show("frmMain.cs - EnableGUI() " + exc, "Error", MessageBoxButtons.OK, MessageBoxIcon.Error);
\r
2290 /// Disable the GUI
\r
2292 private void DisableGUI()
\r
2294 foreach (Control ctrl in Controls)
\r
2295 if (!(ctrl is StatusStrip || ctrl is MenuStrip || ctrl is ToolStrip))
\r
2296 ctrl.Enabled = false;
\r
2298 labelSource.Enabled = true;
\r
2299 labelStaticSource.Enabled = true;
\r
2300 SourceLayoutPanel.Enabled = true;
\r
2301 btn_source.Enabled = false;
\r
2302 btn_start.Enabled = false;
\r
2303 btn_showQueue.Enabled = false;
\r
2304 btn_add2Queue.Enabled = false;
\r
2305 tb_preview.Enabled = false;
\r
2306 mnu_killCLI.Visible = true;
\r
2312 private void KillScan()
\r
2314 SourceScan.ScanCompleted -= this.SourceScanScanCompleted;
\r
2318 SourceScan.Stop();
\r
2320 labelSource.Text = "Scan Cancelled";
\r
2326 private void ResetGUI()
\r
2328 drp_dvdtitle.Items.Clear();
\r
2329 drop_chapterStart.Items.Clear();
\r
2330 drop_chapterFinish.Items.Clear();
\r
2331 lbl_duration.Text = "Select a Title";
\r
2332 PictureSettings.lbl_src_res.Text = "Select a Title";
\r
2333 sourcePath = String.Empty;
\r
2334 text_destination.Text = String.Empty;
\r
2335 selectedTitle = null;
\r
2339 /// Update the Source Label
\r
2341 private void UpdateSourceLabel()
\r
2343 labelSource.Text = string.IsNullOrEmpty(sourcePath) ? "Select \"Source\" to continue." : this.SourceName;
\r
2347 /// Take a job from the Queue, rescan it, and reload the GUI for that job.
\r
2349 /// <param name="job">
\r
2352 public void RecievingJob(QueueTask job)
\r
2355 this.currentlySelectedPreset = null;
\r
2356 x264Panel.Reset2Defaults();
\r
2359 queueEdit = job; // Nasty but will do for now. TODO
\r
2360 StartScan(job.Source, job.Title);
\r
2365 #region GUI Functions and Actions
\r
2368 /// Set the GUI to it's finished encoding state.
\r
2370 private void SetEncodeFinished()
\r
2374 if (InvokeRequired)
\r
2376 BeginInvoke(new UpdateWindowHandler(SetEncodeFinished));
\r
2380 lbl_encode.Text = "Encoding Finished";
\r
2381 ProgressBarStatus.Visible = false;
\r
2382 btn_start.Text = "Start";
\r
2383 btn_start.ToolTipText = "Start the encoding process";
\r
2384 btn_start.Image = Properties.Resources.Play;
\r
2386 // If the window is minimized, display the notification in a popup.
\r
2387 if (Properties.Settings.Default.trayIconAlerts)
\r
2388 if (FormWindowState.Minimized == this.WindowState)
\r
2390 notifyIcon.BalloonTipText = lbl_encode.Text;
\r
2391 notifyIcon.ShowBalloonTip(500);
\r
2394 catch (Exception exc)
\r
2396 MessageBox.Show(exc.ToString());
\r
2401 /// Set the GUI to it's started encoding state.
\r
2403 private void SetEncodeStarted()
\r
2407 if (InvokeRequired)
\r
2409 BeginInvoke(new UpdateWindowHandler(SetEncodeStarted));
\r
2412 lbl_encode.Visible = true;
\r
2413 ProgressBarStatus.Value = 0;
\r
2414 ProgressBarStatus.Visible = true;
\r
2415 lbl_encode.Text = "Encoding with " + this.queueProcessor.QueueManager.Count + " encode(s) pending";
\r
2416 btn_start.Text = "Stop";
\r
2417 btn_start.ToolTipText = "Stop the encoding process.";
\r
2418 btn_start.Image = Properties.Resources.stop;
\r
2420 catch (Exception exc)
\r
2422 MessageBox.Show(exc.ToString());
\r
2427 /// Display the Encode Status
\r
2429 /// <param name="sender">
\r
2432 /// <param name="e">
\r
2435 private void EncodeQueue_EncodeStatusChanged(object sender, EncodeProgressEventArgs e)
\r
2437 if (this.InvokeRequired)
\r
2439 this.BeginInvoke(new EncodeProgessStatus(EncodeQueue_EncodeStatusChanged), new[] { sender, e });
\r
2445 "{0:00.00}%, FPS: {1:000.0}, Avg FPS: {2:000.0}, Time Remaining: {3}, Encode(s) Pending {4}",
\r
2446 e.PercentComplete,
\r
2447 e.CurrentFrameRate,
\r
2448 e.AverageFrameRate,
\r
2449 e.EstimatedTimeLeft,
\r
2450 this.queueProcessor.QueueManager.Count);
\r
2452 ProgressBarStatus.Value = (int)Math.Round(e.PercentComplete);
\r
2456 /// Set the DVD Drive selection in the "Source" Menu
\r
2458 private void SetDriveSelectionMenuItem()
\r
2462 if (InvokeRequired)
\r
2464 BeginInvoke(new UpdateWindowHandler(SetDriveSelectionMenuItem));
\r
2468 drives = UtilityService.GetDrives();
\r
2470 List<ToolStripMenuItem> menuItems = new List<ToolStripMenuItem>();
\r
2471 foreach (DriveInformation drive in drives)
\r
2473 ToolStripMenuItem menuItem = new ToolStripMenuItem
\r
2475 Name = drive.ToString(),
\r
2476 Text = drive.RootDirectory + " (" + drive.VolumeLabel + ")",
\r
2477 Image = Resources.disc_small
\r
2479 menuItem.Click += new EventHandler(MnuDvdDriveClick);
\r
2480 menuItems.Add(menuItem);
\r
2483 foreach (ToolStripMenuItem item in menuItems)
\r
2484 btn_source.DropDownItems.Add(item);
\r
2486 catch (Exception exc)
\r
2488 MessageBox.Show("Error in SetDriveSelectionMenuItem" + exc);
\r
2493 /// Access the preset Handler and setup the preset panel.
\r
2495 private void LoadPresetPanel()
\r
2497 if (presetHandler.CheckIfPresetsAreOutOfDate())
\r
2498 if (!Settings.Default.presetNotification)
\r
2499 MessageBox.Show(this,
\r
2500 "HandBrake has determined your built-in presets are out of date... These presets will now be updated.",
\r
2501 "Preset Update", MessageBoxButtons.OK, MessageBoxIcon.Information);
\r
2503 // Clear the old presets
\r
2504 treeView_presets.Nodes.Clear();
\r
2507 string category = string.Empty; // The category we are currnetly processing
\r
2508 TreeNode rootNode = null;
\r
2509 foreach (Preset preset in this.presetHandler.Presets.Where(p => p.IsBuildIn))
\r
2511 // If the category of this preset doesn't match the current category we are processing
\r
2512 // Then we need to create a new root node.
\r
2513 if (preset.Category != category)
\r
2515 rootNode = new TreeNode(preset.Category) { ForeColor = Color.DarkBlue };
\r
2516 treeView_presets.Nodes.Add(rootNode);
\r
2517 category = preset.Category;
\r
2520 if (preset.Category == category && rootNode != null)
\r
2521 rootNode.Nodes.Add(new TreeNode(preset.Name) { ToolTipText = preset.Description, ForeColor = Color.DarkBlue });
\r
2526 foreach (Preset preset in this.presetHandler.Presets.Where(p => !p.IsBuildIn)) // User Presets
\r
2528 if (preset.Category != category && preset.Category != string.Empty)
\r
2530 rootNode = new TreeNode(preset.Category) { ForeColor = Color.Black };
\r
2531 treeView_presets.Nodes.Add(rootNode);
\r
2532 category = preset.Category;
\r
2535 if (preset.Category == category && rootNode != null)
\r
2536 rootNode.Nodes.Add(new TreeNode(preset.Name) { ForeColor = Color.Black, ToolTipText = preset.Description });
\r
2538 treeView_presets.Nodes.Add(new TreeNode(preset.Name) { ForeColor = Color.Black, ToolTipText = preset.Description });
\r
2541 treeView_presets.Update();
\r
2545 /// Get the title from the selected item in the title dropdown.
\r
2550 private int GetTitle()
\r
2553 if (drp_dvdtitle.SelectedItem != null)
\r
2555 string[] titleInfo = drp_dvdtitle.SelectedItem.ToString().Split(' ');
\r
2556 int.TryParse(titleInfo[0], out title);
\r
2563 /// Handle the Update Check Finishing.
\r
2565 /// <param name="result">
\r
2568 private void UpdateCheckDoneMenu(IAsyncResult result)
\r
2570 // Make sure it's running on the calling thread
\r
2571 if (InvokeRequired)
\r
2573 Invoke(new MethodInvoker(() => this.UpdateCheckDoneMenu(result)));
\r
2576 UpdateCheckInformation info;
\r
2579 // Get the information about the new build, if any, and close the window
\r
2580 info = UpdateService.EndCheckForUpdates(result);
\r
2582 if (info.NewVersionAvailable && info.BuildInformation != null)
\r
2584 UpdateInfo updateWindow = new UpdateInfo(info.BuildInformation, Settings.Default.hb_version, Settings.Default.hb_build.ToString());
\r
2585 updateWindow.ShowDialog();
\r
2588 MessageBox.Show("There are no new updates at this time.", "Update Check", MessageBoxButtons.OK,
\r
2589 MessageBoxIcon.Information);
\r
2590 lbl_updateCheck.Visible = false;
\r
2593 catch (Exception ex)
\r
2595 if ((bool)result.AsyncState)
\r
2597 "Unable to check for updates, Please try again later.\n\nDetailed Error Information:\n" + ex,
\r
2598 "Error", MessageBoxButtons.OK, MessageBoxIcon.Error);
\r
2607 /// Handle GUI shortcuts
\r
2609 /// <param name="msg">Message</param>
\r
2610 /// <param name="keyData">Keys</param>
\r
2611 /// <returns>Bool</returns>
\r
2612 protected override bool ProcessCmdKey(ref Message msg, Keys keyData)
\r
2614 if (keyData == (Keys.Control | Keys.S))
\r
2616 btn_start_Click(this, new EventArgs());
\r
2620 if (keyData == (Keys.Control | Keys.Shift | Keys.A))
\r
2622 btn_add2Queue_Click(this, new EventArgs());
\r
2625 return base.ProcessCmdKey(ref msg, keyData);
\r
2629 /// If the queue is being processed, prompt the user to confirm application close.
\r
2631 /// <param name="e">FormClosingEventArgs</param>
\r
2632 protected override void OnFormClosing(FormClosingEventArgs e)
\r
2636 // If currently encoding, the queue isn't paused, and there are queue items to process, prompt to confirm close.
\r
2637 if (this.queueProcessor.EncodeService.IsEncoding)
\r
2639 DialogResult result =
\r
2641 "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
2642 "Close HandBrake?",
\r
2643 MessageBoxButtons.YesNo,
\r
2644 MessageBoxIcon.Question);
\r
2646 if (result == DialogResult.No)
\r
2652 this.queueProcessor.Pause();
\r
2653 this.queueProcessor.EncodeService.Stop();
\r
2656 if (SourceScan.IsScanning)
\r
2658 SourceScan.Stop();
\r
2661 SourceScan.ScanCompleted -= this.SourceScanScanCompleted;
\r
2662 SourceScan.ScanStatusChanged -= this.SourceScanScanStatusChanged;
\r
2664 catch (Exception exc)
\r
2666 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
2670 base.OnFormClosing(e);
\r
2676 // This is the END of the road ****************************************
\r