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
15 using System.Threading;
\r
16 using System.Windows.Forms;
\r
19 using HandBrake.ApplicationServices.EventArgs;
\r
20 using HandBrake.Framework.Model;
\r
21 using HandBrake.Framework.Services;
\r
22 using HandBrake.Framework.Views;
\r
23 using HandBrake.ApplicationServices.Functions;
\r
24 using HandBrake.ApplicationServices.Model;
\r
25 using HandBrake.ApplicationServices.Parsing;
\r
26 using HandBrake.ApplicationServices.Services;
\r
27 using HandBrake.ApplicationServices.Services.Interfaces;
\r
29 using Handbrake.ToolWindows;
\r
35 using Main = Handbrake.Functions.Main;
\r
40 public partial class frmMain : Form
\r
42 // Objects which may be used by one or more other objects *************
\r
43 private IQueueProcessor queueProcessor = new QueueProcessor(Program.InstanceId);
\r
44 private PresetsHandler presetHandler = new PresetsHandler();
\r
46 // Windows ************************************************************
\r
47 private frmQueue queueWindow;
\r
48 private frmPreview qtpreview;
\r
49 private frmActivityWindow activityWindow;
\r
51 // Globals: Mainly used for tracking. *********************************
\r
52 public Title selectedTitle;
\r
53 public string sourcePath;
\r
54 private SourceType selectedSourceType;
\r
55 private string dvdDrivePath;
\r
56 private string dvdDriveLabel;
\r
57 private Preset currentlySelectedPreset;
\r
58 private Source currentSource;
\r
60 private IScan SourceScan;
\r
61 private List<DriveInformation> drives;
\r
62 private QueueTask queueEdit;
\r
64 // Delegates **********************************************************
\r
65 private delegate void UpdateWindowHandler();
\r
67 // Applicaiton Startup ************************************************
\r
72 /// Gets SourceName.
\r
74 public string SourceName
\r
78 if (this.selectedSourceType == SourceType.DvdDrive)
\r
80 return this.dvdDriveLabel;
\r
83 if (selectedTitle != null && !string.IsNullOrEmpty(selectedTitle.SourceName))
\r
85 return Path.GetFileName(selectedTitle.SourceName);
\r
88 // We have a drive, selected as a folder.
\r
89 if (this.sourcePath.EndsWith("\\"))
\r
91 drives = UtilityService.GetDrives();
\r
92 foreach (DriveInformation item in drives)
\r
94 if (item.RootDirectory.Contains(this.sourcePath))
\r
96 return item.VolumeLabel;
\r
101 if (Path.GetFileNameWithoutExtension(this.sourcePath) != "VIDEO_TS")
\r
102 return Path.GetFileNameWithoutExtension(this.sourcePath);
\r
104 return Path.GetFileNameWithoutExtension(Path.GetDirectoryName(this.sourcePath));
\r
110 #region Application Startup
\r
113 /// Initializes a new instance of the <see cref="frmMain"/> class.
\r
115 /// <param name="args">
\r
116 /// The arguments passed in on application startup.
\r
118 public frmMain(string[] args)
\r
120 InitializeComponent();
\r
122 // We can use LibHB, if the library hb.dll exists.
\r
123 this.SourceScan = File.Exists("hb.dll") ? (IScan)new LibScan() : new ScanService();
\r
125 // Update the users config file with the CLI version data.
\r
126 Main.SetCliVersionData();
\r
128 if (Settings.Default.hb_version.Contains("svn"))
\r
130 this.Text += " " + Settings.Default.hb_version;
\r
133 // Check for new versions, if update checking is enabled
\r
134 if (Settings.Default.updateStatus)
\r
136 if (DateTime.Now.Subtract(Settings.Default.lastUpdateCheckDate).TotalDays > Properties.Settings.Default.daysBetweenUpdateCheck)
\r
138 // Set when the last update was
\r
139 Settings.Default.lastUpdateCheckDate = DateTime.Now;
\r
140 Settings.Default.Save();
\r
141 string url = Settings.Default.hb_build.ToString().EndsWith("1")
\r
142 ? Settings.Default.appcast_unstable
\r
143 : Settings.Default.appcast;
\r
144 UpdateService.BeginCheckForUpdates(new AsyncCallback(UpdateCheckDone), false, url, Settings.Default.hb_build, Settings.Default.skipversion, Settings.Default.hb_version);
\r
148 // Clear the log files in the background
\r
149 if (Settings.Default.clearOldLogs)
\r
151 Thread clearLog = new Thread(() => UtilityService.ClearLogFiles(30));
\r
155 // Setup the GUI components
\r
156 LoadPresetPanel(); // Load the Preset Panel
\r
157 treeView_presets.ExpandAll();
\r
158 lbl_encode.Text = string.Empty;
\r
159 drop_mode.SelectedIndex = 0;
\r
160 queueWindow = new frmQueue(this.queueProcessor, this); // Prepare the Queue
\r
161 if (!Settings.Default.QueryEditorTab)
\r
162 tabs_panel.TabPages.RemoveAt(7); // Remove the query editor tab if the user does not want it enabled.
\r
163 if (Settings.Default.tooltipEnable)
\r
164 ToolTip.Active = true;
\r
166 // Load the user's default settings or Normal Preset
\r
167 if (Settings.Default.defaultPreset != string.Empty && presetHandler.GetPreset(Properties.Settings.Default.defaultPreset) != null)
\r
169 string query = presetHandler.GetPreset(Settings.Default.defaultPreset).Query;
\r
172 x264Panel.Reset2Defaults();
\r
174 QueryParser presetQuery = QueryParser.Parse(query);
\r
175 PresetLoader.LoadPreset(this, presetQuery, Settings.Default.defaultPreset);
\r
177 x264Panel.StandardizeOptString();
\r
178 x264Panel.SetCurrentSettingsInPanel();
\r
182 loadNormalPreset();
\r
184 // Register with Growl (if not using Growl for the encoding completion action, this wont hurt anything)
\r
185 GrowlCommunicator.Register();
\r
187 // Event Handlers and Queue Recovery
\r
189 Main.RecoverQueue(this.queueProcessor);
\r
191 // If have a file passed in via command arguemtents, check it's a file and try scanning it.
\r
192 if (args.Length >= 1 && (File.Exists(args[0]) || Directory.Exists(args[0])))
\r
194 this.StartScan(args[0], 0);
\r
199 /// When the update check is done, process the results.
\r
201 /// <param name="result">IAsyncResult result</param>
\r
202 private void UpdateCheckDone(IAsyncResult result)
\r
204 if (InvokeRequired)
\r
206 Invoke(new MethodInvoker(() => UpdateCheckDone(result)));
\r
212 UpdateCheckInformation info = UpdateService.EndCheckForUpdates(result);
\r
214 if (info.NewVersionAvailable)
\r
216 UpdateInfo updateWindow = new UpdateInfo(info.BuildInformation, Settings.Default.hb_version, Settings.Default.hb_build.ToString());
\r
217 updateWindow.ShowDialog();
\r
220 catch (Exception ex)
\r
222 if ((bool)result.AsyncState)
\r
223 Main.ShowExceptiowWindow("Unable to check for updates, Please try again later.", ex.ToString());
\r
231 // Encoding Events for setting up the GUI
\r
232 private void events()
\r
234 // Handle Widget changes when preset is selected.
\r
235 RegisterPresetEventHandler();
\r
237 // Handle Window Resize
\r
238 if (Settings.Default.MainWindowMinimize)
\r
239 this.Resize += this.frmMain_Resize;
\r
241 // Handle Encode Start / Finish / Pause
\r
242 this.queueProcessor.EncodeService.EncodeStarted += this.encodeStarted;
\r
243 this.queueProcessor.EncodeService.EncodeCompleted += encodeEnded;
\r
245 // Scan Started and Completed Events
\r
246 SourceScan.ScanStatusChanged += this.SourceScanScanStatusChanged;
\r
247 SourceScan.ScanCompleted += this.SourceScanScanCompleted;
\r
249 // Handle a file being draged onto the GUI.
\r
250 this.DragEnter += frmMain_DragEnter;
\r
251 this.DragDrop += this.frmMain_DragDrop;
\r
254 // Change the preset label to custom when a user changes a setting. Don't want to give the impression that users can change settings and still be using a preset
\r
255 private void RegisterPresetEventHandler()
\r
258 drop_format.SelectedIndexChanged += this.changePresetLabel;
\r
259 check_largeFile.CheckedChanged += this.changePresetLabel;
\r
260 check_iPodAtom.CheckedChanged += this.changePresetLabel;
\r
261 check_optimiseMP4.CheckedChanged += this.changePresetLabel;
\r
263 // Picture Settings
\r
264 PictureSettings.PictureSettingsChanged += this.changePresetLabel;
\r
267 Filters.FilterSettingsChanged += this.changePresetLabel;
\r
270 drp_videoEncoder.SelectedIndexChanged += this.changePresetLabel;
\r
271 check_2PassEncode.CheckedChanged += this.changePresetLabel;
\r
272 check_turbo.CheckedChanged += this.changePresetLabel;
\r
273 text_filesize.TextChanged += this.changePresetLabel;
\r
274 text_bitrate.TextChanged += this.changePresetLabel;
\r
275 slider_videoQuality.ValueChanged += this.changePresetLabel;
\r
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_filesize.TextChanged -= this.changePresetLabel;
\r
303 text_bitrate.TextChanged -= this.changePresetLabel;
\r
304 slider_videoQuality.ValueChanged -= this.changePresetLabel;
\r
307 AudioSettings.AudioListChanged -= this.changePresetLabel;
\r
310 x264Panel.rtf_x264Query.TextChanged -= this.changePresetLabel;
\r
313 private void changePresetLabel(object sender, EventArgs e)
\r
315 labelPreset.Text = "Output Settings (Preset: Custom)";
\r
316 this.currentlySelectedPreset = null;
\r
319 private static void frmMain_DragEnter(object sender, DragEventArgs e)
\r
321 if (e.Data.GetDataPresent(DataFormats.FileDrop, false))
\r
322 e.Effect = DragDropEffects.All;
\r
325 private void frmMain_DragDrop(object sender, DragEventArgs e)
\r
327 string[] fileList = e.Data.GetData(DataFormats.FileDrop) as string[];
\r
328 sourcePath = string.Empty;
\r
330 if (fileList != null)
\r
332 if (!string.IsNullOrEmpty(fileList[0]))
\r
334 this.selectedSourceType = SourceType.VideoFile;
\r
335 StartScan(fileList[0], 0);
\r
338 UpdateSourceLabel();
\r
341 UpdateSourceLabel();
\r
344 private void encodeStarted(object sender, EventArgs e)
\r
346 SetEncodeStarted();
\r
347 this.queueProcessor.EncodeService.EncodeStatusChanged += EncodeQueue_EncodeStatusChanged;
\r
350 private void encodeEnded(object sender, EventArgs e)
\r
352 this.queueProcessor.EncodeService.EncodeStatusChanged -= EncodeQueue_EncodeStatusChanged;
\r
353 SetEncodeFinished();
\r
357 // User Interface Menus / Tool Strips *********************************
\r
362 /// Kill The scan menu Item
\r
364 /// <param name="sender">
\r
367 /// <param name="e">
\r
370 private void mnu_killCLI_Click(object sender, EventArgs e)
\r
376 /// Exit the Application Menu Item
\r
378 /// <param name="sender">
\r
381 /// <param name="e">
\r
384 private void mnu_exit_Click(object sender, EventArgs e)
\r
386 Application.Exit();
\r
394 /// Menu - Start Button
\r
396 /// <param name="sender">
\r
399 /// <param name="e">
\r
402 private void mnu_encode_Click(object sender, EventArgs e)
\r
404 queueWindow.Show();
\r
408 /// Menu - Display the Log Window
\r
410 /// <param name="sender">
\r
413 /// <param name="e">
\r
416 private void mnu_encodeLog_Click(object sender, EventArgs e)
\r
418 this.btn_ActivityWindow_Click(this, null);
\r
422 /// Menu - Display the Options Window
\r
424 /// <param name="sender">
\r
427 /// <param name="e">
\r
430 private void mnu_options_Click(object sender, EventArgs e)
\r
432 Form options = new frmOptions(this);
\r
433 options.ShowDialog();
\r
438 #region Presets Menu
\r
441 /// Reset the Built in Presets
\r
443 /// <param name="sender">
\r
446 /// <param name="e">
\r
449 private void mnu_presetReset_Click(object sender, EventArgs e)
\r
451 presetHandler.UpdateBuiltInPresets();
\r
453 if (treeView_presets.Nodes.Count == 0)
\r
455 "Unable to load the presets.xml file. Please select \"Update Built-in Presets\" from the Presets Menu. \nMake sure you are running the program in Admin mode if running on Vista. See Windows FAQ for details!",
\r
456 "Error", MessageBoxButtons.OK, MessageBoxIcon.Error);
\r
458 MessageBox.Show("Presets have been updated!", "Alert", MessageBoxButtons.OK, MessageBoxIcon.Information);
\r
460 treeView_presets.ExpandAll();
\r
464 /// Delete the selected preset
\r
466 /// <param name="sender">
\r
469 /// <param name="e">
\r
472 private void mnu_delete_preset_Click(object sender, EventArgs e)
\r
474 presetHandler.RemoveBuiltInPresets();
\r
475 LoadPresetPanel(); // Reload the preset panel
\r
479 /// Select the Normal preset
\r
481 /// <param name="sender">
\r
484 /// <param name="e">
\r
487 private void mnu_SelectDefault_Click(object sender, EventArgs e)
\r
489 loadNormalPreset();
\r
493 /// Import a plist Preset
\r
495 /// <param name="sender">
\r
498 /// <param name="e">
\r
501 private void mnu_importMacPreset_Click(object sender, EventArgs e)
\r
507 /// Export a Plist Preset
\r
509 /// <param name="sender">
\r
512 /// <param name="e">
\r
515 private void mnu_exportMacPreset_Click(object sender, EventArgs e)
\r
521 /// Create a new Preset
\r
523 /// <param name="sender">
\r
526 /// <param name="e">
\r
529 private void btn_new_preset_Click(object sender, EventArgs e)
\r
531 Form preset = new frmAddPreset(this, presetHandler);
\r
532 if (preset.ShowDialog() == DialogResult.OK)
\r
534 TreeNode presetTreeview = new TreeNode(presetHandler.LastPresetAdded.Name) { ForeColor = Color.Black };
\r
535 treeView_presets.Nodes.Add(presetTreeview);
\r
536 presetHandler.LastPresetAdded = null;
\r
545 /// Menu - Display the User Guide Web Page
\r
547 /// <param name="sender">
\r
550 /// <param name="e">
\r
553 private void mnu_user_guide_Click(object sender, EventArgs e)
\r
555 Process.Start("http://trac.handbrake.fr/wiki/HandBrakeGuide");
\r
559 /// Menu - Check for Updates
\r
561 /// <param name="sender">
\r
564 /// <param name="e">
\r
567 private void mnu_UpdateCheck_Click(object sender, EventArgs e)
\r
569 lbl_updateCheck.Visible = true;
\r
570 Settings.Default.lastUpdateCheckDate = DateTime.Now;
\r
571 Settings.Default.Save();
\r
572 string url = Settings.Default.hb_build.ToString().EndsWith("1")
\r
573 ? Settings.Default.appcast_unstable
\r
574 : Settings.Default.appcast;
\r
575 UpdateService.BeginCheckForUpdates(new AsyncCallback(UpdateCheckDoneMenu), false, url, Settings.Default.hb_build, Settings.Default.skipversion, Settings.Default.hb_version);
\r
579 /// Menu - Display the About Window
\r
581 /// <param name="sender">
\r
584 /// <param name="e">
\r
587 private void mnu_about_Click(object sender, EventArgs e)
\r
589 using (frmAbout About = new frmAbout())
\r
591 About.ShowDialog();
\r
600 /// RMenu - Expand All
\r
602 /// <param name="sender">
\r
605 /// <param name="e">
\r
608 private void pmnu_expandAll_Click(object sender, EventArgs e)
\r
610 treeView_presets.ExpandAll();
\r
614 /// RMenu - Collaspe All
\r
616 /// <param name="sender">
\r
619 /// <param name="e">
\r
622 private void pmnu_collapse_Click(object sender, EventArgs e)
\r
624 treeView_presets.CollapseAll();
\r
628 /// Menu - Import Preset
\r
630 /// <param name="sender">
\r
633 /// <param name="e">
\r
636 private void pmnu_import_Click(object sender, EventArgs e)
\r
642 /// RMenu - Save Changes to Preset
\r
644 /// <param name="sender">
\r
647 /// <param name="e">
\r
650 private void pmnu_saveChanges_Click(object sender, EventArgs e)
\r
652 // TODO this requires a re-think since the Query Editor has changed.
\r
653 DialogResult result =
\r
655 "Do you wish to include picture settings when updating the preset: " +
\r
656 treeView_presets.SelectedNode.Text, "Update Preset", MessageBoxButtons.YesNoCancel,
\r
657 MessageBoxIcon.Question);
\r
658 if (result == DialogResult.Yes)
\r
659 presetHandler.Update(treeView_presets.SelectedNode.Text,
\r
660 QueryGenerator.GenerateQueryForPreset(this, QueryPictureSettingsMode.SourceMaximum, true, 0, 0), true);
\r
661 else if (result == DialogResult.No)
\r
662 presetHandler.Update(treeView_presets.SelectedNode.Text,
\r
663 QueryGenerator.GenerateQueryForPreset(this, QueryPictureSettingsMode.SourceMaximum, true, 0, 0), false);
\r
667 /// RMenu - Delete Preset
\r
669 /// <param name="sender">
\r
672 /// <param name="e">
\r
675 private void pmnu_delete_click(object sender, EventArgs e)
\r
677 if (treeView_presets.SelectedNode != null)
\r
679 presetHandler.Remove(treeView_presets.SelectedNode.Text);
\r
680 treeView_presets.Nodes.Remove(treeView_presets.SelectedNode);
\r
682 treeView_presets.Select();
\r
686 /// Preset Menu Is Opening. Setup the Menu
\r
688 /// <param name="sender">
\r
691 /// <param name="e">
\r
694 private void presets_menu_Opening(object sender, CancelEventArgs e)
\r
696 // Make sure that the save menu is always disabled by default
\r
697 pmnu_saveChanges.Enabled = false;
\r
699 // Now enable the save menu if the selected preset is a user preset
\r
700 if (treeView_presets.SelectedNode != null)
\r
701 if (presetHandler.CheckIfUserPresetExists(treeView_presets.SelectedNode.Text))
\r
702 pmnu_saveChanges.Enabled = true;
\r
704 treeView_presets.Select();
\r
707 // Presets Management
\r
710 /// Button - Add a preset
\r
712 /// <param name="sender">
\r
715 /// <param name="e">
\r
718 private void btn_addPreset_Click(object sender, EventArgs e)
\r
720 Form preset = new frmAddPreset(this, presetHandler);
\r
721 if (preset.ShowDialog() == DialogResult.OK)
\r
723 TreeNode presetTreeview = new TreeNode(presetHandler.LastPresetAdded.Name) { ForeColor = Color.Black };
\r
724 treeView_presets.Nodes.Add(presetTreeview);
\r
725 presetHandler.LastPresetAdded = null;
\r
730 /// Button - remove a Preset
\r
732 /// <param name="sender">
\r
735 /// <param name="e">
\r
738 private void btn_removePreset_Click(object sender, EventArgs e)
\r
740 DialogResult result = MessageBox.Show("Are you sure you wish to delete the selected preset?", "Preset",
\r
741 MessageBoxButtons.YesNo, MessageBoxIcon.Question);
\r
742 if (result == DialogResult.Yes)
\r
744 if (treeView_presets.SelectedNode != null)
\r
746 presetHandler.Remove(treeView_presets.SelectedNode.Text);
\r
747 treeView_presets.Nodes.Remove(treeView_presets.SelectedNode);
\r
750 treeView_presets.Select();
\r
754 /// Button - Set the selected preset as the default
\r
756 /// <param name="sender">
\r
759 /// <param name="e">
\r
762 private void btn_setDefault_Click(object sender, EventArgs e)
\r
764 if (treeView_presets.SelectedNode != null)
\r
766 DialogResult result = MessageBox.Show("Are you sure you wish to set this preset as the default?",
\r
767 "Preset", MessageBoxButtons.YesNo, MessageBoxIcon.Question);
\r
768 if (result == DialogResult.Yes)
\r
770 Properties.Settings.Default.defaultPreset = treeView_presets.SelectedNode.Text;
\r
771 Properties.Settings.Default.Save();
\r
772 MessageBox.Show("New default preset set.", "Alert", MessageBoxButtons.OK, MessageBoxIcon.Information);
\r
776 MessageBox.Show("Please select a preset first.", "Warning", MessageBoxButtons.OK, MessageBoxIcon.Warning);
\r
780 /// PresetBar Mouse Down event
\r
782 /// <param name="sender">
\r
785 /// <param name="e">
\r
788 private void treeview_presets_mouseUp(object sender, MouseEventArgs e)
\r
790 if (e.Button == MouseButtons.Right)
\r
791 treeView_presets.SelectedNode = treeView_presets.GetNodeAt(e.Location);
\r
792 else if (e.Button == MouseButtons.Left)
\r
794 if (treeView_presets.GetNodeAt(e.Location) != null)
\r
796 if (labelPreset.Text.Contains(treeView_presets.GetNodeAt(e.Location).Text))
\r
801 treeView_presets.Select();
\r
805 /// Preset Bar after selecting the preset
\r
807 /// <param name="sender">
\r
810 /// <param name="e">
\r
813 private void treeView_presets_AfterSelect(object sender, TreeViewEventArgs e)
\r
819 /// When the mouse moves, display a preset
\r
821 /// <param name="sender">The Sender</param>
\r
822 /// <param name="e">the MouseEventArgs</param>
\r
823 private void TreeViewPresetsMouseMove(object sender, MouseEventArgs e)
\r
825 TreeNode theNode = this.treeView_presets.GetNodeAt(e.X, e.Y);
\r
827 if ((theNode != null))
\r
829 // Change the ToolTip only if the pointer moved to a new node.
\r
830 if (theNode.ToolTipText != this.ToolTip.GetToolTip(this.treeView_presets))
\r
832 this.ToolTip.SetToolTip(this.treeView_presets, theNode.ToolTipText);
\r
835 else // Pointer is not over a node so clear the ToolTip.
\r
837 this.ToolTip.SetToolTip(this.treeView_presets, string.Empty);
\r
842 /// Preset Bar - Handle the Delete Key
\r
844 /// <param name="sender">
\r
847 /// <param name="e">
\r
850 private void treeView_presets_deleteKey(object sender, KeyEventArgs e)
\r
852 if (e.KeyCode == Keys.Delete)
\r
854 DialogResult result = MessageBox.Show("Are you sure you wish to delete the selected preset?", "Preset",
\r
855 MessageBoxButtons.YesNo, MessageBoxIcon.Question);
\r
856 if (result == DialogResult.Yes)
\r
858 if (treeView_presets.SelectedNode != null)
\r
859 presetHandler.Remove(treeView_presets.SelectedNode.Text);
\r
861 // Remember each nodes expanded status so we can reload it
\r
862 List<bool> nodeStatus = new List<bool>();
\r
863 foreach (TreeNode node in treeView_presets.Nodes)
\r
864 nodeStatus.Add(node.IsExpanded);
\r
866 // Now reload the preset panel
\r
869 // And finally, re-expand any of the nodes if required
\r
871 foreach (TreeNode node in treeView_presets.Nodes)
\r
883 /// Select the selected preset and setup the GUI
\r
885 private void selectPreset()
\r
887 if (treeView_presets.SelectedNode != null)
\r
889 // Ok, so, we've selected a preset. Now we want to load it.
\r
890 string presetName = treeView_presets.SelectedNode.Text;
\r
891 Preset preset = presetHandler.GetPreset(presetName);
\r
892 if (preset != null)
\r
894 string query = presetHandler.GetPreset(presetName).Query;
\r
898 // Ok, Reset all the H264 widgets before changing the preset
\r
899 x264Panel.Reset2Defaults();
\r
901 // Send the query from the file to the Query Parser class
\r
902 QueryParser presetQuery = QueryParser.Parse(query);
\r
904 // Now load the preset
\r
905 PresetLoader.LoadPreset(this, presetQuery, presetName);
\r
907 // The x264 widgets will need updated, so do this now:
\r
908 x264Panel.StandardizeOptString();
\r
909 x264Panel.SetCurrentSettingsInPanel();
\r
911 // Finally, let this window have a copy of the preset settings.
\r
912 this.currentlySelectedPreset = preset;
\r
913 PictureSettings.SetPresetCropWarningLabel(preset);
\r
920 /// Load the Normal Preset
\r
922 private void loadNormalPreset()
\r
924 foreach (TreeNode treenode in treeView_presets.Nodes)
\r
926 foreach (TreeNode node in treenode.Nodes)
\r
928 if (node.Text.Equals("Normal"))
\r
929 treeView_presets.SelectedNode = treeView_presets.Nodes[treenode.Index].Nodes[0];
\r
935 /// Import a plist preset
\r
937 private void ImportPreset()
\r
939 if (openPreset.ShowDialog() == DialogResult.OK)
\r
941 QueryParser parsed = PlistPresetHandler.Import(openPreset.FileName);
\r
942 if (presetHandler.CheckIfUserPresetExists(parsed.PresetName + " (Imported)"))
\r
944 DialogResult result =
\r
945 MessageBox.Show("This preset appears to already exist. Would you like to overwrite it?",
\r
946 "Overwrite preset?",
\r
947 MessageBoxButtons.YesNo, MessageBoxIcon.Warning);
\r
948 if (result == DialogResult.Yes)
\r
950 PresetLoader.LoadPreset(this, parsed, parsed.PresetName);
\r
951 presetHandler.Update(parsed.PresetName + " (Imported)",
\r
952 QueryGenerator.GenerateFullQuery(this),
\r
953 parsed.UsesPictureSettings);
\r
958 PresetLoader.LoadPreset(this, parsed, parsed.PresetName);
\r
959 if (presetHandler.Add(parsed.PresetName + " (Imported)",
\r
960 QueryGenerator.GenerateFullQuery(this),
\r
961 parsed.UsesPictureSettings, string.Empty))
\r
963 TreeNode preset_treeview = new TreeNode(parsed.PresetName + " (Imported)")
\r
965 ForeColor = Color.Black
\r
967 treeView_presets.Nodes.Add(preset_treeview);
\r
974 /// Export a plist Preset
\r
976 private void ExportPreset()
\r
978 SaveFileDialog savefiledialog = new SaveFileDialog { Filter = "plist|*.plist" };
\r
980 if (treeView_presets.SelectedNode != null)
\r
982 if (savefiledialog.ShowDialog() == DialogResult.OK)
\r
984 Preset preset = presetHandler.GetPreset(treeView_presets.SelectedNode.Text);
\r
985 PlistPresetHandler.Export(savefiledialog.FileName, preset);
\r
995 /// Toolbar - When the Source button is clicked, Clear any DVD drives and add any available DVD drives that can be used as a source.
\r
997 /// <param name="sender">
\r
1000 /// <param name="e">
\r
1003 private void btn_source_Click(object sender, EventArgs e)
\r
1005 // Remove old Drive Menu Items.
\r
1006 List<ToolStripMenuItem> itemsToRemove = new List<ToolStripMenuItem>();
\r
1007 foreach (var item in btn_source.DropDownItems)
\r
1009 if (item.GetType() == typeof(ToolStripMenuItem))
\r
1011 ToolStripMenuItem menuItem = (ToolStripMenuItem)item;
\r
1012 if (menuItem.Name.StartsWith("Drive"))
\r
1014 itemsToRemove.Add(menuItem);
\r
1019 foreach (ToolStripMenuItem item in itemsToRemove)
\r
1020 btn_source.DropDownItems.Remove(item);
\r
1022 Thread driveInfoThread = new Thread(SetDriveSelectionMenuItem);
\r
1023 driveInfoThread.Start();
\r
1027 /// Toolbar - Start The Encode
\r
1029 /// <param name="sender">
\r
1032 /// <param name="e">
\r
1035 private void btn_start_Click(object sender, EventArgs e)
\r
1037 if (btn_start.Text == "Stop")
\r
1039 DialogResult result = !Properties.Settings.Default.showCliForInGuiEncodeStatus
\r
1040 ? MessageBox.Show(
\r
1041 "Are you sure you wish to cancel the encode?\n\nPlease note: Stopping this encode will render the file unplayable. ",
\r
1043 MessageBoxButtons.YesNo,
\r
1044 MessageBoxIcon.Question)
\r
1045 : MessageBox.Show(
\r
1046 "Are you sure you wish to cancel the encode?",
\r
1048 MessageBoxButtons.YesNo,
\r
1049 MessageBoxIcon.Question);
\r
1051 if (result == DialogResult.Yes)
\r
1053 // Pause The Queue
\r
1054 this.queueProcessor.Pause();
\r
1056 if (Settings.Default.showCliForInGuiEncodeStatus)
\r
1057 this.queueProcessor.EncodeService.SafelyStop();
\r
1059 this.queueProcessor.EncodeService.Stop();
\r
1064 // If we have a custom query, then we'll want to figure out what the new source and destination is, otherwise we'll just use the gui components.
\r
1065 string jobSourcePath = !string.IsNullOrEmpty(rtf_query.Text) ? Main.GetSourceFromQuery(rtf_query.Text) : sourcePath;
\r
1066 string jobDestination = !string.IsNullOrEmpty(rtf_query.Text) ? Main.GetDestinationFromQuery(rtf_query.Text) : text_destination.Text;
\r
1068 if (this.queueProcessor.QueueManager.Count != 0 || (!string.IsNullOrEmpty(jobSourcePath) && !string.IsNullOrEmpty(jobDestination)))
\r
1070 string generatedQuery = QueryGenerator.GenerateFullQuery(this);
\r
1071 string specifiedQuery = rtf_query.Text != string.Empty
\r
1073 : QueryGenerator.GenerateFullQuery(this);
\r
1074 string query = string.Empty;
\r
1076 // Check to make sure the generated query matches the GUI settings
\r
1077 if (Properties.Settings.Default.PromptOnUnmatchingQueries && !string.IsNullOrEmpty(specifiedQuery) &&
\r
1078 generatedQuery != specifiedQuery)
\r
1080 DialogResult result = MessageBox.Show("The query under the \"Query Editor\" tab " +
\r
1081 "does not match the current GUI settings.\n\nBecause the manual query takes " +
\r
1082 "priority over the GUI, your recently updated settings will not be taken " +
\r
1083 "into account when encoding this job." +
\r
1084 Environment.NewLine + Environment.NewLine +
\r
1085 "Do you want to replace the manual query with the updated GUI-generated query?",
\r
1086 "Manual Query does not Match GUI",
\r
1087 MessageBoxButtons.YesNoCancel, MessageBoxIcon.Asterisk,
\r
1088 MessageBoxDefaultButton.Button3);
\r
1092 case DialogResult.Yes:
\r
1093 // Replace the manual query with the generated one
\r
1094 query = generatedQuery;
\r
1095 rtf_query.Text = generatedQuery;
\r
1097 case DialogResult.No:
\r
1098 // Use the manual query
\r
1099 query = specifiedQuery;
\r
1101 case DialogResult.Cancel:
\r
1102 // Don't start the encode
\r
1108 query = specifiedQuery;
\r
1111 DialogResult overwrite = DialogResult.Yes;
\r
1112 if (!string.IsNullOrEmpty(jobDestination) && File.Exists(jobDestination))
\r
1114 overwrite = MessageBox.Show(
\r
1115 "The destination file already exists. Are you sure you want to overwrite it?",
\r
1116 "Overwrite File?",
\r
1117 MessageBoxButtons.YesNo,
\r
1118 MessageBoxIcon.Question);
\r
1121 if (overwrite == DialogResult.Yes)
\r
1123 QueueTask task = new QueueTask(query)
\r
1125 Title = this.GetTitle(),
\r
1126 Source = jobSourcePath,
\r
1127 Destination = jobDestination,
\r
1128 CustomQuery = (this.rtf_query.Text != string.Empty)
\r
1131 if (this.queueProcessor.QueueManager.Count == 0)
\r
1132 this.queueProcessor.QueueManager.Add(task);
\r
1134 queueWindow.SetQueue();
\r
1135 if (this.queueProcessor.QueueManager.Count > 1)
\r
1136 queueWindow.Show(false);
\r
1138 SetEncodeStarted(); // Encode is running, so setup the GUI appropriately
\r
1139 this.queueProcessor.Start(); // Start The Queue Encoding Process
\r
1144 else if (string.IsNullOrEmpty(sourcePath) || string.IsNullOrEmpty(text_destination.Text))
\r
1145 MessageBox.Show("No source or destination selected.", "Warning", MessageBoxButtons.OK,
\r
1146 MessageBoxIcon.Warning);
\r
1151 /// Toolbar - Add the current job to the Queue
\r
1153 /// <param name="sender">
\r
1156 /// <param name="e">
\r
1159 private void btn_add2Queue_Click(object sender, EventArgs e)
\r
1161 // Add the item to the queue.
\r
1162 AddItemToQueue(true);
\r
1163 queueWindow.Show();
\r
1167 /// Add Multiple Items to the Queue at once.
\r
1169 /// <param name="sender">The Sender</param>
\r
1170 /// <param name="e">The EventArgs</param>
\r
1171 private void MnuAddMultiToQueueClick(object sender, EventArgs e)
\r
1173 if (!Settings.Default.autoNaming)
\r
1175 MessageBox.Show("Destination Auto Naming must be enabled in preferences for this feature to work.", "Error", MessageBoxButtons.OK, MessageBoxIcon.Error);
\r
1179 if (this.SourceScan.SouceData == null)
\r
1181 MessageBox.Show("You must first scan a source or collection of source to use this feature.", "Error", MessageBoxButtons.OK, MessageBoxIcon.Error);
\r
1185 BatchAdd batchAdd = new BatchAdd();
\r
1186 if (batchAdd.ShowDialog() == DialogResult.OK)
\r
1188 int min = batchAdd.Min;
\r
1189 int max = batchAdd.Max;
\r
1190 bool errors = false;
\r
1192 foreach (Title title in this.SourceScan.SouceData.Titles)
\r
1194 if (title.Duration.TotalMinutes > min && title.Duration.TotalMinutes < max)
\r
1197 this.drp_dvdtitle.SelectedItem = title;
\r
1199 if (!this.AddItemToQueue(false))
\r
1209 "One or more items could not be added to the queue. You should check your queue and manually add any missing jobs.",
\r
1211 MessageBoxButtons.OK,
\r
1212 MessageBoxIcon.Warning);
\r
1217 private bool AddItemToQueue(bool showError)
\r
1219 string query = QueryGenerator.GenerateFullQuery(this);
\r
1220 if (!string.IsNullOrEmpty(rtf_query.Text))
\r
1221 query = rtf_query.Text;
\r
1223 // If we have a custom query, then we'll want to figure out what the new source and destination is, otherwise we'll just use the gui components.
\r
1224 string jobSourcePath = !string.IsNullOrEmpty(rtf_query.Text) ? Main.GetSourceFromQuery(rtf_query.Text) : sourcePath;
\r
1225 string jobDestination = !string.IsNullOrEmpty(rtf_query.Text) ? Main.GetDestinationFromQuery(rtf_query.Text) : text_destination.Text;
\r
1227 // Make sure we have a Source and Destination.
\r
1228 if (string.IsNullOrEmpty(jobSourcePath) || string.IsNullOrEmpty(jobDestination))
\r
1231 MessageBox.Show("No source or destination selected.", "Warning", MessageBoxButtons.OK, MessageBoxIcon.Warning);
\r
1235 // Make sure the destination path exists.
\r
1236 if (!Directory.Exists(Path.GetDirectoryName(jobDestination)))
\r
1239 MessageBox.Show(string.Format("Destination Path does not exist.\nPath: {0}\n\nThis item was not added to the Queue.", Path.GetDirectoryName(jobDestination)), "Warning", MessageBoxButtons.OK, MessageBoxIcon.Warning);
\r
1243 // Make sure we don't have a duplciate on the queue.
\r
1244 if (this.queueProcessor.QueueManager.CheckForDestinationPathDuplicates(jobDestination))
\r
1248 DialogResult result;
\r
1252 "There is already a queue item for this destination path.\nDestination Path: {0} \n\nIf you continue, the encode will be overwritten. Do you wish to continue?",
\r
1255 MessageBoxButtons.YesNo,
\r
1256 MessageBoxIcon.Warning);
\r
1258 if (result != DialogResult.Yes) return false;
\r
1267 QueueTask task = new QueueTask(query)
\r
1269 Title = this.GetTitle(),
\r
1270 Source = jobSourcePath,
\r
1271 Destination = jobDestination,
\r
1272 CustomQuery = (this.rtf_query.Text != string.Empty)
\r
1274 this.queueProcessor.QueueManager.Add(task);
\r
1276 lbl_encode.Text = this.queueProcessor.QueueManager.Count + " encode(s) pending in the queue";
\r
1282 /// Toolbar - Show the Queue
\r
1284 /// <param name="sender">
\r
1287 /// <param name="e">
\r
1290 private void btn_showQueue_Click(object sender, EventArgs e)
\r
1292 queueWindow.Show();
\r
1293 queueWindow.Activate();
\r
1297 /// Toolbar - Show the Preview Window
\r
1299 /// <param name="sender">
\r
1302 /// <param name="e">
\r
1305 private void tb_preview_Click(object sender, EventArgs e)
\r
1307 if (string.IsNullOrEmpty(sourcePath) || string.IsNullOrEmpty(text_destination.Text))
\r
1308 MessageBox.Show("No source or destination selected.", "Warning", MessageBoxButtons.OK,
\r
1309 MessageBoxIcon.Warning);
\r
1312 if (qtpreview == null)
\r
1314 qtpreview = new frmPreview(this);
\r
1317 else if (qtpreview.IsDisposed)
\r
1319 qtpreview = new frmPreview(this);
\r
1323 MessageBox.Show(qtpreview, "The preview window is already open!", "Warning", MessageBoxButtons.OK,
\r
1324 MessageBoxIcon.Warning);
\r
1329 /// Toolbar - Show the Activity log Window
\r
1331 /// <param name="sender">
\r
1334 /// <param name="e">
\r
1337 private void btn_ActivityWindow_Click(object sender, EventArgs e)
\r
1339 if (this.activityWindow == null || !this.activityWindow.IsHandleCreated)
\r
1340 this.activityWindow = new frmActivityWindow(this.queueProcessor.EncodeService, SourceScan);
\r
1342 this.activityWindow.Show();
\r
1343 this.activityWindow.Activate();
\r
1348 #region System Tray Icon
\r
1351 /// Handle Resizing of the main window when deaing with the Notify Icon
\r
1353 /// <param name="sender">
\r
1356 /// <param name="e">
\r
1359 private void frmMain_Resize(object sender, EventArgs e)
\r
1361 if (FormWindowState.Minimized == this.WindowState)
\r
1363 notifyIcon.Visible = true;
\r
1366 else if (FormWindowState.Normal == this.WindowState)
\r
1367 notifyIcon.Visible = false;
\r
1371 /// Double Click the Tray Icon
\r
1373 /// <param name="sender">
\r
1376 /// <param name="e">
\r
1379 private void notifyIcon_MouseDoubleClick(object sender, MouseEventArgs e)
\r
1381 this.Visible = true;
\r
1383 this.WindowState = FormWindowState.Normal;
\r
1384 notifyIcon.Visible = false;
\r
1388 /// Tray Icon - Restore Menu Item - Resture the Window
\r
1390 /// <param name="sender">
\r
1393 /// <param name="e">
\r
1396 private void btn_restore_Click(object sender, EventArgs e)
\r
1398 this.Visible = true;
\r
1400 this.WindowState = FormWindowState.Normal;
\r
1401 notifyIcon.Visible = false;
\r
1406 #region Main Window and Tab Control
\r
1409 private void BtnFolderScanClicked(object sender, EventArgs e)
\r
1411 this.btn_source.HideDropDown();
\r
1412 if (DVD_Open.ShowDialog() == DialogResult.OK)
\r
1414 this.selectedSourceType = SourceType.Folder;
\r
1415 SelectSource(DVD_Open.SelectedPath, 0);
\r
1418 UpdateSourceLabel();
\r
1421 private void BtnFileScanClicked(object sender, EventArgs e)
\r
1423 this.btn_source.HideDropDown();
\r
1424 if (ISO_Open.ShowDialog() == DialogResult.OK)
\r
1426 this.selectedSourceType = SourceType.VideoFile;
\r
1427 SelectSource(ISO_Open.FileName, 0);
\r
1430 UpdateSourceLabel();
\r
1433 private void MnuDvdDriveClick(object sender, EventArgs e)
\r
1435 ToolStripMenuItem item = sender as ToolStripMenuItem;
\r
1438 string driveId = item.Name.Replace("Drive", string.Empty);
\r
1440 if (int.TryParse(driveId, out id))
\r
1442 this.dvdDrivePath = drives[id].RootDirectory;
\r
1443 this.dvdDriveLabel = drives[id].VolumeLabel;
\r
1445 if (this.dvdDrivePath == null) return;
\r
1446 this.selectedSourceType = SourceType.DvdDrive;
\r
1447 SelectSource(this.dvdDrivePath, 0);
\r
1452 private void VideoTitleSpecificScanClick(object sender, EventArgs e)
\r
1454 this.btn_source.HideDropDown();
\r
1455 if (ISO_Open.ShowDialog() == DialogResult.OK)
\r
1457 this.selectedSourceType = SourceType.VideoFile;
\r
1459 int sourceTitle = 0;
\r
1460 TitleSpecificScan title = new TitleSpecificScan();
\r
1461 if (title.ShowDialog() == DialogResult.OK)
\r
1463 sourceTitle = title.Title;
\r
1464 SelectSource(ISO_Open.FileName, sourceTitle);
\r
1468 UpdateSourceLabel();
\r
1471 private void FolderTitleSpecificScanClick(object sender, EventArgs e)
\r
1473 this.btn_source.HideDropDown();
\r
1474 if (DVD_Open.ShowDialog() == DialogResult.OK)
\r
1476 this.selectedSourceType = SourceType.Folder;
\r
1478 int sourceTitle = 0;
\r
1479 TitleSpecificScan title = new TitleSpecificScan();
\r
1480 if (title.ShowDialog() == DialogResult.OK)
\r
1482 sourceTitle = title.Title;
\r
1483 SelectSource(DVD_Open.SelectedPath, sourceTitle);
\r
1487 UpdateSourceLabel();
\r
1490 private void SelectSource(string file, int titleSpecific)
\r
1492 Check_ChapterMarkers.Enabled = true;
\r
1493 sourcePath = string.Empty;
\r
1495 if (file == string.Empty) // Must have a file or path
\r
1497 UpdateSourceLabel();
\r
1501 sourcePath = Path.GetFileName(file);
\r
1502 StartScan(file, titleSpecific);
\r
1505 private void drp_dvdtitle_Click(object sender, EventArgs e)
\r
1507 if ((drp_dvdtitle.Items.Count == 1) && (drp_dvdtitle.Items[0].ToString() == "Automatic"))
\r
1509 "There are no titles to select. Please load a source file by clicking the 'Source' button above before trying to select a title.",
\r
1510 "Alert", MessageBoxButtons.OK, MessageBoxIcon.Asterisk);
\r
1513 private void drp_dvdtitle_SelectedIndexChanged(object sender, EventArgs e)
\r
1515 UnRegisterPresetEventHandler();
\r
1516 drop_mode.SelectedIndex = 0;
\r
1518 drop_chapterStart.Items.Clear();
\r
1519 drop_chapterFinish.Items.Clear();
\r
1521 // If the dropdown is set to automatic nothing else needs to be done.
\r
1522 // Otheriwse if its not, title data has to be loaded from parsing.
\r
1523 if (drp_dvdtitle.Text != "Automatic")
\r
1525 selectedTitle = drp_dvdtitle.SelectedItem as Title;
\r
1526 lbl_duration.Text = selectedTitle.Duration.ToString();
\r
1527 PictureSettings.CurrentlySelectedPreset = this.currentlySelectedPreset;
\r
1528 PictureSettings.Source = selectedTitle; // Setup Picture Settings Tab Control
\r
1530 // Populate the Angles dropdown
\r
1531 drop_angle.Items.Clear();
\r
1532 if (!Properties.Settings.Default.noDvdNav)
\r
1534 drop_angle.Visible = true;
\r
1535 lbl_angle.Visible = true;
\r
1537 for (int i = 1; i <= selectedTitle.AngleCount; i++)
\r
1538 drop_angle.Items.Add(i.ToString());
\r
1540 if (drop_angle.Items.Count == 0)
\r
1542 drop_angle.Visible = false;
\r
1543 lbl_angle.Visible = false;
\r
1546 if (drop_angle.Items.Count != 0)
\r
1547 drop_angle.SelectedIndex = 0;
\r
1551 drop_angle.Visible = false;
\r
1552 lbl_angle.Visible = false;
\r
1555 // Populate the Start chapter Dropdown
\r
1556 drop_chapterStart.Items.Clear();
\r
1557 drop_chapterStart.Items.AddRange(selectedTitle.Chapters.ToArray());
\r
1558 if (drop_chapterStart.Items.Count > 0)
\r
1559 drop_chapterStart.Text = drop_chapterStart.Items[0].ToString();
\r
1561 // Populate the Final Chapter Dropdown
\r
1562 drop_chapterFinish.Items.Clear();
\r
1563 drop_chapterFinish.Items.AddRange(selectedTitle.Chapters.ToArray());
\r
1564 if (drop_chapterFinish.Items.Count > 0)
\r
1565 drop_chapterFinish.Text = drop_chapterFinish.Items[drop_chapterFinish.Items.Count - 1].ToString();
\r
1567 // Populate the Audio Channels Dropdown
\r
1568 AudioSettings.SetTrackListFromPreset(selectedTitle, this.currentlySelectedPreset);
\r
1570 // Populate the Subtitles dropdown
\r
1571 Subtitles.SetSubtitleTrackAuto(selectedTitle.Subtitles.ToArray());
\r
1573 // Update the source label if we have multiple streams
\r
1574 if (selectedTitle != null)
\r
1575 if (!string.IsNullOrEmpty(selectedTitle.SourceName))
\r
1576 labelSource.Text = Path.GetFileName(selectedTitle.SourceName);
\r
1578 // Run the AutoName & ChapterNaming functions
\r
1579 if (Properties.Settings.Default.autoNaming)
\r
1581 string autoPath = Main.AutoName(this);
\r
1582 if (autoPath != null)
\r
1583 text_destination.Text = autoPath;
\r
1586 "You currently have \"Automatically name output files\" enabled for the destination file box, but you do not have a valid default directory set.\n\nYou should set a \"Default Path\" in HandBrakes preferences. (See 'Tools' menu -> 'Options' -> 'General' Tab -> 'Default Path')",
\r
1587 "Warning", MessageBoxButtons.OK, MessageBoxIcon.Warning);
\r
1590 data_chpt.Rows.Clear();
\r
1591 if (selectedTitle.Chapters.Count != 1)
\r
1593 DataGridView chapterGridView = Main.ChapterNaming(selectedTitle, data_chpt, drop_chapterFinish.Text);
\r
1594 if (chapterGridView != null)
\r
1595 data_chpt = chapterGridView;
\r
1599 Check_ChapterMarkers.Checked = false;
\r
1600 Check_ChapterMarkers.Enabled = false;
\r
1603 // Hack to force the redraw of the scrollbars which don't resize properly when the control is disabled.
\r
1604 data_chpt.Columns[0].Width = 166;
\r
1605 data_chpt.Columns[0].Width = 165;
\r
1607 RegisterPresetEventHandler();
\r
1610 private void chapersChanged(object sender, EventArgs e)
\r
1612 if (drop_mode.SelectedIndex != 0) // Function is not used if we are not in chapters mode.
\r
1615 Control ctl = (Control)sender;
\r
1616 int chapterStart, chapterEnd;
\r
1617 int.TryParse(drop_chapterStart.Text, out chapterStart);
\r
1618 int.TryParse(drop_chapterFinish.Text, out chapterEnd);
\r
1622 case "drop_chapterStart":
\r
1623 if (drop_chapterFinish.SelectedIndex == -1 && drop_chapterFinish.Items.Count != 0)
\r
1624 drop_chapterFinish.SelectedIndex = drop_chapterFinish.Items.Count - 1;
\r
1626 if (chapterEnd != 0)
\r
1627 if (chapterStart > chapterEnd)
\r
1628 drop_chapterFinish.Text = chapterStart.ToString();
\r
1630 case "drop_chapterFinish":
\r
1631 if (drop_chapterStart.Items.Count >= 1 && drop_chapterStart.SelectedIndex == -1)
\r
1632 drop_chapterStart.SelectedIndex = 0;
\r
1634 if (chapterStart != 0)
\r
1635 if (chapterEnd < chapterStart)
\r
1636 drop_chapterFinish.Text = chapterStart.ToString();
\r
1638 // Add more rows to the Chapter menu if needed.
\r
1639 if (Check_ChapterMarkers.Checked)
\r
1641 int i = data_chpt.Rows.Count, finish = 0;
\r
1642 int.TryParse(drop_chapterFinish.Text, out finish);
\r
1644 while (i < finish)
\r
1646 int n = data_chpt.Rows.Add();
\r
1647 data_chpt.Rows[n].Cells[0].Value = (i + 1);
\r
1648 data_chpt.Rows[n].Cells[1].Value = "Chapter " + (i + 1);
\r
1649 data_chpt.Rows[n].Cells[0].ValueType = typeof(int);
\r
1650 data_chpt.Rows[n].Cells[1].ValueType = typeof(string);
\r
1657 // Update the Duration
\r
1658 lbl_duration.Text =
\r
1659 Main.CalculateDuration(drop_chapterStart.SelectedIndex, drop_chapterFinish.SelectedIndex, selectedTitle)
\r
1662 // Run the Autonaming function
\r
1663 if (Properties.Settings.Default.autoNaming)
\r
1664 text_destination.Text = Main.AutoName(this);
\r
1666 // Disable chapter markers if only 1 chapter is selected.
\r
1667 if (chapterStart == chapterEnd)
\r
1669 Check_ChapterMarkers.Enabled = false;
\r
1670 btn_importChapters.Enabled = false;
\r
1671 data_chpt.Enabled = false;
\r
1675 Check_ChapterMarkers.Enabled = true;
\r
1676 if (Check_ChapterMarkers.Checked)
\r
1678 btn_importChapters.Enabled = true;
\r
1679 data_chpt.Enabled = true;
\r
1684 private void SecondsOrFramesChanged(object sender, EventArgs e)
\r
1687 int.TryParse(drop_chapterStart.Text, out start);
\r
1688 int.TryParse(drop_chapterFinish.Text, out end);
\r
1689 double duration = end - start;
\r
1691 switch (drop_mode.SelectedIndex)
\r
1694 lbl_duration.Text = TimeSpan.FromSeconds(duration).ToString();
\r
1697 if (selectedTitle != null)
\r
1699 duration = duration / selectedTitle.Fps;
\r
1700 lbl_duration.Text = TimeSpan.FromSeconds(duration).ToString();
\r
1703 lbl_duration.Text = "--:--:--";
\r
1709 private void drop_mode_SelectedIndexChanged(object sender, EventArgs e)
\r
1712 this.drop_chapterFinish.TextChanged -= new EventHandler(this.SecondsOrFramesChanged);
\r
1713 this.drop_chapterStart.TextChanged -= new EventHandler(this.SecondsOrFramesChanged);
\r
1716 switch (drop_mode.SelectedIndex)
\r
1719 drop_chapterStart.DropDownStyle = ComboBoxStyle.DropDownList;
\r
1720 drop_chapterFinish.DropDownStyle = ComboBoxStyle.DropDownList;
\r
1721 if (drop_chapterStart.Items.Count != 0)
\r
1723 drop_chapterStart.SelectedIndex = 0;
\r
1724 drop_chapterFinish.SelectedIndex = drop_chapterFinish.Items.Count - 1;
\r
1727 lbl_duration.Text = "--:--:--";
\r
1730 this.drop_chapterStart.TextChanged += new EventHandler(this.SecondsOrFramesChanged);
\r
1731 this.drop_chapterFinish.TextChanged += new EventHandler(this.SecondsOrFramesChanged);
\r
1732 drop_chapterStart.DropDownStyle = ComboBoxStyle.Simple;
\r
1733 drop_chapterFinish.DropDownStyle = ComboBoxStyle.Simple;
\r
1734 if (selectedTitle != null)
\r
1736 drop_chapterStart.Text = "0";
\r
1737 drop_chapterFinish.Text = selectedTitle.Duration.TotalSeconds.ToString();
\r
1741 this.drop_chapterStart.TextChanged += new EventHandler(this.SecondsOrFramesChanged);
\r
1742 this.drop_chapterFinish.TextChanged += new EventHandler(this.SecondsOrFramesChanged);
\r
1743 drop_chapterStart.DropDownStyle = ComboBoxStyle.Simple;
\r
1744 drop_chapterFinish.DropDownStyle = ComboBoxStyle.Simple;
\r
1745 if (selectedTitle != null)
\r
1747 drop_chapterStart.Text = "0";
\r
1748 drop_chapterFinish.Text = (selectedTitle.Fps * selectedTitle.Duration.TotalSeconds).ToString();
\r
1755 private void btn_destBrowse_Click(object sender, EventArgs e)
\r
1757 // This removes the file extension from the filename box on the save file dialog.
\r
1758 // It's daft but some users don't realise that typing an extension overrides the dropdown extension selected.
\r
1759 DVD_Save.FileName = Path.GetFileNameWithoutExtension(text_destination.Text);
\r
1761 if (Path.IsPathRooted(text_destination.Text))
\r
1762 DVD_Save.InitialDirectory = Path.GetDirectoryName(text_destination.Text);
\r
1764 // Show the dialog and set the main form file path
\r
1765 if (drop_format.SelectedIndex.Equals(0))
\r
1766 DVD_Save.FilterIndex = 1;
\r
1767 else if (drop_format.SelectedIndex.Equals(1))
\r
1768 DVD_Save.FilterIndex = 2;
\r
1770 if (DVD_Save.ShowDialog() == DialogResult.OK)
\r
1772 // Add a file extension manually, as FileDialog.AddExtension has issues with dots in filenames
\r
1773 switch (DVD_Save.FilterIndex)
\r
1777 !Path.GetExtension(DVD_Save.FileName).Equals(".mp4",
\r
1778 StringComparison.InvariantCultureIgnoreCase))
\r
1779 if (Properties.Settings.Default.useM4v)
\r
1780 DVD_Save.FileName = DVD_Save.FileName.Replace(".mp4", ".m4v").Replace(".mkv", ".m4v");
\r
1782 DVD_Save.FileName = DVD_Save.FileName.Replace(".m4v", ".mp4").Replace(".mkv", ".mp4");
\r
1786 !Path.GetExtension(DVD_Save.FileName).Equals(".mkv", StringComparison.InvariantCultureIgnoreCase))
\r
1787 DVD_Save.FileName = DVD_Save.FileName.Replace(".mp4", ".mkv").Replace(".m4v", ".mkv");
\r
1793 text_destination.Text = DVD_Save.FileName;
\r
1795 // Quicktime requires .m4v file for chapter markers to work. If checked, change the extension to .m4v (mp4 and m4v are the same thing)
\r
1796 if (Check_ChapterMarkers.Checked && DVD_Save.FilterIndex != 2)
\r
1797 SetExtension(".m4v");
\r
1801 private void text_destination_TextChanged(object sender, EventArgs e)
\r
1803 string path = text_destination.Text;
\r
1804 if (path.EndsWith(".mp4") || path.EndsWith(".m4v"))
\r
1805 drop_format.SelectedIndex = 0;
\r
1806 else if (path.EndsWith(".mkv"))
\r
1807 drop_format.SelectedIndex = 1;
\r
1810 // Output Settings
\r
1811 private void drop_format_SelectedIndexChanged(object sender, EventArgs e)
\r
1813 switch (drop_format.SelectedIndex)
\r
1816 if (Properties.Settings.Default.useM4v || Check_ChapterMarkers.Checked ||
\r
1817 AudioSettings.RequiresM4V() || Subtitles.RequiresM4V())
\r
1818 SetExtension(".m4v");
\r
1820 SetExtension(".mp4");
\r
1823 SetExtension(".mkv");
\r
1827 AudioSettings.SetContainer(drop_format.Text);
\r
1829 if (drop_format.Text.Contains("MP4"))
\r
1831 if (drp_videoEncoder.Items.Contains("VP3 (Theora)"))
\r
1833 drp_videoEncoder.Items.Remove("VP3 (Theora)");
\r
1834 drp_videoEncoder.SelectedIndex = 1;
\r
1837 else if (drop_format.Text.Contains("MKV"))
\r
1838 drp_videoEncoder.Items.Add("VP3 (Theora)");
\r
1841 public void SetExtension(string newExtension)
\r
1843 if (newExtension == ".mp4" || newExtension == ".m4v")
\r
1844 if (Properties.Settings.Default.useM4v || Check_ChapterMarkers.Checked || AudioSettings.RequiresM4V() ||
\r
1845 Subtitles.RequiresM4V())
\r
1846 newExtension = ".m4v";
\r
1848 newExtension = ".mp4";
\r
1850 if (Path.HasExtension(newExtension))
\r
1851 text_destination.Text = Path.ChangeExtension(text_destination.Text, newExtension);
\r
1855 private void drp_videoEncoder_SelectedIndexChanged(object sender, EventArgs e)
\r
1857 setContainerOpts();
\r
1859 // Turn off some options which are H.264 only when the user selects a non h.264 encoder
\r
1860 if (drp_videoEncoder.Text.Contains("H.264"))
\r
1862 if (check_2PassEncode.CheckState == CheckState.Checked)
\r
1863 check_turbo.Enabled = true;
\r
1865 tab_advanced.Enabled = true;
\r
1866 if ((drop_format.Text.Contains("MP4")) || (drop_format.Text.Contains("M4V")))
\r
1867 check_iPodAtom.Enabled = true;
\r
1869 check_iPodAtom.Enabled = false;
\r
1873 check_turbo.CheckState = CheckState.Unchecked;
\r
1874 check_turbo.Enabled = false;
\r
1875 tab_advanced.Enabled = false;
\r
1876 x264Panel.X264Query = string.Empty;
\r
1877 check_iPodAtom.Enabled = false;
\r
1878 check_iPodAtom.Checked = false;
\r
1881 // Setup the CQ Slider
\r
1882 switch (drp_videoEncoder.Text)
\r
1884 case "MPEG-4 (FFmpeg)":
\r
1885 if (slider_videoQuality.Value > 31)
\r
1886 slider_videoQuality.Value = 20; // Just reset to 70% QP 10 on encode change.
\r
1887 slider_videoQuality.Minimum = 1;
\r
1888 slider_videoQuality.Maximum = 31;
\r
1890 case "H.264 (x264)":
\r
1891 slider_videoQuality.Minimum = 0;
\r
1892 slider_videoQuality.TickFrequency = 1;
\r
1894 CultureInfo culture = CultureInfo.CreateSpecificCulture("en-US");
\r
1895 double cqStep = Properties.Settings.Default.x264cqstep;
\r
1896 double multiplier = 1.0 / cqStep;
\r
1897 double value = slider_videoQuality.Value * multiplier;
\r
1899 slider_videoQuality.Maximum = (int)(51 / Properties.Settings.Default.x264cqstep);
\r
1901 if (value < slider_videoQuality.Maximum)
\r
1902 slider_videoQuality.Value = slider_videoQuality.Maximum - (int)value;
\r
1905 case "VP3 (Theora)":
\r
1906 if (slider_videoQuality.Value > 63)
\r
1907 slider_videoQuality.Value = 45; // Just reset to 70% QP 45 on encode change.
\r
1908 slider_videoQuality.Minimum = 0;
\r
1909 slider_videoQuality.Maximum = 63;
\r
1915 /// When the FrameRate is not Same As Source, show the Max/Constant Mode dropdown
\r
1917 /// <param name="sender">
\r
1920 /// <param name="e">
\r
1923 private void drp_videoFramerate_SelectedIndexChanged(object sender, EventArgs e)
\r
1925 if (this.drp_videoFramerate.SelectedIndex == 0)
\r
1927 this.checkMaximumFramerate.Visible = false;
\r
1928 this.checkMaximumFramerate.CheckState = CheckState.Unchecked;
\r
1932 this.checkMaximumFramerate.Visible = true;
\r
1937 /// Set the container format options
\r
1939 public void setContainerOpts()
\r
1941 if ((drop_format.Text.Contains("MP4")) || (drop_format.Text.Contains("M4V")))
\r
1943 check_largeFile.Enabled = true;
\r
1944 check_optimiseMP4.Enabled = true;
\r
1945 check_iPodAtom.Enabled = true;
\r
1949 check_largeFile.Enabled = false;
\r
1950 check_optimiseMP4.Enabled = false;
\r
1951 check_iPodAtom.Enabled = false;
\r
1952 check_largeFile.Checked = false;
\r
1953 check_optimiseMP4.Checked = false;
\r
1954 check_iPodAtom.Checked = false;
\r
1958 private double cachedCqStep = Properties.Settings.Default.x264cqstep;
\r
1961 /// Update the CQ slider for x264 for a new CQ step. This is set from option
\r
1963 public void setQualityFromSlider()
\r
1965 // Work out the current RF value.
\r
1966 double cqStep = this.cachedCqStep;
\r
1967 double rfValue = 51.0 - slider_videoQuality.Value * cqStep;
\r
1969 // Change the maximum value for the slider
\r
1970 slider_videoQuality.Maximum = (int)(51 / Properties.Settings.Default.x264cqstep);
\r
1972 // Reset the CQ slider to RF0
\r
1973 slider_videoQuality.Value = slider_videoQuality.Maximum;
\r
1975 // Reset the CQ slider back to the previous value as close as possible
\r
1976 double cqStepNew = Properties.Settings.Default.x264cqstep;
\r
1977 double rfValueCurrent = 51.0 - slider_videoQuality.Value * cqStepNew;
\r
1978 while (rfValueCurrent < rfValue)
\r
1980 slider_videoQuality.Value--;
\r
1981 rfValueCurrent = 51.0 - slider_videoQuality.Value * cqStepNew;
\r
1984 // Cache the CQ step for the next calculation
\r
1985 this.cachedCqStep = Properties.Settings.Default.x264cqstep;
\r
1988 private void slider_videoQuality_Scroll(object sender, EventArgs e)
\r
1990 double cqStep = Properties.Settings.Default.x264cqstep;
\r
1991 switch (drp_videoEncoder.Text)
\r
1993 case "MPEG-4 (FFmpeg)":
\r
1994 lbl_SliderValue.Text = "QP:" + (32 - slider_videoQuality.Value);
\r
1996 case "H.264 (x264)":
\r
1997 double rfValue = 51.0 - slider_videoQuality.Value * cqStep;
\r
1998 rfValue = Math.Round(rfValue, 2);
\r
1999 lbl_SliderValue.Text = "RF:" + rfValue.ToString(new CultureInfo("en-US"));
\r
2000 this.lbl_rfwarn.Visible = rfValue == 0;
\r
2002 case "VP3 (Theora)":
\r
2003 lbl_SliderValue.Text = "QP:" + slider_videoQuality.Value;
\r
2008 private void radio_targetFilesize_CheckedChanged(object sender, EventArgs e)
\r
2010 text_bitrate.Enabled = false;
\r
2011 text_filesize.Enabled = true;
\r
2012 slider_videoQuality.Enabled = false;
\r
2014 check_2PassEncode.Enabled = true;
\r
2017 private void radio_avgBitrate_CheckedChanged(object sender, EventArgs e)
\r
2019 text_bitrate.Enabled = true;
\r
2020 text_filesize.Enabled = false;
\r
2021 slider_videoQuality.Enabled = false;
\r
2023 check_2PassEncode.Enabled = true;
\r
2026 private void radio_cq_CheckedChanged(object sender, EventArgs e)
\r
2028 text_bitrate.Enabled = false;
\r
2029 text_filesize.Enabled = false;
\r
2030 slider_videoQuality.Enabled = true;
\r
2032 check_2PassEncode.Enabled = false;
\r
2033 check_2PassEncode.CheckState = CheckState.Unchecked;
\r
2036 private void check_2PassEncode_CheckedChanged(object sender, EventArgs e)
\r
2038 if (check_2PassEncode.CheckState.ToString() == "Checked")
\r
2040 if (drp_videoEncoder.Text.Contains("H.264"))
\r
2041 check_turbo.Enabled = true;
\r
2045 check_turbo.Enabled = false;
\r
2046 check_turbo.CheckState = CheckState.Unchecked;
\r
2050 // Chapter Marker Tab
\r
2051 private void Check_ChapterMarkers_CheckedChanged(object sender, EventArgs e)
\r
2053 if (Check_ChapterMarkers.Checked)
\r
2055 if (drop_format.SelectedIndex != 1)
\r
2056 SetExtension(".m4v");
\r
2057 data_chpt.Enabled = true;
\r
2058 btn_importChapters.Enabled = true;
\r
2062 if (drop_format.SelectedIndex != 1 && !Properties.Settings.Default.useM4v)
\r
2063 SetExtension(".mp4");
\r
2064 data_chpt.Enabled = false;
\r
2065 btn_importChapters.Enabled = false;
\r
2069 private void btn_importChapters_Click(object sender, EventArgs e)
\r
2071 if (File_ChapterImport.ShowDialog() == DialogResult.OK)
\r
2073 string filename = File_ChapterImport.FileName;
\r
2074 DataGridView imported = Main.ImportChapterNames(data_chpt, filename);
\r
2075 if (imported != null)
\r
2076 data_chpt = imported;
\r
2080 private void btn_export_Click(object sender, EventArgs e)
\r
2082 SaveFileDialog saveFileDialog = new SaveFileDialog();
\r
2083 saveFileDialog.Filter = "Csv File|*.csv";
\r
2084 saveFileDialog.DefaultExt = "csv";
\r
2085 if (saveFileDialog.ShowDialog() == DialogResult.OK)
\r
2087 string filename = saveFileDialog.FileName;
\r
2089 Main.SaveChapterMarkersToCsv(this, filename);
\r
2093 private void mnu_resetChapters_Click(object sender, EventArgs e)
\r
2095 data_chpt.Rows.Clear();
\r
2096 DataGridView chapterGridView = Main.ChapterNaming(selectedTitle, data_chpt, drop_chapterFinish.Text);
\r
2097 if (chapterGridView != null)
\r
2099 data_chpt = chapterGridView;
\r
2103 // Query Editor Tab
\r
2104 private void btn_generate_Query_Click(object sender, EventArgs e)
\r
2106 rtf_query.Text = QueryGenerator.GenerateFullQuery(this);
\r
2109 private void btn_clear_Click(object sender, EventArgs e)
\r
2111 rtf_query.Clear();
\r
2116 // MainWindow Components, Actions and Functions ***********************
\r
2118 #region Source Scan
\r
2121 /// Start the Scan Process
\r
2123 /// <param name="filename">
\r
2126 /// <param name="title">
\r
2129 private void StartScan(string filename, int title)
\r
2131 // Setup the GUI components for the scan.
\r
2132 sourcePath = filename;
\r
2134 this.DisableGUI();
\r
2139 SourceScan.Scan(sourcePath, title);
\r
2141 catch (Exception exc)
\r
2143 MessageBox.Show("frmMain.cs - StartScan " + exc, "Error", MessageBoxButtons.OK, MessageBoxIcon.Error);
\r
2148 /// Update the Status label for the scan
\r
2150 /// <param name="sender">
\r
2153 /// <param name="e">
\r
2156 private void SourceScanScanStatusChanged(object sender, ScanProgressEventArgs e)
\r
2158 if (this.InvokeRequired)
\r
2160 this.BeginInvoke(new ScanProgessStatus(this.SourceScanScanStatusChanged), new[] { sender, e });
\r
2164 labelSource.Text = string.Format("Processing Title: {0} of {1}", e.CurrentTitle, e.Titles);
\r
2168 /// Update the UI after the scan has completed
\r
2170 /// <param name="sender">
\r
2173 /// <param name="e">
\r
2176 private void SourceScanScanCompleted(object sender, EventArgs e)
\r
2178 if (this.InvokeRequired)
\r
2180 this.BeginInvoke(new ScanCompletedStatus(this.SourceScanScanCompleted), new[] { sender, e });
\r
2186 currentSource = SourceScan.SouceData;
\r
2188 // Setup some GUI components
\r
2189 drp_dvdtitle.Items.Clear();
\r
2190 if (currentSource.Titles.Count != 0)
\r
2191 drp_dvdtitle.Items.AddRange(currentSource.Titles.ToArray());
\r
2193 foreach (Title title in currentSource.Titles)
\r
2195 if (title.MainTitle)
\r
2197 drp_dvdtitle.SelectedItem = title;
\r
2201 if (drp_dvdtitle.SelectedItem == null && drp_dvdtitle.Items.Count > 0)
\r
2203 drp_dvdtitle.SelectedIndex = 0;
\r
2206 // Enable the creation of chapter markers if the file is an image of a dvd
\r
2207 if (drop_chapterStart.Items.Count > 0)
\r
2210 int.TryParse(drop_chapterStart.Items[0].ToString(), out start);
\r
2211 int.TryParse(drop_chapterFinish.Items[drop_chapterFinish.Items.Count - 1].ToString(), out end);
\r
2212 if (end > start) Check_ChapterMarkers.Enabled = true;
\r
2215 Check_ChapterMarkers.Enabled = false;
\r
2216 Check_ChapterMarkers.Checked = false;
\r
2217 data_chpt.Rows.Clear();
\r
2221 // If no titles were found, Display an error message
\r
2222 if (drp_dvdtitle.Items.Count == 0)
\r
2225 "No Title(s) found. \n\nYour Source may be copy protected, badly mastered or in a format which HandBrake does not support. \nPlease refer to the Documentation and FAQ (see Help Menu).",
\r
2226 "Error", MessageBoxButtons.OK, MessageBoxIcon.Hand);
\r
2227 sourcePath = string.Empty;
\r
2229 UpdateSourceLabel();
\r
2231 // This is a bit of a hack to fix the queue editing.
\r
2232 // If afte the scan, we find a job sitting in queueEdit, then the user has rescaned the source from the queue by clicking edit.
\r
2233 // When this occures, we want to repopulate their old settings.
\r
2234 if (queueEdit != null)
\r
2237 if (queueEdit.Query != null)
\r
2239 // Send the query from the file to the Query Parser class
\r
2240 QueryParser presetQuery = QueryParser.Parse(queueEdit.Query);
\r
2242 // Now load the preset
\r
2243 PresetLoader.LoadPreset(this, presetQuery, "Load Back From Queue");
\r
2245 // Set the destination path
\r
2246 this.text_destination.Text = queueEdit.Destination;
\r
2248 // The x264 widgets will need updated, so do this now:
\r
2249 x264Panel.StandardizeOptString();
\r
2250 x264Panel.SetCurrentSettingsInPanel();
\r
2252 // Set the crop label
\r
2253 PictureSettings.SetPresetCropWarningLabel(null);
\r
2259 // Enable the GUI components and enable any disabled components
\r
2262 catch (Exception exc)
\r
2264 MessageBox.Show("frmMain.cs - updateUIafterScan " + exc, "Error", MessageBoxButtons.OK,
\r
2265 MessageBoxIcon.Error);
\r
2271 /// Enable the GUI
\r
2273 private void EnableGUI()
\r
2277 if (InvokeRequired)
\r
2278 BeginInvoke(new UpdateWindowHandler(EnableGUI));
\r
2279 foreach (Control ctrl in Controls)
\r
2280 ctrl.Enabled = true;
\r
2281 btn_start.Enabled = true;
\r
2282 btn_showQueue.Enabled = true;
\r
2283 btn_add2Queue.Enabled = true;
\r
2284 tb_preview.Enabled = true;
\r
2285 btn_source.Enabled = true;
\r
2286 mnu_killCLI.Visible = false;
\r
2288 catch (Exception exc)
\r
2290 MessageBox.Show("frmMain.cs - EnableGUI() " + exc, "Error", MessageBoxButtons.OK, MessageBoxIcon.Error);
\r
2295 /// Disable the GUI
\r
2297 private void DisableGUI()
\r
2299 foreach (Control ctrl in Controls)
\r
2300 if (!(ctrl is StatusStrip || ctrl is MenuStrip || ctrl is ToolStrip))
\r
2301 ctrl.Enabled = false;
\r
2303 labelSource.Enabled = true;
\r
2304 labelStaticSource.Enabled = true;
\r
2305 SourceLayoutPanel.Enabled = true;
\r
2306 btn_source.Enabled = false;
\r
2307 btn_start.Enabled = false;
\r
2308 btn_showQueue.Enabled = false;
\r
2309 btn_add2Queue.Enabled = false;
\r
2310 tb_preview.Enabled = false;
\r
2311 mnu_killCLI.Visible = true;
\r
2317 private void KillScan()
\r
2319 SourceScan.ScanCompleted -= this.SourceScanScanCompleted;
\r
2323 SourceScan.Stop();
\r
2325 labelSource.Text = "Scan Cancelled";
\r
2331 private void ResetGUI()
\r
2333 drp_dvdtitle.Items.Clear();
\r
2334 drop_chapterStart.Items.Clear();
\r
2335 drop_chapterFinish.Items.Clear();
\r
2336 lbl_duration.Text = "Select a Title";
\r
2337 PictureSettings.lbl_src_res.Text = "Select a Title";
\r
2338 sourcePath = String.Empty;
\r
2339 text_destination.Text = String.Empty;
\r
2340 selectedTitle = null;
\r
2344 /// Update the Source Label
\r
2346 private void UpdateSourceLabel()
\r
2348 labelSource.Text = string.IsNullOrEmpty(sourcePath) ? "Select \"Source\" to continue." : this.SourceName;
\r
2352 /// Take a job from the Queue, rescan it, and reload the GUI for that job.
\r
2354 /// <param name="job">
\r
2357 public void RecievingJob(QueueTask job)
\r
2360 this.currentlySelectedPreset = null;
\r
2361 x264Panel.Reset2Defaults();
\r
2364 queueEdit = job; // Nasty but will do for now. TODO
\r
2365 StartScan(job.Source, job.Title);
\r
2370 #region GUI Functions and Actions
\r
2373 /// Set the GUI to it's finished encoding state.
\r
2375 private void SetEncodeFinished()
\r
2379 if (InvokeRequired)
\r
2381 BeginInvoke(new UpdateWindowHandler(SetEncodeFinished));
\r
2385 lbl_encode.Text = "Encoding Finished";
\r
2386 ProgressBarStatus.Visible = false;
\r
2387 btn_start.Text = "Start";
\r
2388 btn_start.ToolTipText = "Start the encoding process";
\r
2389 btn_start.Image = Properties.Resources.Play;
\r
2391 // If the window is minimized, display the notification in a popup.
\r
2392 if (Properties.Settings.Default.trayIconAlerts)
\r
2393 if (FormWindowState.Minimized == this.WindowState)
\r
2395 notifyIcon.BalloonTipText = lbl_encode.Text;
\r
2396 notifyIcon.ShowBalloonTip(500);
\r
2399 catch (Exception exc)
\r
2401 MessageBox.Show(exc.ToString());
\r
2406 /// Set the GUI to it's started encoding state.
\r
2408 private void SetEncodeStarted()
\r
2412 if (InvokeRequired)
\r
2414 BeginInvoke(new UpdateWindowHandler(SetEncodeStarted));
\r
2417 lbl_encode.Visible = true;
\r
2418 ProgressBarStatus.Value = 0;
\r
2419 ProgressBarStatus.Visible = true;
\r
2420 lbl_encode.Text = "Encoding with " + this.queueProcessor.QueueManager.Count + " encode(s) pending";
\r
2421 btn_start.Text = "Stop";
\r
2422 btn_start.ToolTipText = "Stop the encoding process.";
\r
2423 btn_start.Image = Properties.Resources.stop;
\r
2425 catch (Exception exc)
\r
2427 MessageBox.Show(exc.ToString());
\r
2432 /// Display the Encode Status
\r
2434 /// <param name="sender">
\r
2437 /// <param name="e">
\r
2440 private void EncodeQueue_EncodeStatusChanged(object sender, EncodeProgressEventArgs e)
\r
2442 if (this.InvokeRequired)
\r
2444 this.BeginInvoke(new EncodeProgessStatus(EncodeQueue_EncodeStatusChanged), new[] { sender, e });
\r
2450 "{0:00.00}%, FPS: {1:000.0}, Avg FPS: {2:000.0}, Time Remaining: {3}, Encode(s) Pending {4}",
\r
2451 e.PercentComplete,
\r
2452 e.CurrentFrameRate,
\r
2453 e.AverageFrameRate,
\r
2454 e.EstimatedTimeLeft,
\r
2455 this.queueProcessor.QueueManager.Count);
\r
2457 ProgressBarStatus.Value = (int)Math.Round(e.PercentComplete);
\r
2461 /// Set the DVD Drive selection in the "Source" Menu
\r
2463 private void SetDriveSelectionMenuItem()
\r
2467 if (InvokeRequired)
\r
2469 BeginInvoke(new UpdateWindowHandler(SetDriveSelectionMenuItem));
\r
2473 drives = UtilityService.GetDrives();
\r
2475 List<ToolStripMenuItem> menuItems = new List<ToolStripMenuItem>();
\r
2476 foreach (DriveInformation drive in drives)
\r
2478 ToolStripMenuItem menuItem = new ToolStripMenuItem
\r
2480 Name = drive.ToString(),
\r
2481 Text = drive.RootDirectory + " (" + drive.VolumeLabel + ")",
\r
2482 Image = Resources.disc_small
\r
2484 menuItem.Click += new EventHandler(MnuDvdDriveClick);
\r
2485 menuItems.Add(menuItem);
\r
2488 foreach (ToolStripMenuItem item in menuItems)
\r
2489 btn_source.DropDownItems.Add(item);
\r
2491 catch (Exception exc)
\r
2493 MessageBox.Show("Error in SetDriveSelectionMenuItem" + exc);
\r
2498 /// Access the preset Handler and setup the preset panel.
\r
2500 private void LoadPresetPanel()
\r
2502 if (presetHandler.CheckIfPresetsAreOutOfDate())
\r
2503 if (!Settings.Default.presetNotification)
\r
2504 MessageBox.Show(this,
\r
2505 "HandBrake has determined your built-in presets are out of date... These presets will now be updated.",
\r
2506 "Preset Update", MessageBoxButtons.OK, MessageBoxIcon.Information);
\r
2508 presetHandler.GetPresetPanel(ref treeView_presets);
\r
2509 treeView_presets.Update();
\r
2513 /// Get the title from the selected item in the title dropdown.
\r
2518 private int GetTitle()
\r
2521 if (drp_dvdtitle.SelectedItem != null)
\r
2523 string[] titleInfo = drp_dvdtitle.SelectedItem.ToString().Split(' ');
\r
2524 int.TryParse(titleInfo[0], out title);
\r
2531 /// Handle the Update Check Finishing.
\r
2533 /// <param name="result">
\r
2536 private void UpdateCheckDoneMenu(IAsyncResult result)
\r
2538 // Make sure it's running on the calling thread
\r
2539 if (InvokeRequired)
\r
2541 Invoke(new MethodInvoker(() => this.UpdateCheckDoneMenu(result)));
\r
2544 UpdateCheckInformation info;
\r
2547 // Get the information about the new build, if any, and close the window
\r
2548 info = UpdateService.EndCheckForUpdates(result);
\r
2550 if (info.NewVersionAvailable && info.BuildInformation != null)
\r
2552 UpdateInfo updateWindow = new UpdateInfo(info.BuildInformation, Settings.Default.hb_version, Settings.Default.hb_build.ToString());
\r
2553 updateWindow.ShowDialog();
\r
2556 MessageBox.Show("There are no new updates at this time.", "Update Check", MessageBoxButtons.OK,
\r
2557 MessageBoxIcon.Information);
\r
2558 lbl_updateCheck.Visible = false;
\r
2561 catch (Exception ex)
\r
2563 if ((bool)result.AsyncState)
\r
2565 "Unable to check for updates, Please try again later.\n\nDetailed Error Information:\n" + ex,
\r
2566 "Error", MessageBoxButtons.OK, MessageBoxIcon.Error);
\r
2575 /// Handle GUI shortcuts
\r
2577 /// <param name="msg">Message</param>
\r
2578 /// <param name="keyData">Keys</param>
\r
2579 /// <returns>Bool</returns>
\r
2580 protected override bool ProcessCmdKey(ref Message msg, Keys keyData)
\r
2582 if (keyData == (Keys.Control | Keys.S))
\r
2584 btn_start_Click(this, new EventArgs());
\r
2588 if (keyData == (Keys.Control | Keys.Shift | Keys.A))
\r
2590 btn_add2Queue_Click(this, new EventArgs());
\r
2593 return base.ProcessCmdKey(ref msg, keyData);
\r
2597 /// If the queue is being processed, prompt the user to confirm application close.
\r
2599 /// <param name="e">FormClosingEventArgs</param>
\r
2600 protected override void OnFormClosing(FormClosingEventArgs e)
\r
2604 // If currently encoding, the queue isn't paused, and there are queue items to process, prompt to confirm close.
\r
2605 if (this.queueProcessor.EncodeService.IsEncoding)
\r
2607 DialogResult result =
\r
2609 "HandBrake is currently encoding. Closing HandBrake will stop the current encode and will result in an unplayable file.\n\nDo you want to close HandBrake?",
\r
2610 "Close HandBrake?",
\r
2611 MessageBoxButtons.YesNo,
\r
2612 MessageBoxIcon.Question);
\r
2614 if (result == DialogResult.No)
\r
2620 this.queueProcessor.Pause();
\r
2621 this.queueProcessor.EncodeService.Stop();
\r
2624 if (SourceScan.IsScanning)
\r
2626 SourceScan.Stop();
\r
2629 SourceScan.ScanCompleted -= this.SourceScanScanCompleted;
\r
2630 SourceScan.ScanStatusChanged -= this.SourceScanScanStatusChanged;
\r
2632 catch (Exception exc)
\r
2634 Main.ShowExceptiowWindow("HandBrake was not able to shutdown properly. You may need to forcefully quit HandBrake CLI from TaskManager if it's still running.", exc.ToString());
\r
2638 base.OnFormClosing(e);
\r
2644 // This is the END of the road ****************************************
\r