2 This file is part of the HandBrake source code.
\r
3 Homepage: <http://handbrake.fr/>.
\r
4 It may be used under the terms of the GNU General Public License. */
\r
9 using System.Collections.Generic;
\r
10 using System.ComponentModel;
\r
11 using System.Diagnostics;
\r
12 using System.Drawing;
\r
13 using System.Globalization;
\r
15 using System.Reflection;
\r
16 using System.Threading;
\r
17 using System.Windows.Forms;
\r
25 public partial class frmMain : Form
\r
27 // Objects which may be used by one or more other objects *************
\r
28 private Queue encodeQueue = new Queue();
\r
29 private PresetsHandler presetHandler = new PresetsHandler();
\r
31 // Globals: Mainly used for tracking. *********************************
\r
32 public Title selectedTitle;
\r
33 private frmQueue queueWindow;
\r
34 private frmPreview qtpreview;
\r
35 private frmActivityWindow ActivityWindow;
\r
36 private Form splash;
\r
37 public string sourcePath;
\r
38 private SourceType selectedSourceType;
\r
39 private string dvdDrivePath;
\r
40 private string dvdDriveLabel;
\r
41 private Preset CurrentlySelectedPreset;
\r
42 private DVD currentSource;
\r
43 private ScanService SourceScan = new ScanService();
\r
44 private List<DriveInformation> drives;
\r
46 // Delegates **********************************************************
\r
47 private delegate void UpdateWindowHandler();
\r
49 // Applicaiton Startup ************************************************
\r
51 #region Application Startup
\r
55 // Load and setup the splash screen in this thread
\r
56 splash = new frmSplashScreen();
\r
58 Label lblStatus = new Label { Size = new Size(150, 20), Location = new Point(182, 102) };
\r
59 splash.Controls.Add(lblStatus);
\r
61 InitializeComponent();
\r
63 // Update the users config file with the CLI version data.
\r
64 lblStatus.Text = "Checking CLI Version Data ...";
\r
65 Application.DoEvents();
\r
66 Main.SetCliVersionData();
\r
67 Main.CheckForValidCliVersion();
\r
69 if (Settings.Default.hb_version.Contains("svn"))
\r
71 Version v = Assembly.GetExecutingAssembly().GetName().Version;
\r
72 this.Text += " " + v.ToString(4);
\r
75 // Show the form, but leave disabled until preloading is complete then show the main form)
\r
76 this.Enabled = false;
\r
78 Application.DoEvents(); // Forces frmMain to draw
\r
80 // Check for new versions, if update checking is enabled
\r
81 if (Properties.Settings.Default.updateStatus)
\r
83 DateTime now = DateTime.Now;
\r
84 DateTime lastCheck = Properties.Settings.Default.lastUpdateCheckDate;
\r
85 TimeSpan elapsed = now.Subtract(lastCheck);
\r
86 if (elapsed.TotalDays > Properties.Settings.Default.daysBetweenUpdateCheck)
\r
88 lblStatus.Text = "Checking for updates ...";
\r
89 Application.DoEvents();
\r
91 Main.BeginCheckForUpdates(new AsyncCallback(UpdateCheckDone), false);
\r
95 // Clear the log files in the background
\r
96 if (Properties.Settings.Default.clearOldLogs)
\r
98 lblStatus.Text = "Clearing Old Log Files ...";
\r
99 Application.DoEvents();
\r
100 Thread clearLog = new Thread(Main.ClearOldLogs);
\r
104 // Setup the GUI components
\r
105 lblStatus.Text = "Setting up the GUI ...";
\r
106 Application.DoEvents();
\r
107 LoadPresetPanel(); // Load the Preset Panel
\r
108 treeView_presets.ExpandAll();
\r
109 lbl_encode.Text = string.Empty;
\r
110 drop_mode.SelectedIndex = 0;
\r
111 queueWindow = new frmQueue(encodeQueue, this); // Prepare the Queue
\r
112 if (!Properties.Settings.Default.QueryEditorTab)
\r
113 tabs_panel.TabPages.RemoveAt(7); // Remove the query editor tab if the user does not want it enabled.
\r
115 // Load the user's default settings or Normal Preset
\r
116 if (Properties.Settings.Default.defaultPreset != string.Empty)
\r
118 if (presetHandler.GetPreset(Properties.Settings.Default.defaultPreset) != null)
\r
120 string query = presetHandler.GetPreset(Properties.Settings.Default.defaultPreset).Query;
\r
121 bool loadPictureSettings =
\r
122 presetHandler.GetPreset(Properties.Settings.Default.defaultPreset).PictureSettings;
\r
126 x264Panel.Reset2Defaults();
\r
128 QueryParser presetQuery = QueryParser.Parse(query);
\r
129 PresetLoader.LoadPreset(this, presetQuery, Properties.Settings.Default.defaultPreset,
\r
130 loadPictureSettings);
\r
132 x264Panel.X264_StandardizeOptString();
\r
133 x264Panel.X264_SetCurrentSettingsInPanel();
\r
137 loadNormalPreset();
\r
140 loadNormalPreset();
\r
142 // Enabled GUI tooltip's if Required
\r
143 if (Properties.Settings.Default.tooltipEnable)
\r
144 ToolTip.Active = true;
\r
146 // Register with Growl (if not using Growl for the encoding completion action, this wont hurt anything)
\r
147 GrowlCommunicator.Register();
\r
149 // Finished Loading
\r
150 lblStatus.Text = "Loading Complete!";
\r
151 Application.DoEvents();
\r
154 this.Enabled = true;
\r
156 // Event Handlers and Queue Recovery
\r
161 private void UpdateCheckDone(IAsyncResult result)
\r
163 if (InvokeRequired)
\r
165 Invoke(new MethodInvoker(() => UpdateCheckDone(result)));
\r
169 UpdateCheckInformation info;
\r
173 info = Main.EndCheckForUpdates(result);
\r
175 if (info.NewVersionAvailable)
\r
177 frmUpdater updateWindow = new frmUpdater(info.BuildInformation);
\r
178 updateWindow.ShowDialog();
\r
181 catch (Exception ex)
\r
183 if ((bool)result.AsyncState)
\r
185 "Unable to check for updates, Please try again later.\n\nDetailed Error Information:\n" + ex,
\r
186 "Error", MessageBoxButtons.OK, MessageBoxIcon.Error);
\r
190 // Startup Functions
\r
191 private void queueRecovery()
\r
193 if (Main.CheckQueueRecovery())
\r
195 DialogResult result =
\r
197 "HandBrake has detected unfinished items on the queue from the last time the application was launched. Would you like to recover these?",
\r
198 "Queue Recovery Possible", MessageBoxButtons.YesNo, MessageBoxIcon.Question);
\r
200 if (result == DialogResult.Yes)
\r
201 encodeQueue.LoadQueueFromFile("hb_queue_recovery.xml"); // Start Recovery
\r
204 // Remove the Queue recovery file if the user doesn't want to recovery the last queue.
\r
205 string queuePath = Path.Combine(Path.GetTempPath(), "hb_queue_recovery.xml");
\r
206 if (File.Exists(queuePath))
\r
207 File.Delete(queuePath);
\r
216 public string SourceName
\r
220 if (this.selectedSourceType == SourceType.DvdDrive)
\r
222 return this.dvdDriveLabel;
\r
225 if (Path.GetFileNameWithoutExtension(this.sourcePath) != "VIDEO_TS")
\r
226 return Path.GetFileNameWithoutExtension(this.sourcePath);
\r
228 return Path.GetFileNameWithoutExtension(Path.GetDirectoryName(this.sourcePath));
\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 (Properties.Settings.Default.MainWindowMinimize)
\r
244 this.Resize += new EventHandler(frmMain_Resize);
\r
246 // Handle Encode Start / Finish / Pause
\r
248 encodeQueue.QueuePauseRequested += new EventHandler(encodePaused);
\r
249 encodeQueue.EncodeStarted += new EventHandler(encodeStarted);
\r
250 encodeQueue.EncodeEnded += new EventHandler(encodeEnded);
\r
252 // Handle a file being draged onto the GUI.
\r
253 this.DragEnter += new DragEventHandler(frmMain_DragEnter);
\r
254 this.DragDrop += new DragEventHandler(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 += new EventHandler(changePresetLabel);
\r
262 check_largeFile.CheckedChanged += new EventHandler(changePresetLabel);
\r
263 check_iPodAtom.CheckedChanged += new EventHandler(changePresetLabel);
\r
264 check_optimiseMP4.CheckedChanged += new EventHandler(changePresetLabel);
\r
266 // Picture Settings
\r
267 // PictureSettings.PictureSettingsChanged += new EventHandler(changePresetLabel);
\r
270 Filters.FilterSettingsChanged += new EventHandler(changePresetLabel);
\r
273 drp_videoEncoder.SelectedIndexChanged += new EventHandler(changePresetLabel);
\r
274 check_2PassEncode.CheckedChanged += new EventHandler(changePresetLabel);
\r
275 check_turbo.CheckedChanged += new EventHandler(changePresetLabel);
\r
276 text_filesize.TextChanged += new EventHandler(changePresetLabel);
\r
277 text_bitrate.TextChanged += new EventHandler(changePresetLabel);
\r
278 slider_videoQuality.ValueChanged += new EventHandler(changePresetLabel);
\r
281 AudioSettings.AudioListChanged += new EventHandler(changePresetLabel);
\r
284 x264Panel.rtf_x264Query.TextChanged += new EventHandler(changePresetLabel);
\r
287 private void UnRegisterPresetEventHandler()
\r
289 // Output Settings
\r
290 drop_format.SelectedIndexChanged -= new EventHandler(changePresetLabel);
\r
291 check_largeFile.CheckedChanged -= new EventHandler(changePresetLabel);
\r
292 check_iPodAtom.CheckedChanged -= new EventHandler(changePresetLabel);
\r
293 check_optimiseMP4.CheckedChanged -= new EventHandler(changePresetLabel);
\r
295 // Picture Settings
\r
296 // PictureSettings.PictureSettingsChanged -= new EventHandler(changePresetLabel);
\r
299 Filters.FilterSettingsChanged -= new EventHandler(changePresetLabel);
\r
302 drp_videoEncoder.SelectedIndexChanged -= new EventHandler(changePresetLabel);
\r
303 check_2PassEncode.CheckedChanged -= new EventHandler(changePresetLabel);
\r
304 check_turbo.CheckedChanged -= new EventHandler(changePresetLabel);
\r
305 text_filesize.TextChanged -= new EventHandler(changePresetLabel);
\r
306 text_bitrate.TextChanged -= new EventHandler(changePresetLabel);
\r
307 slider_videoQuality.ValueChanged -= new EventHandler(changePresetLabel);
\r
310 AudioSettings.AudioListChanged -= new EventHandler(changePresetLabel);
\r
313 x264Panel.rtf_x264Query.TextChanged -= new EventHandler(changePresetLabel);
\r
316 private void changePresetLabel(object sender, EventArgs e)
\r
318 labelPreset.Text = "Output Settings (Preset: Custom)";
\r
319 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 (fileList[0] != string.Empty)
\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
351 // Experimental HBProc Process Monitoring.
\r
352 if (Properties.Settings.Default.enocdeStatusInGui)
\r
354 Thread encodeMon = new Thread(EncodeMonitorThread);
\r
359 private void encodeEnded(object sender, EventArgs e)
\r
361 SetEncodeFinished();
\r
364 private void encodePaused(object sender, EventArgs e)
\r
366 SetEncodeFinished();
\r
371 // User Interface Menus / Tool Strips *********************************
\r
375 private void mnu_killCLI_Click(object sender, EventArgs e)
\r
380 private void mnu_exit_Click(object sender, EventArgs e)
\r
382 Application.Exit();
\r
389 private void mnu_encode_Click(object sender, EventArgs e)
\r
391 queueWindow.Show();
\r
394 private void mnu_encodeLog_Click(object sender, EventArgs e)
\r
396 frmActivityWindow dvdInfoWindow = new frmActivityWindow(encodeQueue, SourceScan);
\r
397 dvdInfoWindow.Show();
\r
400 private void mnu_options_Click(object sender, EventArgs e)
\r
402 Form options = new frmOptions(this);
\r
403 options.ShowDialog();
\r
408 #region Presets Menu
\r
410 private void mnu_presetReset_Click(object sender, EventArgs e)
\r
412 presetHandler.UpdateBuiltInPresets();
\r
414 if (treeView_presets.Nodes.Count == 0)
\r
416 "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
417 "Error", MessageBoxButtons.OK, MessageBoxIcon.Error);
\r
419 MessageBox.Show("Presets have been updated!", "Alert", MessageBoxButtons.OK, MessageBoxIcon.Information);
\r
421 treeView_presets.ExpandAll();
\r
424 private void mnu_delete_preset_Click(object sender, EventArgs e)
\r
426 presetHandler.RemoveBuiltInPresets();
\r
427 LoadPresetPanel(); // Reload the preset panel
\r
430 private void mnu_SelectDefault_Click(object sender, EventArgs e)
\r
432 loadNormalPreset();
\r
435 private void mnu_importMacPreset_Click(object sender, EventArgs e)
\r
440 private void btn_new_preset_Click(object sender, EventArgs e)
\r
442 Form preset = new frmAddPreset(this, QueryGenerator.GenerateCliQuery(this, drop_mode.SelectedIndex, 0, null),
\r
444 preset.ShowDialog();
\r
451 private void mnu_user_guide_Click(object sender, EventArgs e)
\r
453 Process.Start("http://trac.handbrake.fr/wiki/HandBrakeGuide");
\r
456 private void mnu_handbrake_home_Click(object sender, EventArgs e)
\r
458 Process.Start("http://handbrake.fr");
\r
461 private void mnu_UpdateCheck_Click(object sender, EventArgs e)
\r
463 lbl_updateCheck.Visible = true;
\r
464 Main.BeginCheckForUpdates(new AsyncCallback(updateCheckDoneMenu), false);
\r
467 private void updateCheckDoneMenu(IAsyncResult result)
\r
469 // Make sure it's running on the calling thread
\r
470 if (InvokeRequired)
\r
472 Invoke(new MethodInvoker(() => updateCheckDoneMenu(result)));
\r
475 UpdateCheckInformation info;
\r
478 // Get the information about the new build, if any, and close the window
\r
479 info = Main.EndCheckForUpdates(result);
\r
481 if (info.NewVersionAvailable && info.BuildInformation != null)
\r
483 frmUpdater updateWindow = new frmUpdater(info.BuildInformation);
\r
484 updateWindow.ShowDialog();
\r
487 MessageBox.Show("There are no new updates at this time.", "Update Check", MessageBoxButtons.OK,
\r
488 MessageBoxIcon.Information);
\r
489 lbl_updateCheck.Visible = false;
\r
492 catch (Exception ex)
\r
494 if ((bool)result.AsyncState)
\r
496 "Unable to check for updates, Please try again later.\n\nDetailed Error Information:\n" + ex,
\r
497 "Error", MessageBoxButtons.OK, MessageBoxIcon.Error);
\r
501 private void mnu_about_Click(object sender, EventArgs e)
\r
503 using (frmAbout About = new frmAbout())
\r
505 About.ShowDialog();
\r
513 // Right Click Menu Code
\r
514 private void pmnu_expandAll_Click(object sender, EventArgs e)
\r
516 treeView_presets.ExpandAll();
\r
519 private void pmnu_collapse_Click(object sender, EventArgs e)
\r
521 treeView_presets.CollapseAll();
\r
524 private void pmnu_import_Click(object sender, EventArgs e)
\r
529 private void pmnu_saveChanges_Click(object sender, EventArgs e)
\r
531 DialogResult result =
\r
533 "Do you wish to include picture settings when updating the preset: " +
\r
534 treeView_presets.SelectedNode.Text, "Update Preset", MessageBoxButtons.YesNoCancel,
\r
535 MessageBoxIcon.Question);
\r
536 if (result == DialogResult.Yes)
\r
537 presetHandler.Update(treeView_presets.SelectedNode.Text,
\r
538 QueryGenerator.GenerateTabbedComponentsQuery(this), true);
\r
539 else if (result == DialogResult.No)
\r
540 presetHandler.Update(treeView_presets.SelectedNode.Text,
\r
541 QueryGenerator.GenerateTabbedComponentsQuery(this), false);
\r
544 private void pmnu_delete_click(object sender, EventArgs e)
\r
546 if (treeView_presets.SelectedNode != null)
\r
548 presetHandler.Remove(treeView_presets.SelectedNode.Text);
\r
549 treeView_presets.Nodes.Remove(treeView_presets.SelectedNode);
\r
551 treeView_presets.Select();
\r
554 private void presets_menu_Opening(object sender, CancelEventArgs e)
\r
556 // Make sure that the save menu is always disabled by default
\r
557 pmnu_saveChanges.Enabled = false;
\r
559 // Now enable the save menu if the selected preset is a user preset
\r
560 if (treeView_presets.SelectedNode != null)
\r
561 if (presetHandler.CheckIfUserPresetExists(treeView_presets.SelectedNode.Text))
\r
562 pmnu_saveChanges.Enabled = true;
\r
564 treeView_presets.Select();
\r
567 // Presets Management
\r
568 private void btn_addPreset_Click(object sender, EventArgs e)
\r
570 Form preset = new frmAddPreset(this, QueryGenerator.GenerateTabbedComponentsQuery(this), presetHandler);
\r
571 preset.ShowDialog();
\r
574 private void btn_removePreset_Click(object sender, EventArgs e)
\r
576 DialogResult result = MessageBox.Show("Are you sure you wish to delete the selected preset?", "Preset",
\r
577 MessageBoxButtons.YesNo, MessageBoxIcon.Question);
\r
578 if (result == DialogResult.Yes)
\r
580 if (treeView_presets.SelectedNode != null)
\r
582 presetHandler.Remove(treeView_presets.SelectedNode.Text);
\r
583 treeView_presets.Nodes.Remove(treeView_presets.SelectedNode);
\r
586 treeView_presets.Select();
\r
589 private void btn_setDefault_Click(object sender, EventArgs e)
\r
591 if (treeView_presets.SelectedNode != null)
\r
593 DialogResult result = MessageBox.Show("Are you sure you wish to set this preset as the default?",
\r
594 "Preset", MessageBoxButtons.YesNo, MessageBoxIcon.Question);
\r
595 if (result == DialogResult.Yes)
\r
597 Properties.Settings.Default.defaultPreset = treeView_presets.SelectedNode.Text;
\r
598 Properties.Settings.Default.Save();
\r
599 MessageBox.Show("New default preset set.", "Alert", MessageBoxButtons.OK, MessageBoxIcon.Information);
\r
603 MessageBox.Show("Please select a preset first.", "Warning", MessageBoxButtons.OK, MessageBoxIcon.Warning);
\r
606 private void treeview_presets_mouseUp(object sender, MouseEventArgs e)
\r
608 if (e.Button == MouseButtons.Right)
\r
609 treeView_presets.SelectedNode = treeView_presets.GetNodeAt(e.Location);
\r
610 else if (e.Button == MouseButtons.Left)
\r
612 if (treeView_presets.GetNodeAt(e.Location) != null)
\r
614 if (labelPreset.Text.Contains(treeView_presets.GetNodeAt(e.Location).Text))
\r
619 treeView_presets.Select();
\r
622 private void treeView_presets_AfterSelect(object sender, TreeViewEventArgs e)
\r
627 private void treeView_presets_deleteKey(object sender, KeyEventArgs e)
\r
629 if (e.KeyCode == Keys.Delete)
\r
631 DialogResult result = MessageBox.Show("Are you sure you wish to delete the selected preset?", "Preset",
\r
632 MessageBoxButtons.YesNo, MessageBoxIcon.Question);
\r
633 if (result == DialogResult.Yes)
\r
635 if (treeView_presets.SelectedNode != null)
\r
636 presetHandler.Remove(treeView_presets.SelectedNode.Text);
\r
638 // Remember each nodes expanded status so we can reload it
\r
639 List<bool> nodeStatus = new List<bool>();
\r
640 foreach (TreeNode node in treeView_presets.Nodes)
\r
641 nodeStatus.Add(node.IsExpanded);
\r
643 // Now reload the preset panel
\r
646 // And finally, re-expand any of the nodes if required
\r
648 foreach (TreeNode node in treeView_presets.Nodes)
\r
659 private void selectPreset()
\r
661 if (treeView_presets.SelectedNode != null)
\r
663 // Ok, so, we've selected a preset. Now we want to load it.
\r
664 string presetName = treeView_presets.SelectedNode.Text;
\r
665 Preset preset = presetHandler.GetPreset(presetName);
\r
666 if (preset != null)
\r
668 string query = presetHandler.GetPreset(presetName).Query;
\r
669 bool loadPictureSettings = presetHandler.GetPreset(presetName).PictureSettings;
\r
673 // Ok, Reset all the H264 widgets before changing the preset
\r
674 x264Panel.Reset2Defaults();
\r
676 // Send the query from the file to the Query Parser class
\r
677 QueryParser presetQuery = QueryParser.Parse(query);
\r
679 // Now load the preset
\r
680 PresetLoader.LoadPreset(this, presetQuery, presetName, loadPictureSettings);
\r
682 // The x264 widgets will need updated, so do this now:
\r
683 x264Panel.X264_StandardizeOptString();
\r
684 x264Panel.X264_SetCurrentSettingsInPanel();
\r
686 // Finally, let this window have a copy of the preset settings.
\r
687 CurrentlySelectedPreset = preset;
\r
688 PictureSettings.SetPresetCropWarningLabel(preset);
\r
694 private void loadNormalPreset()
\r
696 foreach (TreeNode treenode in treeView_presets.Nodes)
\r
698 foreach (TreeNode node in treenode.Nodes)
\r
700 if (node.Text.Equals("Normal"))
\r
701 treeView_presets.SelectedNode = treeView_presets.Nodes[treenode.Index].Nodes[0];
\r
706 private void ImportPreset()
\r
708 if (openPreset.ShowDialog() == DialogResult.OK)
\r
710 QueryParser parsed = PlistPresetHandler.Import(openPreset.FileName);
\r
711 if (presetHandler.CheckIfUserPresetExists(parsed.PresetName + " (Imported)"))
\r
713 DialogResult result =
\r
714 MessageBox.Show("This preset appears to already exist. Would you like to overwrite it?",
\r
715 "Overwrite preset?",
\r
716 MessageBoxButtons.YesNo, MessageBoxIcon.Warning);
\r
717 if (result == DialogResult.Yes)
\r
719 PresetLoader.LoadPreset(this, parsed, parsed.PresetName, parsed.UsesPictureSettings);
\r
720 presetHandler.Update(parsed.PresetName + " (Imported)",
\r
721 QueryGenerator.GenerateCliQuery(this, drop_mode.SelectedIndex, 0, null),
\r
722 parsed.UsesPictureSettings);
\r
727 PresetLoader.LoadPreset(this, parsed, parsed.PresetName, parsed.UsesPictureSettings);
\r
728 if (presetHandler.Add(parsed.PresetName + " (Imported)",
\r
729 QueryGenerator.GenerateCliQuery(this, drop_mode.SelectedIndex, 0, null),
\r
730 parsed.UsesPictureSettings))
\r
732 TreeNode preset_treeview = new TreeNode(parsed.PresetName + " (Imported)")
\r
734 ForeColor = Color.Black
\r
736 treeView_presets.Nodes.Add(preset_treeview);
\r
746 private void btn_source_Click(object sender, EventArgs e)
\r
748 // Remove old Drive Menu Items.
\r
749 List<ToolStripMenuItem> itemsToRemove = new List<ToolStripMenuItem>();
\r
750 foreach (var item in btn_source.DropDownItems)
\r
752 if (item.GetType() == typeof(ToolStripMenuItem))
\r
754 ToolStripMenuItem menuItem = (ToolStripMenuItem)item;
\r
755 if (menuItem.Name.StartsWith("Drive"))
\r
757 itemsToRemove.Add(menuItem);
\r
762 foreach (ToolStripMenuItem item in itemsToRemove)
\r
763 btn_source.DropDownItems.Remove(item);
\r
765 Thread driveInfoThread = new Thread(SetDriveSelectionMenuItem);
\r
766 driveInfoThread.Start();
\r
769 private void btn_start_Click(object sender, EventArgs e)
\r
771 if (btn_start.Text == "Stop")
\r
773 DialogResult result;
\r
774 if (Properties.Settings.Default.enocdeStatusInGui &&
\r
775 !Properties.Settings.Default.showCliForInGuiEncodeStatus)
\r
777 result = MessageBox.Show(
\r
778 "Are you sure you wish to cancel the encode?\n\nPlease note, when 'Enable in-GUI encode status' is enabled, stopping this encode will render the file unplayable. ",
\r
779 "Cancel Encode?", MessageBoxButtons.YesNo, MessageBoxIcon.Question);
\r
783 result = MessageBox.Show("Are you sure you wish to cancel the encode?", "Cancel Encode?",
\r
784 MessageBoxButtons.YesNo, MessageBoxIcon.Question);
\r
787 if (result == DialogResult.Yes)
\r
790 encodeQueue.Pause();
\r
792 if (Properties.Settings.Default.enocdeStatusInGui &&
\r
793 !Properties.Settings.Default.showCliForInGuiEncodeStatus)
\r
795 encodeQueue.Stop();
\r
796 if (encodeQueue.HbProcess != null)
\r
797 encodeQueue.HbProcess.WaitForExit();
\r
801 encodeQueue.SafelyClose();
\r
805 SetEncodeFinished();
\r
810 if (encodeQueue.Count != 0 ||
\r
811 (!string.IsNullOrEmpty(sourcePath) && !string.IsNullOrEmpty(text_destination.Text)))
\r
813 string generatedQuery = QueryGenerator.GenerateCliQuery(this, drop_mode.SelectedIndex, 0, null);
\r
814 string specifiedQuery = rtf_query.Text != string.Empty
\r
816 : QueryGenerator.GenerateCliQuery(this, drop_mode.SelectedIndex, 0, null);
\r
817 string query = string.Empty;
\r
819 // Check to make sure the generated query matches the GUI settings
\r
820 if (Properties.Settings.Default.PromptOnUnmatchingQueries && !string.IsNullOrEmpty(specifiedQuery) &&
\r
821 generatedQuery != specifiedQuery)
\r
823 DialogResult result = MessageBox.Show("The query under the \"Query Editor\" tab " +
\r
824 "does not match the current GUI settings.\n\nBecause the manual query takes " +
\r
825 "priority over the GUI, your recently updated settings will not be taken " +
\r
826 "into account when encoding this job." +
\r
827 Environment.NewLine + Environment.NewLine +
\r
828 "Do you want to replace the manual query with the updated GUI-generated query?",
\r
829 "Manual Query does not Match GUI",
\r
830 MessageBoxButtons.YesNoCancel, MessageBoxIcon.Asterisk,
\r
831 MessageBoxDefaultButton.Button3);
\r
835 case DialogResult.Yes:
\r
836 // Replace the manual query with the generated one
\r
837 query = generatedQuery;
\r
838 rtf_query.Text = generatedQuery;
\r
840 case DialogResult.No:
\r
841 // Use the manual query
\r
842 query = specifiedQuery;
\r
844 case DialogResult.Cancel:
\r
845 // Don't start the encode
\r
851 query = specifiedQuery;
\r
854 DialogResult overwrite = DialogResult.Yes;
\r
855 if (text_destination.Text != string.Empty)
\r
856 if (File.Exists(text_destination.Text))
\r
859 "The destination file already exists. Are you sure you want to overwrite it?",
\r
860 "Overwrite File?", MessageBoxButtons.YesNo, MessageBoxIcon.Question);
\r
862 if (overwrite == DialogResult.Yes)
\r
864 if (encodeQueue.Count == 0)
\r
865 encodeQueue.Add(query, getTitle(), sourcePath, text_destination.Text, (rtf_query.Text != string.Empty));
\r
867 queueWindow.SetQueue();
\r
868 if (encodeQueue.Count > 1)
\r
869 queueWindow.Show(false);
\r
871 SetEncodeStarted(); // Encode is running, so setup the GUI appropriately
\r
872 encodeQueue.Start(); // Start The Queue Encoding Process
\r
877 else if (string.IsNullOrEmpty(sourcePath) || string.IsNullOrEmpty(text_destination.Text))
\r
878 MessageBox.Show("No source or destination selected.", "Warning", MessageBoxButtons.OK,
\r
879 MessageBoxIcon.Warning);
\r
883 private void btn_add2Queue_Click(object sender, EventArgs e)
\r
885 if (string.IsNullOrEmpty(sourcePath) || string.IsNullOrEmpty(text_destination.Text))
\r
886 MessageBox.Show("No source or destination selected.", "Warning", MessageBoxButtons.OK,
\r
887 MessageBoxIcon.Warning);
\r
890 string query = QueryGenerator.GenerateCliQuery(this, drop_mode.SelectedIndex, 0, null);
\r
891 if (rtf_query.Text != string.Empty)
\r
892 query = rtf_query.Text;
\r
894 if (encodeQueue.CheckForDestinationDuplicate(text_destination.Text))
\r
896 DialogResult result =
\r
898 "There is already a queue item for this destination path. \n\n If you continue, the encode will be overwritten. Do you wish to continue?",
\r
899 "Warning", MessageBoxButtons.YesNo, MessageBoxIcon.Warning);
\r
900 if (result == DialogResult.Yes)
\r
901 encodeQueue.Add(query, getTitle(), sourcePath, text_destination.Text, (rtf_query.Text != string.Empty));
\r
904 encodeQueue.Add(query, getTitle(), sourcePath, text_destination.Text, (rtf_query.Text != string.Empty));
\r
906 lbl_encode.Text = encodeQueue.Count + " encode(s) pending in the queue";
\r
908 queueWindow.Show();
\r
912 private void btn_showQueue_Click(object sender, EventArgs e)
\r
914 queueWindow.Show();
\r
915 queueWindow.Activate();
\r
918 private void tb_preview_Click(object sender, EventArgs e)
\r
920 if (string.IsNullOrEmpty(sourcePath) || string.IsNullOrEmpty(text_destination.Text))
\r
921 MessageBox.Show("No source or destination selected.", "Warning", MessageBoxButtons.OK,
\r
922 MessageBoxIcon.Warning);
\r
925 if (qtpreview == null)
\r
927 qtpreview = new frmPreview(this);
\r
930 else if (qtpreview.IsDisposed)
\r
932 qtpreview = new frmPreview(this);
\r
936 MessageBox.Show(qtpreview, "The preview window is already open!", "Warning", MessageBoxButtons.OK,
\r
937 MessageBoxIcon.Warning);
\r
941 private void btn_ActivityWindow_Click(object sender, EventArgs e)
\r
943 if (ActivityWindow == null || !ActivityWindow.IsHandleCreated)
\r
944 ActivityWindow = new frmActivityWindow(encodeQueue, SourceScan);
\r
946 ActivityWindow.Show();
\r
947 ActivityWindow.Activate();
\r
952 #region System Tray Icon
\r
954 private void frmMain_Resize(object sender, EventArgs e)
\r
956 if (FormWindowState.Minimized == this.WindowState)
\r
958 notifyIcon.Visible = true;
\r
961 else if (FormWindowState.Normal == this.WindowState)
\r
962 notifyIcon.Visible = false;
\r
965 private void notifyIcon_MouseDoubleClick(object sender, MouseEventArgs e)
\r
967 this.Visible = true;
\r
969 this.WindowState = FormWindowState.Normal;
\r
970 notifyIcon.Visible = false;
\r
973 private void btn_restore_Click(object sender, EventArgs e)
\r
975 this.Visible = true;
\r
977 this.WindowState = FormWindowState.Normal;
\r
978 notifyIcon.Visible = false;
\r
983 #region Tab Control
\r
986 private void btn_dvd_source_Click(object sender, EventArgs e)
\r
988 if (DVD_Open.ShowDialog() == DialogResult.OK)
\r
990 this.selectedSourceType = SourceType.Folder;
\r
991 SelectSource(DVD_Open.SelectedPath);
\r
994 UpdateSourceLabel();
\r
997 private void btn_file_source_Click(object sender, EventArgs e)
\r
999 if (ISO_Open.ShowDialog() == DialogResult.OK)
\r
1001 this.selectedSourceType = SourceType.VideoFile;
\r
1002 SelectSource(ISO_Open.FileName);
\r
1005 UpdateSourceLabel();
\r
1008 private void mnu_dvd_drive_Click(object sender, EventArgs e)
\r
1010 ToolStripMenuItem item = sender as ToolStripMenuItem;
\r
1013 string driveId = item.Name.Replace("Drive", string.Empty);
\r
1015 if (int.TryParse(driveId, out id))
\r
1018 this.dvdDrivePath = drives[id].RootDirectory;
\r
1019 this.dvdDriveLabel = drives[id].VolumeLabel;
\r
1021 if (this.dvdDrivePath == null) return;
\r
1022 this.selectedSourceType = SourceType.DvdDrive;
\r
1023 SelectSource(this.dvdDrivePath);
\r
1028 private void SelectSource(string file)
\r
1030 Check_ChapterMarkers.Enabled = true;
\r
1031 sourcePath = string.Empty;
\r
1033 if (file == string.Empty) // Must have a file or path
\r
1035 UpdateSourceLabel();
\r
1039 sourcePath = Path.GetFileName(file);
\r
1040 StartScan(file, 0);
\r
1043 private void drp_dvdtitle_Click(object sender, EventArgs e)
\r
1045 if ((drp_dvdtitle.Items.Count == 1) && (drp_dvdtitle.Items[0].ToString() == "Automatic"))
\r
1047 "There are no titles to select. Please load a source file by clicking the 'Source' button above before trying to select a title.",
\r
1048 "Alert", MessageBoxButtons.OK, MessageBoxIcon.Asterisk);
\r
1051 private void drp_dvdtitle_SelectedIndexChanged(object sender, EventArgs e)
\r
1053 UnRegisterPresetEventHandler();
\r
1054 drop_mode.SelectedIndex = 0;
\r
1056 drop_chapterStart.Items.Clear();
\r
1057 drop_chapterFinish.Items.Clear();
\r
1059 // If the dropdown is set to automatic nothing else needs to be done.
\r
1060 // Otheriwse if its not, title data has to be loaded from parsing.
\r
1061 if (drp_dvdtitle.Text != "Automatic")
\r
1063 selectedTitle = drp_dvdtitle.SelectedItem as Title;
\r
1064 lbl_duration.Text = selectedTitle.Duration.ToString();
\r
1065 PictureSettings.CurrentlySelectedPreset = CurrentlySelectedPreset;
\r
1066 PictureSettings.Source = selectedTitle; // Setup Picture Settings Tab Control
\r
1068 // Populate the Angles dropdown
\r
1069 drop_angle.Items.Clear();
\r
1070 if (!Properties.Settings.Default.noDvdNav)
\r
1072 drop_angle.Visible = true;
\r
1073 lbl_angle.Visible = true;
\r
1074 drop_angle.Items.AddRange(selectedTitle.Angles.ToArray());
\r
1075 if (drop_angle.Items.Count != 0)
\r
1076 drop_angle.SelectedIndex = 0;
\r
1080 drop_angle.Visible = false;
\r
1081 lbl_angle.Visible = false;
\r
1084 // Populate the Start chapter Dropdown
\r
1085 drop_chapterStart.Items.Clear();
\r
1086 drop_chapterStart.Items.AddRange(selectedTitle.Chapters.ToArray());
\r
1087 if (drop_chapterStart.Items.Count > 0)
\r
1088 drop_chapterStart.Text = drop_chapterStart.Items[0].ToString();
\r
1090 // Populate the Final Chapter Dropdown
\r
1091 drop_chapterFinish.Items.Clear();
\r
1092 drop_chapterFinish.Items.AddRange(selectedTitle.Chapters.ToArray());
\r
1093 if (drop_chapterFinish.Items.Count > 0)
\r
1094 drop_chapterFinish.Text = drop_chapterFinish.Items[drop_chapterFinish.Items.Count - 1].ToString();
\r
1096 // Populate the Audio Channels Dropdown
\r
1097 AudioSettings.SetTrackList(selectedTitle, CurrentlySelectedPreset);
\r
1099 // Populate the Subtitles dropdown
\r
1100 Subtitles.SetSubtitleTrackAuto(selectedTitle.Subtitles.ToArray());
\r
1102 // Update the source label if we have multiple streams
\r
1103 if (selectedTitle != null)
\r
1104 if (!string.IsNullOrEmpty(selectedTitle.SourceName))
\r
1105 labelSource.Text = labelSource.Text = Path.GetFileName(selectedTitle.SourceName);
\r
1107 // Run the AutoName & ChapterNaming functions
\r
1108 if (Properties.Settings.Default.autoNaming)
\r
1110 string autoPath = Main.AutoName(this);
\r
1111 if (autoPath != null)
\r
1112 text_destination.Text = autoPath;
\r
1115 "You currently have \"Automatically name output files\" enabled for the destination file box, but you do not have a default directory set.\n\nYou should set a \"Default Path\" in HandBrakes preferences. (See 'Tools' menu -> 'Options' -> 'General' Tab -> 'Default Path')",
\r
1116 "Warning", MessageBoxButtons.OK, MessageBoxIcon.Warning);
\r
1119 data_chpt.Rows.Clear();
\r
1120 if (selectedTitle.Chapters.Count != 1)
\r
1122 DataGridView chapterGridView = Main.ChapterNaming(data_chpt, drop_chapterFinish.Text);
\r
1123 if (chapterGridView != null)
\r
1124 data_chpt = chapterGridView;
\r
1128 Check_ChapterMarkers.Checked = false;
\r
1129 Check_ChapterMarkers.Enabled = false;
\r
1132 // Hack to force the redraw of the scrollbars which don't resize properly when the control is disabled.
\r
1133 data_chpt.Columns[0].Width = 166;
\r
1134 data_chpt.Columns[0].Width = 165;
\r
1136 RegisterPresetEventHandler();
\r
1139 private void chapersChanged(object sender, EventArgs e)
\r
1141 if (drop_mode.SelectedIndex != 0) // Function is not used if we are not in chapters mode.
\r
1144 Control ctl = (Control)sender;
\r
1145 int chapterStart, chapterEnd;
\r
1146 int.TryParse(drop_chapterStart.Text, out chapterStart);
\r
1147 int.TryParse(drop_chapterFinish.Text, out chapterEnd);
\r
1151 case "drop_chapterStart":
\r
1152 if (drop_chapterFinish.SelectedIndex == -1 && drop_chapterFinish.Items.Count != 0)
\r
1153 drop_chapterFinish.SelectedIndex = drop_chapterFinish.Items.Count - 1;
\r
1155 if (chapterEnd != 0)
\r
1156 if (chapterStart > chapterEnd)
\r
1157 drop_chapterFinish.Text = chapterStart.ToString();
\r
1159 case "drop_chapterFinish":
\r
1160 if (drop_chapterStart.Items.Count >= 1 && drop_chapterStart.SelectedIndex == -1)
\r
1161 drop_chapterStart.SelectedIndex = 0;
\r
1163 if (chapterStart != 0)
\r
1164 if (chapterEnd < chapterStart)
\r
1165 drop_chapterFinish.Text = chapterStart.ToString();
\r
1167 // Add more rows to the Chapter menu if needed.
\r
1168 if (Check_ChapterMarkers.Checked)
\r
1170 int i = data_chpt.Rows.Count, finish = 0;
\r
1171 int.TryParse(drop_chapterFinish.Text, out finish);
\r
1173 while (i < finish)
\r
1175 int n = data_chpt.Rows.Add();
\r
1176 data_chpt.Rows[n].Cells[0].Value = (i + 1);
\r
1177 data_chpt.Rows[n].Cells[1].Value = "Chapter " + (i + 1);
\r
1178 data_chpt.Rows[n].Cells[0].ValueType = typeof(int);
\r
1179 data_chpt.Rows[n].Cells[1].ValueType = typeof(string);
\r
1186 // Update the Duration
\r
1187 lbl_duration.Text =
\r
1188 Main.CalculateDuration(drop_chapterStart.SelectedIndex, drop_chapterFinish.SelectedIndex, selectedTitle)
\r
1191 // Run the Autonaming function
\r
1192 if (Properties.Settings.Default.autoNaming)
\r
1193 text_destination.Text = Main.AutoName(this);
\r
1195 // Disable chapter markers if only 1 chapter is selected.
\r
1196 if (chapterStart == chapterEnd)
\r
1198 Check_ChapterMarkers.Enabled = false;
\r
1199 btn_importChapters.Enabled = false;
\r
1200 data_chpt.Enabled = false;
\r
1204 Check_ChapterMarkers.Enabled = true;
\r
1205 if (Check_ChapterMarkers.Checked)
\r
1207 btn_importChapters.Enabled = true;
\r
1208 data_chpt.Enabled = true;
\r
1213 private void SecondsOrFramesChanged(object sender, EventArgs e)
\r
1216 int.TryParse(drop_chapterStart.Text, out start);
\r
1217 int.TryParse(drop_chapterFinish.Text, out end);
\r
1218 double duration = end - start;
\r
1220 switch (drop_mode.SelectedIndex)
\r
1223 lbl_duration.Text = TimeSpan.FromSeconds(duration).ToString();
\r
1226 if (selectedTitle != null)
\r
1228 duration = duration / selectedTitle.Fps;
\r
1229 lbl_duration.Text = TimeSpan.FromSeconds(duration).ToString();
\r
1232 lbl_duration.Text = "--:--:--";
\r
1238 private void drop_mode_SelectedIndexChanged(object sender, EventArgs e)
\r
1241 this.drop_chapterFinish.TextChanged -= new EventHandler(this.SecondsOrFramesChanged);
\r
1242 this.drop_chapterStart.TextChanged -= new EventHandler(this.SecondsOrFramesChanged);
\r
1245 switch (drop_mode.SelectedIndex)
\r
1248 drop_chapterStart.DropDownStyle = ComboBoxStyle.DropDownList;
\r
1249 drop_chapterFinish.DropDownStyle = ComboBoxStyle.DropDownList;
\r
1250 if (drop_chapterStart.Items.Count != 0)
\r
1252 drop_chapterStart.SelectedIndex = 0;
\r
1253 drop_chapterFinish.SelectedIndex = drop_chapterFinish.Items.Count - 1;
\r
1256 lbl_duration.Text = "--:--:--";
\r
1259 this.drop_chapterStart.TextChanged += new EventHandler(this.SecondsOrFramesChanged);
\r
1260 this.drop_chapterFinish.TextChanged += new EventHandler(this.SecondsOrFramesChanged);
\r
1261 drop_chapterStart.DropDownStyle = ComboBoxStyle.Simple;
\r
1262 drop_chapterFinish.DropDownStyle = ComboBoxStyle.Simple;
\r
1263 if (selectedTitle != null)
\r
1265 drop_chapterStart.Text = "0";
\r
1266 drop_chapterFinish.Text = selectedTitle.Duration.TotalSeconds.ToString();
\r
1270 this.drop_chapterStart.TextChanged += new EventHandler(this.SecondsOrFramesChanged);
\r
1271 this.drop_chapterFinish.TextChanged += new EventHandler(this.SecondsOrFramesChanged);
\r
1272 drop_chapterStart.DropDownStyle = ComboBoxStyle.Simple;
\r
1273 drop_chapterFinish.DropDownStyle = ComboBoxStyle.Simple;
\r
1274 if (selectedTitle != null)
\r
1276 drop_chapterStart.Text = "0";
\r
1277 drop_chapterFinish.Text = (selectedTitle.Fps * selectedTitle.Duration.TotalSeconds).ToString();
\r
1284 private void btn_destBrowse_Click(object sender, EventArgs e)
\r
1286 // This removes the file extension from the filename box on the save file dialog.
\r
1287 // It's daft but some users don't realise that typing an extension overrides the dropdown extension selected.
\r
1288 DVD_Save.FileName = Path.GetFileNameWithoutExtension(text_destination.Text);
\r
1290 if (Path.IsPathRooted(text_destination.Text))
\r
1291 DVD_Save.InitialDirectory = Path.GetDirectoryName(text_destination.Text);
\r
1293 // Show the dialog and set the main form file path
\r
1294 if (drop_format.SelectedIndex.Equals(0))
\r
1295 DVD_Save.FilterIndex = 1;
\r
1296 else if (drop_format.SelectedIndex.Equals(1))
\r
1297 DVD_Save.FilterIndex = 2;
\r
1299 if (DVD_Save.ShowDialog() == DialogResult.OK)
\r
1301 // Add a file extension manually, as FileDialog.AddExtension has issues with dots in filenames
\r
1302 switch (DVD_Save.FilterIndex)
\r
1306 !Path.GetExtension(DVD_Save.FileName).Equals(".mp4",
\r
1307 StringComparison.InvariantCultureIgnoreCase))
\r
1308 if (Properties.Settings.Default.useM4v)
\r
1309 DVD_Save.FileName = DVD_Save.FileName.Replace(".mp4", ".m4v").Replace(".mkv", ".m4v");
\r
1311 DVD_Save.FileName = DVD_Save.FileName.Replace(".m4v", ".mp4").Replace(".mkv", ".mp4");
\r
1315 !Path.GetExtension(DVD_Save.FileName).Equals(".mkv", StringComparison.InvariantCultureIgnoreCase))
\r
1316 DVD_Save.FileName = DVD_Save.FileName.Replace(".mp4", ".mkv").Replace(".m4v", ".mkv");
\r
1322 text_destination.Text = DVD_Save.FileName;
\r
1324 // Quicktime requires .m4v file for chapter markers to work. If checked, change the extension to .m4v (mp4 and m4v are the same thing)
\r
1325 if (Check_ChapterMarkers.Checked && DVD_Save.FilterIndex != 2)
\r
1326 SetExtension(".m4v");
\r
1330 private void text_destination_TextChanged(object sender, EventArgs e)
\r
1332 string path = text_destination.Text;
\r
1333 if (path.EndsWith(".mp4") || path.EndsWith(".m4v"))
\r
1334 drop_format.SelectedIndex = 0;
\r
1335 else if (path.EndsWith(".mkv"))
\r
1336 drop_format.SelectedIndex = 1;
\r
1339 // Output Settings
\r
1340 private void drop_format_SelectedIndexChanged(object sender, EventArgs e)
\r
1342 switch (drop_format.SelectedIndex)
\r
1345 if (Properties.Settings.Default.useM4v || Check_ChapterMarkers.Checked ||
\r
1346 AudioSettings.RequiresM4V() || Subtitles.RequiresM4V())
\r
1347 SetExtension(".m4v");
\r
1349 SetExtension(".mp4");
\r
1352 SetExtension(".mkv");
\r
1356 AudioSettings.SetContainer(drop_format.Text);
\r
1357 Subtitles.SetContainer(drop_format.SelectedIndex);
\r
1359 if (drop_format.Text.Contains("MP4"))
\r
1361 if (drp_videoEncoder.Items.Contains("VP3 (Theora)"))
\r
1363 drp_videoEncoder.Items.Remove("VP3 (Theora)");
\r
1364 drp_videoEncoder.SelectedIndex = 1;
\r
1367 else if (drop_format.Text.Contains("MKV"))
\r
1368 drp_videoEncoder.Items.Add("VP3 (Theora)");
\r
1371 public void SetExtension(string newExtension)
\r
1373 if (newExtension == ".mp4" || newExtension == ".m4v")
\r
1374 if (Properties.Settings.Default.useM4v || Check_ChapterMarkers.Checked || AudioSettings.RequiresM4V() ||
\r
1375 Subtitles.RequiresM4V())
\r
1376 newExtension = ".m4v";
\r
1378 newExtension = ".mp4";
\r
1380 if (Path.HasExtension(newExtension))
\r
1381 text_destination.Text = Path.ChangeExtension(text_destination.Text, newExtension);
\r
1385 private void drp_videoEncoder_SelectedIndexChanged(object sender, EventArgs e)
\r
1387 setContainerOpts();
\r
1389 // Turn off some options which are H.264 only when the user selects a non h.264 encoder
\r
1390 if (drp_videoEncoder.Text.Contains("H.264"))
\r
1392 if (check_2PassEncode.CheckState == CheckState.Checked)
\r
1393 check_turbo.Enabled = true;
\r
1395 tab_advanced.Enabled = true;
\r
1396 if ((drop_format.Text.Contains("MP4")) || (drop_format.Text.Contains("M4V")))
\r
1397 check_iPodAtom.Enabled = true;
\r
1399 check_iPodAtom.Enabled = false;
\r
1403 check_turbo.CheckState = CheckState.Unchecked;
\r
1404 check_turbo.Enabled = false;
\r
1405 tab_advanced.Enabled = false;
\r
1406 x264Panel.X264Query = string.Empty;
\r
1407 check_iPodAtom.Enabled = false;
\r
1408 check_iPodAtom.Checked = false;
\r
1411 // Setup the CQ Slider
\r
1412 switch (drp_videoEncoder.Text)
\r
1414 case "MPEG-4 (FFmpeg)":
\r
1415 if (slider_videoQuality.Value > 31)
\r
1416 slider_videoQuality.Value = 20; // Just reset to 70% QP 10 on encode change.
\r
1417 slider_videoQuality.Minimum = 1;
\r
1418 slider_videoQuality.Maximum = 31;
\r
1420 case "H.264 (x264)":
\r
1421 slider_videoQuality.Minimum = 0;
\r
1422 slider_videoQuality.TickFrequency = 1;
\r
1424 CultureInfo culture = CultureInfo.CreateSpecificCulture("en-US");
\r
1425 double cqStep = Properties.Settings.Default.x264cqstep;
\r
1426 double multiplier = 1.0 / cqStep;
\r
1427 double value = slider_videoQuality.Value * multiplier;
\r
1429 slider_videoQuality.Maximum = (int)(51 / Properties.Settings.Default.x264cqstep);
\r
1431 if (value < slider_videoQuality.Maximum)
\r
1432 slider_videoQuality.Value = slider_videoQuality.Maximum - (int)value;
\r
1435 case "VP3 (Theora)":
\r
1436 if (slider_videoQuality.Value > 63)
\r
1437 slider_videoQuality.Value = 45; // Just reset to 70% QP 45 on encode change.
\r
1438 slider_videoQuality.Minimum = 0;
\r
1439 slider_videoQuality.Maximum = 63;
\r
1445 /// Set the container format options
\r
1447 public void setContainerOpts()
\r
1449 if ((drop_format.Text.Contains("MP4")) || (drop_format.Text.Contains("M4V")))
\r
1451 check_largeFile.Enabled = true;
\r
1452 check_optimiseMP4.Enabled = true;
\r
1453 check_iPodAtom.Enabled = true;
\r
1457 check_largeFile.Enabled = false;
\r
1458 check_optimiseMP4.Enabled = false;
\r
1459 check_iPodAtom.Enabled = false;
\r
1460 check_largeFile.Checked = false;
\r
1461 check_optimiseMP4.Checked = false;
\r
1462 check_iPodAtom.Checked = false;
\r
1466 private double _cachedCqStep = Properties.Settings.Default.x264cqstep;
\r
1469 /// Update the CQ slider for x264 for a new CQ step. This is set from option
\r
1471 public void setQualityFromSlider()
\r
1473 // Work out the current RF value.
\r
1474 double cqStep = _cachedCqStep;
\r
1475 double rfValue = 51.0 - slider_videoQuality.Value * cqStep;
\r
1477 // Change the maximum value for the slider
\r
1478 slider_videoQuality.Maximum = (int)(51 / Properties.Settings.Default.x264cqstep);
\r
1480 // Reset the CQ slider to RF0
\r
1481 slider_videoQuality.Value = slider_videoQuality.Maximum;
\r
1483 // Reset the CQ slider back to the previous value as close as possible
\r
1484 double cqStepNew = Properties.Settings.Default.x264cqstep;
\r
1485 double rfValueCurrent = 51.0 - slider_videoQuality.Value * cqStepNew;
\r
1486 while (rfValueCurrent < rfValue)
\r
1488 slider_videoQuality.Value--;
\r
1489 rfValueCurrent = 51.0 - slider_videoQuality.Value * cqStepNew;
\r
1492 // Cache the CQ step for the next calculation
\r
1493 _cachedCqStep = Properties.Settings.Default.x264cqstep;
\r
1496 private void slider_videoQuality_Scroll(object sender, EventArgs e)
\r
1498 double cqStep = Properties.Settings.Default.x264cqstep;
\r
1499 switch (drp_videoEncoder.Text)
\r
1501 case "MPEG-4 (FFmpeg)":
\r
1502 lbl_SliderValue.Text = "QP:" + (32 - slider_videoQuality.Value);
\r
1504 case "H.264 (x264)":
\r
1505 double rfValue = 51.0 - slider_videoQuality.Value * cqStep;
\r
1506 rfValue = Math.Round(rfValue, 2);
\r
1507 lbl_SliderValue.Text = "RF:" + rfValue.ToString(new CultureInfo("en-US"));
\r
1509 case "VP3 (Theora)":
\r
1510 lbl_SliderValue.Text = "QP:" + slider_videoQuality.Value;
\r
1515 private void radio_targetFilesize_CheckedChanged(object sender, EventArgs e)
\r
1517 text_bitrate.Enabled = false;
\r
1518 text_filesize.Enabled = true;
\r
1519 slider_videoQuality.Enabled = false;
\r
1521 check_2PassEncode.Enabled = true;
\r
1524 private void radio_avgBitrate_CheckedChanged(object sender, EventArgs e)
\r
1526 text_bitrate.Enabled = true;
\r
1527 text_filesize.Enabled = false;
\r
1528 slider_videoQuality.Enabled = false;
\r
1530 check_2PassEncode.Enabled = true;
\r
1533 private void radio_cq_CheckedChanged(object sender, EventArgs e)
\r
1535 text_bitrate.Enabled = false;
\r
1536 text_filesize.Enabled = false;
\r
1537 slider_videoQuality.Enabled = true;
\r
1539 check_2PassEncode.Enabled = false;
\r
1540 check_2PassEncode.CheckState = CheckState.Unchecked;
\r
1543 private void check_2PassEncode_CheckedChanged(object sender, EventArgs e)
\r
1545 if (check_2PassEncode.CheckState.ToString() == "Checked")
\r
1547 if (drp_videoEncoder.Text.Contains("H.264"))
\r
1548 check_turbo.Enabled = true;
\r
1552 check_turbo.Enabled = false;
\r
1553 check_turbo.CheckState = CheckState.Unchecked;
\r
1557 // Chapter Marker Tab
\r
1558 private void Check_ChapterMarkers_CheckedChanged(object sender, EventArgs e)
\r
1560 if (Check_ChapterMarkers.Checked)
\r
1562 if (drop_format.SelectedIndex != 1)
\r
1563 SetExtension(".m4v");
\r
1564 data_chpt.Enabled = true;
\r
1565 btn_importChapters.Enabled = true;
\r
1569 if (drop_format.SelectedIndex != 1 && !Properties.Settings.Default.useM4v)
\r
1570 SetExtension(".mp4");
\r
1571 data_chpt.Enabled = false;
\r
1572 btn_importChapters.Enabled = false;
\r
1576 private void btn_importChapters_Click(object sender, EventArgs e)
\r
1578 if (File_ChapterImport.ShowDialog() == DialogResult.OK)
\r
1580 string filename = File_ChapterImport.FileName;
\r
1581 DataGridView imported = Main.ImportChapterNames(data_chpt, filename);
\r
1582 if (imported != null)
\r
1583 data_chpt = imported;
\r
1587 private void btn_export_Click(object sender, EventArgs e)
\r
1589 SaveFileDialog saveFileDialog = new SaveFileDialog();
\r
1590 saveFileDialog.Filter = "Csv File|*.csv";
\r
1591 saveFileDialog.DefaultExt = "csv";
\r
1592 if (saveFileDialog.ShowDialog() == DialogResult.OK)
\r
1594 string filename = saveFileDialog.FileName;
\r
1596 Main.SaveChapterMarkersToCsv(this, filename);
\r
1600 private void mnu_resetChapters_Click(object sender, EventArgs e)
\r
1602 data_chpt.Rows.Clear();
\r
1603 DataGridView chapterGridView = Main.ChapterNaming(data_chpt, drop_chapterFinish.Text);
\r
1604 if (chapterGridView != null)
\r
1606 data_chpt = chapterGridView;
\r
1610 // Query Editor Tab
\r
1611 private void btn_generate_Query_Click(object sender, EventArgs e)
\r
1613 rtf_query.Text = QueryGenerator.GenerateCliQuery(this, drop_mode.SelectedIndex, 0, null);
\r
1616 private void btn_clear_Click(object sender, EventArgs e)
\r
1618 rtf_query.Clear();
\r
1623 // MainWindow Components, Actions and Functions ***********************
\r
1625 #region Source Scan
\r
1627 public bool isScanning { get; set; }
\r
1629 private void StartScan(string filename, int title)
\r
1631 // Setup the GUI components for the scan.
\r
1632 sourcePath = filename;
\r
1634 this.DisableGUI();
\r
1639 isScanning = true;
\r
1640 SourceScan.Scan(sourcePath, title);
\r
1641 SourceScan.ScanStatusChanged += new EventHandler(SourceScan_ScanStatusChanged);
\r
1642 SourceScan.ScanCompleted += new EventHandler(SourceScan_ScanCompleted);
\r
1644 catch (Exception exc)
\r
1646 MessageBox.Show("frmMain.cs - StartScan " + exc, "Error", MessageBoxButtons.OK, MessageBoxIcon.Error);
\r
1650 private void SourceScan_ScanStatusChanged(object sender, EventArgs e)
\r
1652 UpdateScanStatusLabel();
\r
1655 private void SourceScan_ScanCompleted(object sender, EventArgs e)
\r
1657 UpdateGuiAfterScan();
\r
1660 private void UpdateScanStatusLabel()
\r
1662 if (InvokeRequired)
\r
1664 BeginInvoke(new UpdateWindowHandler(UpdateScanStatusLabel));
\r
1667 lbl_encode.Text = SourceScan.ScanStatus;
\r
1670 private void UpdateGuiAfterScan()
\r
1672 if (InvokeRequired)
\r
1674 BeginInvoke(new UpdateWindowHandler(UpdateGuiAfterScan));
\r
1680 currentSource = SourceScan.SouceData;
\r
1682 // Setup some GUI components
\r
1683 drp_dvdtitle.Items.Clear();
\r
1684 if (currentSource.Titles.Count != 0)
\r
1685 drp_dvdtitle.Items.AddRange(currentSource.Titles.ToArray());
\r
1687 foreach (Title title in currentSource.Titles)
\r
1689 if (title.MainTitle)
\r
1691 drp_dvdtitle.SelectedItem = title;
\r
1695 if (drp_dvdtitle.SelectedItem == null && drp_dvdtitle.Items.Count > 0)
\r
1697 drp_dvdtitle.SelectedIndex = 0;
\r
1700 // Enable the creation of chapter markers if the file is an image of a dvd.
\r
1702 int.TryParse(drop_chapterStart.Items[0].ToString(), out start);
\r
1703 int.TryParse(drop_chapterFinish.Items[drop_chapterFinish.Items.Count - 1].ToString(), out end);
\r
1705 Check_ChapterMarkers.Enabled = true;
\r
1708 Check_ChapterMarkers.Enabled = false;
\r
1709 Check_ChapterMarkers.Checked = false;
\r
1710 data_chpt.Rows.Clear();
\r
1713 // If no titles were found, Display an error message
\r
1714 if (drp_dvdtitle.Items.Count == 0)
\r
1717 "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
1718 "Error", MessageBoxButtons.OK, MessageBoxIcon.Hand);
\r
1719 sourcePath = string.Empty;
\r
1721 UpdateSourceLabel();
\r
1723 // Enable the GUI components and enable any disabled components
\r
1726 catch (Exception exc)
\r
1728 MessageBox.Show("frmMain.cs - updateUIafterScan " + exc, "Error", MessageBoxButtons.OK,
\r
1729 MessageBoxIcon.Error);
\r
1734 private void EnableGUI()
\r
1738 if (InvokeRequired)
\r
1739 BeginInvoke(new UpdateWindowHandler(EnableGUI));
\r
1740 lbl_encode.Text = "Scan Completed";
\r
1741 foreach (Control ctrl in Controls)
\r
1742 ctrl.Enabled = true;
\r
1743 btn_start.Enabled = true;
\r
1744 btn_showQueue.Enabled = true;
\r
1745 btn_add2Queue.Enabled = true;
\r
1746 tb_preview.Enabled = true;
\r
1747 btn_source.Enabled = true;
\r
1748 mnu_killCLI.Visible = false;
\r
1750 catch (Exception exc)
\r
1752 MessageBox.Show("frmMain.cs - EnableGUI() " + exc, "Error", MessageBoxButtons.OK, MessageBoxIcon.Error);
\r
1756 private void DisableGUI()
\r
1758 foreach (Control ctrl in Controls)
\r
1759 if (!(ctrl is StatusStrip || ctrl is MenuStrip || ctrl is ToolStrip))
\r
1760 ctrl.Enabled = false;
\r
1762 lbl_encode.Visible = true;
\r
1763 lbl_encode.Text = "Scanning ...";
\r
1764 btn_source.Enabled = false;
\r
1765 btn_start.Enabled = false;
\r
1766 btn_showQueue.Enabled = false;
\r
1767 btn_add2Queue.Enabled = false;
\r
1768 tb_preview.Enabled = false;
\r
1769 mnu_killCLI.Visible = true;
\r
1772 private void KillScan()
\r
1774 SourceScan.ScanCompleted -= new EventHandler(SourceScan_ScanCompleted);
\r
1778 SourceScan.Stop();
\r
1780 lbl_encode.Text = "Scan Cancelled!";
\r
1783 private void ResetGUI()
\r
1785 drp_dvdtitle.Items.Clear();
\r
1786 drop_chapterStart.Items.Clear();
\r
1787 drop_chapterFinish.Items.Clear();
\r
1788 lbl_duration.Text = "Select a Title";
\r
1789 PictureSettings.lbl_src_res.Text = "Select a Title";
\r
1790 sourcePath = String.Empty;
\r
1791 text_destination.Text = String.Empty;
\r
1792 selectedTitle = null;
\r
1793 isScanning = false;
\r
1796 private void UpdateSourceLabel()
\r
1798 labelSource.Text = string.IsNullOrEmpty(sourcePath) ? "Select \"Source\" to continue." : this.SourceName;
\r
1800 if (selectedTitle != null)
\r
1801 if (!string.IsNullOrEmpty(selectedTitle.SourceName))
\r
1802 // If it's one of multiple source files, make sure we don't use the folder name
\r
1803 labelSource.Text = Path.GetFileName(selectedTitle.SourceName);
\r
1806 public void RecievingJob(Job job)
\r
1808 string query = job.Query;
\r
1809 StartScan(job.Source, job.Title);
\r
1811 if (query != null)
\r
1813 // Ok, Reset all the H264 widgets before changing the preset
\r
1814 x264Panel.Reset2Defaults();
\r
1816 // Send the query from the file to the Query Parser class
\r
1817 QueryParser presetQuery = QueryParser.Parse(query);
\r
1819 // Now load the preset
\r
1820 PresetLoader.LoadPreset(this, presetQuery, "Load Back From Queue", true);
\r
1822 // The x264 widgets will need updated, so do this now:
\r
1823 x264Panel.X264_StandardizeOptString();
\r
1824 x264Panel.X264_SetCurrentSettingsInPanel();
\r
1826 // Finally, let this window have a copy of the preset settings.
\r
1827 CurrentlySelectedPreset = null;
\r
1828 PictureSettings.SetPresetCropWarningLabel(null);
\r
1834 #region GUI Functions and Actions
\r
1837 /// Set the GUI to it's finished encoding state.
\r
1839 private void SetEncodeFinished()
\r
1843 if (InvokeRequired)
\r
1845 BeginInvoke(new UpdateWindowHandler(SetEncodeFinished));
\r
1849 lbl_encode.Text = "Encoding Finished";
\r
1850 btn_start.Text = "Start";
\r
1851 btn_start.ToolTipText = "Start the encoding process";
\r
1852 btn_start.Image = Properties.Resources.Play;
\r
1854 // If the window is minimized, display the notification in a popup.
\r
1855 if (Properties.Settings.Default.trayIconAlerts)
\r
1856 if (FormWindowState.Minimized == this.WindowState)
\r
1858 notifyIcon.BalloonTipText = lbl_encode.Text;
\r
1859 notifyIcon.ShowBalloonTip(500);
\r
1862 catch (Exception exc)
\r
1864 MessageBox.Show(exc.ToString());
\r
1869 /// Set the GUI to it's started encoding state.
\r
1871 private void SetEncodeStarted()
\r
1875 if (InvokeRequired)
\r
1877 BeginInvoke(new UpdateWindowHandler(SetEncodeStarted));
\r
1881 lbl_encode.Visible = true;
\r
1882 lbl_encode.Text = "Encoding with " + encodeQueue.Count + " encode(s) pending";
\r
1883 btn_start.Text = "Stop";
\r
1884 btn_start.ToolTipText = "Stop the encoding process.";
\r
1885 btn_start.Image = Properties.Resources.stop;
\r
1887 catch (Exception exc)
\r
1889 MessageBox.Show(exc.ToString());
\r
1894 /// Set the DVD Drive selection in the "Source" Menu
\r
1896 private void SetDriveSelectionMenuItem()
\r
1900 if (InvokeRequired)
\r
1902 BeginInvoke(new UpdateWindowHandler(SetDriveSelectionMenuItem));
\r
1906 drives = Main.GetDrives();
\r
1908 List<ToolStripMenuItem> menuItems = new List<ToolStripMenuItem>();
\r
1909 foreach (DriveInformation drive in drives)
\r
1911 ToolStripMenuItem menuItem = new ToolStripMenuItem();
\r
1912 menuItem.Name = drive.ToString();
\r
1913 menuItem.Text = drive.RootDirectory + " (" + drive.VolumeLabel + ")";
\r
1914 menuItem.Image = Resources.disc_small;
\r
1915 menuItem.Click += new EventHandler(mnu_dvd_drive_Click);
\r
1916 menuItems.Add(menuItem);
\r
1919 foreach (ToolStripMenuItem item in menuItems)
\r
1920 btn_source.DropDownItems.Add(item);
\r
1922 catch (Exception exc)
\r
1924 MessageBox.Show("Error in SetDriveSelectionMenuItem" + exc);
\r
1929 /// Access the preset Handler and setup the preset panel.
\r
1931 private void LoadPresetPanel()
\r
1933 if (presetHandler.CheckIfPresetsAreOutOfDate())
\r
1934 if (!Properties.Settings.Default.presetNotification)
\r
1935 MessageBox.Show(splash,
\r
1936 "HandBrake has determined your built-in presets are out of date... These presets will now be updated.",
\r
1937 "Preset Update", MessageBoxButtons.OK, MessageBoxIcon.Information);
\r
1939 presetHandler.GetPresetPanel(ref treeView_presets);
\r
1940 treeView_presets.Update();
\r
1944 /// Get the title from the selected item in the title dropdown.
\r
1949 private int getTitle()
\r
1952 if (drp_dvdtitle.SelectedItem != null)
\r
1954 string[] titleInfo = drp_dvdtitle.SelectedItem.ToString().Split(' ');
\r
1955 int.TryParse(titleInfo[0], out title);
\r
1966 /// Handle GUI shortcuts
\r
1968 /// <param name="msg">Message</param>
\r
1969 /// <param name="keyData">Keys</param>
\r
1970 /// <returns>Bool</returns>
\r
1971 protected override bool ProcessCmdKey(ref Message msg, Keys keyData)
\r
1973 if (keyData == (Keys.Control | Keys.S))
\r
1975 btn_start_Click(this, new EventArgs());
\r
1979 if (keyData == (Keys.Control | Keys.A))
\r
1981 btn_add2Queue_Click(this, new EventArgs());
\r
1984 return base.ProcessCmdKey(ref msg, keyData);
\r
1988 /// If the queue is being processed, prompt the user to confirm application close.
\r
1990 /// <param name="e">FormClosingEventArgs</param>
\r
1991 protected override void OnFormClosing(FormClosingEventArgs e)
\r
1993 // If currently encoding, the queue isn't paused, and there are queue items to process, prompt to confirm close.
\r
1994 if (encodeQueue.IsEncoding)
\r
1996 DialogResult result =
\r
1998 "HandBrake has queue items to process. Closing HandBrake will stop the current encoding.\n\nDo you want to close HandBrake?",
\r
1999 "Close HandBrake?", MessageBoxButtons.YesNo, MessageBoxIcon.Question);
\r
2001 if (result == DialogResult.No)
\r
2004 // Try to safely close out if we can, or kill the cli if using in-gui status
\r
2005 if (Settings.Default.enocdeStatusInGui)
\r
2006 encodeQueue.Stop();
\r
2008 encodeQueue.SafelyClose();
\r
2011 if (SourceScan.IsScanning)
\r
2013 SourceScan.ScanCompleted -= new EventHandler(SourceScan_ScanCompleted);
\r
2014 SourceScan.Stop();
\r
2016 base.OnFormClosing(e);
\r
2021 #region In-GUI Encode Status (Experimental)
\r
2024 /// Starts a new thread to monitor and process the CLI encode status
\r
2026 private void EncodeMonitorThread()
\r
2030 Parser encode = new Parser(encodeQueue.HbProcess.StandardOutput.BaseStream);
\r
2031 encode.OnEncodeProgress += EncodeOnEncodeProgress;
\r
2032 while (!encode.EndOfStream)
\r
2033 encode.ReadEncodeStatus();
\r
2035 catch (Exception exc)
\r
2037 MessageBox.Show(exc.ToString(), "Error", MessageBoxButtons.OK, MessageBoxIcon.Error);
\r
2042 /// Displays the Encode status in the GUI
\r
2044 /// <param name="Sender"></param>
\r
2045 /// <param name="CurrentTask"></param>
\r
2046 /// <param name="TaskCount"></param>
\r
2047 /// <param name="PercentComplete"></param>
\r
2048 /// <param name="CurrentFps"></param>
\r
2049 /// <param name="AverageFps"></param>
\r
2050 /// <param name="TimeRemaining"></param>
\r
2051 private void EncodeOnEncodeProgress(object Sender, int CurrentTask, int TaskCount, float PercentComplete, float CurrentFps, float AverageFps, TimeSpan TimeRemaining)
\r
2053 if (this.InvokeRequired)
\r
2056 new EncodeProgressEventHandler(EncodeOnEncodeProgress),
\r
2057 new[] { Sender, CurrentTask, TaskCount, PercentComplete, CurrentFps, AverageFps, TimeRemaining });
\r
2061 string.Format("Encode Progress: {0}%, FPS: {1}, Avg FPS: {2}, Time Remaining: {3} ", PercentComplete, CurrentFps, AverageFps, TimeRemaining);
\r
2066 // This is the END of the road ****************************************
\r