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.ApplicationServices.Utilities;
\r
21 using HandBrake.Framework.Model;
\r
22 using HandBrake.Framework.Services;
\r
23 using HandBrake.Framework.Views;
\r
24 using HandBrake.ApplicationServices.Functions;
\r
25 using HandBrake.ApplicationServices.Model;
\r
26 using HandBrake.ApplicationServices.Parsing;
\r
27 using HandBrake.ApplicationServices.Services;
\r
28 using HandBrake.ApplicationServices.Services.Interfaces;
\r
30 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 PresetsHandler presetHandler = new PresetsHandler();
\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();
\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.RemoveBuiltInPresets();
\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 // TODO this requires a re-think since the Query Editor has changed.
\r
652 DialogResult result =
\r
654 "Do you wish to include picture settings when updating the preset: " +
\r
655 treeView_presets.SelectedNode.Text, "Update Preset", MessageBoxButtons.YesNoCancel,
\r
656 MessageBoxIcon.Question);
\r
657 if (result == DialogResult.Yes)
\r
658 presetHandler.Update(treeView_presets.SelectedNode.Text,
\r
659 QueryGenerator.GenerateQueryForPreset(this, QueryPictureSettingsMode.SourceMaximum, true, 0, 0), true);
\r
660 else if (result == DialogResult.No)
\r
661 presetHandler.Update(treeView_presets.SelectedNode.Text,
\r
662 QueryGenerator.GenerateQueryForPreset(this, QueryPictureSettingsMode.SourceMaximum, true, 0, 0), false);
\r
666 /// RMenu - Delete Preset
\r
668 /// <param name="sender">
\r
671 /// <param name="e">
\r
674 private void pmnu_delete_click(object sender, EventArgs e)
\r
676 if (treeView_presets.SelectedNode != null)
\r
678 presetHandler.Remove(treeView_presets.SelectedNode.Text);
\r
679 treeView_presets.Nodes.Remove(treeView_presets.SelectedNode);
\r
681 treeView_presets.Select();
\r
685 /// Preset Menu Is Opening. Setup the Menu
\r
687 /// <param name="sender">
\r
690 /// <param name="e">
\r
693 private void presets_menu_Opening(object sender, CancelEventArgs e)
\r
695 // Make sure that the save menu is always disabled by default
\r
696 pmnu_saveChanges.Enabled = false;
\r
698 // Now enable the save menu if the selected preset is a user preset
\r
699 if (treeView_presets.SelectedNode != null)
\r
700 if (presetHandler.CheckIfUserPresetExists(treeView_presets.SelectedNode.Text))
\r
701 pmnu_saveChanges.Enabled = true;
\r
703 treeView_presets.Select();
\r
706 // Presets Management
\r
709 /// Button - Add a preset
\r
711 /// <param name="sender">
\r
714 /// <param name="e">
\r
717 private void btn_addPreset_Click(object sender, EventArgs e)
\r
719 Form preset = new frmAddPreset(this, presetHandler);
\r
720 if (preset.ShowDialog() == DialogResult.OK)
\r
722 TreeNode presetTreeview = new TreeNode(presetHandler.LastPresetAdded.Name) { ForeColor = Color.Black };
\r
723 treeView_presets.Nodes.Add(presetTreeview);
\r
724 presetHandler.LastPresetAdded = null;
\r
729 /// Button - remove a Preset
\r
731 /// <param name="sender">
\r
734 /// <param name="e">
\r
737 private void btn_removePreset_Click(object sender, EventArgs e)
\r
739 DialogResult result = MessageBox.Show("Are you sure you wish to delete the selected preset?", "Preset",
\r
740 MessageBoxButtons.YesNo, MessageBoxIcon.Question);
\r
741 if (result == DialogResult.Yes)
\r
743 if (treeView_presets.SelectedNode != null)
\r
745 presetHandler.Remove(treeView_presets.SelectedNode.Text);
\r
746 treeView_presets.Nodes.Remove(treeView_presets.SelectedNode);
\r
749 treeView_presets.Select();
\r
753 /// Button - Set the selected preset as the default
\r
755 /// <param name="sender">
\r
758 /// <param name="e">
\r
761 private void btn_setDefault_Click(object sender, EventArgs e)
\r
763 if (treeView_presets.SelectedNode != null)
\r
765 DialogResult result = MessageBox.Show("Are you sure you wish to set this preset as the default?",
\r
766 "Preset", MessageBoxButtons.YesNo, MessageBoxIcon.Question);
\r
767 if (result == DialogResult.Yes)
\r
769 Properties.Settings.Default.defaultPreset = treeView_presets.SelectedNode.Text;
\r
770 Properties.Settings.Default.Save();
\r
771 MessageBox.Show("New default preset set.", "Alert", MessageBoxButtons.OK, MessageBoxIcon.Information);
\r
775 MessageBox.Show("Please select a preset first.", "Warning", MessageBoxButtons.OK, MessageBoxIcon.Warning);
\r
779 /// PresetBar Mouse Down event
\r
781 /// <param name="sender">
\r
784 /// <param name="e">
\r
787 private void treeview_presets_mouseUp(object sender, MouseEventArgs e)
\r
789 if (e.Button == MouseButtons.Right)
\r
790 treeView_presets.SelectedNode = treeView_presets.GetNodeAt(e.Location);
\r
791 else if (e.Button == MouseButtons.Left)
\r
793 if (treeView_presets.GetNodeAt(e.Location) != null)
\r
795 if (labelPreset.Text.Contains(treeView_presets.GetNodeAt(e.Location).Text))
\r
800 treeView_presets.Select();
\r
804 /// Preset Bar after selecting the preset
\r
806 /// <param name="sender">
\r
809 /// <param name="e">
\r
812 private void treeView_presets_AfterSelect(object sender, TreeViewEventArgs e)
\r
818 /// When the mouse moves, display a preset
\r
820 /// <param name="sender">The Sender</param>
\r
821 /// <param name="e">the MouseEventArgs</param>
\r
822 private void TreeViewPresetsMouseMove(object sender, MouseEventArgs e)
\r
824 TreeNode theNode = this.treeView_presets.GetNodeAt(e.X, e.Y);
\r
826 if ((theNode != null))
\r
828 // Change the ToolTip only if the pointer moved to a new node.
\r
829 if (theNode.ToolTipText != this.ToolTip.GetToolTip(this.treeView_presets))
\r
831 this.ToolTip.SetToolTip(this.treeView_presets, theNode.ToolTipText);
\r
834 else // Pointer is not over a node so clear the ToolTip.
\r
836 this.ToolTip.SetToolTip(this.treeView_presets, string.Empty);
\r
841 /// Preset Bar - Handle the Delete Key
\r
843 /// <param name="sender">
\r
846 /// <param name="e">
\r
849 private void treeView_presets_deleteKey(object sender, KeyEventArgs e)
\r
851 if (e.KeyCode == Keys.Delete)
\r
853 DialogResult result = MessageBox.Show("Are you sure you wish to delete the selected preset?", "Preset",
\r
854 MessageBoxButtons.YesNo, MessageBoxIcon.Question);
\r
855 if (result == DialogResult.Yes)
\r
857 if (treeView_presets.SelectedNode != null)
\r
858 presetHandler.Remove(treeView_presets.SelectedNode.Text);
\r
860 // Remember each nodes expanded status so we can reload it
\r
861 List<bool> nodeStatus = new List<bool>();
\r
862 foreach (TreeNode node in treeView_presets.Nodes)
\r
863 nodeStatus.Add(node.IsExpanded);
\r
865 // Now reload the preset panel
\r
868 // And finally, re-expand any of the nodes if required
\r
870 foreach (TreeNode node in treeView_presets.Nodes)
\r
882 /// Select the selected preset and setup the GUI
\r
884 private void selectPreset()
\r
886 if (treeView_presets.SelectedNode != null)
\r
888 // Ok, so, we've selected a preset. Now we want to load it.
\r
889 string presetName = treeView_presets.SelectedNode.Text;
\r
890 Preset preset = presetHandler.GetPreset(presetName);
\r
891 if (preset != null)
\r
893 string query = presetHandler.GetPreset(presetName).Query;
\r
897 // Ok, Reset all the H264 widgets before changing the preset
\r
898 x264Panel.Reset2Defaults();
\r
900 // Send the query from the file to the Query Parser class
\r
901 EncodeTask presetQuery = QueryParserUtility.Parse(query);
\r
903 // Now load the preset
\r
904 PresetLoader.LoadPreset(this, presetQuery, presetName);
\r
906 // The x264 widgets will need updated, so do this now:
\r
907 x264Panel.StandardizeOptString();
\r
908 x264Panel.SetCurrentSettingsInPanel();
\r
910 // Finally, let this window have a copy of the preset settings.
\r
911 this.currentlySelectedPreset = preset;
\r
912 PictureSettings.SetPresetCropWarningLabel(preset);
\r
919 /// Load the Normal Preset
\r
921 private void loadNormalPreset()
\r
923 foreach (TreeNode treenode in treeView_presets.Nodes)
\r
925 foreach (TreeNode node in treenode.Nodes)
\r
927 if (node.Text.Equals("Normal"))
\r
928 treeView_presets.SelectedNode = treeView_presets.Nodes[treenode.Index].Nodes[0];
\r
934 /// Import a plist preset
\r
936 private void ImportPreset()
\r
938 if (openPreset.ShowDialog() == DialogResult.OK)
\r
940 EncodeTask parsed = PlistPresetHandler.Import(openPreset.FileName);
\r
941 if (presetHandler.CheckIfUserPresetExists(parsed.PresetName + " (Imported)"))
\r
943 DialogResult result =
\r
944 MessageBox.Show("This preset appears to already exist. Would you like to overwrite it?",
\r
945 "Overwrite preset?",
\r
946 MessageBoxButtons.YesNo, MessageBoxIcon.Warning);
\r
947 if (result == DialogResult.Yes)
\r
949 PresetLoader.LoadPreset(this, parsed, parsed.PresetName);
\r
950 presetHandler.Update(parsed.PresetName + " (Imported)",
\r
951 QueryGenerator.GenerateFullQuery(this),
\r
952 parsed.UsesPictureSettings);
\r
957 PresetLoader.LoadPreset(this, parsed, parsed.PresetName);
\r
958 if (presetHandler.Add(parsed.PresetName + " (Imported)",
\r
959 QueryGenerator.GenerateFullQuery(this),
\r
960 parsed.UsesPictureSettings, string.Empty))
\r
962 TreeNode preset_treeview = new TreeNode(parsed.PresetName + " (Imported)")
\r
964 ForeColor = Color.Black
\r
966 treeView_presets.Nodes.Add(preset_treeview);
\r
973 /// Export a plist Preset
\r
975 private void ExportPreset()
\r
977 SaveFileDialog savefiledialog = new SaveFileDialog { Filter = "plist|*.plist" };
\r
979 if (treeView_presets.SelectedNode != null)
\r
981 if (savefiledialog.ShowDialog() == DialogResult.OK)
\r
983 Preset preset = presetHandler.GetPreset(treeView_presets.SelectedNode.Text);
\r
984 PlistPresetHandler.Export(savefiledialog.FileName, preset);
\r
994 /// Toolbar - When the Source button is clicked, Clear any DVD drives and add any available DVD drives that can be used as a source.
\r
996 /// <param name="sender">
\r
999 /// <param name="e">
\r
1002 private void btn_source_Click(object sender, EventArgs e)
\r
1004 // Remove old Drive Menu Items.
\r
1005 List<ToolStripMenuItem> itemsToRemove = new List<ToolStripMenuItem>();
\r
1006 foreach (var item in btn_source.DropDownItems)
\r
1008 if (item.GetType() == typeof(ToolStripMenuItem))
\r
1010 ToolStripMenuItem menuItem = (ToolStripMenuItem)item;
\r
1011 if (menuItem.Name.StartsWith("Drive"))
\r
1013 itemsToRemove.Add(menuItem);
\r
1018 foreach (ToolStripMenuItem item in itemsToRemove)
\r
1019 btn_source.DropDownItems.Remove(item);
\r
1021 Thread driveInfoThread = new Thread(SetDriveSelectionMenuItem);
\r
1022 driveInfoThread.Start();
\r
1026 /// Toolbar - Start The Encode
\r
1028 /// <param name="sender">
\r
1031 /// <param name="e">
\r
1034 private void btn_start_Click(object sender, EventArgs e)
\r
1036 if (btn_start.Text == "Stop")
\r
1038 DialogResult result = !Properties.Settings.Default.showCliForInGuiEncodeStatus
\r
1039 ? MessageBox.Show(
\r
1040 "Are you sure you wish to cancel the encode?\n\nPlease note: Stopping this encode will render the file unplayable. ",
\r
1042 MessageBoxButtons.YesNo,
\r
1043 MessageBoxIcon.Question)
\r
1044 : MessageBox.Show(
\r
1045 "Are you sure you wish to cancel the encode?",
\r
1047 MessageBoxButtons.YesNo,
\r
1048 MessageBoxIcon.Question);
\r
1050 if (result == DialogResult.Yes)
\r
1052 // Pause The Queue
\r
1053 this.queueProcessor.Pause();
\r
1055 if (Settings.Default.showCliForInGuiEncodeStatus)
\r
1056 this.queueProcessor.EncodeService.SafelyStop();
\r
1058 this.queueProcessor.EncodeService.Stop();
\r
1063 // 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
1064 string jobSourcePath = !string.IsNullOrEmpty(rtf_query.Text) ? Main.GetSourceFromQuery(rtf_query.Text) : sourcePath;
\r
1065 string jobDestination = !string.IsNullOrEmpty(rtf_query.Text) ? Main.GetDestinationFromQuery(rtf_query.Text) : text_destination.Text;
\r
1067 if (this.queueProcessor.QueueManager.Count != 0 || (!string.IsNullOrEmpty(jobSourcePath) && !string.IsNullOrEmpty(jobDestination)))
\r
1069 string generatedQuery = QueryGenerator.GenerateFullQuery(this);
\r
1070 string specifiedQuery = rtf_query.Text != string.Empty
\r
1072 : QueryGenerator.GenerateFullQuery(this);
\r
1073 string query = string.Empty;
\r
1075 // Check to make sure the generated query matches the GUI settings
\r
1076 if (Properties.Settings.Default.PromptOnUnmatchingQueries && !string.IsNullOrEmpty(specifiedQuery) &&
\r
1077 generatedQuery != specifiedQuery)
\r
1079 DialogResult result = MessageBox.Show("The query under the \"Query Editor\" tab " +
\r
1080 "does not match the current GUI settings.\n\nBecause the manual query takes " +
\r
1081 "priority over the GUI, your recently updated settings will not be taken " +
\r
1082 "into account when encoding this job." +
\r
1083 Environment.NewLine + Environment.NewLine +
\r
1084 "Do you want to replace the manual query with the updated GUI-generated query?",
\r
1085 "Manual Query does not Match GUI",
\r
1086 MessageBoxButtons.YesNoCancel, MessageBoxIcon.Asterisk,
\r
1087 MessageBoxDefaultButton.Button3);
\r
1091 case DialogResult.Yes:
\r
1092 // Replace the manual query with the generated one
\r
1093 query = generatedQuery;
\r
1094 rtf_query.Text = generatedQuery;
\r
1096 case DialogResult.No:
\r
1097 // Use the manual query
\r
1098 query = specifiedQuery;
\r
1100 case DialogResult.Cancel:
\r
1101 // Don't start the encode
\r
1107 query = specifiedQuery;
\r
1110 DialogResult overwrite = DialogResult.Yes;
\r
1111 if (!string.IsNullOrEmpty(jobDestination) && File.Exists(jobDestination))
\r
1113 overwrite = MessageBox.Show(
\r
1114 "The destination file already exists. Are you sure you want to overwrite it?",
\r
1115 "Overwrite File?",
\r
1116 MessageBoxButtons.YesNo,
\r
1117 MessageBoxIcon.Question);
\r
1120 if (overwrite == DialogResult.Yes)
\r
1122 QueueTask task = new QueueTask(query)
\r
1124 Title = this.GetTitle(),
\r
1125 Source = jobSourcePath,
\r
1126 Destination = jobDestination,
\r
1127 CustomQuery = (this.rtf_query.Text != string.Empty)
\r
1130 if (this.queueProcessor.QueueManager.Count == 0)
\r
1131 this.queueProcessor.QueueManager.Add(task);
\r
1133 queueWindow.SetQueue();
\r
1134 if (this.queueProcessor.QueueManager.Count > 1)
\r
1135 queueWindow.Show(false);
\r
1137 SetEncodeStarted(); // Encode is running, so setup the GUI appropriately
\r
1138 this.queueProcessor.Start(); // Start The Queue Encoding Process
\r
1143 else if (string.IsNullOrEmpty(sourcePath) || string.IsNullOrEmpty(text_destination.Text))
\r
1144 MessageBox.Show("No source or destination selected.", "Warning", MessageBoxButtons.OK,
\r
1145 MessageBoxIcon.Warning);
\r
1150 /// Toolbar - Add the current job to the Queue
\r
1152 /// <param name="sender">
\r
1155 /// <param name="e">
\r
1158 private void btn_add2Queue_Click(object sender, EventArgs e)
\r
1160 // Add the item to the queue.
\r
1161 AddItemToQueue(true);
\r
1162 queueWindow.Show();
\r
1166 /// Add Multiple Items to the Queue at once.
\r
1168 /// <param name="sender">The Sender</param>
\r
1169 /// <param name="e">The EventArgs</param>
\r
1170 private void MnuAddMultiToQueueClick(object sender, EventArgs e)
\r
1172 if (!Settings.Default.autoNaming)
\r
1174 MessageBox.Show("Destination Auto Naming must be enabled in preferences for this feature to work.", "Error", MessageBoxButtons.OK, MessageBoxIcon.Error);
\r
1178 if (this.SourceScan.SouceData == null)
\r
1180 MessageBox.Show("You must first scan a source or collection of source to use this feature.", "Error", MessageBoxButtons.OK, MessageBoxIcon.Error);
\r
1184 BatchAdd batchAdd = new BatchAdd();
\r
1185 if (batchAdd.ShowDialog() == DialogResult.OK)
\r
1187 int min = batchAdd.Min;
\r
1188 int max = batchAdd.Max;
\r
1189 bool errors = false;
\r
1191 foreach (Title title in this.SourceScan.SouceData.Titles)
\r
1193 if (title.Duration.TotalMinutes > min && title.Duration.TotalMinutes < max)
\r
1196 this.drp_dvdtitle.SelectedItem = title;
\r
1198 if (!this.AddItemToQueue(false))
\r
1208 "One or more items could not be added to the queue. You should check your queue and manually add any missing jobs.",
\r
1210 MessageBoxButtons.OK,
\r
1211 MessageBoxIcon.Warning);
\r
1216 private bool AddItemToQueue(bool showError)
\r
1218 string query = QueryGenerator.GenerateFullQuery(this);
\r
1219 if (!string.IsNullOrEmpty(rtf_query.Text))
\r
1220 query = rtf_query.Text;
\r
1222 // 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
1223 string jobSourcePath = !string.IsNullOrEmpty(rtf_query.Text) ? Main.GetSourceFromQuery(rtf_query.Text) : sourcePath;
\r
1224 string jobDestination = !string.IsNullOrEmpty(rtf_query.Text) ? Main.GetDestinationFromQuery(rtf_query.Text) : text_destination.Text;
\r
1226 // Make sure we have a Source and Destination.
\r
1227 if (string.IsNullOrEmpty(jobSourcePath) || string.IsNullOrEmpty(jobDestination))
\r
1230 MessageBox.Show("No source or destination selected.", "Warning", MessageBoxButtons.OK, MessageBoxIcon.Warning);
\r
1234 // Make sure the destination path exists.
\r
1235 if (!Directory.Exists(Path.GetDirectoryName(jobDestination)))
\r
1238 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
1242 // Make sure we don't have a duplciate on the queue.
\r
1243 if (this.queueProcessor.QueueManager.CheckForDestinationPathDuplicates(jobDestination))
\r
1247 DialogResult result;
\r
1251 "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
1254 MessageBoxButtons.YesNo,
\r
1255 MessageBoxIcon.Warning);
\r
1257 if (result != DialogResult.Yes) return false;
\r
1266 QueueTask task = new QueueTask(query)
\r
1268 Title = this.GetTitle(),
\r
1269 Source = jobSourcePath,
\r
1270 Destination = jobDestination,
\r
1271 CustomQuery = (this.rtf_query.Text != string.Empty)
\r
1273 this.queueProcessor.QueueManager.Add(task);
\r
1275 lbl_encode.Text = this.queueProcessor.QueueManager.Count + " encode(s) pending in the queue";
\r
1281 /// Toolbar - Show the Queue
\r
1283 /// <param name="sender">
\r
1286 /// <param name="e">
\r
1289 private void btn_showQueue_Click(object sender, EventArgs e)
\r
1291 queueWindow.Show();
\r
1292 queueWindow.Activate();
\r
1296 /// Toolbar - Show the Preview Window
\r
1298 /// <param name="sender">
\r
1301 /// <param name="e">
\r
1304 private void tb_preview_Click(object sender, EventArgs e)
\r
1306 if (string.IsNullOrEmpty(sourcePath) || string.IsNullOrEmpty(text_destination.Text))
\r
1307 MessageBox.Show("No source or destination selected.", "Warning", MessageBoxButtons.OK,
\r
1308 MessageBoxIcon.Warning);
\r
1311 if (qtpreview == null)
\r
1313 qtpreview = new frmPreview(this);
\r
1316 else if (qtpreview.IsDisposed)
\r
1318 qtpreview = new frmPreview(this);
\r
1322 MessageBox.Show(qtpreview, "The preview window is already open!", "Warning", MessageBoxButtons.OK,
\r
1323 MessageBoxIcon.Warning);
\r
1328 /// Toolbar - Show the Activity log Window
\r
1330 /// <param name="sender">
\r
1333 /// <param name="e">
\r
1336 private void btn_ActivityWindow_Click(object sender, EventArgs e)
\r
1338 if (this.activityWindow == null || !this.activityWindow.IsHandleCreated)
\r
1339 this.activityWindow = new frmActivityWindow(this.queueProcessor.EncodeService, SourceScan);
\r
1341 this.activityWindow.Show();
\r
1342 this.activityWindow.Activate();
\r
1347 #region System Tray Icon
\r
1350 /// Handle Resizing of the main window when deaing with the Notify Icon
\r
1352 /// <param name="sender">
\r
1355 /// <param name="e">
\r
1358 private void frmMain_Resize(object sender, EventArgs e)
\r
1360 if (FormWindowState.Minimized == this.WindowState)
\r
1362 notifyIcon.Visible = true;
\r
1365 else if (FormWindowState.Normal == this.WindowState)
\r
1366 notifyIcon.Visible = false;
\r
1370 /// Double Click the Tray Icon
\r
1372 /// <param name="sender">
\r
1375 /// <param name="e">
\r
1378 private void notifyIcon_MouseDoubleClick(object sender, MouseEventArgs e)
\r
1380 this.Visible = true;
\r
1382 this.WindowState = FormWindowState.Normal;
\r
1383 notifyIcon.Visible = false;
\r
1387 /// Tray Icon - Restore Menu Item - Resture the Window
\r
1389 /// <param name="sender">
\r
1392 /// <param name="e">
\r
1395 private void btn_restore_Click(object sender, EventArgs e)
\r
1397 this.Visible = true;
\r
1399 this.WindowState = FormWindowState.Normal;
\r
1400 notifyIcon.Visible = false;
\r
1405 #region Main Window and Tab Control
\r
1408 private void BtnFolderScanClicked(object sender, EventArgs e)
\r
1410 this.btn_source.HideDropDown();
\r
1411 if (DVD_Open.ShowDialog() == DialogResult.OK)
\r
1413 this.selectedSourceType = SourceType.Folder;
\r
1414 SelectSource(DVD_Open.SelectedPath, 0);
\r
1417 UpdateSourceLabel();
\r
1420 private void BtnFileScanClicked(object sender, EventArgs e)
\r
1422 this.btn_source.HideDropDown();
\r
1423 if (ISO_Open.ShowDialog() == DialogResult.OK)
\r
1425 this.selectedSourceType = SourceType.VideoFile;
\r
1426 SelectSource(ISO_Open.FileName, 0);
\r
1429 UpdateSourceLabel();
\r
1432 private void MnuDvdDriveClick(object sender, EventArgs e)
\r
1434 ToolStripMenuItem item = sender as ToolStripMenuItem;
\r
1437 string driveId = item.Name.Replace("Drive", string.Empty);
\r
1439 if (int.TryParse(driveId, out id))
\r
1441 this.dvdDrivePath = drives[id].RootDirectory;
\r
1442 this.dvdDriveLabel = drives[id].VolumeLabel;
\r
1444 if (this.dvdDrivePath == null) return;
\r
1445 this.selectedSourceType = SourceType.DvdDrive;
\r
1446 SelectSource(this.dvdDrivePath, 0);
\r
1451 private void VideoTitleSpecificScanClick(object sender, EventArgs e)
\r
1453 this.btn_source.HideDropDown();
\r
1454 if (ISO_Open.ShowDialog() == DialogResult.OK)
\r
1456 this.selectedSourceType = SourceType.VideoFile;
\r
1458 int sourceTitle = 0;
\r
1459 TitleSpecificScan title = new TitleSpecificScan();
\r
1460 if (title.ShowDialog() == DialogResult.OK)
\r
1462 sourceTitle = title.Title;
\r
1463 SelectSource(ISO_Open.FileName, sourceTitle);
\r
1467 UpdateSourceLabel();
\r
1470 private void FolderTitleSpecificScanClick(object sender, EventArgs e)
\r
1472 this.btn_source.HideDropDown();
\r
1473 if (DVD_Open.ShowDialog() == DialogResult.OK)
\r
1475 this.selectedSourceType = SourceType.Folder;
\r
1477 int sourceTitle = 0;
\r
1478 TitleSpecificScan title = new TitleSpecificScan();
\r
1479 if (title.ShowDialog() == DialogResult.OK)
\r
1481 sourceTitle = title.Title;
\r
1482 SelectSource(DVD_Open.SelectedPath, sourceTitle);
\r
1486 UpdateSourceLabel();
\r
1489 private void SelectSource(string file, int titleSpecific)
\r
1491 Check_ChapterMarkers.Enabled = true;
\r
1492 sourcePath = string.Empty;
\r
1494 if (file == string.Empty) // Must have a file or path
\r
1496 UpdateSourceLabel();
\r
1500 sourcePath = Path.GetFileName(file);
\r
1501 StartScan(file, titleSpecific);
\r
1504 private void drp_dvdtitle_Click(object sender, EventArgs e)
\r
1506 if ((drp_dvdtitle.Items.Count == 1) && (drp_dvdtitle.Items[0].ToString() == "Automatic"))
\r
1508 "There are no titles to select. Please load a source file by clicking the 'Source' button above before trying to select a title.",
\r
1509 "Alert", MessageBoxButtons.OK, MessageBoxIcon.Asterisk);
\r
1512 private void drp_dvdtitle_SelectedIndexChanged(object sender, EventArgs e)
\r
1514 UnRegisterPresetEventHandler();
\r
1515 drop_mode.SelectedIndex = 0;
\r
1517 drop_chapterStart.Items.Clear();
\r
1518 drop_chapterFinish.Items.Clear();
\r
1520 // If the dropdown is set to automatic nothing else needs to be done.
\r
1521 // Otheriwse if its not, title data has to be loaded from parsing.
\r
1522 if (drp_dvdtitle.Text != "Automatic")
\r
1524 selectedTitle = drp_dvdtitle.SelectedItem as Title;
\r
1525 lbl_duration.Text = selectedTitle.Duration.ToString();
\r
1526 PictureSettings.CurrentlySelectedPreset = this.currentlySelectedPreset;
\r
1527 PictureSettings.Source = selectedTitle; // Setup Picture Settings Tab Control
\r
1529 // Populate the Angles dropdown
\r
1530 drop_angle.Items.Clear();
\r
1531 if (!Properties.Settings.Default.noDvdNav)
\r
1533 drop_angle.Visible = true;
\r
1534 lbl_angle.Visible = true;
\r
1536 for (int i = 1; i <= selectedTitle.AngleCount; i++)
\r
1537 drop_angle.Items.Add(i.ToString());
\r
1539 if (drop_angle.Items.Count == 0)
\r
1541 drop_angle.Visible = false;
\r
1542 lbl_angle.Visible = false;
\r
1545 if (drop_angle.Items.Count != 0)
\r
1546 drop_angle.SelectedIndex = 0;
\r
1550 drop_angle.Visible = false;
\r
1551 lbl_angle.Visible = false;
\r
1554 // Populate the Start chapter Dropdown
\r
1555 drop_chapterStart.Items.Clear();
\r
1556 drop_chapterStart.Items.AddRange(selectedTitle.Chapters.ToArray());
\r
1557 if (drop_chapterStart.Items.Count > 0)
\r
1558 drop_chapterStart.Text = drop_chapterStart.Items[0].ToString();
\r
1560 // Populate the Final Chapter Dropdown
\r
1561 drop_chapterFinish.Items.Clear();
\r
1562 drop_chapterFinish.Items.AddRange(selectedTitle.Chapters.ToArray());
\r
1563 if (drop_chapterFinish.Items.Count > 0)
\r
1564 drop_chapterFinish.Text = drop_chapterFinish.Items[drop_chapterFinish.Items.Count - 1].ToString();
\r
1566 // Populate the Audio Channels Dropdown
\r
1567 AudioSettings.SetTrackListFromPreset(selectedTitle, this.currentlySelectedPreset);
\r
1569 // Populate the Subtitles dropdown
\r
1570 Subtitles.SetSubtitleTrackAuto(selectedTitle.Subtitles.ToArray());
\r
1572 // Update the source label if we have multiple streams
\r
1573 if (selectedTitle != null)
\r
1574 if (!string.IsNullOrEmpty(selectedTitle.SourceName))
\r
1575 labelSource.Text = Path.GetFileName(selectedTitle.SourceName);
\r
1577 // Run the AutoName & ChapterNaming functions
\r
1578 if (Properties.Settings.Default.autoNaming)
\r
1580 string autoPath = Main.AutoName(this);
\r
1581 if (autoPath != null)
\r
1582 text_destination.Text = autoPath;
\r
1585 "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
1586 "Warning", MessageBoxButtons.OK, MessageBoxIcon.Warning);
\r
1589 data_chpt.Rows.Clear();
\r
1590 if (selectedTitle.Chapters.Count != 1)
\r
1592 DataGridView chapterGridView = Main.ChapterNaming(selectedTitle, data_chpt, drop_chapterFinish.Text);
\r
1593 if (chapterGridView != null)
\r
1594 data_chpt = chapterGridView;
\r
1598 Check_ChapterMarkers.Checked = false;
\r
1599 Check_ChapterMarkers.Enabled = false;
\r
1602 // Hack to force the redraw of the scrollbars which don't resize properly when the control is disabled.
\r
1603 data_chpt.Columns[0].Width = 166;
\r
1604 data_chpt.Columns[0].Width = 165;
\r
1606 RegisterPresetEventHandler();
\r
1609 private void chapersChanged(object sender, EventArgs e)
\r
1611 if (drop_mode.SelectedIndex != 0) // Function is not used if we are not in chapters mode.
\r
1614 Control ctl = (Control)sender;
\r
1615 int chapterStart, chapterEnd;
\r
1616 int.TryParse(drop_chapterStart.Text, out chapterStart);
\r
1617 int.TryParse(drop_chapterFinish.Text, out chapterEnd);
\r
1621 case "drop_chapterStart":
\r
1622 if (drop_chapterFinish.SelectedIndex == -1 && drop_chapterFinish.Items.Count != 0)
\r
1623 drop_chapterFinish.SelectedIndex = drop_chapterFinish.Items.Count - 1;
\r
1625 if (chapterEnd != 0)
\r
1626 if (chapterStart > chapterEnd)
\r
1627 drop_chapterFinish.Text = chapterStart.ToString();
\r
1629 case "drop_chapterFinish":
\r
1630 if (drop_chapterStart.Items.Count >= 1 && drop_chapterStart.SelectedIndex == -1)
\r
1631 drop_chapterStart.SelectedIndex = 0;
\r
1633 if (chapterStart != 0)
\r
1634 if (chapterEnd < chapterStart)
\r
1635 drop_chapterFinish.Text = chapterStart.ToString();
\r
1637 // Add more rows to the Chapter menu if needed.
\r
1638 if (Check_ChapterMarkers.Checked)
\r
1640 int i = data_chpt.Rows.Count, finish = 0;
\r
1641 int.TryParse(drop_chapterFinish.Text, out finish);
\r
1643 while (i < finish)
\r
1645 int n = data_chpt.Rows.Add();
\r
1646 data_chpt.Rows[n].Cells[0].Value = (i + 1);
\r
1647 data_chpt.Rows[n].Cells[1].Value = "Chapter " + (i + 1);
\r
1648 data_chpt.Rows[n].Cells[0].ValueType = typeof(int);
\r
1649 data_chpt.Rows[n].Cells[1].ValueType = typeof(string);
\r
1656 // Update the Duration
\r
1657 lbl_duration.Text =
\r
1658 Main.CalculateDuration(drop_chapterStart.SelectedIndex, drop_chapterFinish.SelectedIndex, selectedTitle)
\r
1661 // Run the Autonaming function
\r
1662 if (Properties.Settings.Default.autoNaming)
\r
1663 text_destination.Text = Main.AutoName(this);
\r
1665 // Disable chapter markers if only 1 chapter is selected.
\r
1666 if (chapterStart == chapterEnd)
\r
1668 Check_ChapterMarkers.Enabled = false;
\r
1669 btn_importChapters.Enabled = false;
\r
1670 data_chpt.Enabled = false;
\r
1674 Check_ChapterMarkers.Enabled = true;
\r
1675 if (Check_ChapterMarkers.Checked)
\r
1677 btn_importChapters.Enabled = true;
\r
1678 data_chpt.Enabled = true;
\r
1683 private void SecondsOrFramesChanged(object sender, EventArgs e)
\r
1686 int.TryParse(drop_chapterStart.Text, out start);
\r
1687 int.TryParse(drop_chapterFinish.Text, out end);
\r
1688 double duration = end - start;
\r
1690 switch (drop_mode.SelectedIndex)
\r
1693 lbl_duration.Text = TimeSpan.FromSeconds(duration).ToString();
\r
1696 if (selectedTitle != null)
\r
1698 duration = duration / selectedTitle.Fps;
\r
1699 lbl_duration.Text = TimeSpan.FromSeconds(duration).ToString();
\r
1702 lbl_duration.Text = "--:--:--";
\r
1708 private void drop_mode_SelectedIndexChanged(object sender, EventArgs e)
\r
1711 this.drop_chapterFinish.TextChanged -= new EventHandler(this.SecondsOrFramesChanged);
\r
1712 this.drop_chapterStart.TextChanged -= new EventHandler(this.SecondsOrFramesChanged);
\r
1715 switch (drop_mode.SelectedIndex)
\r
1718 drop_chapterStart.DropDownStyle = ComboBoxStyle.DropDownList;
\r
1719 drop_chapterFinish.DropDownStyle = ComboBoxStyle.DropDownList;
\r
1720 if (drop_chapterStart.Items.Count != 0)
\r
1722 drop_chapterStart.SelectedIndex = 0;
\r
1723 drop_chapterFinish.SelectedIndex = drop_chapterFinish.Items.Count - 1;
\r
1726 lbl_duration.Text = "--:--:--";
\r
1729 this.drop_chapterStart.TextChanged += new EventHandler(this.SecondsOrFramesChanged);
\r
1730 this.drop_chapterFinish.TextChanged += new EventHandler(this.SecondsOrFramesChanged);
\r
1731 drop_chapterStart.DropDownStyle = ComboBoxStyle.Simple;
\r
1732 drop_chapterFinish.DropDownStyle = ComboBoxStyle.Simple;
\r
1733 if (selectedTitle != null)
\r
1735 drop_chapterStart.Text = "0";
\r
1736 drop_chapterFinish.Text = selectedTitle.Duration.TotalSeconds.ToString();
\r
1740 this.drop_chapterStart.TextChanged += new EventHandler(this.SecondsOrFramesChanged);
\r
1741 this.drop_chapterFinish.TextChanged += new EventHandler(this.SecondsOrFramesChanged);
\r
1742 drop_chapterStart.DropDownStyle = ComboBoxStyle.Simple;
\r
1743 drop_chapterFinish.DropDownStyle = ComboBoxStyle.Simple;
\r
1744 if (selectedTitle != null)
\r
1746 drop_chapterStart.Text = "0";
\r
1747 drop_chapterFinish.Text = (selectedTitle.Fps * selectedTitle.Duration.TotalSeconds).ToString();
\r
1754 private void btn_destBrowse_Click(object sender, EventArgs e)
\r
1756 // This removes the file extension from the filename box on the save file dialog.
\r
1757 // It's daft but some users don't realise that typing an extension overrides the dropdown extension selected.
\r
1758 DVD_Save.FileName = Path.GetFileNameWithoutExtension(text_destination.Text);
\r
1760 if (Path.IsPathRooted(text_destination.Text))
\r
1761 DVD_Save.InitialDirectory = Path.GetDirectoryName(text_destination.Text);
\r
1763 // Show the dialog and set the main form file path
\r
1764 if (drop_format.SelectedIndex.Equals(0))
\r
1765 DVD_Save.FilterIndex = 1;
\r
1766 else if (drop_format.SelectedIndex.Equals(1))
\r
1767 DVD_Save.FilterIndex = 2;
\r
1769 if (DVD_Save.ShowDialog() == DialogResult.OK)
\r
1771 // Add a file extension manually, as FileDialog.AddExtension has issues with dots in filenames
\r
1772 switch (DVD_Save.FilterIndex)
\r
1776 !Path.GetExtension(DVD_Save.FileName).Equals(".mp4",
\r
1777 StringComparison.InvariantCultureIgnoreCase))
\r
1778 if (Properties.Settings.Default.useM4v)
\r
1779 DVD_Save.FileName = DVD_Save.FileName.Replace(".mp4", ".m4v").Replace(".mkv", ".m4v");
\r
1781 DVD_Save.FileName = DVD_Save.FileName.Replace(".m4v", ".mp4").Replace(".mkv", ".mp4");
\r
1785 !Path.GetExtension(DVD_Save.FileName).Equals(".mkv", StringComparison.InvariantCultureIgnoreCase))
\r
1786 DVD_Save.FileName = DVD_Save.FileName.Replace(".mp4", ".mkv").Replace(".m4v", ".mkv");
\r
1792 text_destination.Text = DVD_Save.FileName;
\r
1794 // Quicktime requires .m4v file for chapter markers to work. If checked, change the extension to .m4v (mp4 and m4v are the same thing)
\r
1795 if (Check_ChapterMarkers.Checked && DVD_Save.FilterIndex != 2)
\r
1796 SetExtension(".m4v");
\r
1800 private void text_destination_TextChanged(object sender, EventArgs e)
\r
1802 string path = text_destination.Text;
\r
1803 if (path.EndsWith(".mp4") || path.EndsWith(".m4v"))
\r
1804 drop_format.SelectedIndex = 0;
\r
1805 else if (path.EndsWith(".mkv"))
\r
1806 drop_format.SelectedIndex = 1;
\r
1809 // Output Settings
\r
1810 private void drop_format_SelectedIndexChanged(object sender, EventArgs e)
\r
1812 switch (drop_format.SelectedIndex)
\r
1815 if (Properties.Settings.Default.useM4v || Check_ChapterMarkers.Checked ||
\r
1816 AudioSettings.RequiresM4V() || Subtitles.RequiresM4V())
\r
1817 SetExtension(".m4v");
\r
1819 SetExtension(".mp4");
\r
1822 SetExtension(".mkv");
\r
1826 AudioSettings.SetContainer(drop_format.Text);
\r
1828 if (drop_format.Text.Contains("MP4"))
\r
1830 if (drp_videoEncoder.Items.Contains("VP3 (Theora)"))
\r
1832 drp_videoEncoder.Items.Remove("VP3 (Theora)");
\r
1833 drp_videoEncoder.SelectedIndex = 1;
\r
1836 else if (drop_format.Text.Contains("MKV"))
\r
1837 drp_videoEncoder.Items.Add("VP3 (Theora)");
\r
1840 public void SetExtension(string newExtension)
\r
1842 if (newExtension == ".mp4" || newExtension == ".m4v")
\r
1843 if (Properties.Settings.Default.useM4v || Check_ChapterMarkers.Checked || AudioSettings.RequiresM4V() ||
\r
1844 Subtitles.RequiresM4V())
\r
1845 newExtension = ".m4v";
\r
1847 newExtension = ".mp4";
\r
1849 if (Path.HasExtension(newExtension))
\r
1850 text_destination.Text = Path.ChangeExtension(text_destination.Text, newExtension);
\r
1854 private void drp_videoEncoder_SelectedIndexChanged(object sender, EventArgs e)
\r
1856 setContainerOpts();
\r
1858 // Turn off some options which are H.264 only when the user selects a non h.264 encoder
\r
1859 if (drp_videoEncoder.Text.Contains("H.264"))
\r
1861 if (check_2PassEncode.CheckState == CheckState.Checked)
\r
1862 check_turbo.Enabled = true;
\r
1864 tab_advanced.Enabled = true;
\r
1865 if ((drop_format.Text.Contains("MP4")) || (drop_format.Text.Contains("M4V")))
\r
1866 check_iPodAtom.Enabled = true;
\r
1868 check_iPodAtom.Enabled = false;
\r
1872 check_turbo.CheckState = CheckState.Unchecked;
\r
1873 check_turbo.Enabled = false;
\r
1874 tab_advanced.Enabled = false;
\r
1875 x264Panel.X264Query = string.Empty;
\r
1876 check_iPodAtom.Enabled = false;
\r
1877 check_iPodAtom.Checked = false;
\r
1880 // Setup the CQ Slider
\r
1881 switch (drp_videoEncoder.Text)
\r
1883 case "MPEG-4 (FFmpeg)":
\r
1884 if (slider_videoQuality.Value > 31)
\r
1885 slider_videoQuality.Value = 20; // Just reset to 70% QP 10 on encode change.
\r
1886 slider_videoQuality.Minimum = 1;
\r
1887 slider_videoQuality.Maximum = 31;
\r
1889 case "H.264 (x264)":
\r
1890 slider_videoQuality.Minimum = 0;
\r
1891 slider_videoQuality.TickFrequency = 1;
\r
1893 CultureInfo culture = CultureInfo.CreateSpecificCulture("en-US");
\r
1894 double cqStep = Properties.Settings.Default.x264cqstep;
\r
1895 double multiplier = 1.0 / cqStep;
\r
1896 double value = slider_videoQuality.Value * multiplier;
\r
1898 slider_videoQuality.Maximum = (int)(51 / Properties.Settings.Default.x264cqstep);
\r
1900 if (value < slider_videoQuality.Maximum)
\r
1901 slider_videoQuality.Value = slider_videoQuality.Maximum - (int)value;
\r
1904 case "VP3 (Theora)":
\r
1905 if (slider_videoQuality.Value > 63)
\r
1906 slider_videoQuality.Value = 45; // Just reset to 70% QP 45 on encode change.
\r
1907 slider_videoQuality.Minimum = 0;
\r
1908 slider_videoQuality.Maximum = 63;
\r
1914 /// When the FrameRate is not Same As Source, show the Max/Constant Mode dropdown
\r
1916 /// <param name="sender">
\r
1919 /// <param name="e">
\r
1922 private void drp_videoFramerate_SelectedIndexChanged(object sender, EventArgs e)
\r
1924 if (this.drp_videoFramerate.SelectedIndex == 0)
\r
1926 this.checkMaximumFramerate.Visible = false;
\r
1927 this.checkMaximumFramerate.CheckState = CheckState.Unchecked;
\r
1931 this.checkMaximumFramerate.Visible = true;
\r
1936 /// Set the container format options
\r
1938 public void setContainerOpts()
\r
1940 if ((drop_format.Text.Contains("MP4")) || (drop_format.Text.Contains("M4V")))
\r
1942 check_largeFile.Enabled = true;
\r
1943 check_optimiseMP4.Enabled = true;
\r
1944 check_iPodAtom.Enabled = true;
\r
1948 check_largeFile.Enabled = false;
\r
1949 check_optimiseMP4.Enabled = false;
\r
1950 check_iPodAtom.Enabled = false;
\r
1951 check_largeFile.Checked = false;
\r
1952 check_optimiseMP4.Checked = false;
\r
1953 check_iPodAtom.Checked = false;
\r
1957 private double cachedCqStep = Properties.Settings.Default.x264cqstep;
\r
1960 /// Update the CQ slider for x264 for a new CQ step. This is set from option
\r
1962 public void setQualityFromSlider()
\r
1964 // Work out the current RF value.
\r
1965 double cqStep = this.cachedCqStep;
\r
1966 double rfValue = 51.0 - slider_videoQuality.Value * cqStep;
\r
1968 // Change the maximum value for the slider
\r
1969 slider_videoQuality.Maximum = (int)(51 / Properties.Settings.Default.x264cqstep);
\r
1971 // Reset the CQ slider to RF0
\r
1972 slider_videoQuality.Value = slider_videoQuality.Maximum;
\r
1974 // Reset the CQ slider back to the previous value as close as possible
\r
1975 double cqStepNew = Properties.Settings.Default.x264cqstep;
\r
1976 double rfValueCurrent = 51.0 - slider_videoQuality.Value * cqStepNew;
\r
1977 while (rfValueCurrent < rfValue)
\r
1979 slider_videoQuality.Value--;
\r
1980 rfValueCurrent = 51.0 - slider_videoQuality.Value * cqStepNew;
\r
1983 // Cache the CQ step for the next calculation
\r
1984 this.cachedCqStep = Properties.Settings.Default.x264cqstep;
\r
1987 private void slider_videoQuality_Scroll(object sender, EventArgs e)
\r
1989 double cqStep = Properties.Settings.Default.x264cqstep;
\r
1990 switch (drp_videoEncoder.Text)
\r
1992 case "MPEG-4 (FFmpeg)":
\r
1993 lbl_SliderValue.Text = "QP:" + (32 - slider_videoQuality.Value);
\r
1995 case "H.264 (x264)":
\r
1996 double rfValue = 51.0 - slider_videoQuality.Value * cqStep;
\r
1997 rfValue = Math.Round(rfValue, 2);
\r
1998 lbl_SliderValue.Text = "RF:" + rfValue.ToString(new CultureInfo("en-US"));
\r
1999 this.lbl_rfwarn.Visible = rfValue == 0;
\r
2001 case "VP3 (Theora)":
\r
2002 lbl_SliderValue.Text = "QP:" + slider_videoQuality.Value;
\r
2007 private void radio_avgBitrate_CheckedChanged(object sender, EventArgs e)
\r
2009 text_bitrate.Enabled = true;
\r
2010 slider_videoQuality.Enabled = false;
\r
2012 check_2PassEncode.Enabled = true;
\r
2015 private void radio_cq_CheckedChanged(object sender, EventArgs e)
\r
2017 text_bitrate.Enabled = false;
\r
2018 slider_videoQuality.Enabled = true;
\r
2020 check_2PassEncode.Enabled = false;
\r
2021 check_2PassEncode.CheckState = CheckState.Unchecked;
\r
2024 private void check_2PassEncode_CheckedChanged(object sender, EventArgs e)
\r
2026 if (check_2PassEncode.CheckState.ToString() == "Checked")
\r
2028 if (drp_videoEncoder.Text.Contains("H.264"))
\r
2029 check_turbo.Enabled = true;
\r
2033 check_turbo.Enabled = false;
\r
2034 check_turbo.CheckState = CheckState.Unchecked;
\r
2038 // Chapter Marker Tab
\r
2039 private void Check_ChapterMarkers_CheckedChanged(object sender, EventArgs e)
\r
2041 if (Check_ChapterMarkers.Checked)
\r
2043 if (drop_format.SelectedIndex != 1)
\r
2044 SetExtension(".m4v");
\r
2045 data_chpt.Enabled = true;
\r
2046 btn_importChapters.Enabled = true;
\r
2050 if (drop_format.SelectedIndex != 1 && !Properties.Settings.Default.useM4v)
\r
2051 SetExtension(".mp4");
\r
2052 data_chpt.Enabled = false;
\r
2053 btn_importChapters.Enabled = false;
\r
2057 private void btn_importChapters_Click(object sender, EventArgs e)
\r
2059 if (File_ChapterImport.ShowDialog() == DialogResult.OK)
\r
2061 string filename = File_ChapterImport.FileName;
\r
2062 DataGridView imported = Main.ImportChapterNames(data_chpt, filename);
\r
2063 if (imported != null)
\r
2064 data_chpt = imported;
\r
2068 private void btn_export_Click(object sender, EventArgs e)
\r
2070 SaveFileDialog saveFileDialog = new SaveFileDialog();
\r
2071 saveFileDialog.Filter = "Csv File|*.csv";
\r
2072 saveFileDialog.DefaultExt = "csv";
\r
2073 if (saveFileDialog.ShowDialog() == DialogResult.OK)
\r
2075 string filename = saveFileDialog.FileName;
\r
2077 Main.SaveChapterMarkersToCsv(this, filename);
\r
2081 private void mnu_resetChapters_Click(object sender, EventArgs e)
\r
2083 data_chpt.Rows.Clear();
\r
2084 DataGridView chapterGridView = Main.ChapterNaming(selectedTitle, data_chpt, drop_chapterFinish.Text);
\r
2085 if (chapterGridView != null)
\r
2087 data_chpt = chapterGridView;
\r
2091 // Query Editor Tab
\r
2092 private void btn_generate_Query_Click(object sender, EventArgs e)
\r
2094 rtf_query.Text = QueryGenerator.GenerateFullQuery(this);
\r
2097 private void btn_clear_Click(object sender, EventArgs e)
\r
2099 rtf_query.Clear();
\r
2104 // MainWindow Components, Actions and Functions ***********************
\r
2106 #region Source Scan
\r
2109 /// Start the Scan Process
\r
2111 /// <param name="filename">
\r
2114 /// <param name="title">
\r
2117 private void StartScan(string filename, int title)
\r
2119 // Setup the GUI components for the scan.
\r
2120 sourcePath = filename;
\r
2122 this.DisableGUI();
\r
2127 SourceScan.Scan(sourcePath, title);
\r
2129 catch (Exception exc)
\r
2131 MessageBox.Show("frmMain.cs - StartScan " + exc, "Error", MessageBoxButtons.OK, MessageBoxIcon.Error);
\r
2136 /// Update the Status label for the scan
\r
2138 /// <param name="sender">
\r
2141 /// <param name="e">
\r
2144 private void SourceScanScanStatusChanged(object sender, ScanProgressEventArgs e)
\r
2146 if (this.InvokeRequired)
\r
2148 this.BeginInvoke(new ScanProgessStatus(this.SourceScanScanStatusChanged), new[] { sender, e });
\r
2152 labelSource.Text = string.Format("Processing Title: {0} of {1}", e.CurrentTitle, e.Titles);
\r
2156 /// Update the UI after the scan has completed
\r
2158 /// <param name="sender">
\r
2161 /// <param name="e">
\r
2164 private void SourceScanScanCompleted(object sender, EventArgs e)
\r
2166 if (this.InvokeRequired)
\r
2168 this.BeginInvoke(new ScanCompletedStatus(this.SourceScanScanCompleted), new[] { sender, e });
\r
2174 currentSource = SourceScan.SouceData;
\r
2176 // Setup some GUI components
\r
2177 drp_dvdtitle.Items.Clear();
\r
2178 if (currentSource.Titles.Count != 0)
\r
2179 drp_dvdtitle.Items.AddRange(currentSource.Titles.ToArray());
\r
2181 foreach (Title title in currentSource.Titles)
\r
2183 if (title.MainTitle)
\r
2185 drp_dvdtitle.SelectedItem = title;
\r
2189 if (drp_dvdtitle.SelectedItem == null && drp_dvdtitle.Items.Count > 0)
\r
2191 drp_dvdtitle.SelectedIndex = 0;
\r
2194 // Enable the creation of chapter markers if the file is an image of a dvd
\r
2195 if (drop_chapterStart.Items.Count > 0)
\r
2198 int.TryParse(drop_chapterStart.Items[0].ToString(), out start);
\r
2199 int.TryParse(drop_chapterFinish.Items[drop_chapterFinish.Items.Count - 1].ToString(), out end);
\r
2200 if (end > start) Check_ChapterMarkers.Enabled = true;
\r
2203 Check_ChapterMarkers.Enabled = false;
\r
2204 Check_ChapterMarkers.Checked = false;
\r
2205 data_chpt.Rows.Clear();
\r
2209 // If no titles were found, Display an error message
\r
2210 if (drp_dvdtitle.Items.Count == 0)
\r
2213 "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
2214 "Error", MessageBoxButtons.OK, MessageBoxIcon.Hand);
\r
2215 sourcePath = string.Empty;
\r
2217 UpdateSourceLabel();
\r
2219 // This is a bit of a hack to fix the queue editing.
\r
2220 // 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
2221 // When this occures, we want to repopulate their old settings.
\r
2222 if (queueEdit != null)
\r
2225 if (queueEdit.Query != null)
\r
2227 // Send the query from the file to the Query Parser class
\r
2228 EncodeTask presetQuery = QueryParserUtility.Parse(queueEdit.Query);
\r
2230 // Now load the preset
\r
2231 PresetLoader.LoadPreset(this, presetQuery, "Load Back From Queue");
\r
2233 // Set the destination path
\r
2234 this.text_destination.Text = queueEdit.Destination;
\r
2236 // The x264 widgets will need updated, so do this now:
\r
2237 x264Panel.StandardizeOptString();
\r
2238 x264Panel.SetCurrentSettingsInPanel();
\r
2240 // Set the crop label
\r
2241 PictureSettings.SetPresetCropWarningLabel(null);
\r
2247 // Enable the GUI components and enable any disabled components
\r
2250 catch (Exception exc)
\r
2252 MessageBox.Show("frmMain.cs - updateUIafterScan " + exc, "Error", MessageBoxButtons.OK,
\r
2253 MessageBoxIcon.Error);
\r
2259 /// Enable the GUI
\r
2261 private void EnableGUI()
\r
2265 if (InvokeRequired)
\r
2266 BeginInvoke(new UpdateWindowHandler(EnableGUI));
\r
2267 foreach (Control ctrl in Controls)
\r
2268 ctrl.Enabled = true;
\r
2269 btn_start.Enabled = true;
\r
2270 btn_showQueue.Enabled = true;
\r
2271 btn_add2Queue.Enabled = true;
\r
2272 tb_preview.Enabled = true;
\r
2273 btn_source.Enabled = true;
\r
2274 mnu_killCLI.Visible = false;
\r
2276 catch (Exception exc)
\r
2278 MessageBox.Show("frmMain.cs - EnableGUI() " + exc, "Error", MessageBoxButtons.OK, MessageBoxIcon.Error);
\r
2283 /// Disable the GUI
\r
2285 private void DisableGUI()
\r
2287 foreach (Control ctrl in Controls)
\r
2288 if (!(ctrl is StatusStrip || ctrl is MenuStrip || ctrl is ToolStrip))
\r
2289 ctrl.Enabled = false;
\r
2291 labelSource.Enabled = true;
\r
2292 labelStaticSource.Enabled = true;
\r
2293 SourceLayoutPanel.Enabled = true;
\r
2294 btn_source.Enabled = false;
\r
2295 btn_start.Enabled = false;
\r
2296 btn_showQueue.Enabled = false;
\r
2297 btn_add2Queue.Enabled = false;
\r
2298 tb_preview.Enabled = false;
\r
2299 mnu_killCLI.Visible = true;
\r
2305 private void KillScan()
\r
2307 SourceScan.ScanCompleted -= this.SourceScanScanCompleted;
\r
2311 SourceScan.Stop();
\r
2313 labelSource.Text = "Scan Cancelled";
\r
2319 private void ResetGUI()
\r
2321 drp_dvdtitle.Items.Clear();
\r
2322 drop_chapterStart.Items.Clear();
\r
2323 drop_chapterFinish.Items.Clear();
\r
2324 lbl_duration.Text = "Select a Title";
\r
2325 PictureSettings.lbl_src_res.Text = "Select a Title";
\r
2326 sourcePath = String.Empty;
\r
2327 text_destination.Text = String.Empty;
\r
2328 selectedTitle = null;
\r
2332 /// Update the Source Label
\r
2334 private void UpdateSourceLabel()
\r
2336 labelSource.Text = string.IsNullOrEmpty(sourcePath) ? "Select \"Source\" to continue." : this.SourceName;
\r
2340 /// Take a job from the Queue, rescan it, and reload the GUI for that job.
\r
2342 /// <param name="job">
\r
2345 public void RecievingJob(QueueTask job)
\r
2348 this.currentlySelectedPreset = null;
\r
2349 x264Panel.Reset2Defaults();
\r
2352 queueEdit = job; // Nasty but will do for now. TODO
\r
2353 StartScan(job.Source, job.Title);
\r
2358 #region GUI Functions and Actions
\r
2361 /// Set the GUI to it's finished encoding state.
\r
2363 private void SetEncodeFinished()
\r
2367 if (InvokeRequired)
\r
2369 BeginInvoke(new UpdateWindowHandler(SetEncodeFinished));
\r
2373 lbl_encode.Text = "Encoding Finished";
\r
2374 ProgressBarStatus.Visible = false;
\r
2375 btn_start.Text = "Start";
\r
2376 btn_start.ToolTipText = "Start the encoding process";
\r
2377 btn_start.Image = Properties.Resources.Play;
\r
2379 // If the window is minimized, display the notification in a popup.
\r
2380 if (Properties.Settings.Default.trayIconAlerts)
\r
2381 if (FormWindowState.Minimized == this.WindowState)
\r
2383 notifyIcon.BalloonTipText = lbl_encode.Text;
\r
2384 notifyIcon.ShowBalloonTip(500);
\r
2387 catch (Exception exc)
\r
2389 MessageBox.Show(exc.ToString());
\r
2394 /// Set the GUI to it's started encoding state.
\r
2396 private void SetEncodeStarted()
\r
2400 if (InvokeRequired)
\r
2402 BeginInvoke(new UpdateWindowHandler(SetEncodeStarted));
\r
2405 lbl_encode.Visible = true;
\r
2406 ProgressBarStatus.Value = 0;
\r
2407 ProgressBarStatus.Visible = true;
\r
2408 lbl_encode.Text = "Encoding with " + this.queueProcessor.QueueManager.Count + " encode(s) pending";
\r
2409 btn_start.Text = "Stop";
\r
2410 btn_start.ToolTipText = "Stop the encoding process.";
\r
2411 btn_start.Image = Properties.Resources.stop;
\r
2413 catch (Exception exc)
\r
2415 MessageBox.Show(exc.ToString());
\r
2420 /// Display the Encode Status
\r
2422 /// <param name="sender">
\r
2425 /// <param name="e">
\r
2428 private void EncodeQueue_EncodeStatusChanged(object sender, EncodeProgressEventArgs e)
\r
2430 if (this.InvokeRequired)
\r
2432 this.BeginInvoke(new EncodeProgessStatus(EncodeQueue_EncodeStatusChanged), new[] { sender, e });
\r
2438 "{0:00.00}%, FPS: {1:000.0}, Avg FPS: {2:000.0}, Time Remaining: {3}, Encode(s) Pending {4}",
\r
2439 e.PercentComplete,
\r
2440 e.CurrentFrameRate,
\r
2441 e.AverageFrameRate,
\r
2442 e.EstimatedTimeLeft,
\r
2443 this.queueProcessor.QueueManager.Count);
\r
2445 ProgressBarStatus.Value = (int)Math.Round(e.PercentComplete);
\r
2449 /// Set the DVD Drive selection in the "Source" Menu
\r
2451 private void SetDriveSelectionMenuItem()
\r
2455 if (InvokeRequired)
\r
2457 BeginInvoke(new UpdateWindowHandler(SetDriveSelectionMenuItem));
\r
2461 drives = UtilityService.GetDrives();
\r
2463 List<ToolStripMenuItem> menuItems = new List<ToolStripMenuItem>();
\r
2464 foreach (DriveInformation drive in drives)
\r
2466 ToolStripMenuItem menuItem = new ToolStripMenuItem
\r
2468 Name = drive.ToString(),
\r
2469 Text = drive.RootDirectory + " (" + drive.VolumeLabel + ")",
\r
2470 Image = Resources.disc_small
\r
2472 menuItem.Click += new EventHandler(MnuDvdDriveClick);
\r
2473 menuItems.Add(menuItem);
\r
2476 foreach (ToolStripMenuItem item in menuItems)
\r
2477 btn_source.DropDownItems.Add(item);
\r
2479 catch (Exception exc)
\r
2481 MessageBox.Show("Error in SetDriveSelectionMenuItem" + exc);
\r
2486 /// Access the preset Handler and setup the preset panel.
\r
2488 private void LoadPresetPanel()
\r
2490 if (presetHandler.CheckIfPresetsAreOutOfDate())
\r
2491 if (!Settings.Default.presetNotification)
\r
2492 MessageBox.Show(this,
\r
2493 "HandBrake has determined your built-in presets are out of date... These presets will now be updated.",
\r
2494 "Preset Update", MessageBoxButtons.OK, MessageBoxIcon.Information);
\r
2496 presetHandler.GetPresetPanel(ref treeView_presets);
\r
2497 treeView_presets.Update();
\r
2501 /// Get the title from the selected item in the title dropdown.
\r
2506 private int GetTitle()
\r
2509 if (drp_dvdtitle.SelectedItem != null)
\r
2511 string[] titleInfo = drp_dvdtitle.SelectedItem.ToString().Split(' ');
\r
2512 int.TryParse(titleInfo[0], out title);
\r
2519 /// Handle the Update Check Finishing.
\r
2521 /// <param name="result">
\r
2524 private void UpdateCheckDoneMenu(IAsyncResult result)
\r
2526 // Make sure it's running on the calling thread
\r
2527 if (InvokeRequired)
\r
2529 Invoke(new MethodInvoker(() => this.UpdateCheckDoneMenu(result)));
\r
2532 UpdateCheckInformation info;
\r
2535 // Get the information about the new build, if any, and close the window
\r
2536 info = UpdateService.EndCheckForUpdates(result);
\r
2538 if (info.NewVersionAvailable && info.BuildInformation != null)
\r
2540 UpdateInfo updateWindow = new UpdateInfo(info.BuildInformation, Settings.Default.hb_version, Settings.Default.hb_build.ToString());
\r
2541 updateWindow.ShowDialog();
\r
2544 MessageBox.Show("There are no new updates at this time.", "Update Check", MessageBoxButtons.OK,
\r
2545 MessageBoxIcon.Information);
\r
2546 lbl_updateCheck.Visible = false;
\r
2549 catch (Exception ex)
\r
2551 if ((bool)result.AsyncState)
\r
2553 "Unable to check for updates, Please try again later.\n\nDetailed Error Information:\n" + ex,
\r
2554 "Error", MessageBoxButtons.OK, MessageBoxIcon.Error);
\r
2563 /// Handle GUI shortcuts
\r
2565 /// <param name="msg">Message</param>
\r
2566 /// <param name="keyData">Keys</param>
\r
2567 /// <returns>Bool</returns>
\r
2568 protected override bool ProcessCmdKey(ref Message msg, Keys keyData)
\r
2570 if (keyData == (Keys.Control | Keys.S))
\r
2572 btn_start_Click(this, new EventArgs());
\r
2576 if (keyData == (Keys.Control | Keys.Shift | Keys.A))
\r
2578 btn_add2Queue_Click(this, new EventArgs());
\r
2581 return base.ProcessCmdKey(ref msg, keyData);
\r
2585 /// If the queue is being processed, prompt the user to confirm application close.
\r
2587 /// <param name="e">FormClosingEventArgs</param>
\r
2588 protected override void OnFormClosing(FormClosingEventArgs e)
\r
2592 // If currently encoding, the queue isn't paused, and there are queue items to process, prompt to confirm close.
\r
2593 if (this.queueProcessor.EncodeService.IsEncoding)
\r
2595 DialogResult result =
\r
2597 "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
2598 "Close HandBrake?",
\r
2599 MessageBoxButtons.YesNo,
\r
2600 MessageBoxIcon.Question);
\r
2602 if (result == DialogResult.No)
\r
2608 this.queueProcessor.Pause();
\r
2609 this.queueProcessor.EncodeService.Stop();
\r
2612 if (SourceScan.IsScanning)
\r
2614 SourceScan.Stop();
\r
2617 SourceScan.ScanCompleted -= this.SourceScanScanCompleted;
\r
2618 SourceScan.ScanStatusChanged -= this.SourceScanScanStatusChanged;
\r
2620 catch (Exception exc)
\r
2622 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
2626 base.OnFormClosing(e);
\r
2632 // This is the END of the road ****************************************
\r