2 This file is part of the HandBrake source code.
\r
3 Homepage: <http://handbrake.fr/>.
\r
4 It may be used under the terms of the GNU General Public License. */
\r
9 using System.Collections.Generic;
\r
10 using System.ComponentModel;
\r
11 using System.Diagnostics;
\r
12 using System.Drawing;
\r
13 using System.Globalization;
\r
16 using System.Threading;
\r
17 using System.Windows.Forms;
\r
21 using HandBrake.ApplicationServices.EventArgs;
\r
22 using HandBrake.ApplicationServices.Utilities;
\r
23 using HandBrake.Framework.Model;
\r
24 using HandBrake.Framework.Services;
\r
25 using HandBrake.Framework.Views;
\r
26 using HandBrake.ApplicationServices.Functions;
\r
27 using HandBrake.ApplicationServices.Model;
\r
28 using HandBrake.ApplicationServices.Parsing;
\r
29 using HandBrake.ApplicationServices.Services;
\r
30 using HandBrake.ApplicationServices.Services.Interfaces;
\r
32 using Handbrake.ToolWindows;
\r
37 using Main = Handbrake.Functions.Main;
\r
42 public partial class frmMain : Form
\r
44 // Objects which may be used by one or more other objects *************
\r
45 private IQueueProcessor queueProcessor = new QueueProcessor(Program.InstanceId);
\r
46 private PresetService presetHandler = new PresetService();
\r
48 // Windows ************************************************************
\r
49 private frmQueue queueWindow;
\r
50 private frmPreview qtpreview;
\r
51 private frmActivityWindow activityWindow;
\r
53 // Globals: Mainly used for tracking. *********************************
\r
54 public Title selectedTitle;
\r
55 public string sourcePath;
\r
56 private SourceType selectedSourceType;
\r
57 private string dvdDrivePath;
\r
58 private string dvdDriveLabel;
\r
59 private Preset currentlySelectedPreset;
\r
60 private Source currentSource;
\r
62 private IScan SourceScan;
\r
63 private List<DriveInformation> drives;
\r
64 private QueueTask queueEdit;
\r
66 // Delegates **********************************************************
\r
67 private delegate void UpdateWindowHandler();
\r
69 // Applicaiton Startup ************************************************
\r
74 /// Gets SourceName.
\r
76 public string SourceName
\r
80 if (this.selectedSourceType == SourceType.DvdDrive)
\r
82 return this.dvdDriveLabel;
\r
85 if (selectedTitle != null && !string.IsNullOrEmpty(selectedTitle.SourceName))
\r
87 return Path.GetFileName(selectedTitle.SourceName);
\r
90 // We have a drive, selected as a folder.
\r
91 if (this.sourcePath.EndsWith("\\"))
\r
93 drives = UtilityService.GetDrives();
\r
94 foreach (DriveInformation item in drives)
\r
96 if (item.RootDirectory.Contains(this.sourcePath))
\r
98 return item.VolumeLabel;
\r
103 if (Path.GetFileNameWithoutExtension(this.sourcePath) != "VIDEO_TS")
\r
104 return Path.GetFileNameWithoutExtension(this.sourcePath);
\r
106 return Path.GetFileNameWithoutExtension(Path.GetDirectoryName(this.sourcePath));
\r
112 #region Application Startup
\r
115 /// Initializes a new instance of the <see cref="frmMain"/> class.
\r
117 /// <param name="args">
\r
118 /// The arguments passed in on application startup.
\r
120 public frmMain(string[] args)
\r
122 InitializeComponent();
\r
123 this.presetsToolStrip.Renderer = new ToolStripRenderOverride();
\r
125 // We can use LibHB, if the library hb.dll exists.
\r
126 this.SourceScan = File.Exists("hb.dll") ? (IScan)new LibScan() : new ScanService();
\r
128 // Update the users config file with the CLI version data.
\r
129 Main.SetCliVersionData();
\r
131 if (Settings.Default.hb_version.Contains("svn"))
\r
133 this.Text += " " + Settings.Default.hb_version;
\r
136 // Check for new versions, if update checking is enabled
\r
137 if (Settings.Default.updateStatus)
\r
139 if (DateTime.Now.Subtract(Settings.Default.lastUpdateCheckDate).TotalDays > Properties.Settings.Default.daysBetweenUpdateCheck)
\r
141 // Set when the last update was
\r
142 Settings.Default.lastUpdateCheckDate = DateTime.Now;
\r
143 Settings.Default.Save();
\r
144 string url = Settings.Default.hb_build.ToString().EndsWith("1")
\r
145 ? Settings.Default.appcast_unstable
\r
146 : Settings.Default.appcast;
\r
147 UpdateService.BeginCheckForUpdates(new AsyncCallback(UpdateCheckDone), false, url, Settings.Default.hb_build, Settings.Default.skipversion, Settings.Default.hb_version);
\r
151 // Clear the log files in the background
\r
152 if (Settings.Default.clearOldLogs)
\r
154 Thread clearLog = new Thread(() => UtilityService.ClearLogFiles(30));
\r
158 // Setup the GUI components
\r
159 LoadPresetPanel(); // Load the Preset Panel
\r
160 treeView_presets.ExpandAll();
\r
161 lbl_encode.Text = string.Empty;
\r
162 drop_mode.SelectedIndex = 0;
\r
163 queueWindow = new frmQueue(this.queueProcessor, this); // Prepare the Queue
\r
164 if (!Settings.Default.QueryEditorTab)
\r
165 tabs_panel.TabPages.RemoveAt(7); // Remove the query editor tab if the user does not want it enabled.
\r
166 if (Settings.Default.tooltipEnable)
\r
167 ToolTip.Active = true;
\r
169 // Load the user's default settings or Normal Preset
\r
170 if (Settings.Default.defaultPreset != string.Empty && presetHandler.GetPreset(Properties.Settings.Default.defaultPreset) != null)
\r
172 string query = presetHandler.GetPreset(Settings.Default.defaultPreset).Query;
\r
175 x264Panel.Reset2Defaults();
\r
177 EncodeTask presetQuery = QueryParserUtility.Parse(query);
\r
178 PresetLoader.LoadPreset(this, presetQuery, Settings.Default.defaultPreset);
\r
180 x264Panel.StandardizeOptString();
\r
181 x264Panel.SetCurrentSettingsInPanel();
\r
185 loadNormalPreset();
\r
187 // Register with Growl (if not using Growl for the encoding completion action, this wont hurt anything)
\r
188 GrowlCommunicator.Register();
\r
190 // Event Handlers and Queue Recovery
\r
192 Main.RecoverQueue(this.queueProcessor);
\r
194 // If have a file passed in via command arguemtents, check it's a file and try scanning it.
\r
195 if (args.Length >= 1 && (File.Exists(args[0]) || Directory.Exists(args[0])))
\r
197 this.StartScan(args[0], 0);
\r
202 /// When the update check is done, process the results.
\r
204 /// <param name="result">IAsyncResult result</param>
\r
205 private void UpdateCheckDone(IAsyncResult result)
\r
207 if (InvokeRequired)
\r
209 Invoke(new MethodInvoker(() => UpdateCheckDone(result)));
\r
215 UpdateCheckInformation info = UpdateService.EndCheckForUpdates(result);
\r
217 if (info.NewVersionAvailable)
\r
219 UpdateInfo updateWindow = new UpdateInfo(info.BuildInformation, Settings.Default.hb_version, Settings.Default.hb_build.ToString());
\r
220 updateWindow.ShowDialog();
\r
223 catch (Exception ex)
\r
225 if ((bool)result.AsyncState)
\r
226 Main.ShowExceptiowWindow("Unable to check for updates, Please try again later.", ex.ToString());
\r
234 // Encoding Events for setting up the GUI
\r
235 private void events()
\r
237 // Handle Widget changes when preset is selected.
\r
238 RegisterPresetEventHandler();
\r
240 // Handle Window Resize
\r
241 if (Settings.Default.MainWindowMinimize)
\r
242 this.Resize += this.frmMain_Resize;
\r
244 // Handle Encode Start / Finish / Pause
\r
245 this.queueProcessor.EncodeService.EncodeStarted += this.encodeStarted;
\r
246 this.queueProcessor.EncodeService.EncodeCompleted += encodeEnded;
\r
248 // Scan Started and Completed Events
\r
249 SourceScan.ScanStatusChanged += this.SourceScanScanStatusChanged;
\r
250 SourceScan.ScanCompleted += this.SourceScanScanCompleted;
\r
252 // Handle a file being draged onto the GUI.
\r
253 this.DragEnter += frmMain_DragEnter;
\r
254 this.DragDrop += this.frmMain_DragDrop;
\r
257 // 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
258 private void RegisterPresetEventHandler()
\r
261 drop_format.SelectedIndexChanged += this.changePresetLabel;
\r
262 check_largeFile.CheckedChanged += this.changePresetLabel;
\r
263 check_iPodAtom.CheckedChanged += this.changePresetLabel;
\r
264 check_optimiseMP4.CheckedChanged += this.changePresetLabel;
\r
266 // Picture Settings
\r
267 PictureSettings.PictureSettingsChanged += this.changePresetLabel;
\r
270 Filters.FilterSettingsChanged += this.changePresetLabel;
\r
273 drp_videoEncoder.SelectedIndexChanged += this.changePresetLabel;
\r
274 check_2PassEncode.CheckedChanged += this.changePresetLabel;
\r
275 check_turbo.CheckedChanged += this.changePresetLabel;
\r
276 text_bitrate.TextChanged += this.changePresetLabel;
\r
277 slider_videoQuality.ValueChanged += this.changePresetLabel;
\r
280 AudioSettings.AudioListChanged += this.changePresetLabel;
\r
283 x264Panel.rtf_x264Query.TextChanged += this.changePresetLabel;
\r
286 private void UnRegisterPresetEventHandler()
\r
288 // Output Settings
\r
289 drop_format.SelectedIndexChanged -= this.changePresetLabel;
\r
290 check_largeFile.CheckedChanged -= this.changePresetLabel;
\r
291 check_iPodAtom.CheckedChanged -= this.changePresetLabel;
\r
292 check_optimiseMP4.CheckedChanged -= this.changePresetLabel;
\r
294 // Picture Settings
\r
295 PictureSettings.PictureSettingsChanged -= this.changePresetLabel;
\r
298 Filters.FilterSettingsChanged -= this.changePresetLabel;
\r
301 drp_videoEncoder.SelectedIndexChanged -= this.changePresetLabel;
\r
302 check_2PassEncode.CheckedChanged -= this.changePresetLabel;
\r
303 check_turbo.CheckedChanged -= this.changePresetLabel;
\r
304 text_bitrate.TextChanged -= this.changePresetLabel;
\r
305 slider_videoQuality.ValueChanged -= this.changePresetLabel;
\r
308 AudioSettings.AudioListChanged -= this.changePresetLabel;
\r
311 x264Panel.rtf_x264Query.TextChanged -= this.changePresetLabel;
\r
314 private void changePresetLabel(object sender, EventArgs e)
\r
316 labelPreset.Text = "Output Settings (Preset: Custom)";
\r
317 this.currentlySelectedPreset = null;
\r
320 private static void frmMain_DragEnter(object sender, DragEventArgs e)
\r
322 if (e.Data.GetDataPresent(DataFormats.FileDrop, false))
\r
323 e.Effect = DragDropEffects.All;
\r
326 private void frmMain_DragDrop(object sender, DragEventArgs e)
\r
328 string[] fileList = e.Data.GetData(DataFormats.FileDrop) as string[];
\r
329 sourcePath = string.Empty;
\r
331 if (fileList != null)
\r
333 if (!string.IsNullOrEmpty(fileList[0]))
\r
335 this.selectedSourceType = SourceType.VideoFile;
\r
336 StartScan(fileList[0], 0);
\r
339 UpdateSourceLabel();
\r
342 UpdateSourceLabel();
\r
345 private void encodeStarted(object sender, EventArgs e)
\r
347 SetEncodeStarted();
\r
348 this.queueProcessor.EncodeService.EncodeStatusChanged += EncodeQueue_EncodeStatusChanged;
\r
351 private void encodeEnded(object sender, EventArgs e)
\r
353 this.queueProcessor.EncodeService.EncodeStatusChanged -= EncodeQueue_EncodeStatusChanged;
\r
354 SetEncodeFinished();
\r
358 // User Interface Menus / Tool Strips *********************************
\r
363 /// Kill The scan menu Item
\r
365 /// <param name="sender">
\r
368 /// <param name="e">
\r
371 private void mnu_killCLI_Click(object sender, EventArgs e)
\r
377 /// Exit the Application Menu Item
\r
379 /// <param name="sender">
\r
382 /// <param name="e">
\r
385 private void mnu_exit_Click(object sender, EventArgs e)
\r
387 Application.Exit();
\r
395 /// Menu - Start Button
\r
397 /// <param name="sender">
\r
400 /// <param name="e">
\r
403 private void mnu_encode_Click(object sender, EventArgs e)
\r
405 queueWindow.Show();
\r
409 /// Menu - Display the Log Window
\r
411 /// <param name="sender">
\r
414 /// <param name="e">
\r
417 private void mnu_encodeLog_Click(object sender, EventArgs e)
\r
419 this.btn_ActivityWindow_Click(this, null);
\r
423 /// Menu - Display the Options Window
\r
425 /// <param name="sender">
\r
428 /// <param name="e">
\r
431 private void mnu_options_Click(object sender, EventArgs e)
\r
433 Form options = new frmOptions(this);
\r
434 options.ShowDialog();
\r
439 #region Help Menu (Toolbar)
\r
442 /// Menu - Display the User Guide Web Page
\r
444 /// <param name="sender">The Sender</param>
\r
445 /// <param name="e">The EventArgs</param>
\r
446 private void MnuUserGuide_Click(object sender, EventArgs e)
\r
448 Process.Start("http://trac.handbrake.fr/wiki/HandBrakeGuide");
\r
452 /// Check for Updates
\r
454 /// <param name="sender">The Sender</param>
\r
455 /// <param name="e">The EventArgs</param>
\r
456 private void MnuCheckForUpdates_Click(object sender, EventArgs e)
\r
458 lbl_updateCheck.Visible = true;
\r
459 Settings.Default.lastUpdateCheckDate = DateTime.Now;
\r
460 Settings.Default.Save();
\r
461 string url = Settings.Default.hb_build.ToString().EndsWith("1")
\r
462 ? Settings.Default.appcast_unstable
\r
463 : Settings.Default.appcast;
\r
464 UpdateService.BeginCheckForUpdates(new AsyncCallback(UpdateCheckDoneMenu), false, url, Settings.Default.hb_build, Settings.Default.skipversion, Settings.Default.hb_version);
\r
468 /// Menu - Display the About Window
\r
470 /// <param name="sender">The Sender</param>
\r
471 /// <param name="e">The EventArgs</param>
\r
472 private void MnuAboutHandBrake_Click(object sender, EventArgs e)
\r
474 using (frmAbout About = new frmAbout())
\r
476 About.ShowDialog();
\r
485 /// RMenu - Expand All
\r
487 /// <param name="sender">
\r
490 /// <param name="e">
\r
493 private void pmnu_expandAll_Click(object sender, EventArgs e)
\r
495 treeView_presets.ExpandAll();
\r
499 /// RMenu - Collaspe All
\r
501 /// <param name="sender">
\r
504 /// <param name="e">
\r
507 private void pmnu_collapse_Click(object sender, EventArgs e)
\r
509 treeView_presets.CollapseAll();
\r
513 /// Menu - Import Preset
\r
515 /// <param name="sender">
\r
518 /// <param name="e">
\r
521 private void pmnu_import_Click(object sender, EventArgs e)
\r
527 /// RMenu - Save Changes to Preset
\r
529 /// <param name="sender">
\r
532 /// <param name="e">
\r
535 private void pmnu_saveChanges_Click(object sender, EventArgs e)
\r
537 DialogResult result =
\r
539 "Do you wish to include picture settings when updating the preset: " +
\r
540 treeView_presets.SelectedNode.Text, "Update Preset", MessageBoxButtons.YesNoCancel,
\r
541 MessageBoxIcon.Question);
\r
543 Preset preset = new Preset
\r
545 Name = this.treeView_presets.SelectedNode.Text,
\r
547 QueryGenerator.GenerateQueryForPreset(this, QueryPictureSettingsMode.SourceMaximum, true, 0, 0),
\r
548 CropSettings = (result == DialogResult.Yes)
\r
551 presetHandler.Update(preset);
\r
555 /// RMenu - Delete Preset
\r
557 /// <param name="sender">
\r
560 /// <param name="e">
\r
563 private void pmnu_delete_click(object sender, EventArgs e)
\r
565 if (treeView_presets.SelectedNode != null)
\r
567 presetHandler.Remove((Preset)treeView_presets.SelectedNode.Tag);
\r
568 treeView_presets.Nodes.Remove(treeView_presets.SelectedNode);
\r
570 treeView_presets.Select();
\r
574 /// Preset Menu Is Opening. Setup the Menu
\r
576 /// <param name="sender">
\r
579 /// <param name="e">
\r
582 private void presets_menu_Opening(object sender, CancelEventArgs e)
\r
584 // Make sure that the save menu is always disabled by default
\r
585 pmnu_saveChanges.Enabled = false;
\r
587 // Now enable the save menu if the selected preset is a user preset
\r
588 if (treeView_presets.SelectedNode != null)
\r
589 if (presetHandler.CheckIfPresetExists(treeView_presets.SelectedNode.Text))
\r
590 pmnu_saveChanges.Enabled = true;
\r
592 treeView_presets.Select();
\r
595 // Presets Management
\r
597 private void BtnAddPreset_Click(object sender, EventArgs e)
\r
599 Form preset = new frmAddPreset(this, presetHandler);
\r
600 if (preset.ShowDialog() == DialogResult.OK)
\r
602 TreeNode presetTreeview = new TreeNode(presetHandler.LastPresetAdded.Name) { ForeColor = Color.Black };
\r
603 treeView_presets.Nodes.Add(presetTreeview);
\r
604 presetHandler.LastPresetAdded = null;
\r
608 private void BtnRemovePreset_Click(object sender, EventArgs e)
\r
610 DialogResult result = MessageBox.Show("Are you sure you wish to delete the selected preset?", "Preset",
\r
611 MessageBoxButtons.YesNo, MessageBoxIcon.Question);
\r
612 if (result == DialogResult.Yes)
\r
614 if (treeView_presets.SelectedNode != null)
\r
616 presetHandler.Remove((Preset)treeView_presets.SelectedNode.Tag);
\r
617 treeView_presets.Nodes.Remove(treeView_presets.SelectedNode);
\r
620 treeView_presets.Select();
\r
624 private void MnuSetDefaultPreset_Click(object sender, EventArgs e)
\r
626 if (treeView_presets.SelectedNode != null)
\r
628 DialogResult result = MessageBox.Show("Are you sure you wish to set this preset as the default?",
\r
629 "Preset", MessageBoxButtons.YesNo, MessageBoxIcon.Question);
\r
630 if (result == DialogResult.Yes)
\r
632 Properties.Settings.Default.defaultPreset = treeView_presets.SelectedNode.Text;
\r
633 Properties.Settings.Default.Save();
\r
634 MessageBox.Show("New default preset set.", "Alert", MessageBoxButtons.OK, MessageBoxIcon.Information);
\r
638 MessageBox.Show("Please select a preset first.", "Warning", MessageBoxButtons.OK, MessageBoxIcon.Warning);
\r
641 private void MnuImportPreset_Click(object sender, EventArgs e)
\r
643 this.ImportPreset();
\r
646 private void MnuExportPreset_Click(object sender, EventArgs e)
\r
648 this.ExportPreset();
\r
651 private void MnuResetBuiltInPresets_Click(object sender, EventArgs e)
\r
653 presetHandler.UpdateBuiltInPresets(string.Empty);
\r
655 if (treeView_presets.Nodes.Count == 0)
\r
657 "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
658 "Error", MessageBoxButtons.OK, MessageBoxIcon.Error);
\r
660 MessageBox.Show("Presets have been updated!", "Alert", MessageBoxButtons.OK, MessageBoxIcon.Information);
\r
662 treeView_presets.ExpandAll();
\r
666 /// PresetBar Mouse Down event
\r
668 /// <param name="sender">
\r
671 /// <param name="e">
\r
674 private void treeview_presets_mouseUp(object sender, MouseEventArgs e)
\r
676 if (e.Button == MouseButtons.Right)
\r
677 treeView_presets.SelectedNode = treeView_presets.GetNodeAt(e.Location);
\r
678 else if (e.Button == MouseButtons.Left)
\r
680 if (treeView_presets.GetNodeAt(e.Location) != null)
\r
682 if (labelPreset.Text.Contains(treeView_presets.GetNodeAt(e.Location).Text))
\r
687 treeView_presets.Select();
\r
691 /// Preset Bar after selecting the preset
\r
693 /// <param name="sender">
\r
696 /// <param name="e">
\r
699 private void treeView_presets_AfterSelect(object sender, TreeViewEventArgs e)
\r
705 /// When the mouse moves, display a preset
\r
707 /// <param name="sender">The Sender</param>
\r
708 /// <param name="e">the MouseEventArgs</param>
\r
709 private void TreeViewPresetsMouseMove(object sender, MouseEventArgs e)
\r
711 TreeNode theNode = this.treeView_presets.GetNodeAt(e.X, e.Y);
\r
713 if ((theNode != null))
\r
715 // Change the ToolTip only if the pointer moved to a new node.
\r
716 if (theNode.ToolTipText != this.ToolTip.GetToolTip(this.treeView_presets))
\r
718 this.ToolTip.SetToolTip(this.treeView_presets, theNode.ToolTipText);
\r
721 else // Pointer is not over a node so clear the ToolTip.
\r
723 this.ToolTip.SetToolTip(this.treeView_presets, string.Empty);
\r
728 /// Preset Bar - Handle the Delete Key
\r
730 /// <param name="sender">
\r
733 /// <param name="e">
\r
736 private void treeView_presets_deleteKey(object sender, KeyEventArgs e)
\r
738 if (e.KeyCode == Keys.Delete)
\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
745 presetHandler.Remove((Preset)treeView_presets.SelectedNode.Tag);
\r
747 // Remember each nodes expanded status so we can reload it
\r
748 List<bool> nodeStatus = new List<bool>();
\r
749 foreach (TreeNode node in treeView_presets.Nodes)
\r
750 nodeStatus.Add(node.IsExpanded);
\r
752 // Now reload the preset panel
\r
755 // And finally, re-expand any of the nodes if required
\r
757 foreach (TreeNode node in treeView_presets.Nodes)
\r
769 /// Select the selected preset and setup the GUI
\r
771 private void selectPreset()
\r
773 if (treeView_presets.SelectedNode != null)
\r
775 // Ok, so, we've selected a preset. Now we want to load it.
\r
776 string presetName = treeView_presets.SelectedNode.Text;
\r
777 Preset preset = presetHandler.GetPreset(presetName);
\r
778 if (preset != null)
\r
780 string query = presetHandler.GetPreset(presetName).Query;
\r
784 // Ok, Reset all the H264 widgets before changing the preset
\r
785 x264Panel.Reset2Defaults();
\r
787 // Send the query from the file to the Query Parser class
\r
788 EncodeTask presetQuery = QueryParserUtility.Parse(query);
\r
790 // Now load the preset
\r
791 PresetLoader.LoadPreset(this, presetQuery, presetName);
\r
793 // The x264 widgets will need updated, so do this now:
\r
794 x264Panel.StandardizeOptString();
\r
795 x264Panel.SetCurrentSettingsInPanel();
\r
797 // Finally, let this window have a copy of the preset settings.
\r
798 this.currentlySelectedPreset = preset;
\r
799 PictureSettings.SetPresetCropWarningLabel(preset);
\r
806 /// Load the Normal Preset
\r
808 private void loadNormalPreset()
\r
810 foreach (TreeNode treenode in treeView_presets.Nodes)
\r
812 foreach (TreeNode node in treenode.Nodes)
\r
814 if (node.Text.Equals("Normal"))
\r
815 treeView_presets.SelectedNode = treeView_presets.Nodes[treenode.Index].Nodes[0];
\r
821 /// Import a plist preset
\r
823 private void ImportPreset()
\r
825 if (openPreset.ShowDialog() == DialogResult.OK)
\r
827 EncodeTask parsed = PlistPresetHandler.Import(openPreset.FileName);
\r
828 if (presetHandler.CheckIfPresetExists(parsed.PresetName + " (Imported)"))
\r
830 DialogResult result =
\r
831 MessageBox.Show("This preset appears to already exist. Would you like to overwrite it?",
\r
832 "Overwrite preset?",
\r
833 MessageBoxButtons.YesNo, MessageBoxIcon.Warning);
\r
834 if (result == DialogResult.Yes)
\r
836 PresetLoader.LoadPreset(this, parsed, parsed.PresetName);
\r
838 Preset preset = new Preset
\r
840 Name = parsed.PresetName + " (Imported)",
\r
841 Query = QueryGenerator.GenerateFullQuery(this),
\r
842 CropSettings = parsed.UsesPictureSettings
\r
845 presetHandler.Update(preset);
\r
850 PresetLoader.LoadPreset(this, parsed, parsed.PresetName);
\r
852 Preset preset = new Preset
\r
854 Name = parsed.PresetName + " (Imported)",
\r
855 Query = QueryGenerator.GenerateFullQuery(this),
\r
856 CropSettings = parsed.UsesPictureSettings
\r
859 if (presetHandler.Add(preset))
\r
861 TreeNode preset_treeview = new TreeNode(parsed.PresetName + " (Imported)")
\r
863 ForeColor = Color.Black
\r
865 treeView_presets.Nodes.Add(preset_treeview);
\r
872 /// Export a plist Preset
\r
874 private void ExportPreset()
\r
876 SaveFileDialog savefiledialog = new SaveFileDialog { Filter = "plist|*.plist" };
\r
878 if (treeView_presets.SelectedNode != null)
\r
880 if (savefiledialog.ShowDialog() == DialogResult.OK)
\r
882 Preset preset = presetHandler.GetPreset(treeView_presets.SelectedNode.Text);
\r
883 PlistPresetHandler.Export(savefiledialog.FileName, preset);
\r
893 /// 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
895 /// <param name="sender">
\r
898 /// <param name="e">
\r
901 private void btn_source_Click(object sender, EventArgs e)
\r
903 // Remove old Drive Menu Items.
\r
904 List<ToolStripMenuItem> itemsToRemove = new List<ToolStripMenuItem>();
\r
905 foreach (var item in btn_source.DropDownItems)
\r
907 if (item.GetType() == typeof(ToolStripMenuItem))
\r
909 ToolStripMenuItem menuItem = (ToolStripMenuItem)item;
\r
910 if (menuItem.Name.StartsWith("Drive"))
\r
912 itemsToRemove.Add(menuItem);
\r
917 foreach (ToolStripMenuItem item in itemsToRemove)
\r
918 btn_source.DropDownItems.Remove(item);
\r
920 Thread driveInfoThread = new Thread(SetDriveSelectionMenuItem);
\r
921 driveInfoThread.Start();
\r
925 /// Toolbar - Start The Encode
\r
927 /// <param name="sender">
\r
930 /// <param name="e">
\r
933 private void btn_start_Click(object sender, EventArgs e)
\r
935 if (btn_start.Text == "Stop")
\r
937 DialogResult result = !Properties.Settings.Default.showCliForInGuiEncodeStatus
\r
939 "Are you sure you wish to cancel the encode?\n\nPlease note: Stopping this encode will render the file unplayable. ",
\r
941 MessageBoxButtons.YesNo,
\r
942 MessageBoxIcon.Question)
\r
944 "Are you sure you wish to cancel the encode?",
\r
946 MessageBoxButtons.YesNo,
\r
947 MessageBoxIcon.Question);
\r
949 if (result == DialogResult.Yes)
\r
952 this.queueProcessor.Pause();
\r
954 if (Settings.Default.showCliForInGuiEncodeStatus)
\r
955 this.queueProcessor.EncodeService.SafelyStop();
\r
957 this.queueProcessor.EncodeService.Stop();
\r
962 // 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
963 string jobSourcePath = !string.IsNullOrEmpty(rtf_query.Text) ? Main.GetSourceFromQuery(rtf_query.Text) : sourcePath;
\r
964 string jobDestination = !string.IsNullOrEmpty(rtf_query.Text) ? Main.GetDestinationFromQuery(rtf_query.Text) : text_destination.Text;
\r
966 if (this.queueProcessor.QueueManager.Count != 0 || (!string.IsNullOrEmpty(jobSourcePath) && !string.IsNullOrEmpty(jobDestination)))
\r
968 string generatedQuery = QueryGenerator.GenerateFullQuery(this);
\r
969 string specifiedQuery = rtf_query.Text != string.Empty
\r
971 : QueryGenerator.GenerateFullQuery(this);
\r
972 string query = string.Empty;
\r
974 // Check to make sure the generated query matches the GUI settings
\r
975 if (Properties.Settings.Default.PromptOnUnmatchingQueries && !string.IsNullOrEmpty(specifiedQuery) &&
\r
976 generatedQuery != specifiedQuery)
\r
978 DialogResult result = MessageBox.Show("The query under the \"Query Editor\" tab " +
\r
979 "does not match the current GUI settings.\n\nBecause the manual query takes " +
\r
980 "priority over the GUI, your recently updated settings will not be taken " +
\r
981 "into account when encoding this job." +
\r
982 Environment.NewLine + Environment.NewLine +
\r
983 "Do you want to replace the manual query with the updated GUI-generated query?",
\r
984 "Manual Query does not Match GUI",
\r
985 MessageBoxButtons.YesNoCancel, MessageBoxIcon.Asterisk,
\r
986 MessageBoxDefaultButton.Button3);
\r
990 case DialogResult.Yes:
\r
991 // Replace the manual query with the generated one
\r
992 query = generatedQuery;
\r
993 rtf_query.Text = generatedQuery;
\r
995 case DialogResult.No:
\r
996 // Use the manual query
\r
997 query = specifiedQuery;
\r
999 case DialogResult.Cancel:
\r
1000 // Don't start the encode
\r
1006 query = specifiedQuery;
\r
1009 DialogResult overwrite = DialogResult.Yes;
\r
1010 if (!string.IsNullOrEmpty(jobDestination) && File.Exists(jobDestination))
\r
1012 overwrite = MessageBox.Show(
\r
1013 "The destination file already exists. Are you sure you want to overwrite it?",
\r
1014 "Overwrite File?",
\r
1015 MessageBoxButtons.YesNo,
\r
1016 MessageBoxIcon.Question);
\r
1019 if (overwrite == DialogResult.Yes)
\r
1021 QueueTask task = new QueueTask(query)
\r
1023 Title = this.GetTitle(),
\r
1024 Source = jobSourcePath,
\r
1025 Destination = jobDestination,
\r
1026 CustomQuery = (this.rtf_query.Text != string.Empty)
\r
1029 if (this.queueProcessor.QueueManager.Count == 0)
\r
1030 this.queueProcessor.QueueManager.Add(task);
\r
1032 queueWindow.SetQueue();
\r
1033 if (this.queueProcessor.QueueManager.Count > 1)
\r
1034 queueWindow.Show(false);
\r
1036 SetEncodeStarted(); // Encode is running, so setup the GUI appropriately
\r
1037 this.queueProcessor.Start(); // Start The Queue Encoding Process
\r
1042 else if (string.IsNullOrEmpty(sourcePath) || string.IsNullOrEmpty(text_destination.Text))
\r
1043 MessageBox.Show("No source or destination selected.", "Warning", MessageBoxButtons.OK,
\r
1044 MessageBoxIcon.Warning);
\r
1049 /// Toolbar - Add the current job to the Queue
\r
1051 /// <param name="sender">
\r
1054 /// <param name="e">
\r
1057 private void btn_add2Queue_Click(object sender, EventArgs e)
\r
1059 // Add the item to the queue.
\r
1060 AddItemToQueue(true);
\r
1061 queueWindow.Show();
\r
1065 /// Add Multiple Items to the Queue at once.
\r
1067 /// <param name="sender">The Sender</param>
\r
1068 /// <param name="e">The EventArgs</param>
\r
1069 private void MnuAddMultiToQueueClick(object sender, EventArgs e)
\r
1071 if (!Settings.Default.autoNaming)
\r
1073 MessageBox.Show("Destination Auto Naming must be enabled in preferences for this feature to work.", "Error", MessageBoxButtons.OK, MessageBoxIcon.Error);
\r
1077 if (this.SourceScan.SouceData == null)
\r
1079 MessageBox.Show("You must first scan a source or collection of source to use this feature.", "Error", MessageBoxButtons.OK, MessageBoxIcon.Error);
\r
1083 BatchAdd batchAdd = new BatchAdd();
\r
1084 if (batchAdd.ShowDialog() == DialogResult.OK)
\r
1086 int min = batchAdd.Min;
\r
1087 int max = batchAdd.Max;
\r
1088 bool errors = false;
\r
1090 foreach (Title title in this.SourceScan.SouceData.Titles)
\r
1092 if (title.Duration.TotalMinutes > min && title.Duration.TotalMinutes < max)
\r
1095 this.drp_dvdtitle.SelectedItem = title;
\r
1097 if (!this.AddItemToQueue(false))
\r
1107 "One or more items could not be added to the queue. You should check your queue and manually add any missing jobs.",
\r
1109 MessageBoxButtons.OK,
\r
1110 MessageBoxIcon.Warning);
\r
1115 private bool AddItemToQueue(bool showError)
\r
1117 string query = QueryGenerator.GenerateFullQuery(this);
\r
1118 if (!string.IsNullOrEmpty(rtf_query.Text))
\r
1119 query = rtf_query.Text;
\r
1121 // 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
1122 string jobSourcePath = !string.IsNullOrEmpty(rtf_query.Text) ? Main.GetSourceFromQuery(rtf_query.Text) : sourcePath;
\r
1123 string jobDestination = !string.IsNullOrEmpty(rtf_query.Text) ? Main.GetDestinationFromQuery(rtf_query.Text) : text_destination.Text;
\r
1125 // Make sure we have a Source and Destination.
\r
1126 if (string.IsNullOrEmpty(jobSourcePath) || string.IsNullOrEmpty(jobDestination))
\r
1129 MessageBox.Show("No source or destination selected.", "Warning", MessageBoxButtons.OK, MessageBoxIcon.Warning);
\r
1133 // Make sure the destination path exists.
\r
1134 if (!Directory.Exists(Path.GetDirectoryName(jobDestination)))
\r
1137 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
1141 // Make sure we don't have a duplciate on the queue.
\r
1142 if (this.queueProcessor.QueueManager.CheckForDestinationPathDuplicates(jobDestination))
\r
1146 DialogResult result;
\r
1150 "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
1153 MessageBoxButtons.YesNo,
\r
1154 MessageBoxIcon.Warning);
\r
1156 if (result != DialogResult.Yes) return false;
\r
1165 QueueTask task = new QueueTask(query)
\r
1167 Title = this.GetTitle(),
\r
1168 Source = jobSourcePath,
\r
1169 Destination = jobDestination,
\r
1170 CustomQuery = (this.rtf_query.Text != string.Empty)
\r
1172 this.queueProcessor.QueueManager.Add(task);
\r
1174 lbl_encode.Text = this.queueProcessor.QueueManager.Count + " encode(s) pending in the queue";
\r
1180 /// Toolbar - Show the Queue
\r
1182 /// <param name="sender">
\r
1185 /// <param name="e">
\r
1188 private void btn_showQueue_Click(object sender, EventArgs e)
\r
1190 queueWindow.Show();
\r
1191 queueWindow.Activate();
\r
1195 /// Toolbar - Show the Preview Window
\r
1197 /// <param name="sender">
\r
1200 /// <param name="e">
\r
1203 private void tb_preview_Click(object sender, EventArgs e)
\r
1205 if (string.IsNullOrEmpty(sourcePath) || string.IsNullOrEmpty(text_destination.Text))
\r
1206 MessageBox.Show("No source or destination selected.", "Warning", MessageBoxButtons.OK,
\r
1207 MessageBoxIcon.Warning);
\r
1210 if (qtpreview == null)
\r
1212 qtpreview = new frmPreview(this);
\r
1215 else if (qtpreview.IsDisposed)
\r
1217 qtpreview = new frmPreview(this);
\r
1221 MessageBox.Show(qtpreview, "The preview window is already open!", "Warning", MessageBoxButtons.OK,
\r
1222 MessageBoxIcon.Warning);
\r
1227 /// Toolbar - Show the Activity log Window
\r
1229 /// <param name="sender">
\r
1232 /// <param name="e">
\r
1235 private void btn_ActivityWindow_Click(object sender, EventArgs e)
\r
1237 if (this.activityWindow == null || !this.activityWindow.IsHandleCreated)
\r
1238 this.activityWindow = new frmActivityWindow(this.queueProcessor.EncodeService, SourceScan);
\r
1240 this.activityWindow.Show();
\r
1241 this.activityWindow.Activate();
\r
1246 #region System Tray Icon
\r
1249 /// Handle Resizing of the main window when deaing with the Notify Icon
\r
1251 /// <param name="sender">
\r
1254 /// <param name="e">
\r
1257 private void frmMain_Resize(object sender, EventArgs e)
\r
1259 if (FormWindowState.Minimized == this.WindowState)
\r
1261 notifyIcon.Visible = true;
\r
1264 else if (FormWindowState.Normal == this.WindowState)
\r
1265 notifyIcon.Visible = false;
\r
1269 /// Double Click the Tray Icon
\r
1271 /// <param name="sender">
\r
1274 /// <param name="e">
\r
1277 private void notifyIcon_MouseDoubleClick(object sender, MouseEventArgs e)
\r
1279 this.Visible = true;
\r
1281 this.WindowState = FormWindowState.Normal;
\r
1282 notifyIcon.Visible = false;
\r
1286 /// Tray Icon - Restore Menu Item - Resture the Window
\r
1288 /// <param name="sender">
\r
1291 /// <param name="e">
\r
1294 private void btn_restore_Click(object sender, EventArgs e)
\r
1296 this.Visible = true;
\r
1298 this.WindowState = FormWindowState.Normal;
\r
1299 notifyIcon.Visible = false;
\r
1304 #region Main Window and Tab Control
\r
1307 private void BtnFolderScanClicked(object sender, EventArgs e)
\r
1309 this.btn_source.HideDropDown();
\r
1310 if (DVD_Open.ShowDialog() == DialogResult.OK)
\r
1312 this.selectedSourceType = SourceType.Folder;
\r
1313 SelectSource(DVD_Open.SelectedPath, 0);
\r
1316 UpdateSourceLabel();
\r
1319 private void BtnFileScanClicked(object sender, EventArgs e)
\r
1321 this.btn_source.HideDropDown();
\r
1322 if (ISO_Open.ShowDialog() == DialogResult.OK)
\r
1324 this.selectedSourceType = SourceType.VideoFile;
\r
1325 SelectSource(ISO_Open.FileName, 0);
\r
1328 UpdateSourceLabel();
\r
1331 private void MnuDvdDriveClick(object sender, EventArgs e)
\r
1333 ToolStripMenuItem item = sender as ToolStripMenuItem;
\r
1336 string driveId = item.Name.Replace("Drive", string.Empty);
\r
1338 if (int.TryParse(driveId, out id))
\r
1340 this.dvdDrivePath = drives[id].RootDirectory;
\r
1341 this.dvdDriveLabel = drives[id].VolumeLabel;
\r
1343 if (this.dvdDrivePath == null) return;
\r
1344 this.selectedSourceType = SourceType.DvdDrive;
\r
1345 SelectSource(this.dvdDrivePath, 0);
\r
1350 private void VideoTitleSpecificScanClick(object sender, EventArgs e)
\r
1352 this.btn_source.HideDropDown();
\r
1353 if (ISO_Open.ShowDialog() == DialogResult.OK)
\r
1355 this.selectedSourceType = SourceType.VideoFile;
\r
1357 int sourceTitle = 0;
\r
1358 TitleSpecificScan title = new TitleSpecificScan();
\r
1359 if (title.ShowDialog() == DialogResult.OK)
\r
1361 sourceTitle = title.Title;
\r
1362 SelectSource(ISO_Open.FileName, sourceTitle);
\r
1366 UpdateSourceLabel();
\r
1369 private void FolderTitleSpecificScanClick(object sender, EventArgs e)
\r
1371 this.btn_source.HideDropDown();
\r
1372 if (DVD_Open.ShowDialog() == DialogResult.OK)
\r
1374 this.selectedSourceType = SourceType.Folder;
\r
1376 int sourceTitle = 0;
\r
1377 TitleSpecificScan title = new TitleSpecificScan();
\r
1378 if (title.ShowDialog() == DialogResult.OK)
\r
1380 sourceTitle = title.Title;
\r
1381 SelectSource(DVD_Open.SelectedPath, sourceTitle);
\r
1385 UpdateSourceLabel();
\r
1388 private void SelectSource(string file, int titleSpecific)
\r
1390 Check_ChapterMarkers.Enabled = true;
\r
1391 sourcePath = string.Empty;
\r
1393 if (file == string.Empty) // Must have a file or path
\r
1395 UpdateSourceLabel();
\r
1399 sourcePath = Path.GetFileName(file);
\r
1400 StartScan(file, titleSpecific);
\r
1403 private void drp_dvdtitle_Click(object sender, EventArgs e)
\r
1405 if ((drp_dvdtitle.Items.Count == 1) && (drp_dvdtitle.Items[0].ToString() == "Automatic"))
\r
1407 "There are no titles to select. Please load a source file by clicking the 'Source' button above before trying to select a title.",
\r
1408 "Alert", MessageBoxButtons.OK, MessageBoxIcon.Asterisk);
\r
1411 private void drp_dvdtitle_SelectedIndexChanged(object sender, EventArgs e)
\r
1413 UnRegisterPresetEventHandler();
\r
1414 drop_mode.SelectedIndex = 0;
\r
1416 drop_chapterStart.Items.Clear();
\r
1417 drop_chapterFinish.Items.Clear();
\r
1419 // If the dropdown is set to automatic nothing else needs to be done.
\r
1420 // Otheriwse if its not, title data has to be loaded from parsing.
\r
1421 if (drp_dvdtitle.Text != "Automatic")
\r
1423 selectedTitle = drp_dvdtitle.SelectedItem as Title;
\r
1424 lbl_duration.Text = selectedTitle.Duration.ToString();
\r
1425 PictureSettings.CurrentlySelectedPreset = this.currentlySelectedPreset;
\r
1426 PictureSettings.Source = selectedTitle; // Setup Picture Settings Tab Control
\r
1428 // Populate the Angles dropdown
\r
1429 drop_angle.Items.Clear();
\r
1430 if (!Properties.Settings.Default.noDvdNav)
\r
1432 drop_angle.Visible = true;
\r
1433 lbl_angle.Visible = true;
\r
1435 for (int i = 1; i <= selectedTitle.AngleCount; i++)
\r
1436 drop_angle.Items.Add(i.ToString());
\r
1438 if (drop_angle.Items.Count == 0)
\r
1440 drop_angle.Visible = false;
\r
1441 lbl_angle.Visible = false;
\r
1444 if (drop_angle.Items.Count != 0)
\r
1445 drop_angle.SelectedIndex = 0;
\r
1449 drop_angle.Visible = false;
\r
1450 lbl_angle.Visible = false;
\r
1453 // Populate the Start chapter Dropdown
\r
1454 drop_chapterStart.Items.Clear();
\r
1455 drop_chapterStart.Items.AddRange(selectedTitle.Chapters.ToArray());
\r
1456 if (drop_chapterStart.Items.Count > 0)
\r
1457 drop_chapterStart.Text = drop_chapterStart.Items[0].ToString();
\r
1459 // Populate the Final Chapter Dropdown
\r
1460 drop_chapterFinish.Items.Clear();
\r
1461 drop_chapterFinish.Items.AddRange(selectedTitle.Chapters.ToArray());
\r
1462 if (drop_chapterFinish.Items.Count > 0)
\r
1463 drop_chapterFinish.Text = drop_chapterFinish.Items[drop_chapterFinish.Items.Count - 1].ToString();
\r
1465 // Populate the Audio Channels Dropdown
\r
1466 AudioSettings.SetTrackListFromPreset(selectedTitle, this.currentlySelectedPreset);
\r
1468 // Populate the Subtitles dropdown
\r
1469 Subtitles.SetSubtitleTrackAuto(selectedTitle.Subtitles.ToArray());
\r
1471 // Update the source label if we have multiple streams
\r
1472 if (selectedTitle != null)
\r
1473 if (!string.IsNullOrEmpty(selectedTitle.SourceName))
\r
1474 labelSource.Text = Path.GetFileName(selectedTitle.SourceName);
\r
1476 // Run the AutoName & ChapterNaming functions
\r
1477 if (Properties.Settings.Default.autoNaming)
\r
1479 string autoPath = Main.AutoName(this);
\r
1480 if (autoPath != null)
\r
1481 text_destination.Text = autoPath;
\r
1484 "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
1485 "Warning", MessageBoxButtons.OK, MessageBoxIcon.Warning);
\r
1488 data_chpt.Rows.Clear();
\r
1489 if (selectedTitle.Chapters.Count != 1)
\r
1491 DataGridView chapterGridView = Main.ChapterNaming(selectedTitle, data_chpt, drop_chapterFinish.Text);
\r
1492 if (chapterGridView != null)
\r
1493 data_chpt = chapterGridView;
\r
1497 Check_ChapterMarkers.Checked = false;
\r
1498 Check_ChapterMarkers.Enabled = false;
\r
1501 // Hack to force the redraw of the scrollbars which don't resize properly when the control is disabled.
\r
1502 data_chpt.Columns[0].Width = 166;
\r
1503 data_chpt.Columns[0].Width = 165;
\r
1505 RegisterPresetEventHandler();
\r
1508 private void chapersChanged(object sender, EventArgs e)
\r
1510 if (drop_mode.SelectedIndex != 0) // Function is not used if we are not in chapters mode.
\r
1513 Control ctl = (Control)sender;
\r
1514 int chapterStart, chapterEnd;
\r
1515 int.TryParse(drop_chapterStart.Text, out chapterStart);
\r
1516 int.TryParse(drop_chapterFinish.Text, out chapterEnd);
\r
1520 case "drop_chapterStart":
\r
1521 if (drop_chapterFinish.SelectedIndex == -1 && drop_chapterFinish.Items.Count != 0)
\r
1522 drop_chapterFinish.SelectedIndex = drop_chapterFinish.Items.Count - 1;
\r
1524 if (chapterEnd != 0)
\r
1525 if (chapterStart > chapterEnd)
\r
1526 drop_chapterFinish.Text = chapterStart.ToString();
\r
1528 case "drop_chapterFinish":
\r
1529 if (drop_chapterStart.Items.Count >= 1 && drop_chapterStart.SelectedIndex == -1)
\r
1530 drop_chapterStart.SelectedIndex = 0;
\r
1532 if (chapterStart != 0)
\r
1533 if (chapterEnd < chapterStart)
\r
1534 drop_chapterFinish.Text = chapterStart.ToString();
\r
1536 // Add more rows to the Chapter menu if needed.
\r
1537 if (Check_ChapterMarkers.Checked)
\r
1539 int i = data_chpt.Rows.Count, finish = 0;
\r
1540 int.TryParse(drop_chapterFinish.Text, out finish);
\r
1542 while (i < finish)
\r
1544 int n = data_chpt.Rows.Add();
\r
1545 data_chpt.Rows[n].Cells[0].Value = (i + 1);
\r
1546 data_chpt.Rows[n].Cells[1].Value = "Chapter " + (i + 1);
\r
1547 data_chpt.Rows[n].Cells[0].ValueType = typeof(int);
\r
1548 data_chpt.Rows[n].Cells[1].ValueType = typeof(string);
\r
1555 // Update the Duration
\r
1556 lbl_duration.Text =
\r
1557 Main.CalculateDuration(drop_chapterStart.SelectedIndex, drop_chapterFinish.SelectedIndex, selectedTitle)
\r
1560 // Run the Autonaming function
\r
1561 if (Properties.Settings.Default.autoNaming)
\r
1562 text_destination.Text = Main.AutoName(this);
\r
1564 // Disable chapter markers if only 1 chapter is selected.
\r
1565 if (chapterStart == chapterEnd)
\r
1567 Check_ChapterMarkers.Enabled = false;
\r
1568 btn_importChapters.Enabled = false;
\r
1569 data_chpt.Enabled = false;
\r
1573 Check_ChapterMarkers.Enabled = true;
\r
1574 if (Check_ChapterMarkers.Checked)
\r
1576 btn_importChapters.Enabled = true;
\r
1577 data_chpt.Enabled = true;
\r
1582 private void SecondsOrFramesChanged(object sender, EventArgs e)
\r
1585 int.TryParse(drop_chapterStart.Text, out start);
\r
1586 int.TryParse(drop_chapterFinish.Text, out end);
\r
1587 double duration = end - start;
\r
1589 switch (drop_mode.SelectedIndex)
\r
1592 lbl_duration.Text = TimeSpan.FromSeconds(duration).ToString();
\r
1595 if (selectedTitle != null)
\r
1597 duration = duration / selectedTitle.Fps;
\r
1598 lbl_duration.Text = TimeSpan.FromSeconds(duration).ToString();
\r
1601 lbl_duration.Text = "--:--:--";
\r
1607 private void drop_mode_SelectedIndexChanged(object sender, EventArgs e)
\r
1610 this.drop_chapterFinish.TextChanged -= new EventHandler(this.SecondsOrFramesChanged);
\r
1611 this.drop_chapterStart.TextChanged -= new EventHandler(this.SecondsOrFramesChanged);
\r
1614 switch (drop_mode.SelectedIndex)
\r
1617 drop_chapterStart.DropDownStyle = ComboBoxStyle.DropDownList;
\r
1618 drop_chapterFinish.DropDownStyle = ComboBoxStyle.DropDownList;
\r
1619 if (drop_chapterStart.Items.Count != 0)
\r
1621 drop_chapterStart.SelectedIndex = 0;
\r
1622 drop_chapterFinish.SelectedIndex = drop_chapterFinish.Items.Count - 1;
\r
1625 lbl_duration.Text = "--:--:--";
\r
1628 this.drop_chapterStart.TextChanged += new EventHandler(this.SecondsOrFramesChanged);
\r
1629 this.drop_chapterFinish.TextChanged += new EventHandler(this.SecondsOrFramesChanged);
\r
1630 drop_chapterStart.DropDownStyle = ComboBoxStyle.Simple;
\r
1631 drop_chapterFinish.DropDownStyle = ComboBoxStyle.Simple;
\r
1632 if (selectedTitle != null)
\r
1634 drop_chapterStart.Text = "0";
\r
1635 drop_chapterFinish.Text = selectedTitle.Duration.TotalSeconds.ToString();
\r
1639 this.drop_chapterStart.TextChanged += new EventHandler(this.SecondsOrFramesChanged);
\r
1640 this.drop_chapterFinish.TextChanged += new EventHandler(this.SecondsOrFramesChanged);
\r
1641 drop_chapterStart.DropDownStyle = ComboBoxStyle.Simple;
\r
1642 drop_chapterFinish.DropDownStyle = ComboBoxStyle.Simple;
\r
1643 if (selectedTitle != null)
\r
1645 drop_chapterStart.Text = "0";
\r
1646 drop_chapterFinish.Text = (selectedTitle.Fps * selectedTitle.Duration.TotalSeconds).ToString();
\r
1653 private void btn_destBrowse_Click(object sender, EventArgs e)
\r
1655 // This removes the file extension from the filename box on the save file dialog.
\r
1656 // It's daft but some users don't realise that typing an extension overrides the dropdown extension selected.
\r
1657 DVD_Save.FileName = Path.GetFileNameWithoutExtension(text_destination.Text);
\r
1659 if (Path.IsPathRooted(text_destination.Text))
\r
1660 DVD_Save.InitialDirectory = Path.GetDirectoryName(text_destination.Text);
\r
1662 // Show the dialog and set the main form file path
\r
1663 if (drop_format.SelectedIndex.Equals(0))
\r
1664 DVD_Save.FilterIndex = 1;
\r
1665 else if (drop_format.SelectedIndex.Equals(1))
\r
1666 DVD_Save.FilterIndex = 2;
\r
1668 if (DVD_Save.ShowDialog() == DialogResult.OK)
\r
1670 // Add a file extension manually, as FileDialog.AddExtension has issues with dots in filenames
\r
1671 switch (DVD_Save.FilterIndex)
\r
1674 if (!Path.GetExtension(DVD_Save.FileName).Equals(".mp4", StringComparison.InvariantCultureIgnoreCase))
\r
1675 if (Properties.Settings.Default.useM4v == 2 || Properties.Settings.Default.useM4v == 0)
\r
1676 DVD_Save.FileName = DVD_Save.FileName.Replace(".mp4", ".m4v").Replace(".mkv", ".m4v");
\r
1678 DVD_Save.FileName = DVD_Save.FileName.Replace(".m4v", ".mp4").Replace(".mkv", ".mp4");
\r
1681 if (!Path.GetExtension(DVD_Save.FileName).Equals(".mkv", StringComparison.InvariantCultureIgnoreCase))
\r
1682 DVD_Save.FileName = DVD_Save.FileName.Replace(".mp4", ".mkv").Replace(".m4v", ".mkv");
\r
1688 text_destination.Text = DVD_Save.FileName;
\r
1690 // Quicktime requires .m4v file for chapter markers to work. If checked, change the extension to .m4v (mp4 and m4v are the same thing)
\r
1691 if (Check_ChapterMarkers.Checked && DVD_Save.FilterIndex != 2)
\r
1692 SetExtension(".m4v");
\r
1696 private void text_destination_TextChanged(object sender, EventArgs e)
\r
1698 string path = text_destination.Text;
\r
1699 if (path.EndsWith(".mp4") || path.EndsWith(".m4v"))
\r
1700 drop_format.SelectedIndex = 0;
\r
1701 else if (path.EndsWith(".mkv"))
\r
1702 drop_format.SelectedIndex = 1;
\r
1705 // Output Settings
\r
1706 private void drop_format_SelectedIndexChanged(object sender, EventArgs e)
\r
1708 switch (drop_format.SelectedIndex)
\r
1711 SetExtension(".mp4");
\r
1714 SetExtension(".mkv");
\r
1718 AudioSettings.SetContainer(drop_format.Text);
\r
1720 if (drop_format.Text.Contains("MP4"))
\r
1722 if (drp_videoEncoder.Items.Contains("VP3 (Theora)"))
\r
1724 drp_videoEncoder.Items.Remove("VP3 (Theora)");
\r
1725 drp_videoEncoder.SelectedIndex = 1;
\r
1728 else if (drop_format.Text.Contains("MKV"))
\r
1729 drp_videoEncoder.Items.Add("VP3 (Theora)");
\r
1732 public void SetExtension(string newExtension)
\r
1734 if (newExtension == ".mp4" || newExtension == ".m4v")
\r
1735 if (Check_ChapterMarkers.Checked || AudioSettings.RequiresM4V() || Subtitles.RequiresM4V() || Properties.Settings.Default.useM4v == 2)
\r
1736 newExtension = Properties.Settings.Default.useM4v == 1 ? ".mp4" : ".m4v";
\r
1738 newExtension = ".mp4";
\r
1740 if (Path.HasExtension(newExtension))
\r
1741 text_destination.Text = Path.ChangeExtension(text_destination.Text, newExtension);
\r
1745 private void drp_videoEncoder_SelectedIndexChanged(object sender, EventArgs e)
\r
1747 setContainerOpts();
\r
1749 // Turn off some options which are H.264 only when the user selects a non h.264 encoder
\r
1750 if (drp_videoEncoder.Text.Contains("H.264"))
\r
1752 if (check_2PassEncode.CheckState == CheckState.Checked)
\r
1753 check_turbo.Enabled = true;
\r
1755 tab_advanced.Enabled = true;
\r
1756 if ((drop_format.Text.Contains("MP4")) || (drop_format.Text.Contains("M4V")))
\r
1757 check_iPodAtom.Enabled = true;
\r
1759 check_iPodAtom.Enabled = false;
\r
1763 check_turbo.CheckState = CheckState.Unchecked;
\r
1764 check_turbo.Enabled = false;
\r
1765 tab_advanced.Enabled = false;
\r
1766 x264Panel.X264Query = string.Empty;
\r
1767 check_iPodAtom.Enabled = false;
\r
1768 check_iPodAtom.Checked = false;
\r
1771 // Setup the CQ Slider
\r
1772 switch (drp_videoEncoder.Text)
\r
1774 case "MPEG-4 (FFmpeg)":
\r
1775 if (slider_videoQuality.Value > 31)
\r
1776 slider_videoQuality.Value = 20; // Just reset to 70% QP 10 on encode change.
\r
1777 slider_videoQuality.Minimum = 1;
\r
1778 slider_videoQuality.Maximum = 31;
\r
1780 case "H.264 (x264)":
\r
1781 slider_videoQuality.Minimum = 0;
\r
1782 slider_videoQuality.TickFrequency = 1;
\r
1784 CultureInfo culture = CultureInfo.CreateSpecificCulture("en-US");
\r
1785 double cqStep = Properties.Settings.Default.x264cqstep;
\r
1786 double multiplier = 1.0 / cqStep;
\r
1787 double value = slider_videoQuality.Value * multiplier;
\r
1789 slider_videoQuality.Maximum = (int)(51 / Properties.Settings.Default.x264cqstep);
\r
1791 if (value < slider_videoQuality.Maximum)
\r
1792 slider_videoQuality.Value = slider_videoQuality.Maximum - (int)value;
\r
1795 case "VP3 (Theora)":
\r
1796 if (slider_videoQuality.Value > 63)
\r
1797 slider_videoQuality.Value = 45; // Just reset to 70% QP 45 on encode change.
\r
1798 slider_videoQuality.Minimum = 0;
\r
1799 slider_videoQuality.Maximum = 63;
\r
1805 /// When the FrameRate is not Same As Source, show the Max/Constant Mode dropdown
\r
1807 /// <param name="sender">
\r
1810 /// <param name="e">
\r
1813 private void drp_videoFramerate_SelectedIndexChanged(object sender, EventArgs e)
\r
1815 if (this.drp_videoFramerate.SelectedIndex == 0)
\r
1817 this.checkMaximumFramerate.Visible = false;
\r
1818 this.checkMaximumFramerate.CheckState = CheckState.Unchecked;
\r
1822 this.checkMaximumFramerate.Visible = true;
\r
1827 /// Set the container format options
\r
1829 public void setContainerOpts()
\r
1831 if ((drop_format.Text.Contains("MP4")) || (drop_format.Text.Contains("M4V")))
\r
1833 check_largeFile.Enabled = true;
\r
1834 check_optimiseMP4.Enabled = true;
\r
1835 check_iPodAtom.Enabled = true;
\r
1839 check_largeFile.Enabled = false;
\r
1840 check_optimiseMP4.Enabled = false;
\r
1841 check_iPodAtom.Enabled = false;
\r
1842 check_largeFile.Checked = false;
\r
1843 check_optimiseMP4.Checked = false;
\r
1844 check_iPodAtom.Checked = false;
\r
1848 private double cachedCqStep = Properties.Settings.Default.x264cqstep;
\r
1851 /// Update the CQ slider for x264 for a new CQ step. This is set from option
\r
1853 public void setQualityFromSlider()
\r
1855 // Work out the current RF value.
\r
1856 double cqStep = this.cachedCqStep;
\r
1857 double rfValue = 51.0 - slider_videoQuality.Value * cqStep;
\r
1859 // Change the maximum value for the slider
\r
1860 slider_videoQuality.Maximum = (int)(51 / Properties.Settings.Default.x264cqstep);
\r
1862 // Reset the CQ slider to RF0
\r
1863 slider_videoQuality.Value = slider_videoQuality.Maximum;
\r
1865 // Reset the CQ slider back to the previous value as close as possible
\r
1866 double cqStepNew = Properties.Settings.Default.x264cqstep;
\r
1867 double rfValueCurrent = 51.0 - slider_videoQuality.Value * cqStepNew;
\r
1868 while (rfValueCurrent < rfValue)
\r
1870 slider_videoQuality.Value--;
\r
1871 rfValueCurrent = 51.0 - slider_videoQuality.Value * cqStepNew;
\r
1874 // Cache the CQ step for the next calculation
\r
1875 this.cachedCqStep = Properties.Settings.Default.x264cqstep;
\r
1878 private void slider_videoQuality_Scroll(object sender, EventArgs e)
\r
1880 double cqStep = Properties.Settings.Default.x264cqstep;
\r
1881 switch (drp_videoEncoder.Text)
\r
1883 case "MPEG-4 (FFmpeg)":
\r
1884 lbl_SliderValue.Text = "QP:" + (32 - slider_videoQuality.Value);
\r
1886 case "H.264 (x264)":
\r
1887 double rfValue = 51.0 - slider_videoQuality.Value * cqStep;
\r
1888 rfValue = Math.Round(rfValue, 2);
\r
1889 lbl_SliderValue.Text = "RF:" + rfValue.ToString(new CultureInfo("en-US"));
\r
1890 this.lbl_rfwarn.Visible = rfValue == 0;
\r
1892 case "VP3 (Theora)":
\r
1893 lbl_SliderValue.Text = "QP:" + slider_videoQuality.Value;
\r
1898 private void radio_avgBitrate_CheckedChanged(object sender, EventArgs e)
\r
1900 text_bitrate.Enabled = true;
\r
1901 slider_videoQuality.Enabled = false;
\r
1903 check_2PassEncode.Enabled = true;
\r
1906 private void radio_cq_CheckedChanged(object sender, EventArgs e)
\r
1908 text_bitrate.Enabled = false;
\r
1909 slider_videoQuality.Enabled = true;
\r
1911 check_2PassEncode.Enabled = false;
\r
1912 check_2PassEncode.CheckState = CheckState.Unchecked;
\r
1915 private void check_2PassEncode_CheckedChanged(object sender, EventArgs e)
\r
1917 if (check_2PassEncode.CheckState.ToString() == "Checked")
\r
1919 if (drp_videoEncoder.Text.Contains("H.264"))
\r
1920 check_turbo.Enabled = true;
\r
1924 check_turbo.Enabled = false;
\r
1925 check_turbo.CheckState = CheckState.Unchecked;
\r
1929 // Chapter Marker Tab
\r
1930 private void Check_ChapterMarkers_CheckedChanged(object sender, EventArgs e)
\r
1932 if (Check_ChapterMarkers.Checked)
\r
1934 if (drop_format.SelectedIndex != 1)
\r
1935 SetExtension(".m4v");
\r
1936 data_chpt.Enabled = true;
\r
1937 btn_importChapters.Enabled = true;
\r
1941 if (drop_format.SelectedIndex != 1)
\r
1942 SetExtension(".mp4");
\r
1943 data_chpt.Enabled = false;
\r
1944 btn_importChapters.Enabled = false;
\r
1948 private void btn_importChapters_Click(object sender, EventArgs e)
\r
1950 if (File_ChapterImport.ShowDialog() == DialogResult.OK)
\r
1952 string filename = File_ChapterImport.FileName;
\r
1953 DataGridView imported = Main.ImportChapterNames(data_chpt, filename);
\r
1954 if (imported != null)
\r
1955 data_chpt = imported;
\r
1959 private void btn_export_Click(object sender, EventArgs e)
\r
1961 SaveFileDialog saveFileDialog = new SaveFileDialog();
\r
1962 saveFileDialog.Filter = "Csv File|*.csv";
\r
1963 saveFileDialog.DefaultExt = "csv";
\r
1964 if (saveFileDialog.ShowDialog() == DialogResult.OK)
\r
1966 string filename = saveFileDialog.FileName;
\r
1968 Main.SaveChapterMarkersToCsv(this, filename);
\r
1972 private void mnu_resetChapters_Click(object sender, EventArgs e)
\r
1974 data_chpt.Rows.Clear();
\r
1975 DataGridView chapterGridView = Main.ChapterNaming(selectedTitle, data_chpt, drop_chapterFinish.Text);
\r
1976 if (chapterGridView != null)
\r
1978 data_chpt = chapterGridView;
\r
1982 // Query Editor Tab
\r
1983 private void btn_generate_Query_Click(object sender, EventArgs e)
\r
1985 rtf_query.Text = QueryGenerator.GenerateFullQuery(this);
\r
1988 private void btn_clear_Click(object sender, EventArgs e)
\r
1990 rtf_query.Clear();
\r
1995 // MainWindow Components, Actions and Functions ***********************
\r
1997 #region Source Scan
\r
2000 /// Start the Scan Process
\r
2002 /// <param name="filename">
\r
2005 /// <param name="title">
\r
2008 private void StartScan(string filename, int title)
\r
2010 // Setup the GUI components for the scan.
\r
2011 sourcePath = filename;
\r
2013 this.DisableGUI();
\r
2018 SourceScan.Scan(sourcePath, title);
\r
2020 catch (Exception exc)
\r
2022 MessageBox.Show("frmMain.cs - StartScan " + exc, "Error", MessageBoxButtons.OK, MessageBoxIcon.Error);
\r
2027 /// Update the Status label for the scan
\r
2029 /// <param name="sender">
\r
2032 /// <param name="e">
\r
2035 private void SourceScanScanStatusChanged(object sender, ScanProgressEventArgs e)
\r
2037 if (this.InvokeRequired)
\r
2039 this.BeginInvoke(new ScanProgessStatus(this.SourceScanScanStatusChanged), new[] { sender, e });
\r
2043 labelSource.Text = string.Format("Processing Title: {0} of {1}", e.CurrentTitle, e.Titles);
\r
2047 /// Update the UI after the scan has completed
\r
2049 /// <param name="sender">
\r
2052 /// <param name="e">
\r
2055 private void SourceScanScanCompleted(object sender, EventArgs e)
\r
2057 if (this.InvokeRequired)
\r
2059 this.BeginInvoke(new ScanCompletedStatus(this.SourceScanScanCompleted), new[] { sender, e });
\r
2065 currentSource = SourceScan.SouceData;
\r
2067 // Setup some GUI components
\r
2068 drp_dvdtitle.Items.Clear();
\r
2069 if (currentSource.Titles.Count != 0)
\r
2070 drp_dvdtitle.Items.AddRange(currentSource.Titles.ToArray());
\r
2072 foreach (Title title in currentSource.Titles)
\r
2074 if (title.MainTitle)
\r
2076 drp_dvdtitle.SelectedItem = title;
\r
2080 if (drp_dvdtitle.SelectedItem == null && drp_dvdtitle.Items.Count > 0)
\r
2082 drp_dvdtitle.SelectedIndex = 0;
\r
2085 // Enable the creation of chapter markers if the file is an image of a dvd
\r
2086 if (drop_chapterStart.Items.Count > 0)
\r
2089 int.TryParse(drop_chapterStart.Items[0].ToString(), out start);
\r
2090 int.TryParse(drop_chapterFinish.Items[drop_chapterFinish.Items.Count - 1].ToString(), out end);
\r
2091 if (end > start) Check_ChapterMarkers.Enabled = true;
\r
2094 Check_ChapterMarkers.Enabled = false;
\r
2095 Check_ChapterMarkers.Checked = false;
\r
2096 data_chpt.Rows.Clear();
\r
2100 // If no titles were found, Display an error message
\r
2101 if (drp_dvdtitle.Items.Count == 0)
\r
2104 "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
2105 "Error", MessageBoxButtons.OK, MessageBoxIcon.Hand);
\r
2106 sourcePath = string.Empty;
\r
2108 UpdateSourceLabel();
\r
2110 // This is a bit of a hack to fix the queue editing.
\r
2111 // 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
2112 // When this occures, we want to repopulate their old settings.
\r
2113 if (queueEdit != null)
\r
2116 if (queueEdit.Query != null)
\r
2118 // Send the query from the file to the Query Parser class
\r
2119 EncodeTask presetQuery = QueryParserUtility.Parse(queueEdit.Query);
\r
2121 // Now load the preset
\r
2122 PresetLoader.LoadPreset(this, presetQuery, "Load Back From Queue");
\r
2124 // Set the destination path
\r
2125 this.text_destination.Text = queueEdit.Destination;
\r
2127 // The x264 widgets will need updated, so do this now:
\r
2128 x264Panel.StandardizeOptString();
\r
2129 x264Panel.SetCurrentSettingsInPanel();
\r
2131 // Set the crop label
\r
2132 PictureSettings.SetPresetCropWarningLabel(null);
\r
2138 // Enable the GUI components and enable any disabled components
\r
2141 catch (Exception exc)
\r
2143 MessageBox.Show("frmMain.cs - updateUIafterScan " + exc, "Error", MessageBoxButtons.OK,
\r
2144 MessageBoxIcon.Error);
\r
2150 /// Enable the GUI
\r
2152 private void EnableGUI()
\r
2156 if (InvokeRequired)
\r
2157 BeginInvoke(new UpdateWindowHandler(EnableGUI));
\r
2158 foreach (Control ctrl in Controls)
\r
2159 ctrl.Enabled = true;
\r
2160 btn_start.Enabled = true;
\r
2161 btn_showQueue.Enabled = true;
\r
2162 btn_add2Queue.Enabled = true;
\r
2163 tb_preview.Enabled = true;
\r
2164 btn_source.Enabled = true;
\r
2165 mnu_killCLI.Visible = false;
\r
2167 catch (Exception exc)
\r
2169 MessageBox.Show("frmMain.cs - EnableGUI() " + exc, "Error", MessageBoxButtons.OK, MessageBoxIcon.Error);
\r
2174 /// Disable the GUI
\r
2176 private void DisableGUI()
\r
2178 foreach (Control ctrl in Controls)
\r
2179 if (!(ctrl is StatusStrip || ctrl is MenuStrip || ctrl is ToolStrip))
\r
2180 ctrl.Enabled = false;
\r
2182 labelSource.Enabled = true;
\r
2183 labelStaticSource.Enabled = true;
\r
2184 SourceLayoutPanel.Enabled = true;
\r
2185 btn_source.Enabled = false;
\r
2186 btn_start.Enabled = false;
\r
2187 btn_showQueue.Enabled = false;
\r
2188 btn_add2Queue.Enabled = false;
\r
2189 tb_preview.Enabled = false;
\r
2190 mnu_killCLI.Visible = true;
\r
2196 private void KillScan()
\r
2198 SourceScan.ScanCompleted -= this.SourceScanScanCompleted;
\r
2202 SourceScan.Stop();
\r
2204 labelSource.Text = "Scan Cancelled";
\r
2210 private void ResetGUI()
\r
2212 drp_dvdtitle.Items.Clear();
\r
2213 drop_chapterStart.Items.Clear();
\r
2214 drop_chapterFinish.Items.Clear();
\r
2215 lbl_duration.Text = "Select a Title";
\r
2216 PictureSettings.lbl_src_res.Text = "Select a Title";
\r
2217 sourcePath = String.Empty;
\r
2218 text_destination.Text = String.Empty;
\r
2219 selectedTitle = null;
\r
2223 /// Update the Source Label
\r
2225 private void UpdateSourceLabel()
\r
2227 labelSource.Text = string.IsNullOrEmpty(sourcePath) ? "Select \"Source\" to continue." : this.SourceName;
\r
2231 /// Take a job from the Queue, rescan it, and reload the GUI for that job.
\r
2233 /// <param name="job">
\r
2236 public void RecievingJob(QueueTask job)
\r
2239 this.currentlySelectedPreset = null;
\r
2240 x264Panel.Reset2Defaults();
\r
2243 queueEdit = job; // Nasty but will do for now. TODO
\r
2244 StartScan(job.Source, job.Title);
\r
2249 #region GUI Functions and Actions
\r
2252 /// Set the GUI to it's finished encoding state.
\r
2254 private void SetEncodeFinished()
\r
2258 if (InvokeRequired)
\r
2260 BeginInvoke(new UpdateWindowHandler(SetEncodeFinished));
\r
2264 lbl_encode.Text = "Encoding Finished";
\r
2265 ProgressBarStatus.Visible = false;
\r
2266 btn_start.Text = "Start";
\r
2267 btn_start.ToolTipText = "Start the encoding process";
\r
2268 btn_start.Image = Properties.Resources.Play;
\r
2270 // If the window is minimized, display the notification in a popup.
\r
2271 if (Properties.Settings.Default.trayIconAlerts)
\r
2272 if (FormWindowState.Minimized == this.WindowState)
\r
2274 notifyIcon.BalloonTipText = lbl_encode.Text;
\r
2275 notifyIcon.ShowBalloonTip(500);
\r
2278 catch (Exception exc)
\r
2280 MessageBox.Show(exc.ToString());
\r
2285 /// Set the GUI to it's started encoding state.
\r
2287 private void SetEncodeStarted()
\r
2291 if (InvokeRequired)
\r
2293 BeginInvoke(new UpdateWindowHandler(SetEncodeStarted));
\r
2296 lbl_encode.Visible = true;
\r
2297 ProgressBarStatus.Value = 0;
\r
2298 ProgressBarStatus.Visible = true;
\r
2299 lbl_encode.Text = "Encoding with " + this.queueProcessor.QueueManager.Count + " encode(s) pending";
\r
2300 btn_start.Text = "Stop";
\r
2301 btn_start.ToolTipText = "Stop the encoding process.";
\r
2302 btn_start.Image = Properties.Resources.stop;
\r
2304 catch (Exception exc)
\r
2306 MessageBox.Show(exc.ToString());
\r
2311 /// Display the Encode Status
\r
2313 /// <param name="sender">
\r
2316 /// <param name="e">
\r
2319 private void EncodeQueue_EncodeStatusChanged(object sender, EncodeProgressEventArgs e)
\r
2321 if (this.InvokeRequired)
\r
2323 this.BeginInvoke(new EncodeProgessStatus(EncodeQueue_EncodeStatusChanged), new[] { sender, e });
\r
2329 "{0:00.00}%, FPS: {1:000.0}, Avg FPS: {2:000.0}, Time Remaining: {3}, Encode(s) Pending {4}",
\r
2330 e.PercentComplete,
\r
2331 e.CurrentFrameRate,
\r
2332 e.AverageFrameRate,
\r
2333 e.EstimatedTimeLeft,
\r
2334 this.queueProcessor.QueueManager.Count);
\r
2336 ProgressBarStatus.Value = (int)Math.Round(e.PercentComplete);
\r
2340 /// Set the DVD Drive selection in the "Source" Menu
\r
2342 private void SetDriveSelectionMenuItem()
\r
2346 if (InvokeRequired)
\r
2348 BeginInvoke(new UpdateWindowHandler(SetDriveSelectionMenuItem));
\r
2352 drives = UtilityService.GetDrives();
\r
2354 List<ToolStripMenuItem> menuItems = new List<ToolStripMenuItem>();
\r
2355 foreach (DriveInformation drive in drives)
\r
2357 ToolStripMenuItem menuItem = new ToolStripMenuItem
\r
2359 Name = drive.ToString(),
\r
2360 Text = drive.RootDirectory + " (" + drive.VolumeLabel + ")",
\r
2361 Image = Resources.disc_small
\r
2363 menuItem.Click += new EventHandler(MnuDvdDriveClick);
\r
2364 menuItems.Add(menuItem);
\r
2367 foreach (ToolStripMenuItem item in menuItems)
\r
2368 btn_source.DropDownItems.Add(item);
\r
2370 catch (Exception exc)
\r
2372 MessageBox.Show("Error in SetDriveSelectionMenuItem" + exc);
\r
2377 /// Access the preset Handler and setup the preset panel.
\r
2379 private void LoadPresetPanel()
\r
2381 if (presetHandler.CheckIfPresetsAreOutOfDate())
\r
2382 if (!Settings.Default.presetNotification)
\r
2383 MessageBox.Show(this,
\r
2384 "HandBrake has determined your built-in presets are out of date... These presets will now be updated.",
\r
2385 "Preset Update", MessageBoxButtons.OK, MessageBoxIcon.Information);
\r
2387 // Clear the old presets
\r
2388 treeView_presets.Nodes.Clear();
\r
2391 string category = string.Empty; // The category we are currnetly processing
\r
2392 TreeNode rootNode = null;
\r
2393 foreach (Preset preset in this.presetHandler.Presets.Where(p => p.IsBuildIn))
\r
2395 // If the category of this preset doesn't match the current category we are processing
\r
2396 // Then we need to create a new root node.
\r
2397 if (preset.Category != category)
\r
2399 rootNode = new TreeNode(preset.Category) { ForeColor = Color.DarkBlue };
\r
2400 treeView_presets.Nodes.Add(rootNode);
\r
2401 category = preset.Category;
\r
2404 if (preset.Category == category && rootNode != null)
\r
2405 rootNode.Nodes.Add(new TreeNode(preset.Name) { ToolTipText = preset.Description, ForeColor = Color.DarkBlue });
\r
2410 foreach (Preset preset in this.presetHandler.Presets.Where(p => !p.IsBuildIn)) // User Presets
\r
2412 if (preset.Category != category && preset.Category != string.Empty)
\r
2414 rootNode = new TreeNode(preset.Category) { ForeColor = Color.Black };
\r
2415 treeView_presets.Nodes.Add(rootNode);
\r
2416 category = preset.Category;
\r
2419 if (preset.Category == category && rootNode != null)
\r
2420 rootNode.Nodes.Add(new TreeNode(preset.Name) { ForeColor = Color.Black, ToolTipText = preset.Description });
\r
2422 treeView_presets.Nodes.Add(new TreeNode(preset.Name) { ForeColor = Color.Black, ToolTipText = preset.Description });
\r
2425 treeView_presets.Update();
\r
2429 /// Get the title from the selected item in the title dropdown.
\r
2434 private int GetTitle()
\r
2437 if (drp_dvdtitle.SelectedItem != null)
\r
2439 string[] titleInfo = drp_dvdtitle.SelectedItem.ToString().Split(' ');
\r
2440 int.TryParse(titleInfo[0], out title);
\r
2447 /// Handle the Update Check Finishing.
\r
2449 /// <param name="result">
\r
2452 private void UpdateCheckDoneMenu(IAsyncResult result)
\r
2454 // Make sure it's running on the calling thread
\r
2455 if (InvokeRequired)
\r
2457 Invoke(new MethodInvoker(() => this.UpdateCheckDoneMenu(result)));
\r
2460 UpdateCheckInformation info;
\r
2463 // Get the information about the new build, if any, and close the window
\r
2464 info = UpdateService.EndCheckForUpdates(result);
\r
2466 if (info.NewVersionAvailable && info.BuildInformation != null)
\r
2468 UpdateInfo updateWindow = new UpdateInfo(info.BuildInformation, Settings.Default.hb_version, Settings.Default.hb_build.ToString());
\r
2469 updateWindow.ShowDialog();
\r
2472 MessageBox.Show("There are no new updates at this time.", "Update Check", MessageBoxButtons.OK,
\r
2473 MessageBoxIcon.Information);
\r
2474 lbl_updateCheck.Visible = false;
\r
2477 catch (Exception ex)
\r
2479 if ((bool)result.AsyncState)
\r
2481 "Unable to check for updates, Please try again later.\n\nDetailed Error Information:\n" + ex,
\r
2482 "Error", MessageBoxButtons.OK, MessageBoxIcon.Error);
\r
2491 /// Handle GUI shortcuts
\r
2493 /// <param name="msg">Message</param>
\r
2494 /// <param name="keyData">Keys</param>
\r
2495 /// <returns>Bool</returns>
\r
2496 protected override bool ProcessCmdKey(ref Message msg, Keys keyData)
\r
2498 if (keyData == (Keys.Control | Keys.S))
\r
2500 btn_start_Click(this, new EventArgs());
\r
2504 if (keyData == (Keys.Control | Keys.Shift | Keys.A))
\r
2506 btn_add2Queue_Click(this, new EventArgs());
\r
2509 return base.ProcessCmdKey(ref msg, keyData);
\r
2513 /// If the queue is being processed, prompt the user to confirm application close.
\r
2515 /// <param name="e">FormClosingEventArgs</param>
\r
2516 protected override void OnFormClosing(FormClosingEventArgs e)
\r
2520 // If currently encoding, the queue isn't paused, and there are queue items to process, prompt to confirm close.
\r
2521 if (this.queueProcessor.EncodeService.IsEncoding)
\r
2523 DialogResult result =
\r
2525 "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
2526 "Close HandBrake?",
\r
2527 MessageBoxButtons.YesNo,
\r
2528 MessageBoxIcon.Question);
\r
2530 if (result == DialogResult.No)
\r
2536 this.queueProcessor.Pause();
\r
2537 this.queueProcessor.EncodeService.Stop();
\r
2540 if (SourceScan.IsScanning)
\r
2542 SourceScan.Stop();
\r
2545 SourceScan.ScanCompleted -= this.SourceScanScanCompleted;
\r
2546 SourceScan.ScanStatusChanged -= this.SourceScanScanStatusChanged;
\r
2548 catch (Exception exc)
\r
2550 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
2554 base.OnFormClosing(e);
\r
2560 // This is the END of the road ****************************************
\r