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 frmActivityWindow dvdInfoWindow = new frmActivityWindow(lastAction);
\r
357 dvdInfoWindow.Show();
\r
359 private void mnu_options_Click(object sender, EventArgs e)
\r
361 Form options = new frmOptions(this);
\r
362 options.ShowDialog();
\r
366 #region Presets Menu
\r
367 private void mnu_presetReset_Click(object sender, EventArgs e)
\r
369 presetHandler.UpdateBuiltInPresets();
\r
371 if (treeView_presets.Nodes.Count == 0)
\r
372 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
374 MessageBox.Show("Presets have been updated!", "Alert", MessageBoxButtons.OK, MessageBoxIcon.Information);
\r
376 treeView_presets.ExpandAll();
\r
378 private void mnu_delete_preset_Click(object sender, EventArgs e)
\r
380 presetHandler.RemoveBuiltInPresets();
\r
381 loadPresetPanel(); // Reload the preset panel
\r
383 private void mnu_SelectDefault_Click(object sender, EventArgs e)
\r
385 loadNormalPreset();
\r
387 private void mnu_importMacPreset_Click(object sender, EventArgs e)
\r
391 private void btn_new_preset_Click(object sender, EventArgs e)
\r
393 Form preset = new frmAddPreset(this, queryGen.GenerateCLIQuery(this, 0, null), presetHandler);
\r
394 preset.ShowDialog();
\r
399 private void mnu_handbrake_forums_Click(object sender, EventArgs e)
\r
401 Process.Start("http://forum.handbrake.fr/");
\r
403 private void mnu_user_guide_Click(object sender, EventArgs e)
\r
405 Process.Start("http://trac.handbrake.fr/wiki/HandBrakeGuide");
\r
407 private void mnu_handbrake_home_Click(object sender, EventArgs e)
\r
409 Process.Start("http://handbrake.fr");
\r
411 private void mnu_UpdateCheck_Click(object sender, EventArgs e)
\r
413 lbl_updateCheck.Visible = true;
\r
414 Main.BeginCheckForUpdates(new AsyncCallback(updateCheckDoneMenu), false);
\r
416 private void updateCheckDoneMenu(IAsyncResult result)
\r
418 // Make sure it's running on the calling thread
\r
419 if (InvokeRequired)
\r
421 Invoke(new MethodInvoker(() => updateCheckDoneMenu(result)));
\r
424 UpdateCheckInformation info;
\r
427 // Get the information about the new build, if any, and close the window
\r
428 info = Main.EndCheckForUpdates(result);
\r
430 if (info.NewVersionAvailable && info.BuildInformation != null)
\r
432 frmUpdater updateWindow = new frmUpdater(info.BuildInformation);
\r
433 updateWindow.ShowDialog();
\r
436 MessageBox.Show("There are no new updates at this time.", "Update Check", MessageBoxButtons.OK, MessageBoxIcon.Information);
\r
437 lbl_updateCheck.Visible = false;
\r
440 catch (Exception ex)
\r
442 if ((bool)result.AsyncState)
\r
443 MessageBox.Show("Unable to check for updates, Please try again later.\n\nDetailed Error Information:\n" + ex, "Error", MessageBoxButtons.OK, MessageBoxIcon.Error);
\r
446 private void mnu_about_Click(object sender, EventArgs e)
\r
448 using (frmAbout About = new frmAbout())
\r
450 About.ShowDialog();
\r
456 // Right Click Menu Code
\r
457 private void pmnu_expandAll_Click(object sender, EventArgs e)
\r
459 treeView_presets.ExpandAll();
\r
461 private void pmnu_collapse_Click(object sender, EventArgs e)
\r
463 treeView_presets.CollapseAll();
\r
465 private void pmnu_import_Click(object sender, EventArgs e)
\r
469 private void pmnu_saveChanges_Click(object sender, EventArgs e)
\r
471 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
472 if (result == DialogResult.Yes)
\r
473 presetHandler.Update(treeView_presets.SelectedNode.Text, QueryGenerator.GenerateTabbedComponentsQuery(this), true);
\r
474 else if (result == DialogResult.No)
\r
475 presetHandler.Update(treeView_presets.SelectedNode.Text, QueryGenerator.GenerateTabbedComponentsQuery(this), false);
\r
477 private void pmnu_delete_click(object sender, EventArgs e)
\r
479 if (treeView_presets.SelectedNode != null)
\r
481 presetHandler.Remove(treeView_presets.SelectedNode.Text);
\r
482 treeView_presets.Nodes.Remove(treeView_presets.SelectedNode);
\r
484 treeView_presets.Select();
\r
486 private void presets_menu_Opening(object sender, System.ComponentModel.CancelEventArgs e)
\r
488 // Make sure that the save menu is always disabled by default
\r
489 pmnu_saveChanges.Enabled = false;
\r
491 // Now enable the save menu if the selected preset is a user preset
\r
492 if (treeView_presets.SelectedNode != null)
\r
493 if (presetHandler.CheckIfUserPresetExists(treeView_presets.SelectedNode.Text))
\r
494 pmnu_saveChanges.Enabled = true;
\r
496 treeView_presets.Select();
\r
499 // Presets Management
\r
500 private void btn_addPreset_Click(object sender, EventArgs e)
\r
502 Form preset = new frmAddPreset(this, QueryGenerator.GenerateTabbedComponentsQuery(this), presetHandler);
\r
503 preset.ShowDialog();
\r
505 private void btn_removePreset_Click(object sender, EventArgs e)
\r
507 DialogResult result = MessageBox.Show("Are you sure you wish to delete the selected preset?", "Preset", MessageBoxButtons.YesNo, MessageBoxIcon.Question);
\r
508 if (result == DialogResult.Yes)
\r
510 if (treeView_presets.SelectedNode != null)
\r
512 presetHandler.Remove(treeView_presets.SelectedNode.Text);
\r
513 treeView_presets.Nodes.Remove(treeView_presets.SelectedNode);
\r
516 treeView_presets.Select();
\r
518 private void btn_setDefault_Click(object sender, EventArgs e)
\r
520 if (treeView_presets.SelectedNode != null)
\r
522 DialogResult result = MessageBox.Show("Are you sure you wish to set this preset as the default?", "Preset", MessageBoxButtons.YesNo, MessageBoxIcon.Question);
\r
523 if (result == DialogResult.Yes)
\r
525 Properties.Settings.Default.defaultPreset = treeView_presets.SelectedNode.Text;
\r
526 Properties.Settings.Default.Save();
\r
527 MessageBox.Show("New default preset set.", "Alert", MessageBoxButtons.OK, MessageBoxIcon.Information);
\r
531 MessageBox.Show("Please select a preset first.", "Warning", MessageBoxButtons.OK, MessageBoxIcon.Warning);
\r
533 private void treeview_presets_mouseUp(object sender, MouseEventArgs e)
\r
535 if (e.Button == MouseButtons.Right)
\r
536 treeView_presets.SelectedNode = treeView_presets.GetNodeAt(e.Location);
\r
537 else if (e.Button == MouseButtons.Left)
\r
539 if (treeView_presets.GetNodeAt(e.Location) != null)
\r
541 if (labelPreset.Text.Contains(treeView_presets.GetNodeAt(e.Location).Text))
\r
546 treeView_presets.Select();
\r
548 private void treeView_presets_AfterSelect(object sender, TreeViewEventArgs e)
\r
552 private void treeView_presets_deleteKey(object sender, KeyEventArgs e)
\r
554 if (e.KeyCode == Keys.Delete)
\r
556 DialogResult result = MessageBox.Show("Are you sure you wish to delete the selected preset?", "Preset", MessageBoxButtons.YesNo, MessageBoxIcon.Question);
\r
557 if (result == DialogResult.Yes)
\r
559 if (treeView_presets.SelectedNode != null)
\r
560 presetHandler.Remove(treeView_presets.SelectedNode.Text);
\r
562 // Remember each nodes expanded status so we can reload it
\r
563 List<Boolean> nodeStatus = new List<Boolean>();
\r
564 foreach (TreeNode node in treeView_presets.Nodes)
\r
565 nodeStatus.Add(node.IsExpanded);
\r
567 // Now reload the preset panel
\r
570 // And finally, re-expand any of the nodes if required
\r
572 foreach (TreeNode node in treeView_presets.Nodes)
\r
582 private void selectPreset()
\r
584 if (treeView_presets.SelectedNode != null)
\r
586 // Ok, so, we've selected a preset. Now we want to load it.
\r
587 string presetName = treeView_presets.SelectedNode.Text;
\r
588 if (presetHandler.GetPreset(presetName) != null)
\r
590 string query = presetHandler.GetPreset(presetName).Query;
\r
591 Boolean loadPictureSettings = presetHandler.GetPreset(presetName).PictureSettings;
\r
595 //Ok, Reset all the H264 widgets before changing the preset
\r
596 x264Panel.reset2Defaults();
\r
598 // Send the query from the file to the Query Parser class
\r
599 QueryParser presetQuery = QueryParser.Parse(query);
\r
601 // Now load the preset
\r
602 PresetLoader.presetLoader(this, presetQuery, presetName, loadPictureSettings);
\r
604 // The x264 widgets will need updated, so do this now:
\r
605 x264Panel.X264_StandardizeOptString();
\r
606 x264Panel.X264_SetCurrentSettingsInPanel();
\r
611 private void loadNormalPreset()
\r
613 foreach (TreeNode treenode in treeView_presets.Nodes)
\r
615 foreach (TreeNode node in treenode.Nodes)
\r
617 if (node.Text.Equals("Normal"))
\r
618 treeView_presets.SelectedNode = treeView_presets.Nodes[treenode.Index].Nodes[0];
\r
622 private void importPreset()
\r
624 Import imp = new Import();
\r
625 if (openPreset.ShowDialog() == DialogResult.OK)
\r
627 QueryParser parsed = imp.importMacPreset(openPreset.FileName);
\r
628 if (presetHandler.CheckIfUserPresetExists(parsed.PresetName + " (Imported)"))
\r
630 DialogResult result = MessageBox.Show("This preset appears to already exist. Would you like to overwrite it?", "Overwrite preset?",
\r
631 MessageBoxButtons.YesNo, MessageBoxIcon.Warning);
\r
632 if (result == DialogResult.Yes)
\r
634 PresetLoader.presetLoader(this, parsed, parsed.PresetName, parsed.UsesPictureSettings);
\r
635 presetHandler.Update(parsed.PresetName + " (Imported)", queryGen.GenerateCLIQuery(this, 0, null),
\r
636 parsed.UsesPictureSettings);
\r
641 PresetLoader.presetLoader(this, parsed, parsed.PresetName, parsed.UsesPictureSettings);
\r
642 presetHandler.Add(parsed.PresetName, queryGen.GenerateCLIQuery(this, 0, null), parsed.UsesPictureSettings);
\r
644 if (presetHandler.Add(parsed.PresetName + " (Imported)", queryGen.GenerateCLIQuery(this, 0, null), parsed.UsesPictureSettings))
\r
646 TreeNode preset_treeview = new TreeNode(parsed.PresetName + " (Imported)") { ForeColor = Color.Black };
\r
647 treeView_presets.Nodes.Add(preset_treeview);
\r
655 private void btn_source_Click(object sender, EventArgs e)
\r
657 mnu_dvd_drive.Visible = true;
\r
658 Thread driveInfoThread = new Thread(getDriveInfoThread);
\r
659 driveInfoThread.Start();
\r
661 private void btn_start_Click(object sender, EventArgs e)
\r
663 if (btn_start.Text == "Stop")
\r
665 DialogResult result = MessageBox.Show("Are you sure you wish to cancel the encode?", "Cancel Encode?", MessageBoxButtons.YesNo, MessageBoxIcon.Question);
\r
667 if (result == DialogResult.Yes)
\r
670 encodeQueue.RequestPause();
\r
672 // Allow the CLI to exit cleanly
\r
673 Win32.SetForegroundWindow((int)encodeQueue.processHandle);
\r
674 SendKeys.Send("^C");
\r
677 setEncodeFinished();
\r
682 if (encodeQueue.Count != 0 || (!string.IsNullOrEmpty(sourcePath) && !string.IsNullOrEmpty(text_destination.Text)))
\r
684 string generatedQuery = queryGen.GenerateCLIQuery(this, 0, null);
\r
685 string specifiedQuery = rtf_query.Text != "" ? rtf_query.Text : queryGen.GenerateCLIQuery(this, 0, null);
\r
686 string query = string.Empty;
\r
688 // Check to make sure the generated query matches the GUI settings
\r
689 if (Properties.Settings.Default.PromptOnUnmatchingQueries && !string.IsNullOrEmpty(specifiedQuery) && generatedQuery != specifiedQuery)
\r
691 DialogResult result = MessageBox.Show("The query under the \"Query Editor\" tab " +
\r
692 "does not match the current GUI settings.\n\nBecause the manual query takes " +
\r
693 "priority over the GUI, your recently updated settings will not be taken " +
\r
694 "into account when encoding this job." + Environment.NewLine + Environment.NewLine +
\r
695 "Do you want to replace the manual query with the updated GUI-generated query?",
\r
696 "Manual Query does not Match GUI",
\r
697 MessageBoxButtons.YesNoCancel, MessageBoxIcon.Asterisk,
\r
698 MessageBoxDefaultButton.Button3);
\r
702 case DialogResult.Yes:
\r
703 // Replace the manual query with the generated one
\r
704 query = generatedQuery;
\r
705 rtf_query.Text = generatedQuery;
\r
707 case DialogResult.No:
\r
708 // Use the manual query
\r
709 query = specifiedQuery;
\r
711 case DialogResult.Cancel:
\r
712 // Don't start the encode
\r
718 query = specifiedQuery;
\r
721 DialogResult overwrite = DialogResult.Yes;
\r
722 if (text_destination.Text != "")
\r
723 if (File.Exists(text_destination.Text))
\r
724 overwrite = MessageBox.Show("The destination file already exists. Are you sure you want to overwrite it?", "Overwrite File?", MessageBoxButtons.YesNo, MessageBoxIcon.Question);
\r
726 if (overwrite == DialogResult.Yes)
\r
728 if (encodeQueue.Count == 0)
\r
729 encodeQueue.AddJob(query, sourcePath, text_destination.Text, (rtf_query.Text != ""));
\r
731 queueWindow.setQueue();
\r
732 if (encodeQueue.Count > 1)
\r
733 queueWindow.Show(false);
\r
735 setEncodeStarted(); // Encode is running, so setup the GUI appropriately
\r
736 encodeQueue.StartEncodeQueue(); // Start The Queue Encoding Process
\r
737 lastAction = "encode"; // Set the last action to encode - Used for activity window.
\r
739 if (ActivityWindow != null)
\r
740 ActivityWindow.SetEncodeMode();
\r
744 else if (string.IsNullOrEmpty(sourcePath) || string.IsNullOrEmpty(text_destination.Text))
\r
745 MessageBox.Show("No source or destination selected.", "Warning", MessageBoxButtons.OK, MessageBoxIcon.Warning);
\r
748 private void btn_add2Queue_Click(object sender, EventArgs e)
\r
750 if (string.IsNullOrEmpty(sourcePath) || string.IsNullOrEmpty(text_destination.Text))
\r
751 MessageBox.Show("No source or destination selected.", "Warning", MessageBoxButtons.OK, MessageBoxIcon.Warning);
\r
754 String query = queryGen.GenerateCLIQuery(this, 0, null);
\r
755 if (rtf_query.Text != "")
\r
756 query = rtf_query.Text;
\r
758 if (encodeQueue.CheckForDestinationDuplicate(text_destination.Text))
\r
760 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
761 "Warning", MessageBoxButtons.YesNo, MessageBoxIcon.Warning);
\r
762 if (result == DialogResult.Yes)
\r
763 encodeQueue.AddJob(query, sourcePath, text_destination.Text, (rtf_query.Text != ""));
\r
767 encodeQueue.AddJob(query, sourcePath, text_destination.Text, (rtf_query.Text != ""));
\r
769 lbl_encode.Text = encodeQueue.Count + " encode(s) pending in the queue";
\r
771 queueWindow.Show();
\r
774 private void btn_showQueue_Click(object sender, EventArgs e)
\r
776 queueWindow.Show();
\r
777 queueWindow.Activate();
\r
779 private void tb_preview_Click(object sender, EventArgs e)
\r
781 if (string.IsNullOrEmpty(sourcePath) || string.IsNullOrEmpty(text_destination.Text))
\r
782 MessageBox.Show("No source or destination selected.", "Warning", MessageBoxButtons.OK, MessageBoxIcon.Warning);
\r
785 if (qtpreview == null)
\r
787 qtpreview = new frmPreview(this);
\r
790 else if (qtpreview.IsDisposed)
\r
792 qtpreview = new frmPreview(this);
\r
796 MessageBox.Show(qtpreview, "The preview window is already open!", "Warning", MessageBoxButtons.OK, MessageBoxIcon.Warning);
\r
799 private void btn_ActivityWindow_Click(object sender, EventArgs e)
\r
801 if (ActivityWindow == null || !ActivityWindow.IsHandleCreated)
\r
802 ActivityWindow = new frmActivityWindow(lastAction);
\r
804 switch (lastAction)
\r
807 ActivityWindow.SetScanMode();
\r
810 ActivityWindow.SetEncodeMode();
\r
813 ActivityWindow.SetEncodeMode();
\r
817 ActivityWindow.Show();
\r
818 ActivityWindow.Activate();
\r
822 #region System Tray Icon
\r
823 private void frmMain_Resize(object sender, EventArgs e)
\r
825 if (FormWindowState.Minimized == this.WindowState)
\r
827 notifyIcon.Visible = true;
\r
830 else if (FormWindowState.Normal == this.WindowState)
\r
831 notifyIcon.Visible = false;
\r
833 private void notifyIcon_MouseDoubleClick(object sender, MouseEventArgs e)
\r
835 this.Visible = true;
\r
837 this.WindowState = FormWindowState.Normal;
\r
838 notifyIcon.Visible = false;
\r
840 private void btn_restore_Click(object sender, EventArgs e)
\r
842 this.Visible = true;
\r
844 this.WindowState = FormWindowState.Normal;
\r
845 notifyIcon.Visible = false;
\r
849 #region Tab Control
\r
852 private void btn_dvd_source_Click(object sender, EventArgs e)
\r
854 if (DVD_Open.ShowDialog() == DialogResult.OK)
\r
856 this.selectedSourceType = SourceType.Folder;
\r
857 selectSource(DVD_Open.SelectedPath);
\r
860 UpdateSourceLabel();
\r
862 private void btn_file_source_Click(object sender, EventArgs e)
\r
864 if (ISO_Open.ShowDialog() == DialogResult.OK)
\r
866 this.selectedSourceType = SourceType.VideoFile;
\r
867 selectSource(ISO_Open.FileName);
\r
870 UpdateSourceLabel();
\r
872 private void mnu_dvd_drive_Click(object sender, EventArgs e)
\r
874 if (this.dvdDrivePath == null) return;
\r
875 this.selectedSourceType = SourceType.DvdDrive;
\r
876 selectSource(this.dvdDrivePath);
\r
878 private void selectSource(string file)
\r
880 Check_ChapterMarkers.Enabled = true;
\r
881 lastAction = "scan";
\r
882 sourcePath = string.Empty;
\r
884 if (file == string.Empty) // Must have a file or path
\r
886 UpdateSourceLabel();
\r
890 if (file.StartsWith("\\")) // NO UNC Paths
\r
893 "Sorry, HandBrake does not support UNC file paths. \nTry mounting the share as a network drive in My Computer",
\r
894 "Warning", MessageBoxButtons.OK, MessageBoxIcon.Warning);
\r
895 UpdateSourceLabel();
\r
899 sourcePath = Path.GetFileName(file);
\r
902 private void drp_dvdtitle_Click(object sender, EventArgs e)
\r
904 if ((drp_dvdtitle.Items.Count == 1) && (drp_dvdtitle.Items[0].ToString() == "Automatic"))
\r
905 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
907 private void drp_dvdtitle_SelectedIndexChanged(object sender, EventArgs e)
\r
909 UnRegisterPresetEventHandler();
\r
911 PictureSettings.lbl_Aspect.Text = "Select a Title"; // Reset some values on the form
\r
912 drop_chapterStart.Items.Clear();
\r
913 drop_chapterFinish.Items.Clear();
\r
915 // If the dropdown is set to automatic nothing else needs to be done.
\r
916 // Otheriwse if its not, title data has to be loased from parsing.
\r
917 if (drp_dvdtitle.Text != "Automatic")
\r
919 selectedTitle = drp_dvdtitle.SelectedItem as Title;
\r
920 lbl_duration.Text = selectedTitle.Duration.ToString();
\r
921 PictureSettings.Source = selectedTitle; // Setup Picture Settings Tab Control
\r
923 // Populate the Angles dropdown
\r
924 drop_angle.Items.Clear();
\r
925 if (!Properties.Settings.Default.noDvdNav)
\r
927 drop_angle.Visible = true;
\r
928 lbl_angle.Visible = true;
\r
929 drop_angle.Items.AddRange(selectedTitle.Angles.ToArray());
\r
930 if (drop_angle.Items.Count != 0)
\r
931 drop_angle.SelectedIndex = 0;
\r
935 drop_angle.Visible = false;
\r
936 lbl_angle.Visible = false;
\r
939 // Populate the Start chapter Dropdown
\r
940 drop_chapterStart.Items.Clear();
\r
941 drop_chapterStart.Items.AddRange(selectedTitle.Chapters.ToArray());
\r
942 if (drop_chapterStart.Items.Count > 0)
\r
943 drop_chapterStart.Text = drop_chapterStart.Items[0].ToString();
\r
945 // Populate the Final Chapter Dropdown
\r
946 drop_chapterFinish.Items.Clear();
\r
947 drop_chapterFinish.Items.AddRange(selectedTitle.Chapters.ToArray());
\r
948 if (drop_chapterFinish.Items.Count > 0)
\r
949 drop_chapterFinish.Text = drop_chapterFinish.Items[drop_chapterFinish.Items.Count - 1].ToString();
\r
951 // Populate the Audio Channels Dropdown
\r
952 AudioSettings.SetTrackList(selectedTitle);
\r
954 // Populate the Subtitles dropdown
\r
955 Subtitles.drp_subtitleTracks.Items.Clear();
\r
956 Subtitles.drp_subtitleTracks.Items.Add("Foreign Audio Search (Bitmap)");
\r
957 Subtitles.drp_subtitleTracks.Items.AddRange(selectedTitle.Subtitles.ToArray());
\r
958 Subtitles.drp_subtitleTracks.SelectedIndex = 0;
\r
960 Subtitles.SetSubtitleTrackAuto();
\r
962 // Update the source label if we have multiple streams
\r
963 if (selectedTitle != null)
\r
964 if (!string.IsNullOrEmpty(selectedTitle.SourceName))
\r
965 labelSource.Text = labelSource.Text = Path.GetFileName(selectedTitle.SourceName);
\r
967 // Run the autoName & chapterNaming functions
\r
968 if (Properties.Settings.Default.autoNaming)
\r
970 string autoPath = Main.autoName(this);
\r
971 if (autoPath != null)
\r
972 text_destination.Text = autoPath;
\r
974 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
977 data_chpt.Rows.Clear();
\r
978 if (selectedTitle.Chapters.Count != 1)
\r
980 DataGridView chapterGridView = Main.chapterNaming(data_chpt, drop_chapterFinish.Text);
\r
981 if (chapterGridView != null)
\r
982 data_chpt = chapterGridView;
\r
986 Check_ChapterMarkers.Checked = false;
\r
987 Check_ChapterMarkers.Enabled = false;
\r
990 // Hack to force the redraw of the scrollbars which don't resize properly when the control is disabled.
\r
991 data_chpt.Columns[0].Width = 166;
\r
992 data_chpt.Columns[0].Width = 165;
\r
994 RegisterPresetEventHandler();
\r
996 private void chapersChanged(object sender, EventArgs e)
\r
998 Control ctl = (Control)sender;
\r
999 int chapterStart, chapterEnd;
\r
1000 int.TryParse(drop_chapterStart.Text, out chapterStart);
\r
1001 int.TryParse(drop_chapterFinish.Text, out chapterEnd);
\r
1005 case "drop_chapterStart":
\r
1006 if (drop_chapterFinish.SelectedIndex == -1 && drop_chapterFinish.Items.Count != 0)
\r
1007 drop_chapterFinish.SelectedIndex = drop_chapterFinish.Items.Count - 1;
\r
1009 if (chapterEnd != 0)
\r
1010 if (chapterStart > chapterEnd)
\r
1011 drop_chapterFinish.Text = chapterStart.ToString();
\r
1013 case "drop_chapterFinish":
\r
1014 if (drop_chapterStart.Items.Count >= 1 && drop_chapterStart.SelectedIndex == -1)
\r
1015 drop_chapterStart.SelectedIndex = 0;
\r
1017 if (chapterStart != 0)
\r
1018 if (chapterEnd < chapterStart)
\r
1019 drop_chapterFinish.Text = chapterStart.ToString();
\r
1021 // Add more rows to the Chapter menu if needed.
\r
1022 if (Check_ChapterMarkers.Checked)
\r
1024 int i = data_chpt.Rows.Count, finish = 0;
\r
1025 int.TryParse(drop_chapterFinish.Text, out finish);
\r
1027 while (i < finish)
\r
1029 int n = data_chpt.Rows.Add();
\r
1030 data_chpt.Rows[n].Cells[0].Value = (i + 1);
\r
1031 data_chpt.Rows[n].Cells[1].Value = "Chapter " + (i + 1);
\r
1032 data_chpt.Rows[n].Cells[0].ValueType = typeof(int);
\r
1033 data_chpt.Rows[n].Cells[1].ValueType = typeof(string);
\r
1040 // Update the Duration
\r
1041 lbl_duration.Text = Main.calculateDuration(drop_chapterStart.SelectedIndex, drop_chapterFinish.SelectedIndex, selectedTitle).ToString();
\r
1043 // Run the Autonaming function
\r
1044 if (Properties.Settings.Default.autoNaming)
\r
1045 text_destination.Text = Main.autoName(this);
\r
1047 // Disable chapter markers if only 1 chapter is selected.
\r
1048 if (chapterStart == chapterEnd)
\r
1050 Check_ChapterMarkers.Enabled = false;
\r
1051 btn_importChapters.Enabled = false;
\r
1052 data_chpt.Enabled = false;
\r
1056 Check_ChapterMarkers.Enabled = true;
\r
1057 if (Check_ChapterMarkers.Checked)
\r
1059 btn_importChapters.Enabled = true;
\r
1060 data_chpt.Enabled = true;
\r
1066 private void btn_destBrowse_Click(object sender, EventArgs e)
\r
1068 // This removes the file extension from the filename box on the save file dialog.
\r
1069 // It's daft but some users don't realise that typing an extension overrides the dropdown extension selected.
\r
1070 DVD_Save.FileName = Path.GetFileNameWithoutExtension(text_destination.Text);
\r
1072 if (Path.IsPathRooted(text_destination.Text))
\r
1073 DVD_Save.InitialDirectory = Path.GetDirectoryName(text_destination.Text);
\r
1075 // Show the dialog and set the main form file path
\r
1076 if (drop_format.SelectedIndex.Equals(0))
\r
1077 DVD_Save.FilterIndex = 1;
\r
1078 else if (drop_format.SelectedIndex.Equals(1))
\r
1079 DVD_Save.FilterIndex = 2;
\r
1081 if (DVD_Save.ShowDialog() == DialogResult.OK)
\r
1083 if (DVD_Save.FileName.StartsWith("\\"))
\r
1084 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
1087 // Add a file extension manually, as FileDialog.AddExtension has issues with dots in filenames
\r
1088 switch (DVD_Save.FilterIndex)
\r
1091 if (!Path.GetExtension(DVD_Save.FileName).Equals(".mp4", StringComparison.InvariantCultureIgnoreCase))
\r
1092 if (Properties.Settings.Default.useM4v)
\r
1093 DVD_Save.FileName = DVD_Save.FileName.Replace(".mp4", ".m4v").Replace(".mkv", ".m4v");
\r
1095 DVD_Save.FileName = DVD_Save.FileName.Replace(".m4v", ".mp4").Replace(".mkv", ".mp4");
\r
1098 if (!Path.GetExtension(DVD_Save.FileName).Equals(".mkv", StringComparison.InvariantCultureIgnoreCase))
\r
1099 DVD_Save.FileName = DVD_Save.FileName.Replace(".mp4", ".mkv").Replace(".m4v", ".mkv");
\r
1105 text_destination.Text = DVD_Save.FileName;
\r
1107 // Quicktime requires .m4v file for chapter markers to work. If checked, change the extension to .m4v (mp4 and m4v are the same thing)
\r
1108 if (Check_ChapterMarkers.Checked && DVD_Save.FilterIndex != 2)
\r
1109 SetExtension(".m4v");
\r
1113 private void text_destination_TextChanged(object sender, EventArgs e)
\r
1115 string path = text_destination.Text;
\r
1116 if (path.EndsWith(".mp4") || path.EndsWith(".m4v"))
\r
1117 drop_format.SelectedIndex = 0;
\r
1118 else if (path.EndsWith(".mkv"))
\r
1119 drop_format.SelectedIndex = 1;
\r
1122 // Output Settings
\r
1123 private void drop_format_SelectedIndexChanged(object sender, EventArgs e)
\r
1125 switch (drop_format.SelectedIndex)
\r
1128 if (Properties.Settings.Default.useM4v || Check_ChapterMarkers.Checked || AudioSettings.RequiresM4V() || Subtitles.RequiresM4V())
\r
1129 SetExtension(".m4v");
\r
1131 SetExtension(".mp4");
\r
1134 SetExtension(".mkv");
\r
1138 AudioSettings.SetContainer(drop_format.Text);
\r
1139 Subtitles.SetContainer(drop_format.SelectedIndex);
\r
1141 if (drop_format.Text.Contains("MP4"))
\r
1143 if (drp_videoEncoder.Items.Contains("VP3 (Theora)"))
\r
1145 drp_videoEncoder.Items.Remove("VP3 (Theora)");
\r
1146 drp_videoEncoder.SelectedIndex = 1;
\r
1149 else if (drop_format.Text.Contains("MKV"))
\r
1150 drp_videoEncoder.Items.Add("VP3 (Theora)");
\r
1152 public void SetExtension(string newExtension)
\r
1154 if (newExtension == ".mp4" || newExtension == ".m4v")
\r
1155 if (Properties.Settings.Default.useM4v || Check_ChapterMarkers.Checked || AudioSettings.RequiresM4V() || Subtitles.RequiresM4V())
\r
1156 newExtension = ".m4v";
\r
1158 newExtension = ".mp4";
\r
1160 if (Path.HasExtension(newExtension))
\r
1161 text_destination.Text = Path.ChangeExtension(text_destination.Text, newExtension);
\r
1165 private void drp_videoEncoder_SelectedIndexChanged(object sender, EventArgs e)
\r
1167 setContainerOpts();
\r
1169 //Turn off some options which are H.264 only when the user selects a non h.264 encoder
\r
1170 if (drp_videoEncoder.Text.Contains("H.264"))
\r
1172 if (check_2PassEncode.CheckState == CheckState.Checked)
\r
1173 check_turbo.Enabled = true;
\r
1175 tab_advanced.Enabled = true;
\r
1176 if ((drop_format.Text.Contains("MP4")) || (drop_format.Text.Contains("M4V")))
\r
1177 check_iPodAtom.Enabled = true;
\r
1179 check_iPodAtom.Enabled = false;
\r
1183 check_turbo.CheckState = CheckState.Unchecked;
\r
1184 check_turbo.Enabled = false;
\r
1185 tab_advanced.Enabled = false;
\r
1186 x264Panel.x264Query = "";
\r
1187 check_iPodAtom.Enabled = false;
\r
1188 check_iPodAtom.Checked = false;
\r
1191 // Setup the CQ Slider
\r
1192 switch (drp_videoEncoder.Text)
\r
1194 case "MPEG-4 (FFmpeg)":
\r
1195 if (slider_videoQuality.Value > 31)
\r
1196 slider_videoQuality.Value = 20; // Just reset to 70% QP 10 on encode change.
\r
1197 slider_videoQuality.Minimum = 1;
\r
1198 slider_videoQuality.Maximum = 31;
\r
1200 case "H.264 (x264)":
\r
1201 slider_videoQuality.Minimum = 0;
\r
1202 slider_videoQuality.TickFrequency = 1;
\r
1204 CultureInfo culture = CultureInfo.CreateSpecificCulture("en-US");
\r
1205 double cqStep = Properties.Settings.Default.x264cqstep;
\r
1206 double multiplier = 1.0 / cqStep;
\r
1207 double value = slider_videoQuality.Value * multiplier;
\r
1209 switch (Properties.Settings.Default.x264cqstep.ToString(culture))
\r
1212 slider_videoQuality.Maximum = 255;
\r
1215 slider_videoQuality.Maximum = 204;
\r
1218 slider_videoQuality.Maximum = 102;
\r
1221 slider_videoQuality.Maximum = 51;
\r
1224 slider_videoQuality.Maximum = 51;
\r
1227 if (value < slider_videoQuality.Maximum)
\r
1228 slider_videoQuality.Value = slider_videoQuality.Maximum - (int)value;
\r
1231 case "VP3 (Theora)":
\r
1232 if (slider_videoQuality.Value > 63)
\r
1233 slider_videoQuality.Value = 45; // Just reset to 70% QP 45 on encode change.
\r
1234 slider_videoQuality.Minimum = 0;
\r
1235 slider_videoQuality.Maximum = 63;
\r
1240 /// Set the container format options
\r
1242 public void setContainerOpts()
\r
1244 if ((drop_format.Text.Contains("MP4")) || (drop_format.Text.Contains("M4V")))
\r
1246 check_largeFile.Enabled = true;
\r
1247 check_optimiseMP4.Enabled = true;
\r
1248 check_iPodAtom.Enabled = true;
\r
1252 check_largeFile.Enabled = false;
\r
1253 check_optimiseMP4.Enabled = false;
\r
1254 check_iPodAtom.Enabled = false;
\r
1255 check_largeFile.Checked = false;
\r
1256 check_optimiseMP4.Checked = false;
\r
1257 check_iPodAtom.Checked = false;
\r
1260 private double _cachedCqStep = Properties.Settings.Default.x264cqstep;
\r
1262 /// Update the CQ slider for x264 for a new CQ step. This is set from option
\r
1264 public void setQualityFromSlider()
\r
1266 // Work out the current RF value.
\r
1267 double cqStep = _cachedCqStep;
\r
1268 double rfValue = 51.0 - slider_videoQuality.Value * cqStep;
\r
1270 // Change the maximum value for the slider
\r
1271 switch (Properties.Settings.Default.x264cqstep.ToString(new CultureInfo("en-US")))
\r
1274 slider_videoQuality.Maximum = 255;
\r
1277 slider_videoQuality.Maximum = 204;
\r
1280 slider_videoQuality.Maximum = 102;
\r
1283 slider_videoQuality.Maximum = 51;
\r
1286 slider_videoQuality.Maximum = 51;
\r
1290 // Reset the CQ slider to RF0
\r
1291 slider_videoQuality.Value = slider_videoQuality.Maximum;
\r
1293 // Reset the CQ slider back to the previous value as close as possible
\r
1294 double cqStepNew = Properties.Settings.Default.x264cqstep;
\r
1295 double rfValueCurrent = 51.0 - slider_videoQuality.Value * cqStepNew;
\r
1296 while (rfValueCurrent < rfValue)
\r
1298 slider_videoQuality.Value--;
\r
1299 rfValueCurrent = 51.0 - slider_videoQuality.Value * cqStepNew;
\r
1302 // Cache the CQ step for the next calculation
\r
1303 _cachedCqStep = Properties.Settings.Default.x264cqstep;
\r
1305 private void slider_videoQuality_Scroll(object sender, EventArgs e)
\r
1307 double cqStep = Properties.Settings.Default.x264cqstep;
\r
1308 switch (drp_videoEncoder.Text)
\r
1310 case "MPEG-4 (FFmpeg)":
\r
1311 double rfValue = 31 - (slider_videoQuality.Value - 1);
\r
1312 double max = slider_videoQuality.Maximum;
\r
1313 double min = slider_videoQuality.Minimum;
\r
1314 double val = ((max - min) - (rfValue - min)) / (max - min);
\r
1315 lbl_SliderValue.Text = "QP:" + (32 - slider_videoQuality.Value);
\r
1316 lbl_QualityValue.Text = Math.Round((val * 100), 2).ToString(new CultureInfo("en-US")) + "%";
\r
1318 case "H.264 (x264)":
\r
1319 rfValue = 51.0 - slider_videoQuality.Value * cqStep;
\r
1320 max = slider_videoQuality.Maximum * cqStep;
\r
1321 min = slider_videoQuality.Minimum;
\r
1322 val = ((max - min) - (rfValue - min)) / (max - min);
\r
1323 rfValue = Math.Round(rfValue, 2);
\r
1324 lbl_SliderValue.Text = "RF:" + rfValue.ToString(new CultureInfo("en-US"));
\r
1325 lbl_QualityValue.Text = Math.Round((val * 100), 2).ToString(new CultureInfo("en-US")) + "%";
\r
1327 case "VP3 (Theora)":
\r
1328 rfValue = slider_videoQuality.Value;
\r
1329 double value = rfValue / 63;
\r
1330 lbl_SliderValue.Text = "QP:" + slider_videoQuality.Value;
\r
1331 lbl_QualityValue.Text = Math.Round((value * 100), 2).ToString(new CultureInfo("en-US")) + "%";
\r
1335 private void radio_targetFilesize_CheckedChanged(object sender, EventArgs e)
\r
1337 text_bitrate.Enabled = false;
\r
1338 text_filesize.Enabled = true;
\r
1339 slider_videoQuality.Enabled = false;
\r
1341 check_2PassEncode.Enabled = true;
\r
1343 private void radio_avgBitrate_CheckedChanged(object sender, EventArgs e)
\r
1345 text_bitrate.Enabled = true;
\r
1346 text_filesize.Enabled = false;
\r
1347 slider_videoQuality.Enabled = false;
\r
1349 check_2PassEncode.Enabled = true;
\r
1351 private void radio_cq_CheckedChanged(object sender, EventArgs e)
\r
1353 text_bitrate.Enabled = false;
\r
1354 text_filesize.Enabled = false;
\r
1355 slider_videoQuality.Enabled = true;
\r
1357 check_2PassEncode.Enabled = false;
\r
1358 check_2PassEncode.CheckState = CheckState.Unchecked;
\r
1360 private void check_2PassEncode_CheckedChanged(object sender, EventArgs e)
\r
1362 if (check_2PassEncode.CheckState.ToString() == "Checked")
\r
1364 if (drp_videoEncoder.Text.Contains("H.264"))
\r
1365 check_turbo.Enabled = true;
\r
1369 check_turbo.Enabled = false;
\r
1370 check_turbo.CheckState = CheckState.Unchecked;
\r
1374 // Chapter Marker Tab
\r
1375 private void Check_ChapterMarkers_CheckedChanged(object sender, EventArgs e)
\r
1377 if (Check_ChapterMarkers.Checked)
\r
1379 if (drop_format.SelectedIndex != 1)
\r
1380 SetExtension(".m4v");
\r
1381 data_chpt.Enabled = true;
\r
1382 btn_importChapters.Enabled = true;
\r
1386 if (drop_format.SelectedIndex != 1 && !Properties.Settings.Default.useM4v)
\r
1387 SetExtension(".mp4");
\r
1388 data_chpt.Enabled = false;
\r
1389 btn_importChapters.Enabled = false;
\r
1392 private void btn_importChapters_Click(object sender, EventArgs e)
\r
1394 if (File_ChapterImport.ShowDialog() == DialogResult.OK)
\r
1396 String filename = File_ChapterImport.FileName;
\r
1397 DataGridView imported = Main.importChapterNames(data_chpt, filename);
\r
1398 if (imported != null)
\r
1399 data_chpt = imported;
\r
1402 private void mnu_resetChapters_Click(object sender, EventArgs e)
\r
1404 data_chpt.Rows.Clear();
\r
1405 DataGridView chapterGridView = Main.chapterNaming(data_chpt, drop_chapterFinish.Text);
\r
1406 if (chapterGridView != null)
\r
1408 data_chpt = chapterGridView;
\r
1412 // Query Editor Tab
\r
1413 private void btn_generate_Query_Click(object sender, EventArgs e)
\r
1415 rtf_query.Text = queryGen.GenerateCLIQuery(this, 0, null);
\r
1417 private void btn_clear_Click(object sender, EventArgs e)
\r
1419 rtf_query.Clear();
\r
1423 // MainWindow Components, Actions and Functions ***********************
\r
1425 #region Source Scan
\r
1426 public Boolean isScanning { get; set; }
\r
1427 private Scan SourceScan;
\r
1429 private void StartScan(String filename)
\r
1431 // Setup the GUI components for the scan.
\r
1432 sourcePath = filename;
\r
1433 foreach (Control ctrl in Controls)
\r
1434 if (!(ctrl is StatusStrip || ctrl is MenuStrip || ctrl is ToolStrip))
\r
1435 ctrl.Enabled = false;
\r
1437 lbl_encode.Visible = true;
\r
1438 lbl_encode.Text = "Scanning ...";
\r
1439 btn_source.Enabled = false;
\r
1440 btn_start.Enabled = false;
\r
1441 btn_showQueue.Enabled = false;
\r
1442 btn_add2Queue.Enabled = false;
\r
1443 tb_preview.Enabled = false;
\r
1444 mnu_killCLI.Visible = true;
\r
1446 if (ActivityWindow != null)
\r
1447 ActivityWindow.SetScanMode();
\r
1452 // if (ActivityWindow != null)
\r
1453 // ActivityWindow.SetupLogViewer(true);
\r
1454 isScanning = true;
\r
1455 SourceScan = new Scan();
\r
1456 SourceScan.ScanSource(sourcePath);
\r
1457 SourceScan.ScanStatusChanged += new EventHandler(SourceScan_ScanStatusChanged);
\r
1458 SourceScan.ScanCompleted += new EventHandler(SourceScan_ScanCompleted);
\r
1460 catch (Exception exc)
\r
1462 MessageBox.Show("frmMain.cs - StartScan " + exc, "Error", MessageBoxButtons.OK, MessageBoxIcon.Error);
\r
1466 void SourceScan_ScanStatusChanged(object sender, EventArgs e)
\r
1468 UpdateScanStatusLabel();
\r
1470 void SourceScan_ScanCompleted(object sender, EventArgs e)
\r
1472 UpdateGuiAfterScan();
\r
1475 private void UpdateScanStatusLabel()
\r
1477 if (InvokeRequired)
\r
1479 BeginInvoke(new UpdateWindowHandler(UpdateScanStatusLabel));
\r
1482 lbl_encode.Text = SourceScan.ScanStatus();
\r
1484 private void UpdateGuiAfterScan()
\r
1486 if (InvokeRequired)
\r
1488 BeginInvoke(new UpdateWindowHandler(UpdateGuiAfterScan));
\r
1494 DVD thisDVD = SourceScan.SouceData();
\r
1496 // Setup some GUI components
\r
1497 drp_dvdtitle.Items.Clear();
\r
1498 if (thisDVD.Titles.Count != 0)
\r
1499 drp_dvdtitle.Items.AddRange(thisDVD.Titles.ToArray());
\r
1501 // Now select the longest title
\r
1502 if (thisDVD.Titles.Count != 0)
\r
1503 drp_dvdtitle.SelectedItem = Main.selectLongestTitle(thisDVD);
\r
1505 // Enable the creation of chapter markers if the file is an image of a dvd.
\r
1506 if (sourcePath.ToLower().Contains(".iso") || sourcePath.Contains("VIDEO_TS"))
\r
1507 Check_ChapterMarkers.Enabled = true;
\r
1510 Check_ChapterMarkers.Enabled = false;
\r
1511 Check_ChapterMarkers.Checked = false;
\r
1512 data_chpt.Rows.Clear();
\r
1515 // If no titles were found, Display an error message
\r
1516 if (drp_dvdtitle.Items.Count == 0)
\r
1519 "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
1520 "Error", MessageBoxButtons.OK, MessageBoxIcon.Hand);
\r
1521 sourcePath = string.Empty;
\r
1523 UpdateSourceLabel();
\r
1525 // Enable the GUI components and enable any disabled components
\r
1528 catch (Exception exc)
\r
1530 MessageBox.Show("frmMain.cs - updateUIafterScan " + exc, "Error", MessageBoxButtons.OK, MessageBoxIcon.Error);
\r
1535 private void EnableGUI()
\r
1539 if (InvokeRequired)
\r
1540 BeginInvoke(new UpdateWindowHandler(EnableGUI));
\r
1541 lbl_encode.Text = "Scan Completed";
\r
1542 foreach (Control ctrl in Controls)
\r
1543 ctrl.Enabled = true;
\r
1544 btn_start.Enabled = true;
\r
1545 btn_showQueue.Enabled = true;
\r
1546 btn_add2Queue.Enabled = true;
\r
1547 tb_preview.Enabled = true;
\r
1548 btn_source.Enabled = true;
\r
1549 mnu_killCLI.Visible = false;
\r
1551 catch (Exception exc)
\r
1553 MessageBox.Show("frmMain.cs - EnableGUI() " + exc, "Error", MessageBoxButtons.OK, MessageBoxIcon.Error);
\r
1556 private void KillScan()
\r
1560 SourceScan.ScanCompleted -= new EventHandler(SourceScan_ScanCompleted);
\r
1564 if (SourceScan.ScanProcess() != null)
\r
1565 SourceScan.ScanProcess().Kill();
\r
1567 lbl_encode.Text = "Scan Cancelled!";
\r
1569 catch (Exception ex)
\r
1571 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
1574 private void ResetGUI()
\r
1576 drp_dvdtitle.Items.Clear();
\r
1577 drop_chapterStart.Items.Clear();
\r
1578 drop_chapterFinish.Items.Clear();
\r
1579 lbl_duration.Text = "Select a Title";
\r
1580 PictureSettings.lbl_src_res.Text = "Select a Title";
\r
1581 PictureSettings.lbl_Aspect.Text = "Select a Title";
\r
1582 sourcePath = String.Empty;
\r
1583 text_destination.Text = String.Empty;
\r
1584 selectedTitle = null;
\r
1585 isScanning = false;
\r
1587 private void UpdateSourceLabel()
\r
1589 labelSource.Text = string.IsNullOrEmpty(sourcePath) ? "Select \"Source\" to continue." : this.SourceName;
\r
1591 if (selectedTitle != null)
\r
1592 if (!string.IsNullOrEmpty(selectedTitle.SourceName)) // If it's one of multiple source files, make sure we don't use the folder name
\r
1593 labelSource.Text = Path.GetFileName(selectedTitle.SourceName);
\r
1599 /// Set the GUI to it's finished encoding state.
\r
1601 private void setEncodeFinished()
\r
1605 if (InvokeRequired)
\r
1607 BeginInvoke(new UpdateWindowHandler(setEncodeFinished));
\r
1611 lbl_encode.Text = "Encoding Finished";
\r
1612 btn_start.Text = "Start";
\r
1613 btn_start.ToolTipText = "Start the encoding process";
\r
1614 btn_start.Image = Properties.Resources.Play;
\r
1616 // If the window is minimized, display the notification in a popup.
\r
1617 if (Properties.Settings.Default.trayIconAlerts)
\r
1618 if (FormWindowState.Minimized == this.WindowState)
\r
1620 notifyIcon.BalloonTipText = lbl_encode.Text;
\r
1621 notifyIcon.ShowBalloonTip(500);
\r
1624 catch (Exception exc)
\r
1626 MessageBox.Show(exc.ToString());
\r
1631 /// Set the GUI to it's started encoding state.
\r
1633 private void setEncodeStarted()
\r
1637 if (InvokeRequired)
\r
1639 BeginInvoke(new UpdateWindowHandler(setEncodeStarted));
\r
1643 lbl_encode.Visible = true;
\r
1644 lbl_encode.Text = "Encoding with " + encodeQueue.Count + " encode(s) pending";
\r
1645 btn_start.Text = "Stop";
\r
1646 btn_start.ToolTipText = "Stop the encoding process.";
\r
1647 btn_start.Image = Properties.Resources.stop;
\r
1649 catch (Exception exc)
\r
1651 MessageBox.Show(exc.ToString());
\r
1656 #region DVD Drive Detection
\r
1657 private void getDriveInfoThread()
\r
1661 if (InvokeRequired)
\r
1663 BeginInvoke(new UpdateWindowHandler(getDriveInfoThread));
\r
1667 Boolean foundDrive = false;
\r
1668 DriveInfo[] theCollectionOfDrives = DriveInfo.GetDrives();
\r
1669 foreach (DriveInfo curDrive in theCollectionOfDrives)
\r
1671 if (curDrive.DriveType == DriveType.CDRom && curDrive.IsReady)
\r
1673 if (File.Exists(curDrive.RootDirectory + "VIDEO_TS\\VIDEO_TS.IFO"))
\r
1675 this.dvdDrivePath = curDrive.RootDirectory + "VIDEO_TS";
\r
1676 this.dvdDriveLabel = curDrive.VolumeLabel;
\r
1677 mnu_dvd_drive.Text = this.dvdDrivePath + " (" + this.dvdDriveLabel + ")";
\r
1678 foundDrive = true;
\r
1684 if (foundDrive == false)
\r
1685 mnu_dvd_drive.Text = "[No DVD Drive Ready]";
\r
1689 mnu_dvd_drive.Text = "[No DVD Drive Ready / Found]";
\r
1694 #region Public Methods
\r
1696 /// Access the preset Handler and setup the preset panel.
\r
1698 public void loadPresetPanel()
\r
1700 if (presetHandler.CheckIfPresetsAreOutOfDate())
\r
1701 if (!Properties.Settings.Default.presetNotification)
\r
1702 MessageBox.Show(splash,
\r
1703 "HandBrake has determined your built-in presets are out of date... These presets will now be updated.",
\r
1704 "Preset Update", MessageBoxButtons.OK, MessageBoxIcon.Information);
\r
1706 presetHandler.GetPresetPanel(ref treeView_presets);
\r
1707 treeView_presets.Update();
\r
1713 /// If the queue is being processed, prompt the user to confirm application close.
\r
1715 /// <param name="e"></param>
\r
1716 protected override void OnFormClosing(FormClosingEventArgs e)
\r
1718 // If currently encoding, the queue isn't paused, and there are queue items to process, prompt to confirm close.
\r
1719 if ((encodeQueue.isEncoding) && (!encodeQueue.PauseRequested) && (encodeQueue.Count > 0))
\r
1721 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
1722 "Close HandBrake?", MessageBoxButtons.YesNo, MessageBoxIcon.Question);
\r
1723 if (result == DialogResult.No)
\r
1726 base.OnFormClosing(e);
\r
1730 #region In-GUI Encode Status (Experimental)
\r
1731 private void encodeMonitorThread()
\r
1735 Parser encode = new Parser(encodeQueue.hbProcess.StandardOutput.BaseStream);
\r
1736 encode.OnEncodeProgress += encodeOnEncodeProgress;
\r
1737 while (!encode.EndOfStream)
\r
1738 encode.readEncodeStatus();
\r
1740 catch (Exception exc)
\r
1742 MessageBox.Show(exc.ToString(), "Error", MessageBoxButtons.OK, MessageBoxIcon.Error);
\r
1745 private void encodeOnEncodeProgress(object Sender, int CurrentTask, int TaskCount, float PercentComplete, float CurrentFps, float AverageFps, TimeSpan TimeRemaining)
\r
1747 if (this.InvokeRequired)
\r
1749 this.BeginInvoke(new EncodeProgressEventHandler(encodeOnEncodeProgress),
\r
1750 new object[] { Sender, CurrentTask, TaskCount, PercentComplete, CurrentFps, AverageFps, TimeRemaining });
\r
1753 lbl_encode.Text = string.Format("Encode Progress: {0}%, FPS: {1}, Avg FPS: {2}, Time Remaining: {3} ", PercentComplete, CurrentFps, AverageFps, TimeRemaining);
\r
1758 private enum SourceType
\r
1767 // This is the END of the road ****************************************
\r