3 This file is part of the HandBrake source code.
\r
4 Homepage: <http://handbrake.fr/>.
\r
5 It may be used under the terms of the GNU General Public License. */
\r
8 using System.Collections.Generic;
\r
9 using System.Drawing;
\r
10 using System.Globalization;
\r
11 using System.Windows.Forms;
\r
13 using System.Diagnostics;
\r
14 using System.Threading;
\r
15 using Handbrake.EncodeQueue;
\r
16 using Handbrake.Functions;
\r
17 using Handbrake.Presets;
\r
18 using Handbrake.Parsing;
\r
22 public partial class frmMain : Form
\r
24 // Objects which may be used by one or more other objects *************
\r
25 EncodeAndQueueHandler encodeQueue = new EncodeAndQueueHandler();
\r
26 PresetsHandler presetHandler = new PresetsHandler();
\r
27 QueryGenerator queryGen = new QueryGenerator();
\r
29 // Globals: Mainly used for tracking. *********************************
\r
30 public Title selectedTitle;
\r
31 private frmQueue queueWindow;
\r
32 private frmPreview qtpreview;
\r
33 private frmActivityWindow ActivityWindow;
\r
34 private Form splash;
\r
35 public string sourcePath;
\r
36 private string lastAction;
\r
37 private SourceType selectedSourceType;
\r
38 private string dvdDrivePath;
\r
39 private string dvdDriveLabel;
\r
41 // Delegates **********************************************************
\r
42 private delegate void UpdateWindowHandler();
\r
44 // Applicaiton Startup ************************************************
\r
46 #region Application Startup
\r
49 // Load and setup the splash screen in this thread
\r
50 splash = new frmSplashScreen();
\r
52 Label lblStatus = new Label { Size = new Size(150, 20), Location = new Point(182, 102) };
\r
53 splash.Controls.Add(lblStatus);
\r
55 InitializeComponent();
\r
57 // Update the users config file with the CLI version data.
\r
58 lblStatus.Text = "Setting Version Data ...";
\r
59 Application.DoEvents();
\r
60 Main.setCliVersionData();
\r
62 // Show the form, but leave disabled until preloading is complete then show the main form
\r
63 this.Enabled = false;
\r
65 Application.DoEvents(); // Forces frmMain to draw
\r
67 // Check for new versions, if update checking is enabled
\r
68 if (Properties.Settings.Default.updateStatus)
\r
70 DateTime now = DateTime.Now;
\r
71 DateTime lastCheck = Properties.Settings.Default.lastUpdateCheckDate;
\r
72 TimeSpan elapsed = now.Subtract(lastCheck);
\r
73 if (elapsed.TotalDays > Properties.Settings.Default.daysBetweenUpdateCheck)
\r
75 lblStatus.Text = "Checking for updates ...";
\r
76 Application.DoEvents();
\r
78 Main.BeginCheckForUpdates(new AsyncCallback(UpdateCheckDone), false);
\r
82 // Setup the GUI components
\r
83 lblStatus.Text = "Setting up the GUI ...";
\r
84 Application.DoEvents();
\r
85 loadPresetPanel(); // Load the Preset Panel
\r
86 treeView_presets.ExpandAll();
\r
87 lbl_encode.Text = "";
\r
88 queueWindow = new frmQueue(encodeQueue); // Prepare the Queue
\r
89 if (!Properties.Settings.Default.QueryEditorTab)
\r
90 tabs_panel.TabPages.RemoveAt(7); // Remove the query editor tab if the user does not want it enabled.
\r
92 // Load the user's default settings or Normal Preset
\r
93 if (Properties.Settings.Default.defaultPreset != "")
\r
95 if (presetHandler.GetPreset(Properties.Settings.Default.defaultPreset) != null)
\r
97 string query = presetHandler.GetPreset(Properties.Settings.Default.defaultPreset).Query;
\r
98 Boolean loadPictureSettings = presetHandler.GetPreset(Properties.Settings.Default.defaultPreset).PictureSettings;
\r
102 //Ok, Reset all the H264 widgets before changing the preset
\r
103 x264Panel.reset2Defaults();
\r
105 // Send the query from the file to the Query Parser class, then load the preset
\r
106 QueryParser presetQuery = QueryParser.Parse(query);
\r
107 PresetLoader.presetLoader(this, presetQuery, Properties.Settings.Default.defaultPreset, loadPictureSettings);
\r
109 // The x264 widgets will need updated, so do this now:
\r
110 x264Panel.X264_StandardizeOptString();
\r
111 x264Panel.X264_SetCurrentSettingsInPanel();
\r
115 loadNormalPreset();
\r
118 loadNormalPreset();
\r
120 // Enabled GUI tooltip's if Required
\r
121 if (Properties.Settings.Default.tooltipEnable)
\r
122 ToolTip.Active = true;
\r
124 // Register with Growl (if not using Growl for the encoding completion action, this wont hurt anything)
\r
125 GrowlCommunicator.Register();
\r
128 lblStatus.Text = "Loading Complete!";
\r
129 Application.DoEvents();
\r
132 this.Enabled = true;
\r
134 // Event Handlers and Queue Recovery
\r
139 private void UpdateCheckDone(IAsyncResult result)
\r
141 if (InvokeRequired)
\r
143 Invoke(new MethodInvoker(() => UpdateCheckDone(result)));
\r
147 UpdateCheckInformation info;
\r
151 info = Main.EndCheckForUpdates(result);
\r
153 if (info.NewVersionAvailable)
\r
155 frmUpdater updateWindow = new frmUpdater(info.BuildInformation);
\r
156 updateWindow.ShowDialog();
\r
159 catch (Exception ex)
\r
161 if ((bool)result.AsyncState)
\r
162 MessageBox.Show("Unable to check for updates, Please try again later.\n\nDetailed Error Information:\n" + ex, "Error", MessageBoxButtons.OK, MessageBoxIcon.Error);
\r
166 // Startup Functions
\r
167 private void queueRecovery()
\r
169 if (Main.checkQueueRecovery())
\r
171 DialogResult result = MessageBox.Show("HandBrake has detected unfinished items on the queue from the last time the application was launched. Would you like to recover these?", "Queue Recovery Possible", MessageBoxButtons.YesNo, MessageBoxIcon.Question);
\r
173 if (result == DialogResult.Yes)
\r
174 encodeQueue.LoadQueueFromFile("hb_queue_recovery.xml"); // Start Recovery
\r
177 // Remove the Queue recovery file if the user doesn't want to recovery the last queue.
\r
178 string queuePath = Path.Combine(Path.GetTempPath(), "hb_queue_recovery.xml");
\r
179 if (File.Exists(queuePath))
\r
180 File.Delete(queuePath);
\r
187 public string SourceName
\r
191 if (this.selectedSourceType == SourceType.DvdDrive)
\r
193 return this.dvdDriveLabel;
\r
196 return Path.GetFileNameWithoutExtension(this.sourcePath);
\r
202 // Encoding Events for setting up the GUI
\r
203 private void events()
\r
205 // Handle Widget changes when preset is selected.
\r
206 RegisterPresetEventHandler();
\r
208 // Handle Window Resize
\r
209 if (Properties.Settings.Default.MainWindowMinimize)
\r
210 this.Resize += new EventHandler(frmMain_Resize);
\r
212 // Handle Encode Start / Finish / Pause
\r
213 encodeQueue.CurrentJobCompleted += new EventHandler(encodeEnded);
\r
214 encodeQueue.QueuePauseRequested += new EventHandler(encodePaused);
\r
215 encodeQueue.NewJobStarted += new EventHandler(encodeStarted);
\r
217 // Handle a file being draged onto the GUI.
\r
218 this.DragEnter += new DragEventHandler(frmMain_DragEnter);
\r
219 this.DragDrop += new DragEventHandler(frmMain_DragDrop);
\r
222 // 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
223 private void RegisterPresetEventHandler()
\r
226 drop_format.SelectedIndexChanged += new EventHandler(changePresetLabel);
\r
227 check_largeFile.CheckedChanged += new EventHandler(changePresetLabel);
\r
228 check_iPodAtom.CheckedChanged += new EventHandler(changePresetLabel);
\r
229 check_optimiseMP4.CheckedChanged += new EventHandler(changePresetLabel);
\r
231 // Picture Settings
\r
232 //PictureSettings.PictureSettingsChanged += new EventHandler(changePresetLabel);
\r
235 Filters.FilterSettingsChanged += new EventHandler(changePresetLabel);
\r
238 drp_videoEncoder.SelectedIndexChanged += new EventHandler(changePresetLabel);
\r
239 check_2PassEncode.CheckedChanged += new EventHandler(changePresetLabel);
\r
240 check_turbo.CheckedChanged += new EventHandler(changePresetLabel);
\r
241 text_filesize.TextChanged += new EventHandler(changePresetLabel);
\r
242 text_bitrate.TextChanged += new EventHandler(changePresetLabel);
\r
243 slider_videoQuality.ValueChanged += new EventHandler(changePresetLabel);
\r
246 AudioSettings.AudioListChanged += new EventHandler(changePresetLabel);
\r
249 x264Panel.rtf_x264Query.TextChanged += new EventHandler(changePresetLabel);
\r
251 private void UnRegisterPresetEventHandler()
\r
253 // Output Settings
\r
254 drop_format.SelectedIndexChanged -= new EventHandler(changePresetLabel);
\r
255 check_largeFile.CheckedChanged -= new EventHandler(changePresetLabel);
\r
256 check_iPodAtom.CheckedChanged -= new EventHandler(changePresetLabel);
\r
257 check_optimiseMP4.CheckedChanged -= new EventHandler(changePresetLabel);
\r
259 // Picture Settings
\r
260 //PictureSettings.PictureSettingsChanged -= new EventHandler(changePresetLabel);
\r
263 Filters.FilterSettingsChanged -= new EventHandler(changePresetLabel);
\r
266 drp_videoEncoder.SelectedIndexChanged -= new EventHandler(changePresetLabel);
\r
267 check_2PassEncode.CheckedChanged -= new EventHandler(changePresetLabel);
\r
268 check_turbo.CheckedChanged -= new EventHandler(changePresetLabel);
\r
269 text_filesize.TextChanged -= new EventHandler(changePresetLabel);
\r
270 text_bitrate.TextChanged -= new EventHandler(changePresetLabel);
\r
271 slider_videoQuality.ValueChanged -= new EventHandler(changePresetLabel);
\r
274 AudioSettings.AudioListChanged -= new EventHandler(changePresetLabel);
\r
277 x264Panel.rtf_x264Query.TextChanged -= new EventHandler(changePresetLabel);
\r
279 private void changePresetLabel(object sender, EventArgs e)
\r
281 labelPreset.Text = "Output Settings (Preset: Custom)";
\r
284 private static void frmMain_DragEnter(object sender, DragEventArgs e)
\r
286 if (e.Data.GetDataPresent(DataFormats.FileDrop, false))
\r
287 e.Effect = DragDropEffects.All;
\r
289 private void frmMain_DragDrop(object sender, DragEventArgs e)
\r
291 string[] fileList = e.Data.GetData(DataFormats.FileDrop) as string[];
\r
292 sourcePath = string.Empty;
\r
294 if (fileList != null)
\r
296 if (fileList[0].StartsWith("\\"))
\r
299 "Sorry, HandBrake does not support UNC file paths. \nTry mounting the network share as a network drive in My Computer",
\r
300 "Warning", MessageBoxButtons.OK, MessageBoxIcon.Warning);
\r
301 UpdateSourceLabel();
\r
305 if (fileList[0] != "")
\r
306 StartScan(fileList[0]);
\r
308 UpdateSourceLabel();
\r
312 UpdateSourceLabel();
\r
314 private void encodeStarted(object sender, EventArgs e)
\r
316 lastAction = "encode";
\r
317 setEncodeStarted();
\r
319 // Experimental HBProc Process Monitoring.
\r
320 if (Properties.Settings.Default.enocdeStatusInGui)
\r
322 Thread encodeMon = new Thread(encodeMonitorThread);
\r
326 private void encodeEnded(object sender, EventArgs e)
\r
328 setEncodeFinished();
\r
330 private void encodePaused(object sender, EventArgs e)
\r
332 setEncodeFinished();
\r
336 // User Interface Menus / Tool Strips *********************************
\r
339 private void mnu_killCLI_Click(object sender, EventArgs e)
\r
343 private void mnu_exit_Click(object sender, EventArgs e)
\r
345 Application.Exit();
\r
350 private void mnu_encode_Click(object sender, EventArgs e)
\r
352 queueWindow.Show();
\r
354 private void mnu_encodeLog_Click(object sender, EventArgs e)
\r
356 String file = lastAction == "scan" ? "last_scan_log.txt" : "last_encode_log.txt";
\r
358 frmActivityWindow dvdInfoWindow = new frmActivityWindow();
\r
359 dvdInfoWindow.Show();
\r
361 private void mnu_options_Click(object sender, EventArgs e)
\r
363 Form options = new frmOptions(this);
\r
364 options.ShowDialog();
\r
368 #region Presets Menu
\r
369 private void mnu_presetReset_Click(object sender, EventArgs e)
\r
371 presetHandler.UpdateBuiltInPresets();
\r
373 if (treeView_presets.Nodes.Count == 0)
\r
374 MessageBox.Show("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!", "Error", MessageBoxButtons.OK, MessageBoxIcon.Error);
\r
376 MessageBox.Show("Presets have been updated!", "Alert", MessageBoxButtons.OK, MessageBoxIcon.Information);
\r
378 treeView_presets.ExpandAll();
\r
380 private void mnu_delete_preset_Click(object sender, EventArgs e)
\r
382 presetHandler.RemoveBuiltInPresets();
\r
383 loadPresetPanel(); // Reload the preset panel
\r
385 private void mnu_SelectDefault_Click(object sender, EventArgs e)
\r
387 loadNormalPreset();
\r
389 private void mnu_importMacPreset_Click(object sender, EventArgs e)
\r
393 private void btn_new_preset_Click(object sender, EventArgs e)
\r
395 Form preset = new frmAddPreset(this, queryGen.GenerateCLIQuery(this, 0, null), presetHandler);
\r
396 preset.ShowDialog();
\r
401 private void mnu_handbrake_forums_Click(object sender, EventArgs e)
\r
403 Process.Start("http://forum.handbrake.fr/");
\r
405 private void mnu_user_guide_Click(object sender, EventArgs e)
\r
407 Process.Start("http://trac.handbrake.fr/wiki/HandBrakeGuide");
\r
409 private void mnu_handbrake_home_Click(object sender, EventArgs e)
\r
411 Process.Start("http://handbrake.fr");
\r
413 private void mnu_UpdateCheck_Click(object sender, EventArgs e)
\r
415 lbl_updateCheck.Visible = true;
\r
416 Main.BeginCheckForUpdates(new AsyncCallback(updateCheckDoneMenu), false);
\r
418 private void updateCheckDoneMenu(IAsyncResult result)
\r
420 // Make sure it's running on the calling thread
\r
421 if (InvokeRequired)
\r
423 Invoke(new MethodInvoker(() => updateCheckDoneMenu(result)));
\r
426 UpdateCheckInformation info;
\r
429 // Get the information about the new build, if any, and close the window
\r
430 info = Main.EndCheckForUpdates(result);
\r
432 if (info.NewVersionAvailable && info.BuildInformation != null)
\r
434 frmUpdater updateWindow = new frmUpdater(info.BuildInformation);
\r
435 updateWindow.ShowDialog();
\r
438 MessageBox.Show("There are no new updates at this time.", "Update Check", MessageBoxButtons.OK, MessageBoxIcon.Information);
\r
439 lbl_updateCheck.Visible = false;
\r
442 catch (Exception ex)
\r
444 if ((bool)result.AsyncState)
\r
445 MessageBox.Show("Unable to check for updates, Please try again later.\n\nDetailed Error Information:\n" + ex, "Error", MessageBoxButtons.OK, MessageBoxIcon.Error);
\r
448 private void mnu_about_Click(object sender, EventArgs e)
\r
450 using (frmAbout About = new frmAbout())
\r
452 About.ShowDialog();
\r
458 // Right Click Menu Code
\r
459 private void pmnu_expandAll_Click(object sender, EventArgs e)
\r
461 treeView_presets.ExpandAll();
\r
463 private void pmnu_collapse_Click(object sender, EventArgs e)
\r
465 treeView_presets.CollapseAll();
\r
467 private void pmnu_import_Click(object sender, EventArgs e)
\r
471 private void pmnu_saveChanges_Click(object sender, EventArgs e)
\r
473 DialogResult result = MessageBox.Show("Do you wish to include picture settings when updating the preset: " + treeView_presets.SelectedNode.Text, "Update Preset", MessageBoxButtons.YesNoCancel, MessageBoxIcon.Question);
\r
474 if (result == DialogResult.Yes)
\r
475 presetHandler.Update(treeView_presets.SelectedNode.Text, QueryGenerator.GenerateTabbedComponentsQuery(this), true);
\r
476 else if (result == DialogResult.No)
\r
477 presetHandler.Update(treeView_presets.SelectedNode.Text, QueryGenerator.GenerateTabbedComponentsQuery(this), false);
\r
479 private void pmnu_delete_click(object sender, EventArgs e)
\r
481 if (treeView_presets.SelectedNode != null)
\r
483 presetHandler.Remove(treeView_presets.SelectedNode.Text);
\r
484 treeView_presets.Nodes.Remove(treeView_presets.SelectedNode);
\r
486 treeView_presets.Select();
\r
488 private void presets_menu_Opening(object sender, System.ComponentModel.CancelEventArgs e)
\r
490 // Make sure that the save menu is always disabled by default
\r
491 pmnu_saveChanges.Enabled = false;
\r
493 // Now enable the save menu if the selected preset is a user preset
\r
494 if (treeView_presets.SelectedNode != null)
\r
495 if (presetHandler.CheckIfUserPresetExists(treeView_presets.SelectedNode.Text))
\r
496 pmnu_saveChanges.Enabled = true;
\r
498 treeView_presets.Select();
\r
501 // Presets Management
\r
502 private void btn_addPreset_Click(object sender, EventArgs e)
\r
504 Form preset = new frmAddPreset(this, QueryGenerator.GenerateTabbedComponentsQuery(this), presetHandler);
\r
505 preset.ShowDialog();
\r
507 private void btn_removePreset_Click(object sender, EventArgs e)
\r
509 DialogResult result = MessageBox.Show("Are you sure you wish to delete the selected preset?", "Preset", MessageBoxButtons.YesNo, MessageBoxIcon.Question);
\r
510 if (result == DialogResult.Yes)
\r
512 if (treeView_presets.SelectedNode != null)
\r
514 presetHandler.Remove(treeView_presets.SelectedNode.Text);
\r
515 treeView_presets.Nodes.Remove(treeView_presets.SelectedNode);
\r
518 treeView_presets.Select();
\r
520 private void btn_setDefault_Click(object sender, EventArgs e)
\r
522 if (treeView_presets.SelectedNode != null)
\r
524 DialogResult result = MessageBox.Show("Are you sure you wish to set this preset as the default?", "Preset", MessageBoxButtons.YesNo, MessageBoxIcon.Question);
\r
525 if (result == DialogResult.Yes)
\r
527 Properties.Settings.Default.defaultPreset = treeView_presets.SelectedNode.Text;
\r
528 Properties.Settings.Default.Save();
\r
529 MessageBox.Show("New default preset set.", "Alert", MessageBoxButtons.OK, MessageBoxIcon.Information);
\r
533 MessageBox.Show("Please select a preset first.", "Warning", MessageBoxButtons.OK, MessageBoxIcon.Warning);
\r
535 private void treeview_presets_mouseUp(object sender, MouseEventArgs e)
\r
537 if (e.Button == MouseButtons.Right)
\r
538 treeView_presets.SelectedNode = treeView_presets.GetNodeAt(e.Location);
\r
539 else if (e.Button == MouseButtons.Left)
\r
541 if (treeView_presets.GetNodeAt(e.Location) != null)
\r
543 if (labelPreset.Text.Contains(treeView_presets.GetNodeAt(e.Location).Text))
\r
548 treeView_presets.Select();
\r
550 private void treeView_presets_AfterSelect(object sender, TreeViewEventArgs e)
\r
554 private void treeView_presets_deleteKey(object sender, KeyEventArgs e)
\r
556 if (e.KeyCode == Keys.Delete)
\r
558 DialogResult result = MessageBox.Show("Are you sure you wish to delete the selected preset?", "Preset", MessageBoxButtons.YesNo, MessageBoxIcon.Question);
\r
559 if (result == DialogResult.Yes)
\r
561 if (treeView_presets.SelectedNode != null)
\r
562 presetHandler.Remove(treeView_presets.SelectedNode.Text);
\r
564 // Remember each nodes expanded status so we can reload it
\r
565 List<Boolean> nodeStatus = new List<Boolean>();
\r
566 foreach (TreeNode node in treeView_presets.Nodes)
\r
567 nodeStatus.Add(node.IsExpanded);
\r
569 // Now reload the preset panel
\r
572 // And finally, re-expand any of the nodes if required
\r
574 foreach (TreeNode node in treeView_presets.Nodes)
\r
584 private void selectPreset()
\r
586 if (treeView_presets.SelectedNode != null)
\r
588 // Ok, so, we've selected a preset. Now we want to load it.
\r
589 string presetName = treeView_presets.SelectedNode.Text;
\r
590 if (presetHandler.GetPreset(presetName) != null)
\r
592 string query = presetHandler.GetPreset(presetName).Query;
\r
593 Boolean loadPictureSettings = presetHandler.GetPreset(presetName).PictureSettings;
\r
597 //Ok, Reset all the H264 widgets before changing the preset
\r
598 x264Panel.reset2Defaults();
\r
600 // Send the query from the file to the Query Parser class
\r
601 QueryParser presetQuery = QueryParser.Parse(query);
\r
603 // Now load the preset
\r
604 PresetLoader.presetLoader(this, presetQuery, presetName, loadPictureSettings);
\r
606 // The x264 widgets will need updated, so do this now:
\r
607 x264Panel.X264_StandardizeOptString();
\r
608 x264Panel.X264_SetCurrentSettingsInPanel();
\r
613 private void loadNormalPreset()
\r
615 foreach (TreeNode treenode in treeView_presets.Nodes)
\r
617 foreach (TreeNode node in treenode.Nodes)
\r
619 if (node.Text.Equals("Normal"))
\r
620 treeView_presets.SelectedNode = treeView_presets.Nodes[treenode.Index].Nodes[0];
\r
624 private void importPreset()
\r
626 Import imp = new Import();
\r
627 if (openPreset.ShowDialog() == DialogResult.OK)
\r
629 QueryParser parsed = imp.importMacPreset(openPreset.FileName);
\r
630 if (presetHandler.CheckIfUserPresetExists(parsed.PresetName + " (Imported)"))
\r
632 DialogResult result = MessageBox.Show("This preset appears to already exist. Would you like to overwrite it?", "Overwrite preset?",
\r
633 MessageBoxButtons.YesNo, MessageBoxIcon.Warning);
\r
634 if (result == DialogResult.Yes)
\r
636 PresetLoader.presetLoader(this, parsed, parsed.PresetName, parsed.UsesPictureSettings);
\r
637 presetHandler.Update(parsed.PresetName + " (Imported)", queryGen.GenerateCLIQuery(this, 0, null),
\r
638 parsed.UsesPictureSettings);
\r
643 PresetLoader.presetLoader(this, parsed, parsed.PresetName, parsed.UsesPictureSettings);
\r
644 presetHandler.Add(parsed.PresetName, queryGen.GenerateCLIQuery(this, 0, null), parsed.UsesPictureSettings);
\r
646 if (presetHandler.Add(parsed.PresetName + " (Imported)", queryGen.GenerateCLIQuery(this, 0, null), parsed.UsesPictureSettings))
\r
648 TreeNode preset_treeview = new TreeNode(parsed.PresetName + " (Imported)") { ForeColor = Color.Black };
\r
649 treeView_presets.Nodes.Add(preset_treeview);
\r
657 private void btn_source_Click(object sender, EventArgs e)
\r
659 mnu_dvd_drive.Visible = true;
\r
660 Thread driveInfoThread = new Thread(getDriveInfoThread);
\r
661 driveInfoThread.Start();
\r
663 private void btn_start_Click(object sender, EventArgs e)
\r
665 if (btn_start.Text == "Stop")
\r
667 DialogResult result = MessageBox.Show("Are you sure you wish to cancel the encode?", "Cancel Encode?", MessageBoxButtons.YesNo, MessageBoxIcon.Question);
\r
669 if (result == DialogResult.Yes)
\r
672 encodeQueue.RequestPause();
\r
674 // Allow the CLI to exit cleanly
\r
675 Win32.SetForegroundWindow((int)encodeQueue.processHandle);
\r
676 SendKeys.Send("^C");
\r
679 setEncodeFinished();
\r
684 if (encodeQueue.Count != 0 || (!string.IsNullOrEmpty(sourcePath) && !string.IsNullOrEmpty(text_destination.Text)))
\r
686 string generatedQuery = queryGen.GenerateCLIQuery(this, 0, null);
\r
687 string specifiedQuery = rtf_query.Text != "" ? rtf_query.Text : queryGen.GenerateCLIQuery(this, 0, null);
\r
688 string query = string.Empty;
\r
690 // Check to make sure the generated query matches the GUI settings
\r
691 if (Properties.Settings.Default.PromptOnUnmatchingQueries && !string.IsNullOrEmpty(specifiedQuery) && generatedQuery != specifiedQuery)
\r
693 DialogResult result = MessageBox.Show("The query under the \"Query Editor\" tab " +
\r
694 "does not match the current GUI settings.\n\nBecause the manual query takes " +
\r
695 "priority over the GUI, your recently updated settings will not be taken " +
\r
696 "into account when encoding this job." + Environment.NewLine + Environment.NewLine +
\r
697 "Do you want to replace the manual query with the updated GUI-generated query?",
\r
698 "Manual Query does not Match GUI",
\r
699 MessageBoxButtons.YesNoCancel, MessageBoxIcon.Asterisk,
\r
700 MessageBoxDefaultButton.Button3);
\r
704 case DialogResult.Yes:
\r
705 // Replace the manual query with the generated one
\r
706 query = generatedQuery;
\r
707 rtf_query.Text = generatedQuery;
\r
709 case DialogResult.No:
\r
710 // Use the manual query
\r
711 query = specifiedQuery;
\r
713 case DialogResult.Cancel:
\r
714 // Don't start the encode
\r
720 query = specifiedQuery;
\r
723 DialogResult overwrite = DialogResult.Yes;
\r
724 if (text_destination.Text != "")
\r
725 if (File.Exists(text_destination.Text))
\r
726 overwrite = MessageBox.Show("The destination file already exists. Are you sure you want to overwrite it?", "Overwrite File?", MessageBoxButtons.YesNo, MessageBoxIcon.Question);
\r
728 if (overwrite == DialogResult.Yes)
\r
730 if (encodeQueue.Count == 0)
\r
731 encodeQueue.AddJob(query, sourcePath, text_destination.Text, (rtf_query.Text != ""));
\r
733 queueWindow.setQueue();
\r
734 if (encodeQueue.Count > 1)
\r
735 queueWindow.Show(false);
\r
737 setEncodeStarted(); // Encode is running, so setup the GUI appropriately
\r
738 encodeQueue.StartEncodeQueue(); // Start The Queue Encoding Process
\r
739 lastAction = "encode"; // Set the last action to encode - Used for activity window.
\r
741 if (ActivityWindow != null)
\r
742 ActivityWindow.SetEncodeMode();
\r
746 else if (string.IsNullOrEmpty(sourcePath) || string.IsNullOrEmpty(text_destination.Text))
\r
747 MessageBox.Show("No source or destination selected.", "Warning", MessageBoxButtons.OK, MessageBoxIcon.Warning);
\r
750 private void btn_add2Queue_Click(object sender, EventArgs e)
\r
752 if (string.IsNullOrEmpty(sourcePath) || string.IsNullOrEmpty(text_destination.Text))
\r
753 MessageBox.Show("No source or destination selected.", "Warning", MessageBoxButtons.OK, MessageBoxIcon.Warning);
\r
756 String query = queryGen.GenerateCLIQuery(this, 0, null);
\r
757 if (rtf_query.Text != "")
\r
758 query = rtf_query.Text;
\r
760 if (encodeQueue.CheckForDestinationDuplicate(text_destination.Text))
\r
762 DialogResult result = MessageBox.Show("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
763 "Warning", MessageBoxButtons.YesNo, MessageBoxIcon.Warning);
\r
764 if (result == DialogResult.Yes)
\r
765 encodeQueue.AddJob(query, sourcePath, text_destination.Text, (rtf_query.Text != ""));
\r
769 encodeQueue.AddJob(query, sourcePath, text_destination.Text, (rtf_query.Text != ""));
\r
771 lbl_encode.Text = encodeQueue.Count + " encode(s) pending in the queue";
\r
773 queueWindow.Show();
\r
776 private void btn_showQueue_Click(object sender, EventArgs e)
\r
778 queueWindow.Show();
\r
779 queueWindow.Activate();
\r
781 private void tb_preview_Click(object sender, EventArgs e)
\r
783 if (string.IsNullOrEmpty(sourcePath) || string.IsNullOrEmpty(text_destination.Text))
\r
784 MessageBox.Show("No source or destination selected.", "Warning", MessageBoxButtons.OK, MessageBoxIcon.Warning);
\r
787 if (qtpreview == null)
\r
789 qtpreview = new frmPreview(this);
\r
792 else if (qtpreview.IsDisposed)
\r
794 qtpreview = new frmPreview(this);
\r
798 MessageBox.Show(qtpreview, "The preview window is already open!", "Warning", MessageBoxButtons.OK, MessageBoxIcon.Warning);
\r
801 private void btn_ActivityWindow_Click(object sender, EventArgs e)
\r
803 if (ActivityWindow == null || !ActivityWindow.IsHandleCreated)
\r
804 ActivityWindow = new frmActivityWindow();
\r
806 if (encodeQueue.isEncoding)
\r
807 ActivityWindow.SetEncodeMode();
\r
809 ActivityWindow.SetScanMode();
\r
811 ActivityWindow.Show();
\r
812 ActivityWindow.Activate();
\r
816 #region System Tray Icon
\r
817 private void frmMain_Resize(object sender, EventArgs e)
\r
819 if (FormWindowState.Minimized == this.WindowState)
\r
821 notifyIcon.Visible = true;
\r
824 else if (FormWindowState.Normal == this.WindowState)
\r
825 notifyIcon.Visible = false;
\r
827 private void notifyIcon_MouseDoubleClick(object sender, MouseEventArgs e)
\r
829 this.Visible = true;
\r
831 this.WindowState = FormWindowState.Normal;
\r
832 notifyIcon.Visible = false;
\r
834 private void btn_restore_Click(object sender, EventArgs e)
\r
836 this.Visible = true;
\r
838 this.WindowState = FormWindowState.Normal;
\r
839 notifyIcon.Visible = false;
\r
843 #region Tab Control
\r
846 private void btn_dvd_source_Click(object sender, EventArgs e)
\r
848 if (DVD_Open.ShowDialog() == DialogResult.OK)
\r
850 this.selectedSourceType = SourceType.Folder;
\r
851 selectSource(DVD_Open.SelectedPath);
\r
854 UpdateSourceLabel();
\r
856 private void btn_file_source_Click(object sender, EventArgs e)
\r
858 if (ISO_Open.ShowDialog() == DialogResult.OK)
\r
860 this.selectedSourceType = SourceType.VideoFile;
\r
861 selectSource(ISO_Open.FileName);
\r
864 UpdateSourceLabel();
\r
866 private void mnu_dvd_drive_Click(object sender, EventArgs e)
\r
868 if (this.dvdDrivePath == null) return;
\r
869 this.selectedSourceType = SourceType.DvdDrive;
\r
870 selectSource(this.dvdDrivePath);
\r
872 private void selectSource(string file)
\r
874 Check_ChapterMarkers.Enabled = true;
\r
875 lastAction = "scan";
\r
876 sourcePath = string.Empty;
\r
878 if (file == string.Empty) // Must have a file or path
\r
880 UpdateSourceLabel();
\r
884 if (file.StartsWith("\\")) // NO UNC Paths
\r
887 "Sorry, HandBrake does not support UNC file paths. \nTry mounting the share as a network drive in My Computer",
\r
888 "Warning", MessageBoxButtons.OK, MessageBoxIcon.Warning);
\r
889 UpdateSourceLabel();
\r
893 sourcePath = Path.GetFileName(file);
\r
896 private void drp_dvdtitle_Click(object sender, EventArgs e)
\r
898 if ((drp_dvdtitle.Items.Count == 1) && (drp_dvdtitle.Items[0].ToString() == "Automatic"))
\r
899 MessageBox.Show("There are no titles to select. Please load a source file by clicking the 'Source' button above before trying to select a title.", "Alert", MessageBoxButtons.OK, MessageBoxIcon.Asterisk);
\r
901 private void drp_dvdtitle_SelectedIndexChanged(object sender, EventArgs e)
\r
903 UnRegisterPresetEventHandler();
\r
905 PictureSettings.lbl_Aspect.Text = "Select a Title"; // Reset some values on the form
\r
906 drop_chapterStart.Items.Clear();
\r
907 drop_chapterFinish.Items.Clear();
\r
909 // If the dropdown is set to automatic nothing else needs to be done.
\r
910 // Otheriwse if its not, title data has to be loased from parsing.
\r
911 if (drp_dvdtitle.Text != "Automatic")
\r
913 selectedTitle = drp_dvdtitle.SelectedItem as Title;
\r
914 lbl_duration.Text = selectedTitle.Duration.ToString();
\r
915 PictureSettings.Source = selectedTitle; // Setup Picture Settings Tab Control
\r
917 // Populate the Angles dropdown
\r
918 drop_angle.Items.Clear();
\r
919 if (!Properties.Settings.Default.noDvdNav)
\r
921 drop_angle.Visible = true;
\r
922 lbl_angle.Visible = true;
\r
923 drop_angle.Items.AddRange(selectedTitle.Angles.ToArray());
\r
924 if (drop_angle.Items.Count != 0)
\r
925 drop_angle.SelectedIndex = 0;
\r
929 drop_angle.Visible = false;
\r
930 lbl_angle.Visible = false;
\r
933 // Populate the Start chapter Dropdown
\r
934 drop_chapterStart.Items.Clear();
\r
935 drop_chapterStart.Items.AddRange(selectedTitle.Chapters.ToArray());
\r
936 if (drop_chapterStart.Items.Count > 0)
\r
937 drop_chapterStart.Text = drop_chapterStart.Items[0].ToString();
\r
939 // Populate the Final Chapter Dropdown
\r
940 drop_chapterFinish.Items.Clear();
\r
941 drop_chapterFinish.Items.AddRange(selectedTitle.Chapters.ToArray());
\r
942 if (drop_chapterFinish.Items.Count > 0)
\r
943 drop_chapterFinish.Text = drop_chapterFinish.Items[drop_chapterFinish.Items.Count - 1].ToString();
\r
945 // Populate the Audio Channels Dropdown
\r
946 AudioSettings.SetTrackList(selectedTitle);
\r
948 // Populate the Subtitles dropdown
\r
949 Subtitles.drp_subtitleTracks.Items.Clear();
\r
950 Subtitles.drp_subtitleTracks.Items.Add("Foreign Audio Search (Bitmap)");
\r
951 Subtitles.drp_subtitleTracks.Items.AddRange(selectedTitle.Subtitles.ToArray());
\r
952 Subtitles.drp_subtitleTracks.SelectedIndex = 0;
\r
954 Subtitles.SetSubtitleTrackAuto();
\r
956 // Update the source label if we have multiple streams
\r
957 if (selectedTitle != null)
\r
958 if (!string.IsNullOrEmpty(selectedTitle.SourceName))
\r
959 labelSource.Text = labelSource.Text = Path.GetFileName(selectedTitle.SourceName);
\r
961 // Run the autoName & chapterNaming functions
\r
962 if (Properties.Settings.Default.autoNaming)
\r
964 string autoPath = Main.autoName(this);
\r
965 if (autoPath != null)
\r
966 text_destination.Text = autoPath;
\r
968 MessageBox.Show("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')", "Warning", MessageBoxButtons.OK, MessageBoxIcon.Warning);
\r
971 data_chpt.Rows.Clear();
\r
972 if (selectedTitle.Chapters.Count != 1)
\r
974 DataGridView chapterGridView = Main.chapterNaming(data_chpt, drop_chapterFinish.Text);
\r
975 if (chapterGridView != null)
\r
976 data_chpt = chapterGridView;
\r
980 Check_ChapterMarkers.Checked = false;
\r
981 Check_ChapterMarkers.Enabled = false;
\r
984 // Hack to force the redraw of the scrollbars which don't resize properly when the control is disabled.
\r
985 data_chpt.Columns[0].Width = 166;
\r
986 data_chpt.Columns[0].Width = 165;
\r
988 RegisterPresetEventHandler();
\r
990 private void chapersChanged(object sender, EventArgs e)
\r
992 Control ctl = (Control)sender;
\r
993 int chapterStart, chapterEnd;
\r
994 int.TryParse(drop_chapterStart.Text, out chapterStart);
\r
995 int.TryParse(drop_chapterFinish.Text, out chapterEnd);
\r
999 case "drop_chapterStart":
\r
1000 if (drop_chapterFinish.SelectedIndex == -1 && drop_chapterFinish.Items.Count != 0)
\r
1001 drop_chapterFinish.SelectedIndex = drop_chapterFinish.Items.Count - 1;
\r
1003 if (chapterEnd != 0)
\r
1004 if (chapterStart > chapterEnd)
\r
1005 drop_chapterFinish.Text = chapterStart.ToString();
\r
1007 case "drop_chapterFinish":
\r
1008 if (drop_chapterStart.Items.Count >= 1 && drop_chapterStart.SelectedIndex == -1)
\r
1009 drop_chapterStart.SelectedIndex = 0;
\r
1011 if (chapterStart != 0)
\r
1012 if (chapterEnd < chapterStart)
\r
1013 drop_chapterFinish.Text = chapterStart.ToString();
\r
1015 // Add more rows to the Chapter menu if needed.
\r
1016 if (Check_ChapterMarkers.Checked)
\r
1018 int i = data_chpt.Rows.Count, finish = 0;
\r
1019 int.TryParse(drop_chapterFinish.Text, out finish);
\r
1021 while (i < finish)
\r
1023 int n = data_chpt.Rows.Add();
\r
1024 data_chpt.Rows[n].Cells[0].Value = (i + 1);
\r
1025 data_chpt.Rows[n].Cells[1].Value = "Chapter " + (i + 1);
\r
1026 data_chpt.Rows[n].Cells[0].ValueType = typeof(int);
\r
1027 data_chpt.Rows[n].Cells[1].ValueType = typeof(string);
\r
1034 // Update the Duration
\r
1035 lbl_duration.Text = Main.calculateDuration(drop_chapterStart.SelectedIndex, drop_chapterFinish.SelectedIndex, selectedTitle).ToString();
\r
1037 // Run the Autonaming function
\r
1038 if (Properties.Settings.Default.autoNaming)
\r
1039 text_destination.Text = Main.autoName(this);
\r
1041 // Disable chapter markers if only 1 chapter is selected.
\r
1042 if (chapterStart == chapterEnd)
\r
1044 Check_ChapterMarkers.Enabled = false;
\r
1045 btn_importChapters.Enabled = false;
\r
1046 data_chpt.Enabled = false;
\r
1050 Check_ChapterMarkers.Enabled = true;
\r
1051 if (Check_ChapterMarkers.Checked)
\r
1053 btn_importChapters.Enabled = true;
\r
1054 data_chpt.Enabled = true;
\r
1060 private void btn_destBrowse_Click(object sender, EventArgs e)
\r
1062 // This removes the file extension from the filename box on the save file dialog.
\r
1063 // It's daft but some users don't realise that typing an extension overrides the dropdown extension selected.
\r
1064 DVD_Save.FileName = Path.GetFileNameWithoutExtension(text_destination.Text);
\r
1066 if (Path.IsPathRooted(text_destination.Text))
\r
1067 DVD_Save.InitialDirectory = Path.GetDirectoryName(text_destination.Text);
\r
1069 // Show the dialog and set the main form file path
\r
1070 if (drop_format.SelectedIndex.Equals(0))
\r
1071 DVD_Save.FilterIndex = 1;
\r
1072 else if (drop_format.SelectedIndex.Equals(1))
\r
1073 DVD_Save.FilterIndex = 2;
\r
1075 if (DVD_Save.ShowDialog() == DialogResult.OK)
\r
1077 if (DVD_Save.FileName.StartsWith("\\"))
\r
1078 MessageBox.Show("Sorry, HandBrake does not support UNC file paths. \nTry mounting the share as a network drive in My Computer", "Warning", MessageBoxButtons.OK, MessageBoxIcon.Warning);
\r
1081 // Add a file extension manually, as FileDialog.AddExtension has issues with dots in filenames
\r
1082 switch (DVD_Save.FilterIndex)
\r
1085 if (!Path.GetExtension(DVD_Save.FileName).Equals(".mp4", StringComparison.InvariantCultureIgnoreCase))
\r
1086 if (Properties.Settings.Default.useM4v)
\r
1087 DVD_Save.FileName = DVD_Save.FileName.Replace(".mp4", ".m4v").Replace(".mkv", ".m4v");
\r
1089 DVD_Save.FileName = DVD_Save.FileName.Replace(".m4v", ".mp4").Replace(".mkv", ".mp4");
\r
1092 if (!Path.GetExtension(DVD_Save.FileName).Equals(".mkv", StringComparison.InvariantCultureIgnoreCase))
\r
1093 DVD_Save.FileName = DVD_Save.FileName.Replace(".mp4", ".mkv").Replace(".m4v", ".mkv");
\r
1099 text_destination.Text = DVD_Save.FileName;
\r
1101 // Quicktime requires .m4v file for chapter markers to work. If checked, change the extension to .m4v (mp4 and m4v are the same thing)
\r
1102 if (Check_ChapterMarkers.Checked && DVD_Save.FilterIndex != 2)
\r
1103 SetExtension(".m4v");
\r
1107 private void text_destination_TextChanged(object sender, EventArgs e)
\r
1109 string path = text_destination.Text;
\r
1110 if (path.EndsWith(".mp4") || path.EndsWith(".m4v"))
\r
1111 drop_format.SelectedIndex = 0;
\r
1112 else if (path.EndsWith(".mkv"))
\r
1113 drop_format.SelectedIndex = 1;
\r
1116 // Output Settings
\r
1117 private void drop_format_SelectedIndexChanged(object sender, EventArgs e)
\r
1119 switch (drop_format.SelectedIndex)
\r
1122 if (Properties.Settings.Default.useM4v || Check_ChapterMarkers.Checked || AudioSettings.RequiresM4V() || Subtitles.RequiresM4V())
\r
1123 SetExtension(".m4v");
\r
1125 SetExtension(".mp4");
\r
1128 SetExtension(".mkv");
\r
1132 AudioSettings.SetContainer(drop_format.Text);
\r
1133 Subtitles.SetContainer(drop_format.SelectedIndex);
\r
1135 if (drop_format.Text.Contains("MP4"))
\r
1137 if (drp_videoEncoder.Items.Contains("VP3 (Theora)"))
\r
1139 drp_videoEncoder.Items.Remove("VP3 (Theora)");
\r
1140 drp_videoEncoder.SelectedIndex = 1;
\r
1143 else if (drop_format.Text.Contains("MKV"))
\r
1144 drp_videoEncoder.Items.Add("VP3 (Theora)");
\r
1146 public void SetExtension(string newExtension)
\r
1148 if (newExtension == ".mp4" || newExtension == ".m4v")
\r
1149 if (Properties.Settings.Default.useM4v || Check_ChapterMarkers.Checked || AudioSettings.RequiresM4V() || Subtitles.RequiresM4V())
\r
1150 newExtension = ".m4v";
\r
1152 newExtension = ".mp4";
\r
1154 if (Path.HasExtension(newExtension))
\r
1155 text_destination.Text = Path.ChangeExtension(text_destination.Text, newExtension);
\r
1159 private void drp_videoEncoder_SelectedIndexChanged(object sender, EventArgs e)
\r
1161 setContainerOpts();
\r
1163 //Turn off some options which are H.264 only when the user selects a non h.264 encoder
\r
1164 if (drp_videoEncoder.Text.Contains("H.264"))
\r
1166 if (check_2PassEncode.CheckState == CheckState.Checked)
\r
1167 check_turbo.Enabled = true;
\r
1169 tab_advanced.Enabled = true;
\r
1170 if ((drop_format.Text.Contains("MP4")) || (drop_format.Text.Contains("M4V")))
\r
1171 check_iPodAtom.Enabled = true;
\r
1173 check_iPodAtom.Enabled = false;
\r
1177 check_turbo.CheckState = CheckState.Unchecked;
\r
1178 check_turbo.Enabled = false;
\r
1179 tab_advanced.Enabled = false;
\r
1180 x264Panel.x264Query = "";
\r
1181 check_iPodAtom.Enabled = false;
\r
1182 check_iPodAtom.Checked = false;
\r
1185 // Setup the CQ Slider
\r
1186 switch (drp_videoEncoder.Text)
\r
1188 case "MPEG-4 (FFmpeg)":
\r
1189 if (slider_videoQuality.Value > 31)
\r
1190 slider_videoQuality.Value = 20; // Just reset to 70% QP 10 on encode change.
\r
1191 slider_videoQuality.Minimum = 1;
\r
1192 slider_videoQuality.Maximum = 31;
\r
1194 case "H.264 (x264)":
\r
1195 slider_videoQuality.Minimum = 0;
\r
1196 slider_videoQuality.TickFrequency = 1;
\r
1198 CultureInfo culture = CultureInfo.CreateSpecificCulture("en-US");
\r
1199 double cqStep = Properties.Settings.Default.x264cqstep;
\r
1200 double multiplier = 1.0 / cqStep;
\r
1201 double value = slider_videoQuality.Value * multiplier;
\r
1203 switch (Properties.Settings.Default.x264cqstep.ToString(culture))
\r
1206 slider_videoQuality.Maximum = 255;
\r
1209 slider_videoQuality.Maximum = 204;
\r
1212 slider_videoQuality.Maximum = 102;
\r
1215 slider_videoQuality.Maximum = 51;
\r
1218 slider_videoQuality.Maximum = 51;
\r
1221 if (value < slider_videoQuality.Maximum)
\r
1222 slider_videoQuality.Value = slider_videoQuality.Maximum - (int)value;
\r
1225 case "VP3 (Theora)":
\r
1226 if (slider_videoQuality.Value > 63)
\r
1227 slider_videoQuality.Value = 45; // Just reset to 70% QP 45 on encode change.
\r
1228 slider_videoQuality.Minimum = 0;
\r
1229 slider_videoQuality.Maximum = 63;
\r
1234 /// Set the container format options
\r
1236 public void setContainerOpts()
\r
1238 if ((drop_format.Text.Contains("MP4")) || (drop_format.Text.Contains("M4V")))
\r
1240 check_largeFile.Enabled = true;
\r
1241 check_optimiseMP4.Enabled = true;
\r
1242 check_iPodAtom.Enabled = true;
\r
1246 check_largeFile.Enabled = false;
\r
1247 check_optimiseMP4.Enabled = false;
\r
1248 check_iPodAtom.Enabled = false;
\r
1249 check_largeFile.Checked = false;
\r
1250 check_optimiseMP4.Checked = false;
\r
1251 check_iPodAtom.Checked = false;
\r
1254 private double _cachedCqStep = Properties.Settings.Default.x264cqstep;
\r
1256 /// Update the CQ slider for x264 for a new CQ step. This is set from option
\r
1258 public void setQualityFromSlider()
\r
1260 // Work out the current RF value.
\r
1261 double cqStep = _cachedCqStep;
\r
1262 double rfValue = 51.0 - slider_videoQuality.Value * cqStep;
\r
1264 // Change the maximum value for the slider
\r
1265 switch (Properties.Settings.Default.x264cqstep.ToString(new CultureInfo("en-US")))
\r
1268 slider_videoQuality.Maximum = 255;
\r
1271 slider_videoQuality.Maximum = 204;
\r
1274 slider_videoQuality.Maximum = 102;
\r
1277 slider_videoQuality.Maximum = 51;
\r
1280 slider_videoQuality.Maximum = 51;
\r
1284 // Reset the CQ slider to RF0
\r
1285 slider_videoQuality.Value = slider_videoQuality.Maximum;
\r
1287 // Reset the CQ slider back to the previous value as close as possible
\r
1288 double cqStepNew = Properties.Settings.Default.x264cqstep;
\r
1289 double rfValueCurrent = 51.0 - slider_videoQuality.Value * cqStepNew;
\r
1290 while (rfValueCurrent < rfValue)
\r
1292 slider_videoQuality.Value--;
\r
1293 rfValueCurrent = 51.0 - slider_videoQuality.Value * cqStepNew;
\r
1296 // Cache the CQ step for the next calculation
\r
1297 _cachedCqStep = Properties.Settings.Default.x264cqstep;
\r
1299 private void slider_videoQuality_Scroll(object sender, EventArgs e)
\r
1301 double cqStep = Properties.Settings.Default.x264cqstep;
\r
1302 switch (drp_videoEncoder.Text)
\r
1304 case "MPEG-4 (FFmpeg)":
\r
1305 double rfValue = 31 - (slider_videoQuality.Value - 1);
\r
1306 double max = slider_videoQuality.Maximum;
\r
1307 double min = slider_videoQuality.Minimum;
\r
1308 double val = ((max - min) - (rfValue - min)) / (max - min);
\r
1309 SliderValue.Text = Math.Round((val * 100), 2).ToString(new CultureInfo("en-US")) + "% QP:" + (32 - slider_videoQuality.Value);
\r
1311 case "H.264 (x264)":
\r
1312 rfValue = 51.0 - slider_videoQuality.Value * cqStep;
\r
1313 max = slider_videoQuality.Maximum * cqStep;
\r
1314 min = slider_videoQuality.Minimum;
\r
1315 val = ((max - min) - (rfValue - min)) / (max - min);
\r
1316 rfValue = Math.Round(rfValue, 2);
\r
1317 SliderValue.Text = Math.Round((val * 100), 2).ToString(new CultureInfo("en-US")) + "% RF:" + rfValue.ToString(new CultureInfo("en-US"));
\r
1319 case "VP3 (Theora)":
\r
1320 rfValue = slider_videoQuality.Value;
\r
1321 double value = rfValue / 63;
\r
1322 SliderValue.Text = Math.Round((value * 100), 2).ToString(new CultureInfo("en-US")) + "% QP:" + slider_videoQuality.Value;
\r
1326 private void radio_targetFilesize_CheckedChanged(object sender, EventArgs e)
\r
1328 text_bitrate.Enabled = false;
\r
1329 text_filesize.Enabled = true;
\r
1330 slider_videoQuality.Enabled = false;
\r
1332 check_2PassEncode.Enabled = true;
\r
1334 private void radio_avgBitrate_CheckedChanged(object sender, EventArgs e)
\r
1336 text_bitrate.Enabled = true;
\r
1337 text_filesize.Enabled = false;
\r
1338 slider_videoQuality.Enabled = false;
\r
1340 check_2PassEncode.Enabled = true;
\r
1342 private void radio_cq_CheckedChanged(object sender, EventArgs e)
\r
1344 text_bitrate.Enabled = false;
\r
1345 text_filesize.Enabled = false;
\r
1346 slider_videoQuality.Enabled = true;
\r
1348 check_2PassEncode.Enabled = false;
\r
1349 check_2PassEncode.CheckState = CheckState.Unchecked;
\r
1351 private void check_2PassEncode_CheckedChanged(object sender, EventArgs e)
\r
1353 if (check_2PassEncode.CheckState.ToString() == "Checked")
\r
1355 if (drp_videoEncoder.Text.Contains("H.264"))
\r
1356 check_turbo.Enabled = true;
\r
1360 check_turbo.Enabled = false;
\r
1361 check_turbo.CheckState = CheckState.Unchecked;
\r
1365 // Chapter Marker Tab
\r
1366 private void Check_ChapterMarkers_CheckedChanged(object sender, EventArgs e)
\r
1368 if (Check_ChapterMarkers.Checked)
\r
1370 if (drop_format.SelectedIndex != 1)
\r
1371 SetExtension(".m4v");
\r
1372 data_chpt.Enabled = true;
\r
1373 btn_importChapters.Enabled = true;
\r
1377 if (drop_format.SelectedIndex != 1 && !Properties.Settings.Default.useM4v)
\r
1378 SetExtension(".mp4");
\r
1379 data_chpt.Enabled = false;
\r
1380 btn_importChapters.Enabled = false;
\r
1383 private void btn_importChapters_Click(object sender, EventArgs e)
\r
1385 if (File_ChapterImport.ShowDialog() == DialogResult.OK)
\r
1387 String filename = File_ChapterImport.FileName;
\r
1388 DataGridView imported = Main.importChapterNames(data_chpt, filename);
\r
1389 if (imported != null)
\r
1390 data_chpt = imported;
\r
1393 private void mnu_resetChapters_Click(object sender, EventArgs e)
\r
1395 data_chpt.Rows.Clear();
\r
1396 DataGridView chapterGridView = Main.chapterNaming(data_chpt, drop_chapterFinish.Text);
\r
1397 if (chapterGridView != null)
\r
1399 data_chpt = chapterGridView;
\r
1403 // Query Editor Tab
\r
1404 private void btn_generate_Query_Click(object sender, EventArgs e)
\r
1406 rtf_query.Text = queryGen.GenerateCLIQuery(this, 0, null);
\r
1408 private void btn_clear_Click(object sender, EventArgs e)
\r
1410 rtf_query.Clear();
\r
1414 // MainWindow Components, Actions and Functions ***********************
\r
1416 #region Source Scan
\r
1417 public Boolean isScanning { get; set; }
\r
1418 private Scan SourceScan;
\r
1420 private void StartScan(String filename)
\r
1422 // Setup the GUI components for the scan.
\r
1423 sourcePath = filename;
\r
1424 foreach (Control ctrl in Controls)
\r
1425 if (!(ctrl is StatusStrip || ctrl is MenuStrip || ctrl is ToolStrip))
\r
1426 ctrl.Enabled = false;
\r
1428 lbl_encode.Visible = true;
\r
1429 lbl_encode.Text = "Scanning ...";
\r
1430 btn_source.Enabled = false;
\r
1431 btn_start.Enabled = false;
\r
1432 btn_showQueue.Enabled = false;
\r
1433 btn_add2Queue.Enabled = false;
\r
1434 tb_preview.Enabled = false;
\r
1435 mnu_killCLI.Visible = true;
\r
1437 if (ActivityWindow != null)
\r
1438 ActivityWindow.SetScanMode();
\r
1443 // if (ActivityWindow != null)
\r
1444 // ActivityWindow.SetupLogViewer(true);
\r
1445 isScanning = true;
\r
1446 SourceScan = new Scan();
\r
1447 SourceScan.ScanSource(sourcePath);
\r
1448 SourceScan.ScanStatusChanged += new EventHandler(SourceScan_ScanStatusChanged);
\r
1449 SourceScan.ScanCompleted += new EventHandler(SourceScan_ScanCompleted);
\r
1451 catch (Exception exc)
\r
1453 MessageBox.Show("frmMain.cs - StartScan " + exc, "Error", MessageBoxButtons.OK, MessageBoxIcon.Error);
\r
1457 void SourceScan_ScanStatusChanged(object sender, EventArgs e)
\r
1459 UpdateScanStatusLabel();
\r
1461 void SourceScan_ScanCompleted(object sender, EventArgs e)
\r
1463 UpdateGuiAfterScan();
\r
1466 private void UpdateScanStatusLabel()
\r
1468 if (InvokeRequired)
\r
1470 BeginInvoke(new UpdateWindowHandler(UpdateScanStatusLabel));
\r
1473 lbl_encode.Text = SourceScan.ScanStatus();
\r
1475 private void UpdateGuiAfterScan()
\r
1477 if (InvokeRequired)
\r
1479 BeginInvoke(new UpdateWindowHandler(UpdateGuiAfterScan));
\r
1485 DVD thisDVD = SourceScan.SouceData();
\r
1487 // Setup some GUI components
\r
1488 drp_dvdtitle.Items.Clear();
\r
1489 if (thisDVD.Titles.Count != 0)
\r
1490 drp_dvdtitle.Items.AddRange(thisDVD.Titles.ToArray());
\r
1492 // Now select the longest title
\r
1493 if (thisDVD.Titles.Count != 0)
\r
1494 drp_dvdtitle.SelectedItem = Main.selectLongestTitle(thisDVD);
\r
1496 // Enable the creation of chapter markers if the file is an image of a dvd.
\r
1497 if (sourcePath.ToLower().Contains(".iso") || sourcePath.Contains("VIDEO_TS"))
\r
1498 Check_ChapterMarkers.Enabled = true;
\r
1501 Check_ChapterMarkers.Enabled = false;
\r
1502 Check_ChapterMarkers.Checked = false;
\r
1503 data_chpt.Rows.Clear();
\r
1506 // If no titles were found, Display an error message
\r
1507 if (drp_dvdtitle.Items.Count == 0)
\r
1510 "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
1511 "Error", MessageBoxButtons.OK, MessageBoxIcon.Hand);
\r
1512 sourcePath = string.Empty;
\r
1514 UpdateSourceLabel();
\r
1516 // Enable the GUI components and enable any disabled components
\r
1519 catch (Exception exc)
\r
1521 MessageBox.Show("frmMain.cs - updateUIafterScan " + exc, "Error", MessageBoxButtons.OK, MessageBoxIcon.Error);
\r
1526 private void EnableGUI()
\r
1530 if (InvokeRequired)
\r
1531 BeginInvoke(new UpdateWindowHandler(EnableGUI));
\r
1532 lbl_encode.Text = "Scan Completed";
\r
1533 foreach (Control ctrl in Controls)
\r
1534 ctrl.Enabled = true;
\r
1535 btn_start.Enabled = true;
\r
1536 btn_showQueue.Enabled = true;
\r
1537 btn_add2Queue.Enabled = true;
\r
1538 tb_preview.Enabled = true;
\r
1539 btn_source.Enabled = true;
\r
1540 mnu_killCLI.Visible = false;
\r
1542 catch (Exception exc)
\r
1544 MessageBox.Show("frmMain.cs - EnableGUI() " + exc, "Error", MessageBoxButtons.OK, MessageBoxIcon.Error);
\r
1547 private void KillScan()
\r
1551 SourceScan.ScanCompleted -= new EventHandler(SourceScan_ScanCompleted);
\r
1555 if (SourceScan.ScanProcess() != null)
\r
1556 SourceScan.ScanProcess().Kill();
\r
1558 lbl_encode.Text = "Scan Cancelled!";
\r
1560 catch (Exception ex)
\r
1562 MessageBox.Show("Unable to kill HandBrakeCLI.exe \nYou may need to manually kill HandBrakeCLI.exe using the Windows Task Manager if it does not close automatically within the next few minutes. \n\nError Information: \n" + ex.Message, "Error", MessageBoxButtons.OK, MessageBoxIcon.Error);
\r
1565 private void ResetGUI()
\r
1567 drp_dvdtitle.Items.Clear();
\r
1568 drop_chapterStart.Items.Clear();
\r
1569 drop_chapterFinish.Items.Clear();
\r
1570 lbl_duration.Text = "Select a Title";
\r
1571 PictureSettings.lbl_src_res.Text = "Select a Title";
\r
1572 PictureSettings.lbl_Aspect.Text = "Select a Title";
\r
1573 sourcePath = String.Empty;
\r
1574 text_destination.Text = String.Empty;
\r
1575 selectedTitle = null;
\r
1576 isScanning = false;
\r
1578 private void UpdateSourceLabel()
\r
1580 labelSource.Text = string.IsNullOrEmpty(sourcePath) ? "Select \"Source\" to continue." : this.SourceName;
\r
1582 if (selectedTitle != null)
\r
1583 if (!string.IsNullOrEmpty(selectedTitle.SourceName)) // If it's one of multiple source files, make sure we don't use the folder name
\r
1584 labelSource.Text = Path.GetFileName(selectedTitle.SourceName);
\r
1590 /// Set the GUI to it's finished encoding state.
\r
1592 private void setEncodeFinished()
\r
1596 if (InvokeRequired)
\r
1598 BeginInvoke(new UpdateWindowHandler(setEncodeFinished));
\r
1602 lbl_encode.Text = "Encoding Finished";
\r
1603 btn_start.Text = "Start";
\r
1604 btn_start.ToolTipText = "Start the encoding process";
\r
1605 btn_start.Image = Properties.Resources.Play;
\r
1607 // If the window is minimized, display the notification in a popup.
\r
1608 if (Properties.Settings.Default.trayIconAlerts)
\r
1609 if (FormWindowState.Minimized == this.WindowState)
\r
1611 notifyIcon.BalloonTipText = lbl_encode.Text;
\r
1612 notifyIcon.ShowBalloonTip(500);
\r
1615 catch (Exception exc)
\r
1617 MessageBox.Show(exc.ToString());
\r
1622 /// Set the GUI to it's started encoding state.
\r
1624 private void setEncodeStarted()
\r
1628 if (InvokeRequired)
\r
1630 BeginInvoke(new UpdateWindowHandler(setEncodeStarted));
\r
1634 lbl_encode.Visible = true;
\r
1635 lbl_encode.Text = "Encoding with " + encodeQueue.Count + " encode(s) pending";
\r
1636 btn_start.Text = "Stop";
\r
1637 btn_start.ToolTipText = "Stop the encoding process.";
\r
1638 btn_start.Image = Properties.Resources.stop;
\r
1640 catch (Exception exc)
\r
1642 MessageBox.Show(exc.ToString());
\r
1647 #region DVD Drive Detection
\r
1648 private void getDriveInfoThread()
\r
1652 if (InvokeRequired)
\r
1654 BeginInvoke(new UpdateWindowHandler(getDriveInfoThread));
\r
1658 Boolean foundDrive = false;
\r
1659 DriveInfo[] theCollectionOfDrives = DriveInfo.GetDrives();
\r
1660 foreach (DriveInfo curDrive in theCollectionOfDrives)
\r
1662 if (curDrive.DriveType == DriveType.CDRom && curDrive.IsReady)
\r
1664 if (File.Exists(curDrive.RootDirectory + "VIDEO_TS\\VIDEO_TS.IFO"))
\r
1666 this.dvdDrivePath = curDrive.RootDirectory + "VIDEO_TS";
\r
1667 this.dvdDriveLabel = curDrive.VolumeLabel;
\r
1668 mnu_dvd_drive.Text = this.dvdDrivePath + " (" + this.dvdDriveLabel + ")";
\r
1669 foundDrive = true;
\r
1675 if (foundDrive == false)
\r
1676 mnu_dvd_drive.Text = "[No DVD Drive Ready]";
\r
1680 mnu_dvd_drive.Text = "[No DVD Drive Ready / Found]";
\r
1685 #region Public Methods
\r
1687 /// Access the preset Handler and setup the preset panel.
\r
1689 public void loadPresetPanel()
\r
1691 if (presetHandler.CheckIfPresetsAreOutOfDate())
\r
1692 if (!Properties.Settings.Default.presetNotification)
\r
1693 MessageBox.Show(splash,
\r
1694 "HandBrake has determined your built-in presets are out of date... These presets will now be updated.",
\r
1695 "Preset Update", MessageBoxButtons.OK, MessageBoxIcon.Information);
\r
1697 presetHandler.GetPresetPanel(ref treeView_presets);
\r
1698 treeView_presets.Update();
\r
1704 /// If the queue is being processed, prompt the user to confirm application close.
\r
1706 /// <param name="e"></param>
\r
1707 protected override void OnFormClosing(FormClosingEventArgs e)
\r
1709 // If currently encoding, the queue isn't paused, and there are queue items to process, prompt to confirm close.
\r
1710 if ((encodeQueue.isEncoding) && (!encodeQueue.PauseRequested) && (encodeQueue.Count > 0))
\r
1712 DialogResult result = MessageBox.Show("HandBrake has queue items to process. Closing HandBrake will not stop the current encoding, but will stop processing the queue.\n\nDo you want to close HandBrake?",
\r
1713 "Close HandBrake?", MessageBoxButtons.YesNo, MessageBoxIcon.Question);
\r
1714 if (result == DialogResult.No)
\r
1717 base.OnFormClosing(e);
\r
1721 #region In-GUI Encode Status (Experimental)
\r
1722 private void encodeMonitorThread()
\r
1726 Parser encode = new Parser(encodeQueue.hbProcess.StandardOutput.BaseStream);
\r
1727 encode.OnEncodeProgress += encodeOnEncodeProgress;
\r
1728 while (!encode.EndOfStream)
\r
1729 encode.readEncodeStatus();
\r
1731 catch (Exception exc)
\r
1733 MessageBox.Show(exc.ToString(), "Error", MessageBoxButtons.OK, MessageBoxIcon.Error);
\r
1736 private void encodeOnEncodeProgress(object Sender, int CurrentTask, int TaskCount, float PercentComplete, float CurrentFps, float AverageFps, TimeSpan TimeRemaining)
\r
1738 if (this.InvokeRequired)
\r
1740 this.BeginInvoke(new EncodeProgressEventHandler(encodeOnEncodeProgress),
\r
1741 new object[] { Sender, CurrentTask, TaskCount, PercentComplete, CurrentFps, AverageFps, TimeRemaining });
\r
1744 lbl_encode.Text = string.Format("Encode Progress: {0}%, FPS: {1}, Avg FPS: {2}, Time Remaining: {3} ", PercentComplete, CurrentFps, AverageFps, TimeRemaining);
\r
1749 private enum SourceType
\r
1758 // This is the END of the road ****************************************
\r