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
19 using DevExpress.Utils.Menu;
\r
23 using HandBrake.ApplicationServices.EventArgs;
\r
24 using HandBrake.ApplicationServices.Utilities;
\r
25 using HandBrake.Framework.Model;
\r
26 using HandBrake.Framework.Services;
\r
27 using HandBrake.Framework.Views;
\r
28 using HandBrake.ApplicationServices.Functions;
\r
29 using HandBrake.ApplicationServices.Model;
\r
30 using HandBrake.ApplicationServices.Parsing;
\r
31 using HandBrake.ApplicationServices.Services;
\r
32 using HandBrake.ApplicationServices.Services.Interfaces;
\r
34 using Handbrake.ToolWindows;
\r
39 using Main = Handbrake.Functions.Main;
\r
44 public partial class frmMain : Form
\r
46 // Objects which may be used by one or more other objects *************
\r
47 private IQueueProcessor queueProcessor = new QueueProcessor(Program.InstanceId);
\r
48 private PresetService presetHandler = new PresetService();
\r
50 // Windows ************************************************************
\r
51 private frmQueue queueWindow;
\r
52 private frmPreview qtpreview;
\r
53 private frmActivityWindow activityWindow;
\r
55 // Globals: Mainly used for tracking. *********************************
\r
56 public Title selectedTitle;
\r
57 public string sourcePath;
\r
58 private SourceType selectedSourceType;
\r
59 private string dvdDrivePath;
\r
60 private string dvdDriveLabel;
\r
61 private Preset currentlySelectedPreset;
\r
62 private Source currentSource;
\r
64 private IScan SourceScan;
\r
65 private List<DriveInformation> drives;
\r
66 private QueueTask queueEdit;
\r
68 // Delegates **********************************************************
\r
69 private delegate void UpdateWindowHandler();
\r
71 // Applicaiton Startup ************************************************
\r
76 /// Gets SourceName.
\r
78 public string SourceName
\r
82 if (this.selectedSourceType == SourceType.DvdDrive)
\r
84 return this.dvdDriveLabel;
\r
87 if (selectedTitle != null && !string.IsNullOrEmpty(selectedTitle.SourceName))
\r
89 return Path.GetFileName(selectedTitle.SourceName);
\r
92 // We have a drive, selected as a folder.
\r
93 if (this.sourcePath.EndsWith("\\"))
\r
95 drives = UtilityService.GetDrives();
\r
96 foreach (DriveInformation item in drives)
\r
98 if (item.RootDirectory.Contains(this.sourcePath))
\r
100 return item.VolumeLabel;
\r
105 if (Path.GetFileNameWithoutExtension(this.sourcePath) != "VIDEO_TS")
\r
106 return Path.GetFileNameWithoutExtension(this.sourcePath);
\r
108 return Path.GetFileNameWithoutExtension(Path.GetDirectoryName(this.sourcePath));
\r
114 #region Application Startup
\r
117 /// Initializes a new instance of the <see cref="frmMain"/> class.
\r
119 /// <param name="args">
\r
120 /// The arguments passed in on application startup.
\r
122 public frmMain(string[] args)
\r
124 InitializeComponent();
\r
125 this.presetsToolStrip.Renderer = new ToolStripRenderOverride();
\r
127 // We can use LibHB, if the library hb.dll exists.
\r
128 this.SourceScan = File.Exists("hb.dll") ? (IScan)new LibScan() : new ScanService();
\r
130 // Update the users config file with the CLI version data.
\r
131 Main.SetCliVersionData();
\r
133 if (Settings.Default.hb_version.Contains("svn"))
\r
135 this.Text += " " + Settings.Default.hb_version;
\r
138 // Check for new versions, if update checking is enabled
\r
139 if (Settings.Default.updateStatus)
\r
141 if (DateTime.Now.Subtract(Settings.Default.lastUpdateCheckDate).TotalDays > Properties.Settings.Default.daysBetweenUpdateCheck)
\r
143 // Set when the last update was
\r
144 Settings.Default.lastUpdateCheckDate = DateTime.Now;
\r
145 Settings.Default.Save();
\r
146 string url = Settings.Default.hb_build.ToString().EndsWith("1")
\r
147 ? Settings.Default.appcast_unstable
\r
148 : Settings.Default.appcast;
\r
149 UpdateService.BeginCheckForUpdates(new AsyncCallback(UpdateCheckDone), false, url, Settings.Default.hb_build, Settings.Default.skipversion, Settings.Default.hb_version);
\r
153 // Clear the log files in the background
\r
154 if (Settings.Default.clearOldLogs)
\r
156 Thread clearLog = new Thread(() => UtilityService.ClearLogFiles(30));
\r
160 // Setup the GUI components
\r
161 LoadPresetPanel(); // Load the Preset Panel
\r
162 treeView_presets.ExpandAll();
\r
163 lbl_encode.Text = string.Empty;
\r
164 drop_mode.SelectedIndex = 0;
\r
165 queueWindow = new frmQueue(this.queueProcessor, this); // Prepare the Queue
\r
166 if (!Settings.Default.QueryEditorTab)
\r
167 tabs_panel.TabPages.RemoveAt(7); // Remove the query editor tab if the user does not want it enabled.
\r
168 if (Settings.Default.tooltipEnable)
\r
169 ToolTip.Active = true;
\r
171 // Load the user's default settings or Normal Preset
\r
172 if (Settings.Default.defaultPreset != string.Empty && presetHandler.GetPreset(Properties.Settings.Default.defaultPreset) != null)
\r
174 string query = presetHandler.GetPreset(Settings.Default.defaultPreset).Query;
\r
177 x264Panel.Reset2Defaults();
\r
179 EncodeTask presetQuery = QueryParserUtility.Parse(query);
\r
180 PresetLoader.LoadPreset(this, presetQuery, Settings.Default.defaultPreset);
\r
182 x264Panel.StandardizeOptString();
\r
183 x264Panel.SetCurrentSettingsInPanel();
\r
187 loadNormalPreset();
\r
189 // Register with Growl (if not using Growl for the encoding completion action, this wont hurt anything)
\r
190 GrowlCommunicator.Register();
\r
192 // Event Handlers and Queue Recovery
\r
194 Main.RecoverQueue(this.queueProcessor);
\r
196 // If have a file passed in via command arguemtents, check it's a file and try scanning it.
\r
197 if (args.Length >= 1 && (File.Exists(args[0]) || Directory.Exists(args[0])))
\r
199 this.StartScan(args[0], 0);
\r
204 /// When the update check is done, process the results.
\r
206 /// <param name="result">IAsyncResult result</param>
\r
207 private void UpdateCheckDone(IAsyncResult result)
\r
209 if (InvokeRequired)
\r
211 Invoke(new MethodInvoker(() => UpdateCheckDone(result)));
\r
217 UpdateCheckInformation info = UpdateService.EndCheckForUpdates(result);
\r
219 if (info.NewVersionAvailable)
\r
221 UpdateInfo updateWindow = new UpdateInfo(info.BuildInformation, Settings.Default.hb_version, Settings.Default.hb_build.ToString());
\r
222 updateWindow.ShowDialog();
\r
225 catch (Exception ex)
\r
227 if ((bool)result.AsyncState)
\r
228 Main.ShowExceptiowWindow("Unable to check for updates, Please try again later.", ex.ToString());
\r
236 // Encoding Events for setting up the GUI
\r
237 private void events()
\r
239 // Handle Widget changes when preset is selected.
\r
240 RegisterPresetEventHandler();
\r
242 // Handle Window Resize
\r
243 if (Settings.Default.MainWindowMinimize)
\r
244 this.Resize += this.frmMain_Resize;
\r
246 // Handle Encode Start / Finish / Pause
\r
247 this.queueProcessor.EncodeService.EncodeStarted += this.encodeStarted;
\r
248 this.queueProcessor.EncodeService.EncodeCompleted += encodeEnded;
\r
250 // Scan Started and Completed Events
\r
251 SourceScan.ScanStatusChanged += this.SourceScanScanStatusChanged;
\r
252 SourceScan.ScanCompleted += this.SourceScanScanCompleted;
\r
254 // Handle a file being draged onto the GUI.
\r
255 this.DragEnter += frmMain_DragEnter;
\r
256 this.DragDrop += this.frmMain_DragDrop;
\r
259 // 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
260 private void RegisterPresetEventHandler()
\r
263 drop_format.SelectedIndexChanged += this.changePresetLabel;
\r
264 check_largeFile.CheckedChanged += this.changePresetLabel;
\r
265 check_iPodAtom.CheckedChanged += this.changePresetLabel;
\r
266 check_optimiseMP4.CheckedChanged += this.changePresetLabel;
\r
268 // Picture Settings
\r
269 PictureSettings.PictureSettingsChanged += this.changePresetLabel;
\r
272 Filters.FilterSettingsChanged += this.changePresetLabel;
\r
275 drp_videoEncoder.SelectedIndexChanged += this.changePresetLabel;
\r
276 check_2PassEncode.CheckedChanged += this.changePresetLabel;
\r
277 check_turbo.CheckedChanged += this.changePresetLabel;
\r
278 text_bitrate.TextChanged += this.changePresetLabel;
\r
279 slider_videoQuality.ValueChanged += this.changePresetLabel;
\r
282 AudioSettings.AudioListChanged += this.changePresetLabel;
\r
285 x264Panel.rtf_x264Query.TextChanged += this.changePresetLabel;
\r
288 private void UnRegisterPresetEventHandler()
\r
290 // Output Settings
\r
291 drop_format.SelectedIndexChanged -= this.changePresetLabel;
\r
292 check_largeFile.CheckedChanged -= this.changePresetLabel;
\r
293 check_iPodAtom.CheckedChanged -= this.changePresetLabel;
\r
294 check_optimiseMP4.CheckedChanged -= this.changePresetLabel;
\r
296 // Picture Settings
\r
297 PictureSettings.PictureSettingsChanged -= this.changePresetLabel;
\r
300 Filters.FilterSettingsChanged -= this.changePresetLabel;
\r
303 drp_videoEncoder.SelectedIndexChanged -= this.changePresetLabel;
\r
304 check_2PassEncode.CheckedChanged -= this.changePresetLabel;
\r
305 check_turbo.CheckedChanged -= this.changePresetLabel;
\r
306 text_bitrate.TextChanged -= this.changePresetLabel;
\r
307 slider_videoQuality.ValueChanged -= this.changePresetLabel;
\r
310 AudioSettings.AudioListChanged -= this.changePresetLabel;
\r
313 x264Panel.rtf_x264Query.TextChanged -= this.changePresetLabel;
\r
316 private void changePresetLabel(object sender, EventArgs e)
\r
318 labelPreset.Text = "Output Settings (Preset: Custom)";
\r
319 this.currentlySelectedPreset = null;
\r
322 private static void frmMain_DragEnter(object sender, DragEventArgs e)
\r
324 if (e.Data.GetDataPresent(DataFormats.FileDrop, false))
\r
325 e.Effect = DragDropEffects.All;
\r
328 private void frmMain_DragDrop(object sender, DragEventArgs e)
\r
330 string[] fileList = e.Data.GetData(DataFormats.FileDrop) as string[];
\r
331 sourcePath = string.Empty;
\r
333 if (fileList != null)
\r
335 if (!string.IsNullOrEmpty(fileList[0]))
\r
337 this.selectedSourceType = SourceType.VideoFile;
\r
338 StartScan(fileList[0], 0);
\r
341 UpdateSourceLabel();
\r
344 UpdateSourceLabel();
\r
347 private void encodeStarted(object sender, EventArgs e)
\r
349 SetEncodeStarted();
\r
350 this.queueProcessor.EncodeService.EncodeStatusChanged += EncodeQueue_EncodeStatusChanged;
\r
353 private void encodeEnded(object sender, EventArgs e)
\r
355 this.queueProcessor.EncodeService.EncodeStatusChanged -= EncodeQueue_EncodeStatusChanged;
\r
356 SetEncodeFinished();
\r
360 // User Interface Menus / Tool Strips *********************************
\r
365 /// Kill The scan menu Item
\r
367 /// <param name="sender">
\r
370 /// <param name="e">
\r
373 private void mnu_killCLI_Click(object sender, EventArgs e)
\r
379 /// Exit the Application Menu Item
\r
381 /// <param name="sender">
\r
384 /// <param name="e">
\r
387 private void mnu_exit_Click(object sender, EventArgs e)
\r
389 Application.Exit();
\r
397 /// Menu - Start Button
\r
399 /// <param name="sender">
\r
402 /// <param name="e">
\r
405 private void mnu_encode_Click(object sender, EventArgs e)
\r
407 queueWindow.Show();
\r
411 /// Menu - Display the Log Window
\r
413 /// <param name="sender">
\r
416 /// <param name="e">
\r
419 private void mnu_encodeLog_Click(object sender, EventArgs e)
\r
421 this.btn_ActivityWindow_Click(this, null);
\r
425 /// Menu - Display the Options Window
\r
427 /// <param name="sender">
\r
430 /// <param name="e">
\r
433 private void mnu_options_Click(object sender, EventArgs e)
\r
435 Form options = new frmOptions(this);
\r
436 options.ShowDialog();
\r
441 #region Help Menu (Toolbar)
\r
444 /// Menu - Display the User Guide Web Page
\r
446 /// <param name="sender">The Sender</param>
\r
447 /// <param name="e">The EventArgs</param>
\r
448 private void MnuUserGuide_Click(object sender, EventArgs e)
\r
450 Process.Start("http://trac.handbrake.fr/wiki/HandBrakeGuide");
\r
454 /// Check for Updates
\r
456 /// <param name="sender">The Sender</param>
\r
457 /// <param name="e">The EventArgs</param>
\r
458 private void MnuCheckForUpdates_Click(object sender, EventArgs e)
\r
460 lbl_updateCheck.Visible = true;
\r
461 Settings.Default.lastUpdateCheckDate = DateTime.Now;
\r
462 Settings.Default.Save();
\r
463 string url = Settings.Default.hb_build.ToString().EndsWith("1")
\r
464 ? Settings.Default.appcast_unstable
\r
465 : Settings.Default.appcast;
\r
466 UpdateService.BeginCheckForUpdates(new AsyncCallback(UpdateCheckDoneMenu), false, url, Settings.Default.hb_build, Settings.Default.skipversion, Settings.Default.hb_version);
\r
470 /// Menu - Display the About Window
\r
472 /// <param name="sender">The Sender</param>
\r
473 /// <param name="e">The EventArgs</param>
\r
474 private void MnuAboutHandBrake_Click(object sender, EventArgs e)
\r
476 using (frmAbout About = new frmAbout())
\r
478 About.ShowDialog();
\r
487 /// RMenu - Expand All
\r
489 /// <param name="sender">
\r
492 /// <param name="e">
\r
495 private void pmnu_expandAll_Click(object sender, EventArgs e)
\r
497 treeView_presets.ExpandAll();
\r
501 /// RMenu - Collaspe All
\r
503 /// <param name="sender">
\r
506 /// <param name="e">
\r
509 private void pmnu_collapse_Click(object sender, EventArgs e)
\r
511 treeView_presets.CollapseAll();
\r
515 /// Menu - Import Preset
\r
517 /// <param name="sender">
\r
520 /// <param name="e">
\r
523 private void pmnu_import_Click(object sender, EventArgs e)
\r
529 /// RMenu - Save Changes to Preset
\r
531 /// <param name="sender">
\r
534 /// <param name="e">
\r
537 private void pmnu_saveChanges_Click(object sender, EventArgs e)
\r
539 DialogResult result =
\r
541 "Do you wish to include picture settings when updating the preset: " +
\r
542 treeView_presets.SelectedNode.Text, "Update Preset", MessageBoxButtons.YesNoCancel,
\r
543 MessageBoxIcon.Question);
\r
545 Preset preset = new Preset
\r
547 Name = this.treeView_presets.SelectedNode.Text,
\r
549 QueryGenerator.GenerateQueryForPreset(this, QueryPictureSettingsMode.SourceMaximum, true, 0, 0),
\r
550 CropSettings = (result == DialogResult.Yes)
\r
553 presetHandler.Update(preset);
\r
557 /// RMenu - Delete Preset
\r
559 /// <param name="sender">
\r
562 /// <param name="e">
\r
565 private void pmnu_delete_click(object sender, EventArgs e)
\r
567 if (treeView_presets.SelectedNode != null)
\r
569 presetHandler.Remove((Preset)treeView_presets.SelectedNode.Tag);
\r
570 treeView_presets.Nodes.Remove(treeView_presets.SelectedNode);
\r
572 treeView_presets.Select();
\r
576 /// Preset Menu Is Opening. Setup the Menu
\r
578 /// <param name="sender">
\r
581 /// <param name="e">
\r
584 private void presets_menu_Opening(object sender, CancelEventArgs e)
\r
586 // Make sure that the save menu is always disabled by default
\r
587 pmnu_saveChanges.Enabled = false;
\r
589 // Now enable the save menu if the selected preset is a user preset
\r
590 if (treeView_presets.SelectedNode != null)
\r
591 if (presetHandler.CheckIfPresetExists(treeView_presets.SelectedNode.Text))
\r
592 pmnu_saveChanges.Enabled = true;
\r
594 treeView_presets.Select();
\r
597 // Presets Management
\r
599 private void BtnAddPreset_Click(object sender, EventArgs e)
\r
601 Form preset = new frmAddPreset(this, presetHandler);
\r
602 if (preset.ShowDialog() == DialogResult.OK)
\r
604 TreeNode presetTreeview = new TreeNode(presetHandler.LastPresetAdded.Name) { ForeColor = Color.Black };
\r
605 treeView_presets.Nodes.Add(presetTreeview);
\r
606 presetHandler.LastPresetAdded = null;
\r
610 private void BtnRemovePreset_Click(object sender, EventArgs e)
\r
612 DialogResult result = MessageBox.Show("Are you sure you wish to delete the selected preset?", "Preset",
\r
613 MessageBoxButtons.YesNo, MessageBoxIcon.Question);
\r
614 if (result == DialogResult.Yes)
\r
616 if (treeView_presets.SelectedNode != null)
\r
618 presetHandler.Remove((Preset)treeView_presets.SelectedNode.Tag);
\r
619 treeView_presets.Nodes.Remove(treeView_presets.SelectedNode);
\r
622 treeView_presets.Select();
\r
626 private void MnuSetDefaultPreset_Click(object sender, EventArgs e)
\r
628 if (treeView_presets.SelectedNode != null)
\r
630 DialogResult result = MessageBox.Show("Are you sure you wish to set this preset as the default?",
\r
631 "Preset", MessageBoxButtons.YesNo, MessageBoxIcon.Question);
\r
632 if (result == DialogResult.Yes)
\r
634 Properties.Settings.Default.defaultPreset = treeView_presets.SelectedNode.Text;
\r
635 Properties.Settings.Default.Save();
\r
636 MessageBox.Show("New default preset set.", "Alert", MessageBoxButtons.OK, MessageBoxIcon.Information);
\r
640 MessageBox.Show("Please select a preset first.", "Warning", MessageBoxButtons.OK, MessageBoxIcon.Warning);
\r
643 private void MnuImportPreset_Click(object sender, EventArgs e)
\r
645 this.ImportPreset();
\r
648 private void MnuExportPreset_Click(object sender, EventArgs e)
\r
650 this.ExportPreset();
\r
653 private void MnuResetBuiltInPresets_Click(object sender, EventArgs e)
\r
655 presetHandler.UpdateBuiltInPresets(string.Empty);
\r
657 if (treeView_presets.Nodes.Count == 0)
\r
659 "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
660 "Error", MessageBoxButtons.OK, MessageBoxIcon.Error);
\r
662 MessageBox.Show("Presets have been updated!", "Alert", MessageBoxButtons.OK, MessageBoxIcon.Information);
\r
664 treeView_presets.ExpandAll();
\r
668 /// PresetBar Mouse Down event
\r
670 /// <param name="sender">
\r
673 /// <param name="e">
\r
676 private void treeview_presets_mouseUp(object sender, MouseEventArgs e)
\r
678 if (e.Button == MouseButtons.Right)
\r
679 treeView_presets.SelectedNode = treeView_presets.GetNodeAt(e.Location);
\r
680 else if (e.Button == MouseButtons.Left)
\r
682 if (treeView_presets.GetNodeAt(e.Location) != null)
\r
684 if (labelPreset.Text.Contains(treeView_presets.GetNodeAt(e.Location).Text))
\r
689 treeView_presets.Select();
\r
693 /// Preset Bar after selecting the preset
\r
695 /// <param name="sender">
\r
698 /// <param name="e">
\r
701 private void treeView_presets_AfterSelect(object sender, TreeViewEventArgs e)
\r
707 /// When the mouse moves, display a preset
\r
709 /// <param name="sender">The Sender</param>
\r
710 /// <param name="e">the MouseEventArgs</param>
\r
711 private void TreeViewPresetsMouseMove(object sender, MouseEventArgs e)
\r
713 TreeNode theNode = this.treeView_presets.GetNodeAt(e.X, e.Y);
\r
715 if ((theNode != null))
\r
717 // Change the ToolTip only if the pointer moved to a new node.
\r
718 if (theNode.ToolTipText != this.ToolTip.GetToolTip(this.treeView_presets))
\r
720 this.ToolTip.SetToolTip(this.treeView_presets, theNode.ToolTipText);
\r
723 else // Pointer is not over a node so clear the ToolTip.
\r
725 this.ToolTip.SetToolTip(this.treeView_presets, string.Empty);
\r
730 /// Preset Bar - Handle the Delete Key
\r
732 /// <param name="sender">
\r
735 /// <param name="e">
\r
738 private void treeView_presets_deleteKey(object sender, KeyEventArgs e)
\r
740 if (e.KeyCode == Keys.Delete)
\r
742 DialogResult result = MessageBox.Show("Are you sure you wish to delete the selected preset?", "Preset",
\r
743 MessageBoxButtons.YesNo, MessageBoxIcon.Question);
\r
744 if (result == DialogResult.Yes)
\r
746 if (treeView_presets.SelectedNode != null)
\r
747 presetHandler.Remove((Preset)treeView_presets.SelectedNode.Tag);
\r
749 // Remember each nodes expanded status so we can reload it
\r
750 List<bool> nodeStatus = new List<bool>();
\r
751 foreach (TreeNode node in treeView_presets.Nodes)
\r
752 nodeStatus.Add(node.IsExpanded);
\r
754 // Now reload the preset panel
\r
757 // And finally, re-expand any of the nodes if required
\r
759 foreach (TreeNode node in treeView_presets.Nodes)
\r
771 /// Select the selected preset and setup the GUI
\r
773 private void selectPreset()
\r
775 if (treeView_presets.SelectedNode != null)
\r
777 // Ok, so, we've selected a preset. Now we want to load it.
\r
778 string presetName = treeView_presets.SelectedNode.Text;
\r
779 Preset preset = presetHandler.GetPreset(presetName);
\r
780 if (preset != null)
\r
782 string query = presetHandler.GetPreset(presetName).Query;
\r
786 // Ok, Reset all the H264 widgets before changing the preset
\r
787 x264Panel.Reset2Defaults();
\r
789 // Send the query from the file to the Query Parser class
\r
790 EncodeTask presetQuery = QueryParserUtility.Parse(query);
\r
792 // Now load the preset
\r
793 PresetLoader.LoadPreset(this, presetQuery, presetName);
\r
795 // The x264 widgets will need updated, so do this now:
\r
796 x264Panel.StandardizeOptString();
\r
797 x264Panel.SetCurrentSettingsInPanel();
\r
799 // Finally, let this window have a copy of the preset settings.
\r
800 this.currentlySelectedPreset = preset;
\r
801 PictureSettings.SetPresetCropWarningLabel(preset);
\r
808 /// Load the Normal Preset
\r
810 private void loadNormalPreset()
\r
812 foreach (TreeNode treenode in treeView_presets.Nodes)
\r
814 foreach (TreeNode node in treenode.Nodes)
\r
816 if (node.Text.Equals("Normal"))
\r
817 treeView_presets.SelectedNode = treeView_presets.Nodes[treenode.Index].Nodes[0];
\r
823 /// Import a plist preset
\r
825 private void ImportPreset()
\r
827 if (openPreset.ShowDialog() == DialogResult.OK)
\r
829 EncodeTask parsed = PlistPresetHandler.Import(openPreset.FileName);
\r
830 if (presetHandler.CheckIfPresetExists(parsed.PresetName + " (Imported)"))
\r
832 DialogResult result =
\r
833 MessageBox.Show("This preset appears to already exist. Would you like to overwrite it?",
\r
834 "Overwrite preset?",
\r
835 MessageBoxButtons.YesNo, MessageBoxIcon.Warning);
\r
836 if (result == DialogResult.Yes)
\r
838 PresetLoader.LoadPreset(this, parsed, parsed.PresetName);
\r
840 Preset preset = new Preset
\r
842 Name = parsed.PresetName + " (Imported)",
\r
843 Query = QueryGenerator.GenerateFullQuery(this),
\r
844 CropSettings = parsed.UsesPictureSettings
\r
847 presetHandler.Update(preset);
\r
852 PresetLoader.LoadPreset(this, parsed, parsed.PresetName);
\r
854 Preset preset = new Preset
\r
856 Name = parsed.PresetName + " (Imported)",
\r
857 Query = QueryGenerator.GenerateFullQuery(this),
\r
858 CropSettings = parsed.UsesPictureSettings
\r
861 if (presetHandler.Add(preset))
\r
863 TreeNode preset_treeview = new TreeNode(parsed.PresetName + " (Imported)")
\r
865 ForeColor = Color.Black
\r
867 treeView_presets.Nodes.Add(preset_treeview);
\r
874 /// Export a plist Preset
\r
876 private void ExportPreset()
\r
878 SaveFileDialog savefiledialog = new SaveFileDialog { Filter = "plist|*.plist" };
\r
880 if (treeView_presets.SelectedNode != null)
\r
882 if (savefiledialog.ShowDialog() == DialogResult.OK)
\r
884 Preset preset = presetHandler.GetPreset(treeView_presets.SelectedNode.Text);
\r
885 PlistPresetHandler.Export(savefiledialog.FileName, preset);
\r
895 /// 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
897 /// <param name="sender">
\r
900 /// <param name="e">
\r
903 private void btn_source_Click(object sender, EventArgs e)
\r
905 // Remove old Drive Menu Items.
\r
906 List<ToolStripMenuItem> itemsToRemove = new List<ToolStripMenuItem>();
\r
907 foreach (var item in btn_source.DropDownItems)
\r
909 if (item.GetType() == typeof(ToolStripMenuItem))
\r
911 ToolStripMenuItem menuItem = (ToolStripMenuItem)item;
\r
912 if (menuItem.Name.StartsWith("Drive"))
\r
914 itemsToRemove.Add(menuItem);
\r
919 foreach (ToolStripMenuItem item in itemsToRemove)
\r
920 btn_source.DropDownItems.Remove(item);
\r
922 Thread driveInfoThread = new Thread(SetDriveSelectionMenuItem);
\r
923 driveInfoThread.Start();
\r
927 /// Toolbar - Start The Encode
\r
929 /// <param name="sender">
\r
932 /// <param name="e">
\r
935 private void btn_start_Click(object sender, EventArgs e)
\r
937 if (btn_start.Text == "Stop")
\r
939 DialogResult result = !Properties.Settings.Default.showCliForInGuiEncodeStatus
\r
941 "Are you sure you wish to cancel the encode?\n\nPlease note: Stopping this encode will render the file unplayable. ",
\r
943 MessageBoxButtons.YesNo,
\r
944 MessageBoxIcon.Question)
\r
946 "Are you sure you wish to cancel the encode?",
\r
948 MessageBoxButtons.YesNo,
\r
949 MessageBoxIcon.Question);
\r
951 if (result == DialogResult.Yes)
\r
954 this.queueProcessor.Pause();
\r
956 if (Settings.Default.showCliForInGuiEncodeStatus)
\r
957 this.queueProcessor.EncodeService.SafelyStop();
\r
959 this.queueProcessor.EncodeService.Stop();
\r
964 // 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
965 string jobSourcePath = !string.IsNullOrEmpty(rtf_query.Text) ? Main.GetSourceFromQuery(rtf_query.Text) : sourcePath;
\r
966 string jobDestination = !string.IsNullOrEmpty(rtf_query.Text) ? Main.GetDestinationFromQuery(rtf_query.Text) : text_destination.Text;
\r
968 if (this.queueProcessor.QueueManager.Count != 0 || (!string.IsNullOrEmpty(jobSourcePath) && !string.IsNullOrEmpty(jobDestination)))
\r
970 string generatedQuery = QueryGenerator.GenerateFullQuery(this);
\r
971 string specifiedQuery = rtf_query.Text != string.Empty
\r
973 : QueryGenerator.GenerateFullQuery(this);
\r
974 string query = string.Empty;
\r
976 // Check to make sure the generated query matches the GUI settings
\r
977 if (Properties.Settings.Default.PromptOnUnmatchingQueries && !string.IsNullOrEmpty(specifiedQuery) &&
\r
978 generatedQuery != specifiedQuery)
\r
980 DialogResult result = MessageBox.Show("The query under the \"Query Editor\" tab " +
\r
981 "does not match the current GUI settings.\n\nBecause the manual query takes " +
\r
982 "priority over the GUI, your recently updated settings will not be taken " +
\r
983 "into account when encoding this job." +
\r
984 Environment.NewLine + Environment.NewLine +
\r
985 "Do you want to replace the manual query with the updated GUI-generated query?",
\r
986 "Manual Query does not Match GUI",
\r
987 MessageBoxButtons.YesNoCancel, MessageBoxIcon.Asterisk,
\r
988 MessageBoxDefaultButton.Button3);
\r
992 case DialogResult.Yes:
\r
993 // Replace the manual query with the generated one
\r
994 query = generatedQuery;
\r
995 rtf_query.Text = generatedQuery;
\r
997 case DialogResult.No:
\r
998 // Use the manual query
\r
999 query = specifiedQuery;
\r
1001 case DialogResult.Cancel:
\r
1002 // Don't start the encode
\r
1008 query = specifiedQuery;
\r
1011 DialogResult overwrite = DialogResult.Yes;
\r
1012 if (!string.IsNullOrEmpty(jobDestination) && File.Exists(jobDestination))
\r
1014 overwrite = MessageBox.Show(
\r
1015 "The destination file already exists. Are you sure you want to overwrite it?",
\r
1016 "Overwrite File?",
\r
1017 MessageBoxButtons.YesNo,
\r
1018 MessageBoxIcon.Question);
\r
1021 if (overwrite == DialogResult.Yes)
\r
1023 QueueTask task = new QueueTask(query)
\r
1025 Title = this.GetTitle(),
\r
1026 Source = jobSourcePath,
\r
1027 Destination = jobDestination,
\r
1028 CustomQuery = (this.rtf_query.Text != string.Empty)
\r
1031 if (this.queueProcessor.QueueManager.Count == 0)
\r
1032 this.queueProcessor.QueueManager.Add(task);
\r
1034 queueWindow.SetQueue();
\r
1035 if (this.queueProcessor.QueueManager.Count > 1)
\r
1036 queueWindow.Show(false);
\r
1038 SetEncodeStarted(); // Encode is running, so setup the GUI appropriately
\r
1039 this.queueProcessor.Start(); // Start The Queue Encoding Process
\r
1044 else if (string.IsNullOrEmpty(sourcePath) || string.IsNullOrEmpty(text_destination.Text))
\r
1045 MessageBox.Show("No source or destination selected.", "Warning", MessageBoxButtons.OK,
\r
1046 MessageBoxIcon.Warning);
\r
1051 /// Toolbar - Add the current job to the Queue
\r
1053 /// <param name="sender">
\r
1056 /// <param name="e">
\r
1059 private void btn_add2Queue_Click(object sender, EventArgs e)
\r
1061 // Add the item to the queue.
\r
1062 AddItemToQueue(true);
\r
1063 queueWindow.Show();
\r
1067 /// Add Multiple Items to the Queue at once.
\r
1069 /// <param name="sender">The Sender</param>
\r
1070 /// <param name="e">The EventArgs</param>
\r
1071 private void MnuAddMultiToQueueClick(object sender, EventArgs e)
\r
1073 if (!Settings.Default.autoNaming)
\r
1075 MessageBox.Show("Destination Auto Naming must be enabled in preferences for this feature to work.", "Error", MessageBoxButtons.OK, MessageBoxIcon.Error);
\r
1079 if (this.SourceScan.SouceData == null)
\r
1081 MessageBox.Show("You must first scan a source or collection of source to use this feature.", "Error", MessageBoxButtons.OK, MessageBoxIcon.Error);
\r
1085 BatchAdd batchAdd = new BatchAdd();
\r
1086 if (batchAdd.ShowDialog() == DialogResult.OK)
\r
1088 int min = batchAdd.Min;
\r
1089 int max = batchAdd.Max;
\r
1090 bool errors = false;
\r
1092 foreach (Title title in this.SourceScan.SouceData.Titles)
\r
1094 if (title.Duration.TotalMinutes > min && title.Duration.TotalMinutes < max)
\r
1097 this.drp_dvdtitle.SelectedItem = title;
\r
1099 if (!this.AddItemToQueue(false))
\r
1109 "One or more items could not be added to the queue. You should check your queue and manually add any missing jobs.",
\r
1111 MessageBoxButtons.OK,
\r
1112 MessageBoxIcon.Warning);
\r
1117 private bool AddItemToQueue(bool showError)
\r
1119 string query = QueryGenerator.GenerateFullQuery(this);
\r
1120 if (!string.IsNullOrEmpty(rtf_query.Text))
\r
1121 query = rtf_query.Text;
\r
1123 // 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
1124 string jobSourcePath = !string.IsNullOrEmpty(rtf_query.Text) ? Main.GetSourceFromQuery(rtf_query.Text) : sourcePath;
\r
1125 string jobDestination = !string.IsNullOrEmpty(rtf_query.Text) ? Main.GetDestinationFromQuery(rtf_query.Text) : text_destination.Text;
\r
1127 // Make sure we have a Source and Destination.
\r
1128 if (string.IsNullOrEmpty(jobSourcePath) || string.IsNullOrEmpty(jobDestination))
\r
1131 MessageBox.Show("No source or destination selected.", "Warning", MessageBoxButtons.OK, MessageBoxIcon.Warning);
\r
1135 // Make sure the destination path exists.
\r
1136 if (!Directory.Exists(Path.GetDirectoryName(jobDestination)))
\r
1139 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
1143 // Make sure we don't have a duplciate on the queue.
\r
1144 if (this.queueProcessor.QueueManager.CheckForDestinationPathDuplicates(jobDestination))
\r
1148 DialogResult result;
\r
1152 "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
1155 MessageBoxButtons.YesNo,
\r
1156 MessageBoxIcon.Warning);
\r
1158 if (result != DialogResult.Yes) return false;
\r
1167 QueueTask task = new QueueTask(query)
\r
1169 Title = this.GetTitle(),
\r
1170 Source = jobSourcePath,
\r
1171 Destination = jobDestination,
\r
1172 CustomQuery = (this.rtf_query.Text != string.Empty)
\r
1174 this.queueProcessor.QueueManager.Add(task);
\r
1176 lbl_encode.Text = this.queueProcessor.QueueManager.Count + " encode(s) pending in the queue";
\r
1182 /// Toolbar - Show the Queue
\r
1184 /// <param name="sender">
\r
1187 /// <param name="e">
\r
1190 private void btn_showQueue_Click(object sender, EventArgs e)
\r
1192 queueWindow.Show();
\r
1193 queueWindow.Activate();
\r
1197 /// Toolbar - Show the Preview Window
\r
1199 /// <param name="sender">
\r
1202 /// <param name="e">
\r
1205 private void tb_preview_Click(object sender, EventArgs e)
\r
1207 if (string.IsNullOrEmpty(sourcePath) || string.IsNullOrEmpty(text_destination.Text))
\r
1208 MessageBox.Show("No source or destination selected.", "Warning", MessageBoxButtons.OK,
\r
1209 MessageBoxIcon.Warning);
\r
1212 if (qtpreview == null)
\r
1214 qtpreview = new frmPreview(this);
\r
1217 else if (qtpreview.IsDisposed)
\r
1219 qtpreview = new frmPreview(this);
\r
1223 MessageBox.Show(qtpreview, "The preview window is already open!", "Warning", MessageBoxButtons.OK,
\r
1224 MessageBoxIcon.Warning);
\r
1229 /// Toolbar - Show the Activity log Window
\r
1231 /// <param name="sender">
\r
1234 /// <param name="e">
\r
1237 private void btn_ActivityWindow_Click(object sender, EventArgs e)
\r
1239 if (this.activityWindow == null || !this.activityWindow.IsHandleCreated)
\r
1240 this.activityWindow = new frmActivityWindow(this.queueProcessor.EncodeService, SourceScan);
\r
1242 this.activityWindow.Show();
\r
1243 this.activityWindow.Activate();
\r
1248 #region System Tray Icon
\r
1251 /// Handle Resizing of the main window when deaing with the Notify Icon
\r
1253 /// <param name="sender">
\r
1256 /// <param name="e">
\r
1259 private void frmMain_Resize(object sender, EventArgs e)
\r
1261 if (FormWindowState.Minimized == this.WindowState)
\r
1263 notifyIcon.Visible = true;
\r
1266 else if (FormWindowState.Normal == this.WindowState)
\r
1267 notifyIcon.Visible = false;
\r
1271 /// Double Click the Tray Icon
\r
1273 /// <param name="sender">
\r
1276 /// <param name="e">
\r
1279 private void notifyIcon_MouseDoubleClick(object sender, MouseEventArgs e)
\r
1281 this.Visible = true;
\r
1283 this.WindowState = FormWindowState.Normal;
\r
1284 notifyIcon.Visible = false;
\r
1288 /// Tray Icon - Restore Menu Item - Resture the Window
\r
1290 /// <param name="sender">
\r
1293 /// <param name="e">
\r
1296 private void btn_restore_Click(object sender, EventArgs e)
\r
1298 this.Visible = true;
\r
1300 this.WindowState = FormWindowState.Normal;
\r
1301 notifyIcon.Visible = false;
\r
1306 #region Main Window and Tab Control
\r
1309 private void BtnFolderScanClicked(object sender, EventArgs e)
\r
1311 this.btn_source.HideDropDown();
\r
1312 if (DVD_Open.ShowDialog() == DialogResult.OK)
\r
1314 this.selectedSourceType = SourceType.Folder;
\r
1315 SelectSource(DVD_Open.SelectedPath, 0);
\r
1318 UpdateSourceLabel();
\r
1321 private void BtnFileScanClicked(object sender, EventArgs e)
\r
1323 this.btn_source.HideDropDown();
\r
1324 if (ISO_Open.ShowDialog() == DialogResult.OK)
\r
1326 this.selectedSourceType = SourceType.VideoFile;
\r
1327 SelectSource(ISO_Open.FileName, 0);
\r
1330 UpdateSourceLabel();
\r
1333 private void MnuDvdDriveClick(object sender, EventArgs e)
\r
1335 ToolStripMenuItem item = sender as ToolStripMenuItem;
\r
1338 string driveId = item.Name.Replace("Drive", string.Empty);
\r
1340 if (int.TryParse(driveId, out id))
\r
1342 this.dvdDrivePath = drives[id].RootDirectory;
\r
1343 this.dvdDriveLabel = drives[id].VolumeLabel;
\r
1345 if (this.dvdDrivePath == null) return;
\r
1346 this.selectedSourceType = SourceType.DvdDrive;
\r
1347 SelectSource(this.dvdDrivePath, 0);
\r
1352 private void VideoTitleSpecificScanClick(object sender, EventArgs e)
\r
1354 this.btn_source.HideDropDown();
\r
1355 if (ISO_Open.ShowDialog() == DialogResult.OK)
\r
1357 this.selectedSourceType = SourceType.VideoFile;
\r
1359 int sourceTitle = 0;
\r
1360 TitleSpecificScan title = new TitleSpecificScan();
\r
1361 if (title.ShowDialog() == DialogResult.OK)
\r
1363 sourceTitle = title.Title;
\r
1364 SelectSource(ISO_Open.FileName, sourceTitle);
\r
1368 UpdateSourceLabel();
\r
1371 private void FolderTitleSpecificScanClick(object sender, EventArgs e)
\r
1373 this.btn_source.HideDropDown();
\r
1374 if (DVD_Open.ShowDialog() == DialogResult.OK)
\r
1376 this.selectedSourceType = SourceType.Folder;
\r
1378 int sourceTitle = 0;
\r
1379 TitleSpecificScan title = new TitleSpecificScan();
\r
1380 if (title.ShowDialog() == DialogResult.OK)
\r
1382 sourceTitle = title.Title;
\r
1383 SelectSource(DVD_Open.SelectedPath, sourceTitle);
\r
1387 UpdateSourceLabel();
\r
1390 private void SelectSource(string file, int titleSpecific)
\r
1392 Check_ChapterMarkers.Enabled = true;
\r
1393 sourcePath = string.Empty;
\r
1395 if (file == string.Empty) // Must have a file or path
\r
1397 UpdateSourceLabel();
\r
1401 sourcePath = Path.GetFileName(file);
\r
1402 StartScan(file, titleSpecific);
\r
1405 private void drp_dvdtitle_Click(object sender, EventArgs e)
\r
1407 if ((drp_dvdtitle.Items.Count == 1) && (drp_dvdtitle.Items[0].ToString() == "Automatic"))
\r
1409 "There are no titles to select. Please load a source file by clicking the 'Source' button above before trying to select a title.",
\r
1410 "Alert", MessageBoxButtons.OK, MessageBoxIcon.Asterisk);
\r
1413 private void drp_dvdtitle_SelectedIndexChanged(object sender, EventArgs e)
\r
1415 UnRegisterPresetEventHandler();
\r
1416 drop_mode.SelectedIndex = 0;
\r
1418 drop_chapterStart.Items.Clear();
\r
1419 drop_chapterFinish.Items.Clear();
\r
1421 // If the dropdown is set to automatic nothing else needs to be done.
\r
1422 // Otheriwse if its not, title data has to be loaded from parsing.
\r
1423 if (drp_dvdtitle.Text != "Automatic")
\r
1425 selectedTitle = drp_dvdtitle.SelectedItem as Title;
\r
1426 lbl_duration.Text = selectedTitle.Duration.ToString();
\r
1427 PictureSettings.CurrentlySelectedPreset = this.currentlySelectedPreset;
\r
1428 PictureSettings.Source = selectedTitle; // Setup Picture Settings Tab Control
\r
1430 // Populate the Angles dropdown
\r
1431 drop_angle.Items.Clear();
\r
1432 if (!Properties.Settings.Default.noDvdNav)
\r
1434 drop_angle.Visible = true;
\r
1435 lbl_angle.Visible = true;
\r
1437 for (int i = 1; i <= selectedTitle.AngleCount; i++)
\r
1438 drop_angle.Items.Add(i.ToString());
\r
1440 if (drop_angle.Items.Count == 0)
\r
1442 drop_angle.Visible = false;
\r
1443 lbl_angle.Visible = false;
\r
1446 if (drop_angle.Items.Count != 0)
\r
1447 drop_angle.SelectedIndex = 0;
\r
1451 drop_angle.Visible = false;
\r
1452 lbl_angle.Visible = false;
\r
1455 // Populate the Start chapter Dropdown
\r
1456 drop_chapterStart.Items.Clear();
\r
1457 drop_chapterStart.Items.AddRange(selectedTitle.Chapters.ToArray());
\r
1458 if (drop_chapterStart.Items.Count > 0)
\r
1459 drop_chapterStart.Text = drop_chapterStart.Items[0].ToString();
\r
1461 // Populate the Final Chapter Dropdown
\r
1462 drop_chapterFinish.Items.Clear();
\r
1463 drop_chapterFinish.Items.AddRange(selectedTitle.Chapters.ToArray());
\r
1464 if (drop_chapterFinish.Items.Count > 0)
\r
1465 drop_chapterFinish.Text = drop_chapterFinish.Items[drop_chapterFinish.Items.Count - 1].ToString();
\r
1467 // Populate the Audio Channels Dropdown
\r
1468 AudioSettings.SetTrackListFromPreset(selectedTitle, this.currentlySelectedPreset);
\r
1470 // Populate the Subtitles dropdown
\r
1471 Subtitles.SetSubtitleTrackAuto(selectedTitle.Subtitles.ToArray());
\r
1473 // Update the source label if we have multiple streams
\r
1474 if (selectedTitle != null)
\r
1475 if (!string.IsNullOrEmpty(selectedTitle.SourceName))
\r
1476 labelSource.Text = Path.GetFileName(selectedTitle.SourceName);
\r
1478 // Run the AutoName & ChapterNaming functions
\r
1479 if (Properties.Settings.Default.autoNaming)
\r
1481 string autoPath = Main.AutoName(this);
\r
1482 if (autoPath != null)
\r
1483 text_destination.Text = autoPath;
\r
1486 "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
1487 "Warning", MessageBoxButtons.OK, MessageBoxIcon.Warning);
\r
1490 data_chpt.Rows.Clear();
\r
1491 if (selectedTitle.Chapters.Count != 1)
\r
1493 DataGridView chapterGridView = Main.ChapterNaming(selectedTitle, data_chpt, drop_chapterFinish.Text);
\r
1494 if (chapterGridView != null)
\r
1495 data_chpt = chapterGridView;
\r
1499 Check_ChapterMarkers.Checked = false;
\r
1500 Check_ChapterMarkers.Enabled = false;
\r
1503 // Hack to force the redraw of the scrollbars which don't resize properly when the control is disabled.
\r
1504 data_chpt.Columns[0].Width = 166;
\r
1505 data_chpt.Columns[0].Width = 165;
\r
1507 RegisterPresetEventHandler();
\r
1510 private void chapersChanged(object sender, EventArgs e)
\r
1512 if (drop_mode.SelectedIndex != 0) // Function is not used if we are not in chapters mode.
\r
1515 Control ctl = (Control)sender;
\r
1516 int chapterStart, chapterEnd;
\r
1517 int.TryParse(drop_chapterStart.Text, out chapterStart);
\r
1518 int.TryParse(drop_chapterFinish.Text, out chapterEnd);
\r
1522 case "drop_chapterStart":
\r
1523 if (drop_chapterFinish.SelectedIndex == -1 && drop_chapterFinish.Items.Count != 0)
\r
1524 drop_chapterFinish.SelectedIndex = drop_chapterFinish.Items.Count - 1;
\r
1526 if (chapterEnd != 0)
\r
1527 if (chapterStart > chapterEnd)
\r
1528 drop_chapterFinish.Text = chapterStart.ToString();
\r
1530 case "drop_chapterFinish":
\r
1531 if (drop_chapterStart.Items.Count >= 1 && drop_chapterStart.SelectedIndex == -1)
\r
1532 drop_chapterStart.SelectedIndex = 0;
\r
1534 if (chapterStart != 0)
\r
1535 if (chapterEnd < chapterStart)
\r
1536 drop_chapterFinish.Text = chapterStart.ToString();
\r
1538 // Add more rows to the Chapter menu if needed.
\r
1539 if (Check_ChapterMarkers.Checked)
\r
1541 int i = data_chpt.Rows.Count, finish = 0;
\r
1542 int.TryParse(drop_chapterFinish.Text, out finish);
\r
1544 while (i < finish)
\r
1546 int n = data_chpt.Rows.Add();
\r
1547 data_chpt.Rows[n].Cells[0].Value = (i + 1);
\r
1548 data_chpt.Rows[n].Cells[1].Value = "Chapter " + (i + 1);
\r
1549 data_chpt.Rows[n].Cells[0].ValueType = typeof(int);
\r
1550 data_chpt.Rows[n].Cells[1].ValueType = typeof(string);
\r
1557 // Update the Duration
\r
1558 lbl_duration.Text =
\r
1559 Main.CalculateDuration(drop_chapterStart.SelectedIndex, drop_chapterFinish.SelectedIndex, selectedTitle)
\r
1562 // Run the Autonaming function
\r
1563 if (Properties.Settings.Default.autoNaming)
\r
1564 text_destination.Text = Main.AutoName(this);
\r
1566 // Disable chapter markers if only 1 chapter is selected.
\r
1567 if (chapterStart == chapterEnd)
\r
1569 Check_ChapterMarkers.Enabled = false;
\r
1570 btn_importChapters.Enabled = false;
\r
1571 data_chpt.Enabled = false;
\r
1575 Check_ChapterMarkers.Enabled = true;
\r
1576 if (Check_ChapterMarkers.Checked)
\r
1578 btn_importChapters.Enabled = true;
\r
1579 data_chpt.Enabled = true;
\r
1584 private void SecondsOrFramesChanged(object sender, EventArgs e)
\r
1587 int.TryParse(drop_chapterStart.Text, out start);
\r
1588 int.TryParse(drop_chapterFinish.Text, out end);
\r
1589 double duration = end - start;
\r
1591 switch (drop_mode.SelectedIndex)
\r
1594 lbl_duration.Text = TimeSpan.FromSeconds(duration).ToString();
\r
1597 if (selectedTitle != null)
\r
1599 duration = duration / selectedTitle.Fps;
\r
1600 lbl_duration.Text = TimeSpan.FromSeconds(duration).ToString();
\r
1603 lbl_duration.Text = "--:--:--";
\r
1609 private void drop_mode_SelectedIndexChanged(object sender, EventArgs e)
\r
1612 this.drop_chapterFinish.TextChanged -= new EventHandler(this.SecondsOrFramesChanged);
\r
1613 this.drop_chapterStart.TextChanged -= new EventHandler(this.SecondsOrFramesChanged);
\r
1616 switch (drop_mode.SelectedIndex)
\r
1619 drop_chapterStart.DropDownStyle = ComboBoxStyle.DropDownList;
\r
1620 drop_chapterFinish.DropDownStyle = ComboBoxStyle.DropDownList;
\r
1621 if (drop_chapterStart.Items.Count != 0)
\r
1623 drop_chapterStart.SelectedIndex = 0;
\r
1624 drop_chapterFinish.SelectedIndex = drop_chapterFinish.Items.Count - 1;
\r
1627 lbl_duration.Text = "--:--:--";
\r
1630 this.drop_chapterStart.TextChanged += new EventHandler(this.SecondsOrFramesChanged);
\r
1631 this.drop_chapterFinish.TextChanged += new EventHandler(this.SecondsOrFramesChanged);
\r
1632 drop_chapterStart.DropDownStyle = ComboBoxStyle.Simple;
\r
1633 drop_chapterFinish.DropDownStyle = ComboBoxStyle.Simple;
\r
1634 if (selectedTitle != null)
\r
1636 drop_chapterStart.Text = "0";
\r
1637 drop_chapterFinish.Text = selectedTitle.Duration.TotalSeconds.ToString();
\r
1641 this.drop_chapterStart.TextChanged += new EventHandler(this.SecondsOrFramesChanged);
\r
1642 this.drop_chapterFinish.TextChanged += new EventHandler(this.SecondsOrFramesChanged);
\r
1643 drop_chapterStart.DropDownStyle = ComboBoxStyle.Simple;
\r
1644 drop_chapterFinish.DropDownStyle = ComboBoxStyle.Simple;
\r
1645 if (selectedTitle != null)
\r
1647 drop_chapterStart.Text = "0";
\r
1648 drop_chapterFinish.Text = (selectedTitle.Fps * selectedTitle.Duration.TotalSeconds).ToString();
\r
1655 private void btn_destBrowse_Click(object sender, EventArgs e)
\r
1657 // This removes the file extension from the filename box on the save file dialog.
\r
1658 // It's daft but some users don't realise that typing an extension overrides the dropdown extension selected.
\r
1659 DVD_Save.FileName = Path.GetFileNameWithoutExtension(text_destination.Text);
\r
1661 if (Path.IsPathRooted(text_destination.Text))
\r
1662 DVD_Save.InitialDirectory = Path.GetDirectoryName(text_destination.Text);
\r
1664 // Show the dialog and set the main form file path
\r
1665 if (drop_format.SelectedIndex.Equals(0))
\r
1666 DVD_Save.FilterIndex = 1;
\r
1667 else if (drop_format.SelectedIndex.Equals(1))
\r
1668 DVD_Save.FilterIndex = 2;
\r
1670 if (DVD_Save.ShowDialog() == DialogResult.OK)
\r
1672 // Add a file extension manually, as FileDialog.AddExtension has issues with dots in filenames
\r
1673 switch (DVD_Save.FilterIndex)
\r
1676 if (!Path.GetExtension(DVD_Save.FileName).Equals(".mp4", StringComparison.InvariantCultureIgnoreCase))
\r
1677 if (Properties.Settings.Default.useM4v == 2 || Properties.Settings.Default.useM4v == 0)
\r
1678 DVD_Save.FileName = DVD_Save.FileName.Replace(".mp4", ".m4v").Replace(".mkv", ".m4v");
\r
1680 DVD_Save.FileName = DVD_Save.FileName.Replace(".m4v", ".mp4").Replace(".mkv", ".mp4");
\r
1683 if (!Path.GetExtension(DVD_Save.FileName).Equals(".mkv", StringComparison.InvariantCultureIgnoreCase))
\r
1684 DVD_Save.FileName = DVD_Save.FileName.Replace(".mp4", ".mkv").Replace(".m4v", ".mkv");
\r
1690 text_destination.Text = DVD_Save.FileName;
\r
1692 // Quicktime requires .m4v file for chapter markers to work. If checked, change the extension to .m4v (mp4 and m4v are the same thing)
\r
1693 if (Check_ChapterMarkers.Checked && DVD_Save.FilterIndex != 2)
\r
1694 SetExtension(".m4v");
\r
1698 private void text_destination_TextChanged(object sender, EventArgs e)
\r
1700 string path = text_destination.Text;
\r
1701 if (path.EndsWith(".mp4") || path.EndsWith(".m4v"))
\r
1702 drop_format.SelectedIndex = 0;
\r
1703 else if (path.EndsWith(".mkv"))
\r
1704 drop_format.SelectedIndex = 1;
\r
1707 // Output Settings
\r
1708 private void drop_format_SelectedIndexChanged(object sender, EventArgs e)
\r
1710 switch (drop_format.SelectedIndex)
\r
1713 SetExtension(".mp4");
\r
1716 SetExtension(".mkv");
\r
1720 AudioSettings.SetContainer(drop_format.Text);
\r
1722 if (drop_format.Text.Contains("MP4"))
\r
1724 if (drp_videoEncoder.Items.Contains("VP3 (Theora)"))
\r
1726 drp_videoEncoder.Items.Remove("VP3 (Theora)");
\r
1727 drp_videoEncoder.SelectedIndex = 1;
\r
1730 else if (drop_format.Text.Contains("MKV"))
\r
1731 drp_videoEncoder.Items.Add("VP3 (Theora)");
\r
1734 public void SetExtension(string newExtension)
\r
1736 if (newExtension == ".mp4" || newExtension == ".m4v")
\r
1737 if (Check_ChapterMarkers.Checked || AudioSettings.RequiresM4V() || Subtitles.RequiresM4V() || Properties.Settings.Default.useM4v == 2)
\r
1738 newExtension = Properties.Settings.Default.useM4v == 1 ? ".mp4" : ".m4v";
\r
1740 newExtension = ".mp4";
\r
1742 if (Path.HasExtension(newExtension))
\r
1743 text_destination.Text = Path.ChangeExtension(text_destination.Text, newExtension);
\r
1747 private void drp_videoEncoder_SelectedIndexChanged(object sender, EventArgs e)
\r
1749 setContainerOpts();
\r
1751 // Turn off some options which are H.264 only when the user selects a non h.264 encoder
\r
1752 if (drp_videoEncoder.Text.Contains("H.264"))
\r
1754 if (check_2PassEncode.CheckState == CheckState.Checked)
\r
1755 check_turbo.Enabled = true;
\r
1757 tab_advanced.Enabled = true;
\r
1758 if ((drop_format.Text.Contains("MP4")) || (drop_format.Text.Contains("M4V")))
\r
1759 check_iPodAtom.Enabled = true;
\r
1761 check_iPodAtom.Enabled = false;
\r
1765 check_turbo.CheckState = CheckState.Unchecked;
\r
1766 check_turbo.Enabled = false;
\r
1767 tab_advanced.Enabled = false;
\r
1768 x264Panel.X264Query = string.Empty;
\r
1769 check_iPodAtom.Enabled = false;
\r
1770 check_iPodAtom.Checked = false;
\r
1773 // Setup the CQ Slider
\r
1774 switch (drp_videoEncoder.Text)
\r
1776 case "MPEG-4 (FFmpeg)":
\r
1777 if (slider_videoQuality.Value > 31)
\r
1778 slider_videoQuality.Value = 20; // Just reset to 70% QP 10 on encode change.
\r
1779 slider_videoQuality.Minimum = 1;
\r
1780 slider_videoQuality.Maximum = 31;
\r
1782 case "H.264 (x264)":
\r
1783 slider_videoQuality.Minimum = 0;
\r
1784 slider_videoQuality.TickFrequency = 1;
\r
1786 CultureInfo culture = CultureInfo.CreateSpecificCulture("en-US");
\r
1787 double cqStep = Properties.Settings.Default.x264cqstep;
\r
1788 double multiplier = 1.0 / cqStep;
\r
1789 double value = slider_videoQuality.Value * multiplier;
\r
1791 slider_videoQuality.Maximum = (int)(51 / Properties.Settings.Default.x264cqstep);
\r
1793 if (value < slider_videoQuality.Maximum)
\r
1794 slider_videoQuality.Value = slider_videoQuality.Maximum - (int)value;
\r
1797 case "VP3 (Theora)":
\r
1798 if (slider_videoQuality.Value > 63)
\r
1799 slider_videoQuality.Value = 45; // Just reset to 70% QP 45 on encode change.
\r
1800 slider_videoQuality.Minimum = 0;
\r
1801 slider_videoQuality.Maximum = 63;
\r
1807 /// When the FrameRate is not Same As Source, show the Max/Constant Mode dropdown
\r
1809 /// <param name="sender">
\r
1812 /// <param name="e">
\r
1815 private void drp_videoFramerate_SelectedIndexChanged(object sender, EventArgs e)
\r
1817 if (this.drp_videoFramerate.SelectedIndex == 0)
\r
1819 this.checkMaximumFramerate.Visible = false;
\r
1820 this.checkMaximumFramerate.CheckState = CheckState.Unchecked;
\r
1824 this.checkMaximumFramerate.Visible = true;
\r
1829 /// Set the container format options
\r
1831 public void setContainerOpts()
\r
1833 if ((drop_format.Text.Contains("MP4")) || (drop_format.Text.Contains("M4V")))
\r
1835 check_largeFile.Enabled = true;
\r
1836 check_optimiseMP4.Enabled = true;
\r
1837 check_iPodAtom.Enabled = true;
\r
1841 check_largeFile.Enabled = false;
\r
1842 check_optimiseMP4.Enabled = false;
\r
1843 check_iPodAtom.Enabled = false;
\r
1844 check_largeFile.Checked = false;
\r
1845 check_optimiseMP4.Checked = false;
\r
1846 check_iPodAtom.Checked = false;
\r
1850 private double cachedCqStep = Properties.Settings.Default.x264cqstep;
\r
1853 /// Update the CQ slider for x264 for a new CQ step. This is set from option
\r
1855 public void setQualityFromSlider()
\r
1857 // Work out the current RF value.
\r
1858 double cqStep = this.cachedCqStep;
\r
1859 double rfValue = 51.0 - slider_videoQuality.Value * cqStep;
\r
1861 // Change the maximum value for the slider
\r
1862 slider_videoQuality.Maximum = (int)(51 / Properties.Settings.Default.x264cqstep);
\r
1864 // Reset the CQ slider to RF0
\r
1865 slider_videoQuality.Value = slider_videoQuality.Maximum;
\r
1867 // Reset the CQ slider back to the previous value as close as possible
\r
1868 double cqStepNew = Properties.Settings.Default.x264cqstep;
\r
1869 double rfValueCurrent = 51.0 - slider_videoQuality.Value * cqStepNew;
\r
1870 while (rfValueCurrent < rfValue)
\r
1872 slider_videoQuality.Value--;
\r
1873 rfValueCurrent = 51.0 - slider_videoQuality.Value * cqStepNew;
\r
1876 // Cache the CQ step for the next calculation
\r
1877 this.cachedCqStep = Properties.Settings.Default.x264cqstep;
\r
1880 private void slider_videoQuality_Scroll(object sender, EventArgs e)
\r
1882 double cqStep = Properties.Settings.Default.x264cqstep;
\r
1883 switch (drp_videoEncoder.Text)
\r
1885 case "MPEG-4 (FFmpeg)":
\r
1886 lbl_SliderValue.Text = "QP:" + (32 - slider_videoQuality.Value);
\r
1888 case "H.264 (x264)":
\r
1889 double rfValue = 51.0 - slider_videoQuality.Value * cqStep;
\r
1890 rfValue = Math.Round(rfValue, 2);
\r
1891 lbl_SliderValue.Text = "RF:" + rfValue.ToString(new CultureInfo("en-US"));
\r
1892 this.lbl_rfwarn.Visible = rfValue == 0;
\r
1894 case "VP3 (Theora)":
\r
1895 lbl_SliderValue.Text = "QP:" + slider_videoQuality.Value;
\r
1900 private void radio_avgBitrate_CheckedChanged(object sender, EventArgs e)
\r
1902 text_bitrate.Enabled = true;
\r
1903 slider_videoQuality.Enabled = false;
\r
1905 check_2PassEncode.Enabled = true;
\r
1908 private void radio_cq_CheckedChanged(object sender, EventArgs e)
\r
1910 text_bitrate.Enabled = false;
\r
1911 slider_videoQuality.Enabled = true;
\r
1913 check_2PassEncode.Enabled = false;
\r
1914 check_2PassEncode.CheckState = CheckState.Unchecked;
\r
1917 private void check_2PassEncode_CheckedChanged(object sender, EventArgs e)
\r
1919 if (check_2PassEncode.CheckState.ToString() == "Checked")
\r
1921 if (drp_videoEncoder.Text.Contains("H.264"))
\r
1922 check_turbo.Enabled = true;
\r
1926 check_turbo.Enabled = false;
\r
1927 check_turbo.CheckState = CheckState.Unchecked;
\r
1931 // Chapter Marker Tab
\r
1932 private void Check_ChapterMarkers_CheckedChanged(object sender, EventArgs e)
\r
1934 if (Check_ChapterMarkers.Checked)
\r
1936 if (drop_format.SelectedIndex != 1)
\r
1937 SetExtension(".m4v");
\r
1938 data_chpt.Enabled = true;
\r
1939 btn_importChapters.Enabled = true;
\r
1943 if (drop_format.SelectedIndex != 1)
\r
1944 SetExtension(".mp4");
\r
1945 data_chpt.Enabled = false;
\r
1946 btn_importChapters.Enabled = false;
\r
1950 private void btn_importChapters_Click(object sender, EventArgs e)
\r
1952 if (File_ChapterImport.ShowDialog() == DialogResult.OK)
\r
1954 string filename = File_ChapterImport.FileName;
\r
1955 DataGridView imported = Main.ImportChapterNames(data_chpt, filename);
\r
1956 if (imported != null)
\r
1957 data_chpt = imported;
\r
1961 private void btn_export_Click(object sender, EventArgs e)
\r
1963 SaveFileDialog saveFileDialog = new SaveFileDialog();
\r
1964 saveFileDialog.Filter = "Csv File|*.csv";
\r
1965 saveFileDialog.DefaultExt = "csv";
\r
1966 if (saveFileDialog.ShowDialog() == DialogResult.OK)
\r
1968 string filename = saveFileDialog.FileName;
\r
1970 Main.SaveChapterMarkersToCsv(this, filename);
\r
1974 private void mnu_resetChapters_Click(object sender, EventArgs e)
\r
1976 data_chpt.Rows.Clear();
\r
1977 DataGridView chapterGridView = Main.ChapterNaming(selectedTitle, data_chpt, drop_chapterFinish.Text);
\r
1978 if (chapterGridView != null)
\r
1980 data_chpt = chapterGridView;
\r
1984 // Query Editor Tab
\r
1985 private void btn_generate_Query_Click(object sender, EventArgs e)
\r
1987 rtf_query.Text = QueryGenerator.GenerateFullQuery(this);
\r
1990 private void btn_clear_Click(object sender, EventArgs e)
\r
1992 rtf_query.Clear();
\r
1997 // MainWindow Components, Actions and Functions ***********************
\r
1999 #region Source Scan
\r
2002 /// Start the Scan Process
\r
2004 /// <param name="filename">
\r
2007 /// <param name="title">
\r
2010 private void StartScan(string filename, int title)
\r
2012 // Setup the GUI components for the scan.
\r
2013 sourcePath = filename;
\r
2015 this.DisableGUI();
\r
2020 SourceScan.Scan(sourcePath, title);
\r
2022 catch (Exception exc)
\r
2024 MessageBox.Show("frmMain.cs - StartScan " + exc, "Error", MessageBoxButtons.OK, MessageBoxIcon.Error);
\r
2029 /// Update the Status label for the scan
\r
2031 /// <param name="sender">
\r
2034 /// <param name="e">
\r
2037 private void SourceScanScanStatusChanged(object sender, ScanProgressEventArgs e)
\r
2039 if (this.InvokeRequired)
\r
2041 this.BeginInvoke(new ScanProgessStatus(this.SourceScanScanStatusChanged), new[] { sender, e });
\r
2045 labelSource.Text = string.Format("Processing Title: {0} of {1}", e.CurrentTitle, e.Titles);
\r
2049 /// Update the UI after the scan has completed
\r
2051 /// <param name="sender">
\r
2054 /// <param name="e">
\r
2057 private void SourceScanScanCompleted(object sender, EventArgs e)
\r
2059 if (this.InvokeRequired)
\r
2061 this.BeginInvoke(new ScanCompletedStatus(this.SourceScanScanCompleted), new[] { sender, e });
\r
2067 currentSource = SourceScan.SouceData;
\r
2069 // Setup some GUI components
\r
2070 drp_dvdtitle.Items.Clear();
\r
2071 if (currentSource.Titles.Count != 0)
\r
2072 drp_dvdtitle.Items.AddRange(currentSource.Titles.ToArray());
\r
2074 foreach (Title title in currentSource.Titles)
\r
2076 if (title.MainTitle)
\r
2078 drp_dvdtitle.SelectedItem = title;
\r
2082 if (drp_dvdtitle.SelectedItem == null && drp_dvdtitle.Items.Count > 0)
\r
2084 drp_dvdtitle.SelectedIndex = 0;
\r
2087 // Enable the creation of chapter markers if the file is an image of a dvd
\r
2088 if (drop_chapterStart.Items.Count > 0)
\r
2091 int.TryParse(drop_chapterStart.Items[0].ToString(), out start);
\r
2092 int.TryParse(drop_chapterFinish.Items[drop_chapterFinish.Items.Count - 1].ToString(), out end);
\r
2093 if (end > start) Check_ChapterMarkers.Enabled = true;
\r
2096 Check_ChapterMarkers.Enabled = false;
\r
2097 Check_ChapterMarkers.Checked = false;
\r
2098 data_chpt.Rows.Clear();
\r
2102 // If no titles were found, Display an error message
\r
2103 if (drp_dvdtitle.Items.Count == 0)
\r
2106 "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
2107 "Error", MessageBoxButtons.OK, MessageBoxIcon.Hand);
\r
2108 sourcePath = string.Empty;
\r
2110 UpdateSourceLabel();
\r
2112 // This is a bit of a hack to fix the queue editing.
\r
2113 // 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
2114 // When this occures, we want to repopulate their old settings.
\r
2115 if (queueEdit != null)
\r
2118 if (queueEdit.Query != null)
\r
2120 // Send the query from the file to the Query Parser class
\r
2121 EncodeTask presetQuery = QueryParserUtility.Parse(queueEdit.Query);
\r
2123 // Now load the preset
\r
2124 PresetLoader.LoadPreset(this, presetQuery, "Load Back From Queue");
\r
2126 // Set the destination path
\r
2127 this.text_destination.Text = queueEdit.Destination;
\r
2129 // The x264 widgets will need updated, so do this now:
\r
2130 x264Panel.StandardizeOptString();
\r
2131 x264Panel.SetCurrentSettingsInPanel();
\r
2133 // Set the crop label
\r
2134 PictureSettings.SetPresetCropWarningLabel(null);
\r
2140 // Enable the GUI components and enable any disabled components
\r
2143 catch (Exception exc)
\r
2145 MessageBox.Show("frmMain.cs - updateUIafterScan " + exc, "Error", MessageBoxButtons.OK,
\r
2146 MessageBoxIcon.Error);
\r
2152 /// Enable the GUI
\r
2154 private void EnableGUI()
\r
2158 if (InvokeRequired)
\r
2159 BeginInvoke(new UpdateWindowHandler(EnableGUI));
\r
2160 foreach (Control ctrl in Controls)
\r
2161 ctrl.Enabled = true;
\r
2162 btn_start.Enabled = true;
\r
2163 btn_showQueue.Enabled = true;
\r
2164 btn_add2Queue.Enabled = true;
\r
2165 tb_preview.Enabled = true;
\r
2166 btn_source.Enabled = true;
\r
2167 mnu_killCLI.Visible = false;
\r
2169 catch (Exception exc)
\r
2171 MessageBox.Show("frmMain.cs - EnableGUI() " + exc, "Error", MessageBoxButtons.OK, MessageBoxIcon.Error);
\r
2176 /// Disable the GUI
\r
2178 private void DisableGUI()
\r
2180 foreach (Control ctrl in Controls)
\r
2181 if (!(ctrl is StatusStrip || ctrl is MenuStrip || ctrl is ToolStrip))
\r
2182 ctrl.Enabled = false;
\r
2184 labelSource.Enabled = true;
\r
2185 labelStaticSource.Enabled = true;
\r
2186 SourceLayoutPanel.Enabled = true;
\r
2187 btn_source.Enabled = false;
\r
2188 btn_start.Enabled = false;
\r
2189 btn_showQueue.Enabled = false;
\r
2190 btn_add2Queue.Enabled = false;
\r
2191 tb_preview.Enabled = false;
\r
2192 mnu_killCLI.Visible = true;
\r
2198 private void KillScan()
\r
2200 SourceScan.ScanCompleted -= this.SourceScanScanCompleted;
\r
2204 SourceScan.Stop();
\r
2206 labelSource.Text = "Scan Cancelled";
\r
2212 private void ResetGUI()
\r
2214 drp_dvdtitle.Items.Clear();
\r
2215 drop_chapterStart.Items.Clear();
\r
2216 drop_chapterFinish.Items.Clear();
\r
2217 lbl_duration.Text = "Select a Title";
\r
2218 PictureSettings.lbl_src_res.Text = "Select a Title";
\r
2219 sourcePath = String.Empty;
\r
2220 text_destination.Text = String.Empty;
\r
2221 selectedTitle = null;
\r
2225 /// Update the Source Label
\r
2227 private void UpdateSourceLabel()
\r
2229 labelSource.Text = string.IsNullOrEmpty(sourcePath) ? "Select \"Source\" to continue." : this.SourceName;
\r
2233 /// Take a job from the Queue, rescan it, and reload the GUI for that job.
\r
2235 /// <param name="job">
\r
2238 public void RecievingJob(QueueTask job)
\r
2241 this.currentlySelectedPreset = null;
\r
2242 x264Panel.Reset2Defaults();
\r
2245 queueEdit = job; // Nasty but will do for now. TODO
\r
2246 StartScan(job.Source, job.Title);
\r
2251 #region GUI Functions and Actions
\r
2254 /// Set the GUI to it's finished encoding state.
\r
2256 private void SetEncodeFinished()
\r
2260 if (InvokeRequired)
\r
2262 BeginInvoke(new UpdateWindowHandler(SetEncodeFinished));
\r
2266 lbl_encode.Text = "Encoding Finished";
\r
2267 ProgressBarStatus.Visible = false;
\r
2268 btn_start.Text = "Start";
\r
2269 btn_start.ToolTipText = "Start the encoding process";
\r
2270 btn_start.Image = Properties.Resources.Play;
\r
2272 // If the window is minimized, display the notification in a popup.
\r
2273 if (Properties.Settings.Default.trayIconAlerts)
\r
2274 if (FormWindowState.Minimized == this.WindowState)
\r
2276 notifyIcon.BalloonTipText = lbl_encode.Text;
\r
2277 notifyIcon.ShowBalloonTip(500);
\r
2280 catch (Exception exc)
\r
2282 MessageBox.Show(exc.ToString());
\r
2287 /// Set the GUI to it's started encoding state.
\r
2289 private void SetEncodeStarted()
\r
2293 if (InvokeRequired)
\r
2295 BeginInvoke(new UpdateWindowHandler(SetEncodeStarted));
\r
2298 lbl_encode.Visible = true;
\r
2299 ProgressBarStatus.Value = 0;
\r
2300 ProgressBarStatus.Visible = true;
\r
2301 lbl_encode.Text = "Encoding with " + this.queueProcessor.QueueManager.Count + " encode(s) pending";
\r
2302 btn_start.Text = "Stop";
\r
2303 btn_start.ToolTipText = "Stop the encoding process.";
\r
2304 btn_start.Image = Properties.Resources.stop;
\r
2306 catch (Exception exc)
\r
2308 MessageBox.Show(exc.ToString());
\r
2313 /// Display the Encode Status
\r
2315 /// <param name="sender">
\r
2318 /// <param name="e">
\r
2321 private void EncodeQueue_EncodeStatusChanged(object sender, EncodeProgressEventArgs e)
\r
2323 if (this.InvokeRequired)
\r
2325 this.BeginInvoke(new EncodeProgessStatus(EncodeQueue_EncodeStatusChanged), new[] { sender, e });
\r
2331 "{0:00.00}%, FPS: {1:000.0}, Avg FPS: {2:000.0}, Time Remaining: {3}, Encode(s) Pending {4}",
\r
2332 e.PercentComplete,
\r
2333 e.CurrentFrameRate,
\r
2334 e.AverageFrameRate,
\r
2335 e.EstimatedTimeLeft,
\r
2336 this.queueProcessor.QueueManager.Count);
\r
2338 ProgressBarStatus.Value = (int)Math.Round(e.PercentComplete);
\r
2342 /// Set the DVD Drive selection in the "Source" Menu
\r
2344 private void SetDriveSelectionMenuItem()
\r
2348 if (InvokeRequired)
\r
2350 BeginInvoke(new UpdateWindowHandler(SetDriveSelectionMenuItem));
\r
2354 drives = UtilityService.GetDrives();
\r
2356 List<ToolStripMenuItem> menuItems = new List<ToolStripMenuItem>();
\r
2357 foreach (DriveInformation drive in drives)
\r
2359 ToolStripMenuItem menuItem = new ToolStripMenuItem
\r
2361 Name = drive.ToString(),
\r
2362 Text = drive.RootDirectory + " (" + drive.VolumeLabel + ")",
\r
2363 Image = Resources.disc_small
\r
2365 menuItem.Click += new EventHandler(MnuDvdDriveClick);
\r
2366 menuItems.Add(menuItem);
\r
2369 foreach (ToolStripMenuItem item in menuItems)
\r
2370 btn_source.DropDownItems.Add(item);
\r
2372 catch (Exception exc)
\r
2374 MessageBox.Show("Error in SetDriveSelectionMenuItem" + exc);
\r
2379 /// Access the preset Handler and setup the preset panel.
\r
2381 private void LoadPresetPanel()
\r
2383 if (presetHandler.CheckIfPresetsAreOutOfDate())
\r
2384 if (!Settings.Default.presetNotification)
\r
2385 MessageBox.Show(this,
\r
2386 "HandBrake has determined your built-in presets are out of date... These presets will now be updated.",
\r
2387 "Preset Update", MessageBoxButtons.OK, MessageBoxIcon.Information);
\r
2389 // Clear the old presets
\r
2390 treeView_presets.Nodes.Clear();
\r
2393 string category = string.Empty; // The category we are currnetly processing
\r
2394 TreeNode rootNode = null;
\r
2395 foreach (Preset preset in this.presetHandler.Presets.Where(p => p.IsBuildIn))
\r
2397 // If the category of this preset doesn't match the current category we are processing
\r
2398 // Then we need to create a new root node.
\r
2399 if (preset.Category != category)
\r
2401 rootNode = new TreeNode(preset.Category) { ForeColor = Color.DarkBlue };
\r
2402 treeView_presets.Nodes.Add(rootNode);
\r
2403 category = preset.Category;
\r
2406 if (preset.Category == category && rootNode != null)
\r
2407 rootNode.Nodes.Add(new TreeNode(preset.Name) { ToolTipText = preset.Description, ForeColor = Color.DarkBlue });
\r
2412 foreach (Preset preset in this.presetHandler.Presets.Where(p => !p.IsBuildIn)) // User Presets
\r
2414 if (preset.Category != category && preset.Category != string.Empty)
\r
2416 rootNode = new TreeNode(preset.Category) { ForeColor = Color.Black };
\r
2417 treeView_presets.Nodes.Add(rootNode);
\r
2418 category = preset.Category;
\r
2421 if (preset.Category == category && rootNode != null)
\r
2422 rootNode.Nodes.Add(new TreeNode(preset.Name) { ForeColor = Color.Black, ToolTipText = preset.Description });
\r
2424 treeView_presets.Nodes.Add(new TreeNode(preset.Name) { ForeColor = Color.Black, ToolTipText = preset.Description });
\r
2427 treeView_presets.Update();
\r
2431 /// Get the title from the selected item in the title dropdown.
\r
2436 private int GetTitle()
\r
2439 if (drp_dvdtitle.SelectedItem != null)
\r
2441 string[] titleInfo = drp_dvdtitle.SelectedItem.ToString().Split(' ');
\r
2442 int.TryParse(titleInfo[0], out title);
\r
2449 /// Handle the Update Check Finishing.
\r
2451 /// <param name="result">
\r
2454 private void UpdateCheckDoneMenu(IAsyncResult result)
\r
2456 // Make sure it's running on the calling thread
\r
2457 if (InvokeRequired)
\r
2459 Invoke(new MethodInvoker(() => this.UpdateCheckDoneMenu(result)));
\r
2462 UpdateCheckInformation info;
\r
2465 // Get the information about the new build, if any, and close the window
\r
2466 info = UpdateService.EndCheckForUpdates(result);
\r
2468 if (info.NewVersionAvailable && info.BuildInformation != null)
\r
2470 UpdateInfo updateWindow = new UpdateInfo(info.BuildInformation, Settings.Default.hb_version, Settings.Default.hb_build.ToString());
\r
2471 updateWindow.ShowDialog();
\r
2474 MessageBox.Show("There are no new updates at this time.", "Update Check", MessageBoxButtons.OK,
\r
2475 MessageBoxIcon.Information);
\r
2476 lbl_updateCheck.Visible = false;
\r
2479 catch (Exception ex)
\r
2481 if ((bool)result.AsyncState)
\r
2483 "Unable to check for updates, Please try again later.\n\nDetailed Error Information:\n" + ex,
\r
2484 "Error", MessageBoxButtons.OK, MessageBoxIcon.Error);
\r
2493 /// Handle GUI shortcuts
\r
2495 /// <param name="msg">Message</param>
\r
2496 /// <param name="keyData">Keys</param>
\r
2497 /// <returns>Bool</returns>
\r
2498 protected override bool ProcessCmdKey(ref Message msg, Keys keyData)
\r
2500 if (keyData == (Keys.Control | Keys.S))
\r
2502 btn_start_Click(this, new EventArgs());
\r
2506 if (keyData == (Keys.Control | Keys.Shift | Keys.A))
\r
2508 btn_add2Queue_Click(this, new EventArgs());
\r
2511 return base.ProcessCmdKey(ref msg, keyData);
\r
2515 /// If the queue is being processed, prompt the user to confirm application close.
\r
2517 /// <param name="e">FormClosingEventArgs</param>
\r
2518 protected override void OnFormClosing(FormClosingEventArgs e)
\r
2522 // If currently encoding, the queue isn't paused, and there are queue items to process, prompt to confirm close.
\r
2523 if (this.queueProcessor.EncodeService.IsEncoding)
\r
2525 DialogResult result =
\r
2527 "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
2528 "Close HandBrake?",
\r
2529 MessageBoxButtons.YesNo,
\r
2530 MessageBoxIcon.Question);
\r
2532 if (result == DialogResult.No)
\r
2538 this.queueProcessor.Pause();
\r
2539 this.queueProcessor.EncodeService.Stop();
\r
2542 if (SourceScan.IsScanning)
\r
2544 SourceScan.Stop();
\r
2547 SourceScan.ScanCompleted -= this.SourceScanScanCompleted;
\r
2548 SourceScan.ScanStatusChanged -= this.SourceScanScanStatusChanged;
\r
2550 catch (Exception exc)
\r
2552 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
2556 base.OnFormClosing(e);
\r
2562 // This is the END of the road ****************************************
\r