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.Windows.Forms;
\r
12 using System.Diagnostics;
\r
13 using System.Threading;
\r
14 using Handbrake.Functions;
\r
15 using Handbrake.Presets;
\r
16 using Handbrake.Queue;
\r
17 using Handbrake.Parsing;
\r
21 public partial class frmMain : Form
\r
23 // Objects which may be used by one or more other objects
\r
24 QueueHandler encodeQueue = new QueueHandler();
\r
25 PresetsHandler presetHandler = new PresetsHandler();
\r
26 QueryGenerator queryGen = new QueryGenerator();
\r
28 // Globals: Mainly used for tracking.
\r
29 Title selectedTitle;
\r
31 private frmQueue queueWindow;
\r
32 private frmPreview qtpreview;
\r
33 private Form splash;
\r
34 public int maxWidth;
\r
35 public int maxHeight;
\r
38 private delegate void UpdateWindowHandler();
\r
39 private delegate void UpdateStatusChanger();
\r
41 // Applicaiton Startup ************************************************
\r
43 #region Application Startup
\r
46 // Load and setup the splash screen in this thread
\r
47 splash = new frmSplashScreen();
\r
49 Label lblStatus = new Label { Size = new Size(250, 20), Location = new Point(10, 280) };
\r
50 splash.Controls.Add(lblStatus);
\r
52 InitializeComponent();
\r
54 // Update the users config file with the CLI version data.
\r
55 lblStatus.Text = "Setting Version Data ...";
\r
56 Application.DoEvents();
\r
57 Main.setCliVersionData();
\r
59 // Show the form, but leave disabled until preloading is complete then show the main form
\r
60 this.Enabled = false;
\r
62 Application.DoEvents(); // Forces frmMain to draw
\r
64 // Check for new versions, if update checking is enabled
\r
65 if (Properties.Settings.Default.updateStatus == "Checked")
\r
67 lblStatus.Text = "Checking for updates ...";
\r
68 Application.DoEvents();
\r
70 Thread updateCheckThread = new Thread(startupUpdateCheck);
\r
71 updateCheckThread.Start();
\r
74 // Setup the GUI components
\r
75 lblStatus.Text = "Setting up the GUI ...";
\r
76 Application.DoEvents();
\r
77 loadPresetPanel(); // Load the Preset Panel
\r
78 treeView_presets.ExpandAll();
\r
79 lbl_encode.Text = "";
\r
81 queueWindow = new frmQueue(encodeQueue); // Prepare the Queue
\r
82 if (Properties.Settings.Default.QueryEditorTab != "Checked")
\r
83 tabs_panel.TabPages.RemoveAt(7); // Remove the query editor tab if the user does not want it enabled.
\r
85 // Load the user's default settings or Normal Preset
\r
86 if (Properties.Settings.Default.defaultSettings == "Checked" && Properties.Settings.Default.defaultPreset != "")
\r
88 if (presetHandler.getPreset(Properties.Settings.Default.defaultPreset) != null)
\r
90 string query = presetHandler.getPreset(Properties.Settings.Default.defaultPreset).Query;
\r
91 Boolean loadPictureSettings = presetHandler.getPreset(Properties.Settings.Default.defaultPreset).PictureSettings;
\r
95 //Ok, Reset all the H264 widgets before changing the preset
\r
96 x264Panel.reset2Defaults();
\r
98 // Send the query from the file to the Query Parser class, then load the preset
\r
99 QueryParser presetQuery = QueryParser.Parse(query);
\r
100 PresetLoader.presetLoader(this, presetQuery, Properties.Settings.Default.defaultPreset, loadPictureSettings);
\r
102 // The x264 widgets will need updated, so do this now:
\r
103 x264Panel.X264_StandardizeOptString();
\r
104 x264Panel.X264_SetCurrentSettingsInPanel();
\r
108 loadNormalPreset();
\r
111 loadNormalPreset();
\r
113 // Enabled GUI tooltip's if Required
\r
114 if (Properties.Settings.Default.tooltipEnable == "Checked")
\r
115 ToolTip.Active = true;
\r
118 lblStatus.Text = "Loading Complete!";
\r
119 Application.DoEvents();
\r
122 this.Enabled = true;
\r
124 // Event Handlers and Queue Recovery
\r
129 // Startup Functions
\r
130 private void startupUpdateCheck()
\r
134 if (InvokeRequired)
\r
136 BeginInvoke(new UpdateStatusChanger(startupUpdateCheck));
\r
140 Boolean update = Main.updateCheck(false);
\r
143 frmUpdater updateWindow = new frmUpdater();
\r
144 updateWindow.Show();
\r
147 catch (Exception exc)
\r
149 MessageBox.Show(splash, "Unable to perform update check. If this problem persists, you can turn of update checking in the program options. \nError Information: \n\n" + exc, "Error", MessageBoxButtons.OK, MessageBoxIcon.Error);
\r
152 private void queueRecovery()
\r
154 if (Main.check_queue_recovery())
\r
156 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
158 if (result == DialogResult.Yes)
\r
159 encodeQueue.recoverQueue("hb_queue_recovery.xml"); // Start Recovery
\r
162 // Remove the Queue recovery file if the user doesn't want to recovery the last queue.
\r
163 string queuePath = Path.Combine(Path.GetTempPath(), "hb_queue_recovery.xml");
\r
164 if (File.Exists(queuePath))
\r
165 File.Delete(queuePath);
\r
172 // Encoding Events for setting up the GUI
\r
173 private void events()
\r
175 // Handle Window Resize
\r
176 if (Properties.Settings.Default.MainWindowMinimize == "Checked")
\r
177 this.Resize += new EventHandler(frmMain_Resize);
\r
179 // Handle Encode Start / Finish / Pause
\r
180 encodeQueue.OnEncodeEnded += new EventHandler(encodeEnded);
\r
181 encodeQueue.OnPaused += new EventHandler(encodePaused);
\r
182 encodeQueue.OnEncodeStart += new EventHandler(encodeStarted);
\r
184 // Handle a file being draged onto the GUI.
\r
185 this.DragEnter += new DragEventHandler(frmMain_DragEnter);
\r
186 this.DragDrop += new DragEventHandler(frmMain_DragDrop);
\r
189 private static void frmMain_DragEnter(object sender, DragEventArgs e)
\r
191 if (e.Data.GetDataPresent(DataFormats.FileDrop, false))
\r
192 e.Effect = DragDropEffects.All;
\r
194 private void frmMain_DragDrop(object sender, DragEventArgs e)
\r
196 string[] fileList = e.Data.GetData(DataFormats.FileDrop) as string[];
\r
197 if (fileList != null)
\r
199 if (fileList[0].StartsWith("\\"))
\r
200 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
203 if (fileList[0] != "")
\r
205 setupGUIforScan(fileList[0]);
\r
206 startScan(fileList[0]);
\r
209 text_source.Text = "Click 'Source' to continue";
\r
213 private void encodeStarted(object sender, EventArgs e)
\r
215 lastAction = "encode";
\r
216 setEncodeStarted();
\r
218 // Experimental HBProc Process Monitoring.
\r
219 if (Properties.Settings.Default.enocdeStatusInGui == "Checked")
\r
221 HBProcess = encodeQueue.hbProc;
\r
222 Thread EncodeMon = new Thread(encodeMonitorThread);
\r
226 private void encodeEnded(object sender, EventArgs e)
\r
228 setEncodeFinished();
\r
230 private void encodePaused(object sender, EventArgs e)
\r
232 setEncodeFinished();
\r
236 // User Interface Menus / Tool Strips *********************************
\r
239 private void mnu_killCLI_Click(object sender, EventArgs e)
\r
243 private void mnu_exit_Click(object sender, EventArgs e)
\r
245 Application.Exit();
\r
250 private void mnu_encode_Click(object sender, EventArgs e)
\r
252 queueWindow.Show();
\r
254 private void mnu_encodeLog_Click(object sender, EventArgs e)
\r
257 file = lastAction == "scan" ? "last_scan_log.txt" : "last_encode_log.txt";
\r
259 frmActivityWindow dvdInfoWindow = new frmActivityWindow(file, encodeQueue, this);
\r
260 dvdInfoWindow.Show();
\r
262 private void mnu_options_Click(object sender, EventArgs e)
\r
264 Form Options = new frmOptions();
\r
265 Options.ShowDialog();
\r
269 #region Presets Menu
\r
270 private void mnu_presetReset_Click(object sender, EventArgs e)
\r
272 presetHandler.updateBuiltInPresets();
\r
274 if (treeView_presets.Nodes.Count == 0)
\r
275 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
277 MessageBox.Show("Presets have been updated!", "Alert", MessageBoxButtons.OK, MessageBoxIcon.Information);
\r
279 treeView_presets.ExpandAll();
\r
281 private void mnu_delete_preset_Click(object sender, EventArgs e)
\r
283 // Empty the preset file
\r
284 string presetsFile = Application.StartupPath + "\\presets.xml";
\r
285 if (File.Exists(presetsFile))
\r
286 File.Delete(presetsFile);
\r
290 FileStream strm = new FileStream(presetsFile, FileMode.Create, FileAccess.Write);
\r
294 catch (Exception exc)
\r
296 MessageBox.Show("An error has occured during the preset removal process.\n If you are using Windows Vista, you may need to run under Administrator Mode to complete this task. \n" + exc);
\r
299 // Reload the preset panel
\r
302 private void mnu_SelectDefault_Click(object sender, EventArgs e)
\r
304 loadNormalPreset();
\r
306 private void btn_new_preset_Click(object sender, EventArgs e)
\r
308 // Remember each nodes expanded status so we can reload it
\r
309 List<Boolean> nodeStatus = saveTreeViewState();
\r
310 nodeStatus.Add(true);
\r
312 Form preset = new frmAddPreset(this, queryGen.GenerateTheQuery(this), presetHandler);
\r
313 preset.ShowDialog();
\r
315 // Now reload the TreeView states
\r
316 loadTreeViewStates(nodeStatus);
\r
321 private void mnu_handbrake_forums_Click(object sender, EventArgs e)
\r
323 Process.Start("http://forum.handbrake.fr/");
\r
325 private void mnu_user_guide_Click(object sender, EventArgs e)
\r
327 Process.Start("http://trac.handbrake.fr/wiki/HandBrakeGuide");
\r
329 private void mnu_handbrake_home_Click(object sender, EventArgs e)
\r
331 Process.Start("http://handbrake.fr");
\r
333 private void mnu_UpdateCheck_Click(object sender, EventArgs e)
\r
335 Boolean update = Main.updateCheck(true);
\r
338 frmUpdater updateWindow = new frmUpdater();
\r
339 updateWindow.Show();
\r
342 MessageBox.Show("There are no new updates at this time.", "Update Check", MessageBoxButtons.OK, MessageBoxIcon.Information);
\r
344 private void mnu_about_Click(object sender, EventArgs e)
\r
346 Form About = new frmAbout();
\r
347 About.ShowDialog();
\r
352 private void mnu_qptest_Click(object sender, EventArgs e)
\r
354 QueryParserTester qptest = new QueryParserTester();
\r
360 // Right Click Menu Code
\r
361 private void pmnu_expandAll_Click(object sender, EventArgs e)
\r
363 treeView_presets.ExpandAll();
\r
365 private void pmnu_collapse_Click(object sender, EventArgs e)
\r
367 treeView_presets.CollapseAll();
\r
369 private void pmnu_saveChanges_Click(object sender, EventArgs e)
\r
371 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
372 if (result == DialogResult.Yes)
\r
373 presetHandler.updatePreset(treeView_presets.SelectedNode.Text, QueryGenerator.generateTabbedComponentsQuery(this), true);
\r
374 else if (result == DialogResult.No)
\r
375 presetHandler.updatePreset(treeView_presets.SelectedNode.Text, QueryGenerator.generateTabbedComponentsQuery(this), false);
\r
377 private void pmnu_delete_click(object sender, EventArgs e)
\r
379 if (treeView_presets.SelectedNode != null)
\r
381 presetHandler.remove(treeView_presets.SelectedNode.Text);
\r
383 // Remember each nodes expanded status so we can reload it
\r
384 List<Boolean> nodeStatus = saveTreeViewState();
\r
386 // Now reload the preset panel
\r
389 // Now reload the TreeView states
\r
390 loadTreeViewStates(nodeStatus);
\r
392 treeView_presets.Select();
\r
394 private void presets_menu_Opening(object sender, System.ComponentModel.CancelEventArgs e)
\r
396 // Make sure that the save menu is always disabled by default
\r
397 pmnu_saveChanges.Enabled = false;
\r
399 // Now enable the save menu if the selected preset is a user preset
\r
400 if (treeView_presets.SelectedNode != null)
\r
402 if (presetHandler.checkIfUserPresetExists(treeView_presets.SelectedNode.Text))
\r
404 pmnu_saveChanges.Enabled = true;
\r
407 treeView_presets.Select();
\r
410 // Presets Management
\r
411 private void btn_addPreset_Click(object sender, EventArgs e)
\r
413 // Remember each nodes expanded status so we can reload it
\r
414 List<Boolean> nodeStatus = saveTreeViewState();
\r
415 nodeStatus.Add(true);
\r
417 // Now add the new preset
\r
418 Form preset = new frmAddPreset(this, QueryGenerator.generateTabbedComponentsQuery(this), presetHandler);
\r
419 preset.ShowDialog();
\r
421 // Now reload the TreeView states
\r
422 loadTreeViewStates(nodeStatus);
\r
424 private void btn_removePreset_Click(object sender, EventArgs e)
\r
426 DialogResult result = MessageBox.Show("Are you sure you wish to delete the selected preset?", "Preset", MessageBoxButtons.YesNo, MessageBoxIcon.Question);
\r
427 if (result == DialogResult.Yes)
\r
429 if (treeView_presets.SelectedNode != null)
\r
430 presetHandler.remove(treeView_presets.SelectedNode.Text);
\r
432 // Remember each nodes expanded status so we can reload it
\r
433 List<Boolean> nodeStatus = saveTreeViewState();
\r
435 // Now reload the preset panel
\r
438 // Now reload the TreeView states
\r
439 loadTreeViewStates(nodeStatus);
\r
441 treeView_presets.Select();
\r
443 private void btn_setDefault_Click(object sender, EventArgs e)
\r
445 if (treeView_presets.SelectedNode != null)
\r
447 DialogResult result = MessageBox.Show("Are you sure you wish to set this preset as the default?", "Preset", MessageBoxButtons.YesNo, MessageBoxIcon.Question);
\r
448 if (result == DialogResult.Yes)
\r
450 Properties.Settings.Default.defaultPreset = treeView_presets.SelectedNode.Text;
\r
451 Properties.Settings.Default.Save();
\r
452 MessageBox.Show("New default preset set.", "Alert", MessageBoxButtons.OK, MessageBoxIcon.Information);
\r
456 MessageBox.Show("Please select a preset first.", "Warning", MessageBoxButtons.OK, MessageBoxIcon.Warning);
\r
458 private void treeview_presets_mouseUp(object sender, MouseEventArgs e)
\r
460 if (e.Button == MouseButtons.Right)
\r
461 treeView_presets.SelectedNode = treeView_presets.GetNodeAt(e.Location);
\r
462 else if (e.Button == MouseButtons.Left)
\r
464 if (treeView_presets.GetNodeAt(e.Location) != null)
\r
466 if (groupBox_output.Text.Contains(treeView_presets.GetNodeAt(e.Location).Text))
\r
471 treeView_presets.Select();
\r
473 private void treeView_presets_AfterSelect(object sender, TreeViewEventArgs e)
\r
477 private void selectPreset()
\r
479 if (treeView_presets.SelectedNode != null)
\r
481 // Ok, so, we've selected a preset. Now we want to load it.
\r
482 string presetName = treeView_presets.SelectedNode.Text;
\r
483 if (presetHandler.getPreset(presetName) != null)
\r
485 string query = presetHandler.getPreset(presetName).Query;
\r
486 Boolean loadPictureSettings = presetHandler.getPreset(presetName).PictureSettings;
\r
490 //Ok, Reset all the H264 widgets before changing the preset
\r
491 x264Panel.reset2Defaults();
\r
493 // Send the query from the file to the Query Parser class
\r
494 QueryParser presetQuery = QueryParser.Parse(query);
\r
496 // Now load the preset
\r
497 PresetLoader.presetLoader(this, presetQuery, presetName, loadPictureSettings);
\r
499 // The x264 widgets will need updated, so do this now:
\r
500 x264Panel.X264_StandardizeOptString();
\r
501 x264Panel.X264_SetCurrentSettingsInPanel();
\r
503 if (maxWidth != 0 && maxHeight != 0)
\r
504 lbl_max.Text = "Max Width / Height";
\r
505 else if (maxWidth != 0)
\r
506 lbl_max.Text = "Max Width";
\r
513 private void treeView_presets_deleteKey(object sender, KeyEventArgs e)
\r
515 if (e.KeyCode == Keys.Delete)
\r
517 DialogResult result = MessageBox.Show("Are you sure you wish to delete the selected preset?", "Preset", MessageBoxButtons.YesNo, MessageBoxIcon.Question);
\r
518 if (result == DialogResult.Yes)
\r
520 if (treeView_presets.SelectedNode != null)
\r
521 presetHandler.remove(treeView_presets.SelectedNode.Text);
\r
523 // Remember each nodes expanded status so we can reload it
\r
524 List<Boolean> nodeStatus = new List<Boolean>();
\r
525 foreach (TreeNode node in treeView_presets.Nodes)
\r
526 nodeStatus.Add(node.IsExpanded);
\r
528 // Now reload the preset panel
\r
531 // And finally, re-expand any of the nodes if required
\r
533 foreach (TreeNode node in treeView_presets.Nodes)
\r
543 private List<Boolean> saveTreeViewState()
\r
545 // Remember each nodes expanded status so we can reload it
\r
546 List<Boolean> nodeStatus = new List<Boolean>();
\r
547 foreach (TreeNode node in treeView_presets.Nodes)
\r
549 nodeStatus.Add(node.IsExpanded);
\r
550 foreach (TreeNode subNode in node.Nodes)
\r
551 nodeStatus.Add(node.IsExpanded);
\r
555 private void loadTreeViewStates(List<Boolean> nodeStatus)
\r
557 // And finally, re-expand any of the nodes if required
\r
559 foreach (TreeNode node in treeView_presets.Nodes)
\r
564 foreach (TreeNode subNode in node.Nodes)
\r
573 private void loadNormalPreset()
\r
575 foreach (TreeNode treenode in treeView_presets.Nodes)
\r
577 foreach (TreeNode node in treenode.Nodes)
\r
579 if (node.Text.Equals("Normal"))
\r
580 treeView_presets.SelectedNode = treeView_presets.Nodes[treenode.Index].Nodes[0];
\r
587 private void btn_source_Click(object sender, EventArgs e)
\r
589 if (Properties.Settings.Default.drive_detection == "Checked")
\r
591 mnu_dvd_drive.Visible = true;
\r
592 Thread driveInfoThread = new Thread(getDriveInfoThread);
\r
593 driveInfoThread.Start();
\r
596 mnu_dvd_drive.Visible = false;
\r
598 private void btn_start_Click(object sender, EventArgs e)
\r
600 if (btn_start.Text == "Stop")
\r
602 DialogResult result = MessageBox.Show("Are you sure you wish to cancel the encode? Please note that this may break the encoded file. \nTo safely cancel your encode, press ctrl-c on your keyboard in the CLI window. This *may* allow you to preview your encoded content.", "Cancel Encode?", MessageBoxButtons.YesNo, MessageBoxIcon.Question);
\r
604 if (result == DialogResult.Yes)
\r
607 encodeQueue.pauseEncode();
\r
608 encodeQueue.endEncode();
\r
611 setEncodeFinished();
\r
616 if (encodeQueue.count() != 0 || (text_source.Text != string.Empty && text_source.Text != "Click 'Source' to continue" && text_destination.Text != string.Empty))
\r
618 // Set the last action to encode.
\r
619 // This is used for tracking which file to load in the activity window
\r
620 lastAction = "encode";
\r
622 String query = rtf_query.Text != "" ? rtf_query.Text : queryGen.GenerateTheQuery(this);
\r
624 if (encodeQueue.count() == 0)
\r
626 encodeQueue.add(query, text_source.Text, text_destination.Text);
\r
627 encodeQueue.write2disk("hb_queue_recovery.xml");
\r
629 queueWindow.setQueue();
\r
630 if (encodeQueue.count() > 1)
\r
631 queueWindow.Show(false);
\r
633 setEncodeStarted(); // Encode is running, so setup the GUI appropriately
\r
634 encodeQueue.startEncode(); // Start The Queue Encoding Process
\r
637 else if (text_source.Text == string.Empty || text_source.Text == "Click 'Source' to continue" || text_destination.Text == string.Empty)
\r
638 MessageBox.Show("No source OR destination selected.", "Warning", MessageBoxButtons.OK, MessageBoxIcon.Warning);
\r
641 private void btn_add2Queue_Click(object sender, EventArgs e)
\r
644 if (text_source.Text == string.Empty || text_source.Text == "Click 'Source' to continue" || text_destination.Text == string.Empty)
\r
645 MessageBox.Show("No source OR destination selected.", "Warning", MessageBoxButtons.OK, MessageBoxIcon.Warning);
\r
648 String query = queryGen.GenerateTheQuery(this);
\r
649 if (rtf_query.Text != "")
\r
650 query = rtf_query.Text;
\r
653 if (encodeQueue.checkDestinationPath(text_destination.Text))
\r
655 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
656 "Warning", MessageBoxButtons.YesNo, MessageBoxIcon.Warning);
\r
657 if (result == DialogResult.Yes)
\r
658 encodeQueue.add(query, text_source.Text, text_destination.Text);
\r
662 encodeQueue.add(query, text_source.Text, text_destination.Text);
\r
664 encodeQueue.write2disk("hb_queue_recovery.xml"); // Writes the queue to the recovery file, just incase the GUI crashes.
\r
665 queueWindow.Show();
\r
668 private void btn_showQueue_Click(object sender, EventArgs e)
\r
670 queueWindow.Show();
\r
672 private void tb_preview_Click(object sender, EventArgs e)
\r
674 if (text_source.Text == "" || text_source.Text == "Click 'Source' to continue" || text_destination.Text == "")
\r
675 MessageBox.Show("No source OR destination selected.", "Warning", MessageBoxButtons.OK, MessageBoxIcon.Warning);
\r
678 if (qtpreview == null)
\r
680 qtpreview = new frmPreview(this);
\r
683 else if (qtpreview.IsDisposed)
\r
685 qtpreview = new frmPreview(this);
\r
689 MessageBox.Show(qtpreview, "The preview window is already open!", "Warning", MessageBoxButtons.OK, MessageBoxIcon.Warning);
\r
692 private void btn_ActivityWindow_Click(object sender, EventArgs e)
\r
694 String file = lastAction == "scan" ? "last_scan_log.txt" : "last_encode_log.txt";
\r
696 frmActivityWindow ActivityWindow = new frmActivityWindow(file, encodeQueue, this);
\r
697 ActivityWindow.Show();
\r
701 #region System Tray Icon
\r
702 private void frmMain_Resize(object sender, EventArgs e)
\r
704 if (FormWindowState.Minimized == this.WindowState)
\r
706 notifyIcon.Visible = true;
\r
707 if (!encodeQueue.isEncoding)
\r
709 notifyIcon.BalloonTipText = lbl_encode.Text != "" ? lbl_encode.Text : "Not Encoding";
\r
710 notifyIcon.ShowBalloonTip(500);
\r
714 else if (FormWindowState.Normal == this.WindowState)
\r
715 notifyIcon.Visible = false;
\r
717 private void notifyIcon_MouseDoubleClick(object sender, MouseEventArgs e)
\r
719 this.Visible = true;
\r
721 this.WindowState = FormWindowState.Normal;
\r
722 notifyIcon.Visible = false;
\r
724 private void btn_restore_Click(object sender, EventArgs e)
\r
726 this.Visible = true;
\r
728 this.WindowState = FormWindowState.Normal;
\r
729 notifyIcon.Visible = false;
\r
733 #region Tab Control
\r
736 private void btn_dvd_source_Click(object sender, EventArgs e)
\r
738 // Enable the creation of chapter markers.
\r
739 Check_ChapterMarkers.Enabled = true;
\r
741 // Set the last action to scan.
\r
742 // This is used for tracking which file to load in the activity window
\r
743 lastAction = "scan";
\r
744 text_source.Text = "";
\r
746 if (DVD_Open.ShowDialog() == DialogResult.OK)
\r
748 String filename = DVD_Open.SelectedPath;
\r
750 if (filename.StartsWith("\\"))
\r
751 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
754 if (filename != "")
\r
756 setupGUIforScan(filename);
\r
757 startScan(filename);
\r
760 text_source.Text = "Click 'Source' to continue";
\r
764 text_source.Text = "Click 'Source' to continue";
\r
766 private void btn_file_source_Click(object sender, EventArgs e)
\r
768 // Set the last action to scan.
\r
769 // This is used for tracking which file to load in the activity window
\r
770 lastAction = "scan";
\r
771 text_source.Text = "";
\r
773 if (ISO_Open.ShowDialog() == DialogResult.OK)
\r
775 String filename = ISO_Open.FileName;
\r
776 if (filename.StartsWith("\\"))
\r
778 "Sorry, HandBrake does not support UNC file paths. \nTry mounting the share as a network drive in My Computer",
\r
779 "Warning", MessageBoxButtons.OK, MessageBoxIcon.Warning);
\r
782 if (filename != "")
\r
784 setupGUIforScan(filename);
\r
785 startScan(filename);
\r
788 text_source.Text = "Click 'Source' to continue";
\r
792 text_source.Text = "Click 'Source' to continue";
\r
794 private void mnu_dvd_drive_Click(object sender, EventArgs e)
\r
796 // Enable the creation of chapter markers.
\r
797 Check_ChapterMarkers.Enabled = true;
\r
799 // Set the last action to scan.
\r
800 // This is used for tracking which file to load in the activity window
\r
801 lastAction = "scan";
\r
803 if (mnu_dvd_drive.Text.Contains("VIDEO_TS"))
\r
805 string[] path = mnu_dvd_drive.Text.Split(' ');
\r
806 String filename = path[0];
\r
807 setupGUIforScan(filename);
\r
808 startScan(filename);
\r
811 // If there are no titles in the dropdown menu then the scan has obviously failed. Display an error message explaining to the user.
\r
812 if (drp_dvdtitle.Items.Count == 0)
\r
813 MessageBox.Show("No Title(s) found. Please make sure you have selected a valid, non-copy protected source.\nYour Source may be copy protected, badly mastered or a format which HandBrake does not support. \nPlease refer to the Documentation and FAQ (see Help Menu).", "Error", MessageBoxButtons.OK, MessageBoxIcon.Hand);
\r
815 lbl_encode.Text = "";
\r
817 private void drp_dvdtitle_Click(object sender, EventArgs e)
\r
819 if ((drp_dvdtitle.Items.Count == 1) && (drp_dvdtitle.Items[0].ToString() == "Automatic"))
\r
820 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
822 private void drp_dvdtitle_SelectedIndexChanged(object sender, EventArgs e)
\r
824 // Reset some values on the form
\r
825 lbl_Aspect.Text = "Select a Title";
\r
826 //lbl_RecomendedCrop.Text = "Select a Title";
\r
827 drop_chapterStart.Items.Clear();
\r
828 drop_chapterFinish.Items.Clear();
\r
830 // If the dropdown is set to automatic nothing else needs to be done.
\r
831 // Otheriwse if its not, title data has to be loased from parsing.
\r
832 if (drp_dvdtitle.Text != "Automatic")
\r
834 selectedTitle = drp_dvdtitle.SelectedItem as Parsing.Title;
\r
836 // Set the Aspect Ratio
\r
837 lbl_Aspect.Text = selectedTitle.AspectRatio.ToString();
\r
838 lbl_src_res.Text = selectedTitle.Resolution.Width + " x " + selectedTitle.Resolution.Height;
\r
839 lbl_duration.Text = selectedTitle.Duration.ToString();
\r
841 // Set the Recommended Cropping values
\r
842 text_top.Text = selectedTitle.AutoCropDimensions[0].ToString();
\r
843 text_bottom.Text = selectedTitle.AutoCropDimensions[1].ToString();
\r
844 text_left.Text = selectedTitle.AutoCropDimensions[2].ToString();
\r
845 text_right.Text = selectedTitle.AutoCropDimensions[3].ToString();
\r
847 // Populate the Angles dropdown
\r
848 drop_angle.Items.Clear();
\r
849 if (Properties.Settings.Default.dvdnav == "Checked")
\r
851 drop_angle.Visible = true;
\r
852 lbl_angle.Visible = true;
\r
853 drop_angle.Items.AddRange(selectedTitle.Angles.ToArray());
\r
854 if (drop_angle.Items.Count != 0)
\r
855 drop_angle.SelectedIndex = 0;
\r
859 drop_angle.Visible = false;
\r
860 lbl_angle.Visible = false;
\r
863 // Populate the Start chapter Dropdown
\r
864 drop_chapterStart.Items.Clear();
\r
865 drop_chapterStart.Items.AddRange(selectedTitle.Chapters.ToArray());
\r
866 if (drop_chapterStart.Items.Count > 0)
\r
867 drop_chapterStart.Text = drop_chapterStart.Items[0].ToString();
\r
869 // Populate the Final Chapter Dropdown
\r
870 drop_chapterFinish.Items.Clear();
\r
871 drop_chapterFinish.Items.AddRange(selectedTitle.Chapters.ToArray());
\r
872 if (drop_chapterFinish.Items.Count > 0)
\r
873 drop_chapterFinish.Text = drop_chapterFinish.Items[drop_chapterFinish.Items.Count - 1].ToString();
\r
875 // Populate the Audio Channels Dropdown
\r
876 audioPanel.setTrackList(selectedTitle);
\r
878 // Populate the Subtitles dropdown
\r
879 drp_subtitle.Items.Clear();
\r
880 drp_subtitle.Items.Add("None");
\r
881 drp_subtitle.Items.Add("Autoselect");
\r
882 drp_subtitle.Items.AddRange(selectedTitle.Subtitles.ToArray());
\r
883 if (drp_subtitle.Items.Count > 0)
\r
884 drp_subtitle.Text = drp_subtitle.Items[0].ToString();
\r
888 // Run the autoName & chapterNaming functions
\r
889 if (Properties.Settings.Default.autoNaming == "Checked")
\r
891 string autoPath = Main.autoName(drp_dvdtitle, drop_chapterStart.Text, drop_chapterFinish.Text, text_source.Text, text_destination.Text, drop_format.SelectedIndex);
\r
892 if (autoPath != null)
\r
893 text_destination.Text = autoPath;
\r
895 MessageBox.Show("You currently have automatic file naming enabled for the destination box, but you do not have a default direcotry set. You should set this in the program options (see Tools Menu)", "Warning", MessageBoxButtons.OK, MessageBoxIcon.Warning);
\r
898 data_chpt.Rows.Clear();
\r
899 if (selectedTitle.Chapters.Count != 1)
\r
901 DataGridView chapterGridView = Main.chapterNaming(data_chpt, drop_chapterFinish.Text);
\r
902 if (chapterGridView != null)
\r
903 data_chpt = chapterGridView;
\r
907 Check_ChapterMarkers.Checked = false;
\r
908 Check_ChapterMarkers.Enabled = false;
\r
911 // Hack to force the redraw of the scrollbars which don't resize properly when the control is disabled.
\r
912 data_chpt.Columns[0].Width = 166;
\r
913 data_chpt.Columns[0].Width = 165;
\r
915 private void drop_chapterStart_SelectedIndexChanged(object sender, EventArgs e)
\r
917 int c_start, c_end;
\r
919 if (drop_chapterFinish.Text == "Auto" && drop_chapterFinish.Items.Count != 0)
\r
920 drop_chapterFinish.SelectedIndex = drop_chapterFinish.Items.Count - 1;
\r
922 int.TryParse(drop_chapterStart.Text, out c_start);
\r
923 int.TryParse(drop_chapterFinish.Text, out c_end);
\r
927 if (c_start > c_end)
\r
928 drop_chapterFinish.Text = c_start.ToString();
\r
931 lbl_duration.Text = Main.calculateDuration(drop_chapterStart.Text, drop_chapterFinish.Text, selectedTitle).ToString();
\r
933 // Run the Autonaming function
\r
934 if (Properties.Settings.Default.autoNaming == "Checked")
\r
935 text_destination.Text = Main.autoName(drp_dvdtitle, drop_chapterStart.Text, drop_chapterFinish.Text, text_source.Text, text_destination.Text, drop_format.SelectedIndex);
\r
937 // Disable chapter markers if only 1 chapter is selected.
\r
938 if (c_start == c_end)
\r
940 Check_ChapterMarkers.Checked = false;
\r
941 Check_ChapterMarkers.Enabled = false;
\r
944 Check_ChapterMarkers.Enabled = true;
\r
946 private void drop_chapterFinish_SelectedIndexChanged(object sender, EventArgs e)
\r
948 int c_start, c_end;
\r
950 if (drop_chapterStart.Text == "Auto" && drop_chapterStart.Items.Count >= 1)
\r
951 drop_chapterStart.SelectedIndex = 1;
\r
953 int.TryParse(drop_chapterStart.Text, out c_start);
\r
954 int.TryParse(drop_chapterFinish.Text, out c_end);
\r
958 if (c_end < c_start)
\r
959 drop_chapterFinish.Text = c_start.ToString();
\r
962 lbl_duration.Text = Main.calculateDuration(drop_chapterStart.Text, drop_chapterFinish.Text, selectedTitle).ToString();
\r
964 // Run the Autonaming function
\r
965 if (Properties.Settings.Default.autoNaming == "Checked")
\r
966 text_destination.Text = Main.autoName(drp_dvdtitle, drop_chapterStart.Text, drop_chapterFinish.Text, text_source.Text, text_destination.Text, drop_format.SelectedIndex);
\r
968 // Add more rows to the Chapter menu if needed.
\r
969 if (Check_ChapterMarkers.Checked)
\r
971 int i = data_chpt.Rows.Count, finish = 0;
\r
973 if (drop_chapterFinish.Text != "Auto")
\r
974 int.TryParse(drop_chapterFinish.Text, out finish);
\r
978 int n = data_chpt.Rows.Add();
\r
979 data_chpt.Rows[n].Cells[0].Value = (i + 1);
\r
980 data_chpt.Rows[n].Cells[1].Value = "Chapter " + (i + 1);
\r
981 data_chpt.Rows[n].Cells[0].ValueType = typeof(int);
\r
982 data_chpt.Rows[n].Cells[1].ValueType = typeof(string);
\r
987 // Disable chapter markers if only 1 chapter is selected.
\r
988 if (c_start == c_end)
\r
990 Check_ChapterMarkers.Checked = false;
\r
991 Check_ChapterMarkers.Enabled = false;
\r
994 Check_ChapterMarkers.Enabled = true;
\r
998 private void btn_destBrowse_Click(object sender, EventArgs e)
\r
1000 // This removes the file extension from the filename box on the save file dialog.
\r
1001 // It's daft but some users don't realise that typing an extension overrides the dropdown extension selected.
\r
1002 DVD_Save.FileName = Path.GetFileNameWithoutExtension(text_destination.Text);
\r
1004 if (Path.IsPathRooted(text_destination.Text))
\r
1005 DVD_Save.InitialDirectory = Path.GetDirectoryName(text_destination.Text);
\r
1007 // Show the dialog and set the main form file path
\r
1008 if (drop_format.SelectedIndex.Equals(0))
\r
1009 DVD_Save.FilterIndex = 1;
\r
1010 else if (drop_format.SelectedIndex.Equals(1))
\r
1011 DVD_Save.FilterIndex = 2;
\r
1012 else if (drop_format.SelectedIndex.Equals(2))
\r
1013 DVD_Save.FilterIndex = 3;
\r
1015 if (DVD_Save.ShowDialog() == DialogResult.OK)
\r
1017 if (DVD_Save.FileName.StartsWith("\\"))
\r
1018 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
1021 // Add a file extension manually, as FileDialog.AddExtension has issues with dots in filenames
\r
1022 switch (DVD_Save.FilterIndex)
\r
1025 if (!Path.GetExtension(DVD_Save.FileName).Equals(".mp4", StringComparison.InvariantCultureIgnoreCase))
\r
1026 DVD_Save.FileName += ".mp4";
\r
1029 if (!Path.GetExtension(DVD_Save.FileName).Equals(".m4v", StringComparison.InvariantCultureIgnoreCase))
\r
1030 DVD_Save.FileName += ".m4v";
\r
1033 if (!Path.GetExtension(DVD_Save.FileName).Equals(".mkv", StringComparison.InvariantCultureIgnoreCase))
\r
1034 DVD_Save.FileName += ".mkv";
\r
1040 text_destination.Text = DVD_Save.FileName;
\r
1042 // Quicktime requires .m4v file for chapter markers to work. If checked, change the extension to .m4v (mp4 and m4v are the same thing)
\r
1043 if (Check_ChapterMarkers.Checked)
\r
1044 drop_format.SelectedIndex = 1;
\r
1048 private void text_destination_TextChanged(object sender, EventArgs e)
\r
1050 string path = text_destination.Text;
\r
1051 if (path.EndsWith(".mp4"))
\r
1052 drop_format.SelectedIndex = 0;
\r
1053 else if (path.EndsWith(".m4v"))
\r
1054 drop_format.SelectedIndex = 1;
\r
1055 else if (path.EndsWith(".mkv"))
\r
1056 drop_format.SelectedIndex = 2;
\r
1059 // Output Settings
\r
1060 private void drop_format_SelectedIndexChanged(object sender, EventArgs e)
\r
1062 if (drop_format.SelectedIndex == 0)
\r
1063 setExtension(".mp4");
\r
1064 else if (drop_format.SelectedIndex == 1)
\r
1065 setExtension(".m4v");
\r
1066 else if (drop_format.SelectedIndex == 2)
\r
1067 setExtension(".mkv");
\r
1069 audioPanel.setAudioByContainer(drop_format.Text);
\r
1070 setVideoByContainer(drop_format.Text);
\r
1072 private void setExtension(string newExtension)
\r
1074 text_destination.Text = text_destination.Text.Replace(".mp4", newExtension);
\r
1075 text_destination.Text = text_destination.Text.Replace(".m4v", newExtension);
\r
1076 text_destination.Text = text_destination.Text.Replace(".mkv", newExtension);
\r
1080 private void drp_videoEncoder_SelectedIndexChanged(object sender, EventArgs e)
\r
1082 setContainerOpts();
\r
1084 //Turn off some options which are H.264 only when the user selects a non h.264 encoder
\r
1085 if (drp_videoEncoder.Text.Contains("H.264"))
\r
1087 if (check_2PassEncode.CheckState == CheckState.Checked)
\r
1088 check_turbo.Enabled = true;
\r
1090 tab_advanced.Enabled = true;
\r
1091 if ((drop_format.Text.Contains("MP4")) || (drop_format.Text.Contains("M4V")))
\r
1092 check_iPodAtom.Enabled = true;
\r
1094 check_iPodAtom.Enabled = false;
\r
1098 check_turbo.CheckState = CheckState.Unchecked;
\r
1099 check_turbo.Enabled = false;
\r
1100 tab_advanced.Enabled = false;
\r
1101 x264Panel.x264Query = "";
\r
1102 check_iPodAtom.Enabled = false;
\r
1103 check_iPodAtom.Checked = false;
\r
1106 // Setup the CQ Slider
\r
1107 switch (drp_videoEncoder.Text)
\r
1109 case "MPEG-4 (FFmpeg)":
\r
1110 slider_videoQuality.Minimum = 1;
\r
1111 slider_videoQuality.Maximum = 31;
\r
1112 slider_videoQuality.Value = 1;
\r
1113 SliderValue.Text = "0% QP: 31.00";
\r
1115 case "H.264 (x264)":
\r
1116 slider_videoQuality.Minimum = 0;
\r
1117 slider_videoQuality.Value = 0;
\r
1118 slider_videoQuality.TickFrequency = 1;
\r
1119 SliderValue.Text = "0% RF: 51.00";
\r
1120 String step = Properties.Settings.Default.x264cqstep;
\r
1124 slider_videoQuality.Maximum = 255;
\r
1127 slider_videoQuality.Maximum = 204;
\r
1130 slider_videoQuality.Maximum = 155;
\r
1133 slider_videoQuality.Maximum = 102;
\r
1136 slider_videoQuality.Maximum = 51;
\r
1139 slider_videoQuality.Maximum = 51;
\r
1143 case "VP3 (Theora)":
\r
1144 slider_videoQuality.Minimum = 0;
\r
1145 slider_videoQuality.Maximum = 63;
\r
1146 slider_videoQuality.Value = 0;
\r
1147 SliderValue.Text = "0% QP: 0.00";
\r
1152 /// Set the container format options
\r
1154 public void setContainerOpts()
\r
1156 if ((text_destination.Text.Contains(".mp4")) || (text_destination.Text.Contains(".m4v")))
\r
1158 check_largeFile.Enabled = true;
\r
1159 check_optimiseMP4.Enabled = true;
\r
1160 check_iPodAtom.Enabled = true;
\r
1164 check_largeFile.Enabled = false;
\r
1165 check_optimiseMP4.Enabled = false;
\r
1166 check_iPodAtom.Enabled = false;
\r
1167 check_largeFile.Checked = false;
\r
1168 check_optimiseMP4.Checked = false;
\r
1169 check_iPodAtom.Checked = false;
\r
1172 private void slider_videoQuality_Scroll(object sender, EventArgs e)
\r
1174 switch (drp_videoEncoder.Text)
\r
1176 case "MPEG-4 (FFmpeg)":
\r
1177 double rfValue = 31 - (slider_videoQuality.Value - 1);
\r
1178 double max = slider_videoQuality.Maximum;
\r
1179 double min = slider_videoQuality.Minimum;
\r
1180 double val = ((max - min) - (rfValue - min)) / (max - min);
\r
1181 SliderValue.Text = Math.Round((val * 100), 2) + "% QP:" + (32 - slider_videoQuality.Value);
\r
1183 case "H.264 (x264)":
\r
1185 System.Globalization.CultureInfo culture = System.Globalization.CultureInfo.CreateSpecificCulture("en-US");
\r
1186 double.TryParse(Properties.Settings.Default.x264cqstep,
\r
1187 System.Globalization.NumberStyles.Number,
\r
1190 rfValue = 51.0 - slider_videoQuality.Value * divided;
\r
1191 max = slider_videoQuality.Maximum * divided;
\r
1192 min = slider_videoQuality.Minimum;
\r
1193 val = ((max - min) - (rfValue - min)) / (max - min);
\r
1194 rfValue = Math.Round(rfValue, 2);
\r
1195 SliderValue.Text = Math.Round((val * 100), 2) + "% RF:" + rfValue;
\r
1197 case "VP3 (Theora)":
\r
1198 rfValue = slider_videoQuality.Value;
\r
1199 double value = rfValue / 63;
\r
1200 SliderValue.Text = Math.Round((value * 100), 2) + "% QP:" + slider_videoQuality.Value;
\r
1204 private void radio_targetFilesize_CheckedChanged(object sender, EventArgs e)
\r
1206 text_bitrate.Enabled = false;
\r
1207 text_filesize.Enabled = true;
\r
1208 slider_videoQuality.Enabled = false;
\r
1210 check_2PassEncode.Enabled = true;
\r
1212 private void radio_avgBitrate_CheckedChanged(object sender, EventArgs e)
\r
1214 text_bitrate.Enabled = true;
\r
1215 text_filesize.Enabled = false;
\r
1216 slider_videoQuality.Enabled = false;
\r
1218 check_2PassEncode.Enabled = true;
\r
1220 private void radio_cq_CheckedChanged(object sender, EventArgs e)
\r
1222 text_bitrate.Enabled = false;
\r
1223 text_filesize.Enabled = false;
\r
1224 slider_videoQuality.Enabled = true;
\r
1226 check_2PassEncode.Enabled = false;
\r
1227 check_2PassEncode.CheckState = CheckState.Unchecked;
\r
1229 private void check_2PassEncode_CheckedChanged(object sender, EventArgs e)
\r
1231 if (check_2PassEncode.CheckState.ToString() == "Checked")
\r
1233 if (drp_videoEncoder.Text.Contains("H.264"))
\r
1234 check_turbo.Enabled = true;
\r
1238 check_turbo.Enabled = false;
\r
1239 check_turbo.CheckState = CheckState.Unchecked;
\r
1244 private void text_width_TextChanged(object sender, EventArgs e)
\r
1246 if (text_width.Text == "")
\r
1247 text_width.BackColor = Color.White;
\r
1249 maxWidth = 0; maxHeight = 0; // Reset max width so that it's not using the MaxWidth -X. Quick hack to allow -X for preset usage.
\r
1250 lbl_max.Text = "";
\r
1253 Boolean parsed = int.TryParse(text_width.Text, out width);
\r
1256 text_width.BackColor = (width % 16) != 0 ? Color.LightCoral : Color.LightGreen;
\r
1258 if (lbl_Aspect.Text != "Select a Title" && maxWidth == 0 && maxHeight == 0)
\r
1260 if (drp_anamorphic.Text == "None")
\r
1262 int height = Main.cacluateNonAnamorphicHeight(width, text_top.Value, text_bottom.Value, text_left.Value, text_right.Value, selectedTitle);
\r
1264 text_height.Text = height.ToString();
\r
1269 private void text_height_TextChanged(object sender, EventArgs e)
\r
1271 if (text_height.Text == "")
\r
1272 text_height.BackColor = Color.White;
\r
1274 maxHeight = 0; // Reset max height so that it's not using the MaxHeight -Y. Quick hack to allow -Y for preset usage.
\r
1275 if (maxWidth != 0)
\r
1276 lbl_max.Text = "Max Width";
\r
1278 lbl_max.Text = "";
\r
1281 Boolean parsed = int.TryParse(text_height.Text, out height);
\r
1283 text_height.BackColor = (height % 16) != 0 ? Color.LightCoral : Color.LightGreen;
\r
1285 private void check_customCrop_CheckedChanged(object sender, EventArgs e)
\r
1287 text_left.Enabled = true;
\r
1288 text_right.Enabled = true;
\r
1289 text_top.Enabled = true;
\r
1290 text_bottom.Enabled = true;
\r
1291 if (selectedTitle != null)
\r
1293 text_top.Text = selectedTitle.AutoCropDimensions[0].ToString();
\r
1294 text_bottom.Text = selectedTitle.AutoCropDimensions[1].ToString();
\r
1295 text_left.Text = selectedTitle.AutoCropDimensions[2].ToString();
\r
1296 text_right.Text = selectedTitle.AutoCropDimensions[3].ToString();
\r
1300 text_left.Text = "0";
\r
1301 text_right.Text = "0";
\r
1302 text_top.Text = "0";
\r
1303 text_bottom.Text = "0";
\r
1306 private void check_autoCrop_CheckedChanged(object sender, EventArgs e)
\r
1308 text_left.Enabled = false;
\r
1309 text_right.Enabled = false;
\r
1310 text_top.Enabled = false;
\r
1311 text_bottom.Enabled = false;
\r
1313 private void drp_anamorphic_SelectedIndexChanged(object sender, EventArgs e)
\r
1315 if (drp_anamorphic.SelectedIndex == 1)
\r
1317 text_height.BackColor = Color.LightGray;
\r
1318 text_width.BackColor = Color.LightGray;
\r
1319 text_height.Text = "";
\r
1320 text_width.Text = "";
\r
1321 text_height.Enabled = false;
\r
1322 text_width.Enabled = false;
\r
1325 if (drp_anamorphic.SelectedIndex == 2)
\r
1327 text_height.Text = "";
\r
1328 text_height.Enabled = false;
\r
1329 text_height.BackColor = Color.LightGray;
\r
1331 text_width.Enabled = true;
\r
1332 text_width.BackColor = Color.White;
\r
1335 if (drp_anamorphic.SelectedIndex == 0)
\r
1337 text_height.BackColor = Color.White;
\r
1338 text_width.BackColor = Color.White;
\r
1339 text_height.Enabled = true;
\r
1340 text_width.Enabled = true;
\r
1345 private void ctl_decomb_changed(object sender, EventArgs e)
\r
1347 if (ctl_decomb.getDropValue != "Off")
\r
1348 if (ctl_deinterlace.getDropValue != "None")
\r
1349 ctl_deinterlace.setOption("None");
\r
1351 private void ctl_deinterlace_changed(object sender, EventArgs e)
\r
1353 if (ctl_detelecine.getDropValue != "None")
\r
1354 if (ctl_decomb.getDropValue != "Off")
\r
1355 ctl_decomb.setOption("Off");
\r
1357 private void slider_deblock_Scroll(object sender, EventArgs e)
\r
1359 lbl_deblockVal.Text = slider_deblock.Value == 4 ? "Off" : slider_deblock.Value.ToString();
\r
1364 private void drp_subtitle_SelectedIndexChanged(object sender, EventArgs e)
\r
1366 if (drp_subtitle.Text.Contains("None"))
\r
1368 check_forced.Enabled = false;
\r
1369 check_forced.Checked = false;
\r
1372 check_forced.Enabled = true;
\r
1375 // Chapter Marker Tab
\r
1376 private void Check_ChapterMarkers_CheckedChanged(object sender, EventArgs e)
\r
1378 if (Check_ChapterMarkers.Checked)
\r
1380 text_destination.Text = text_destination.Text.Replace(".m4v", ".mp4");
\r
1381 data_chpt.Rows.Clear();
\r
1382 data_chpt.Enabled = true;
\r
1383 DataGridView chapterGridView = Main.chapterNaming(data_chpt, drop_chapterFinish.Text);
\r
1384 if (chapterGridView != null)
\r
1385 data_chpt = chapterGridView;
\r
1389 text_destination.Text = text_destination.Text.Replace(".m4v", ".mp4");
\r
1390 data_chpt.Rows.Clear();
\r
1391 data_chpt.Enabled = false;
\r
1395 // Query Editor Tab
\r
1396 private void btn_generate_Query_Click(object sender, EventArgs e)
\r
1398 rtf_query.Text = queryGen.GenerateTheQuery(this);
\r
1400 private void btn_clear_Click(object sender, EventArgs e)
\r
1402 rtf_query.Clear();
\r
1406 // MainWindow Components, Actions and Functions ***********************
\r
1408 #region Source Scan
\r
1409 public Boolean isScanning { get; set; }
\r
1410 private static int scanProcessID { get; set; }
\r
1411 private void setupGUIforScan(String filename)
\r
1413 text_source.Text = filename;
\r
1415 foreach (Control ctrl in Controls)
\r
1417 if (!(ctrl is StatusStrip || ctrl is MenuStrip || ctrl is ToolStrip))
\r
1418 ctrl.Enabled = false;
\r
1420 lbl_encode.Visible = true;
\r
1421 lbl_encode.Text = "Scanning ...";
\r
1422 gb_source.Text = "Source: Scanning ...";
\r
1423 btn_source.Enabled = false;
\r
1424 btn_start.Enabled = false;
\r
1425 btn_showQueue.Enabled = false;
\r
1426 btn_add2Queue.Enabled = false;
\r
1427 tb_preview.Enabled = false;
\r
1428 mnu_killCLI.Visible = true;
\r
1430 private void startScan(String filename)
\r
1434 lbl_encode.Visible = true;
\r
1435 lbl_encode.Text = "Scanning...";
\r
1436 isScanning = true;
\r
1437 ThreadPool.QueueUserWorkItem(scanProcess, filename);
\r
1439 catch (Exception exc)
\r
1441 MessageBox.Show("frmMain.cs - startScan " + exc, "Error", MessageBoxButtons.OK, MessageBoxIcon.Error);
\r
1444 private void scanProcess(object state)
\r
1448 string inputFile = (string)state;
\r
1449 string handbrakeCLIPath = Path.Combine(Application.StartupPath, "HandBrakeCLI.exe");
\r
1450 string logDir = Environment.GetFolderPath(Environment.SpecialFolder.ApplicationData) + "\\HandBrake\\logs";
\r
1451 string dvdInfoPath = Path.Combine(logDir, "last_scan_log.txt");
\r
1453 // Make we don't pick up a stale last_encode_log.txt (and that we have rights to the file)
\r
1454 if (File.Exists(dvdInfoPath))
\r
1455 File.Delete(dvdInfoPath);
\r
1457 String dvdnav = string.Empty;
\r
1458 if (Properties.Settings.Default.dvdnav == "Checked")
\r
1459 dvdnav = " --dvdnav";
\r
1460 string strCmdLine = String.Format(@"cmd /c """"{0}"" -i ""{1}"" -t0 {2} -v >""{3}"" 2>&1""", handbrakeCLIPath, inputFile, dvdnav, dvdInfoPath);
\r
1462 ProcessStartInfo hbParseDvd = new ProcessStartInfo("CMD.exe", strCmdLine) { WindowStyle = ProcessWindowStyle.Hidden };
\r
1464 Boolean cleanExit = true;
\r
1465 using (hbproc = Process.Start(hbParseDvd))
\r
1467 Process[] before = Process.GetProcesses(); // Get a list of running processes before starting.
\r
1468 scanProcessID = Main.getCliProcess(before);
\r
1469 hbproc.WaitForExit();
\r
1470 if (hbproc.ExitCode != 0)
\r
1471 cleanExit = false;
\r
1474 if (cleanExit) // If 0 exit code, CLI exited cleanly.
\r
1476 if (!File.Exists(dvdInfoPath))
\r
1478 throw new Exception(
\r
1479 "Unable to retrieve the DVD Info. last_scan_log.txt is missing. \nExpected location of last_scan_log.txt: \n" +
\r
1483 using (StreamReader sr = new StreamReader(dvdInfoPath))
\r
1485 thisDVD = DVD.Parse(sr);
\r
1490 updateUIafterScan();
\r
1493 catch (Exception exc)
\r
1495 MessageBox.Show("frmMain.cs - scanProcess() " + exc, "Error", MessageBoxButtons.OK, MessageBoxIcon.Error);
\r
1499 private void updateUIafterScan()
\r
1503 if (InvokeRequired)
\r
1505 BeginInvoke(new UpdateWindowHandler(updateUIafterScan));
\r
1509 // Setup some GUI components
\r
1510 drp_dvdtitle.Items.Clear();
\r
1511 if (thisDVD.Titles.Count != 0)
\r
1512 drp_dvdtitle.Items.AddRange(thisDVD.Titles.ToArray());
\r
1513 drp_dvdtitle.Text = "Automatic";
\r
1514 drop_chapterFinish.Text = "Auto";
\r
1515 drop_chapterStart.Text = "Auto";
\r
1517 // Now select the longest title
\r
1518 if (thisDVD.Titles.Count != 0)
\r
1519 drp_dvdtitle.SelectedItem = Main.selectLongestTitle(drp_dvdtitle);
\r
1521 // Enable the creation of chapter markers if the file is an image of a dvd.
\r
1522 if (text_source.Text.ToLower().Contains(".iso") || text_source.Text.ToLower().Contains("VIDEO_TS"))
\r
1523 Check_ChapterMarkers.Enabled = true;
\r
1526 Check_ChapterMarkers.Enabled = false;
\r
1527 Check_ChapterMarkers.Checked = false;
\r
1528 data_chpt.Rows.Clear();
\r
1531 // If no titles were found, Display an error message
\r
1532 if (drp_dvdtitle.Items.Count == 0)
\r
1533 MessageBox.Show("No Title(s) found. \n\nYour Source may be copy protected, badly mastered or a format which HandBrake does not support. \nPlease refer to the Documentation and FAQ (see Help Menu).", "Error", MessageBoxButtons.OK, MessageBoxIcon.Hand);
\r
1535 // Enable the GUI components and enable any disabled components
\r
1538 catch (Exception exc)
\r
1540 MessageBox.Show("frmMain.cs - updateUIafterScan " + exc, "Error", MessageBoxButtons.OK, MessageBoxIcon.Error);
\r
1544 private void enableGUI()
\r
1548 if (InvokeRequired)
\r
1549 BeginInvoke(new UpdateWindowHandler(enableGUI));
\r
1550 lbl_encode.Text = "Scan Completed";
\r
1551 gb_source.Text = "Source";
\r
1552 foreach (Control ctrl in Controls)
\r
1553 ctrl.Enabled = true;
\r
1554 btn_start.Enabled = true;
\r
1555 btn_showQueue.Enabled = true;
\r
1556 btn_add2Queue.Enabled = true;
\r
1557 tb_preview.Enabled = true;
\r
1558 btn_source.Enabled = true;
\r
1559 mnu_killCLI.Visible = false;
\r
1561 catch (Exception exc)
\r
1563 MessageBox.Show("frmMain.cs - enableGUI() " + exc, "Error", MessageBoxButtons.OK, MessageBoxIcon.Error);
\r
1566 private void killScan()
\r
1573 Process[] prs = Process.GetProcesses();
\r
1574 foreach (Process process in prs)
\r
1576 if (process.Id == scanProcessID)
\r
1578 process.Refresh();
\r
1579 if (!process.HasExited)
\r
1584 catch (Exception ex)
\r
1586 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
1589 private void resetGUI()
\r
1591 drp_dvdtitle.Items.Clear();
\r
1592 drp_dvdtitle.Text = "Automatic";
\r
1593 drop_chapterStart.Items.Clear();
\r
1594 drop_chapterStart.Text = "Auto";
\r
1595 drop_chapterFinish.Items.Clear();
\r
1596 drop_chapterFinish.Text = "Auto";
\r
1597 lbl_duration.Text = "Select a Title";
\r
1598 lbl_src_res.Text = "Select a Title";
\r
1599 lbl_Aspect.Text = "Select a Title";
\r
1600 text_source.Text = "Click 'Source' to continue";
\r
1601 text_destination.Text = "";
\r
1603 selectedTitle = null;
\r
1604 isScanning = false;
\r
1610 /// Set the GUI to it's finished encoding state.
\r
1612 private void setEncodeFinished()
\r
1616 if (InvokeRequired)
\r
1618 BeginInvoke(new UpdateWindowHandler(setEncodeFinished));
\r
1622 lbl_encode.Text = "Encoding Finished";
\r
1623 btn_start.Text = "Start";
\r
1624 btn_start.ToolTipText = "Start the encoding process";
\r
1625 btn_start.Image = Properties.Resources.Play;
\r
1627 // If the window is minimized, display the notification in a popup.
\r
1628 if (FormWindowState.Minimized == this.WindowState)
\r
1630 notifyIcon.BalloonTipText = lbl_encode.Text;
\r
1631 notifyIcon.ShowBalloonTip(500);
\r
1634 catch (Exception exc)
\r
1636 MessageBox.Show(exc.ToString());
\r
1641 /// Set the GUI to it's started encoding state.
\r
1643 private void setEncodeStarted()
\r
1647 if (InvokeRequired)
\r
1649 BeginInvoke(new UpdateWindowHandler(setEncodeStarted));
\r
1653 lbl_encode.Visible = true;
\r
1654 lbl_encode.Text = "Encoding in Progress";
\r
1655 btn_start.Text = "Stop";
\r
1656 btn_start.ToolTipText = "Stop the encoding process. \nWarning: This may break your file. Press ctrl-c in the CLI window if you wish it to exit cleanly.";
\r
1657 btn_start.Image = Properties.Resources.stop;
\r
1659 catch (Exception exc)
\r
1661 MessageBox.Show(exc.ToString());
\r
1666 #region DVD Drive Detection
\r
1667 private delegate void ProgressUpdateHandler();
\r
1668 private void getDriveInfoThread()
\r
1672 if (InvokeRequired)
\r
1674 BeginInvoke(new ProgressUpdateHandler(getDriveInfoThread));
\r
1678 Boolean foundDrive = false;
\r
1679 DriveInfo[] theCollectionOfDrives = DriveInfo.GetDrives();
\r
1680 foreach (DriveInfo curDrive in theCollectionOfDrives)
\r
1682 if (curDrive.DriveType == DriveType.CDRom && curDrive.IsReady)
\r
1684 if (File.Exists(curDrive.RootDirectory + "VIDEO_TS\\VIDEO_TS.IFO"))
\r
1686 mnu_dvd_drive.Text = curDrive.RootDirectory + "VIDEO_TS (" + curDrive.VolumeLabel + ")";
\r
1687 foundDrive = true;
\r
1693 if (foundDrive == false)
\r
1694 mnu_dvd_drive.Text = "[No DVD Drive Ready]";
\r
1698 mnu_dvd_drive.Text = "[No DVD Drive Ready / Found]";
\r
1703 #region Audio Panel Code Helpers
\r
1705 private void setVideoByContainer(String path)
\r
1709 if ((path.Contains("MP4")) || (path.Contains("M4V")))
\r
1711 oldval = drp_videoEncoder.Text;
\r
1712 drp_videoEncoder.Items.Clear();
\r
1713 drp_videoEncoder.Items.Add("MPEG-4 (FFmpeg)");
\r
1714 drp_videoEncoder.Items.Add("H.264 (x264)");
\r
1715 if (oldval == "VP3 (Theora)")
\r
1716 drp_videoEncoder.SelectedIndex = 1;
\r
1718 drp_videoEncoder.Text = oldval;
\r
1721 else if (path.Contains("MKV"))
\r
1723 oldval = drp_videoEncoder.Text;
\r
1724 drp_videoEncoder.Items.Clear();
\r
1725 drp_videoEncoder.Items.Add("MPEG-4 (FFmpeg)");
\r
1726 drp_videoEncoder.Items.Add("H.264 (x264)");
\r
1727 drp_videoEncoder.Items.Add("VP3 (Theora)");
\r
1728 drp_videoEncoder.Text = oldval;
\r
1733 #region Public Methods
\r
1735 /// Access the preset Handler and setup the preset panel.
\r
1737 public void loadPresetPanel()
\r
1739 if (presetHandler.checkIfPresetsAreOutOfDate())
\r
1740 if (Properties.Settings.Default.presetNotification == "Unchecked")
\r
1742 "HandBrake has determined your built-in presets are out of date... These presets will now be updated.",
\r
1743 "Preset Update", MessageBoxButtons.OK, MessageBoxIcon.Information);
\r
1745 presetHandler.getPresetPanel(ref treeView_presets);
\r
1746 treeView_presets.Update();
\r
1750 /// Either Encode or Scan was last performed.
\r
1752 public string lastAction { get; set; }
\r
1757 /// If the queue is being processed, prompt the user to confirm application close.
\r
1759 /// <param name="e"></param>
\r
1760 protected override void OnFormClosing(FormClosingEventArgs e)
\r
1762 // If currently encoding, the queue isn't paused, and there are queue items to process, prompt to confirm close.
\r
1763 if ((encodeQueue.isEncoding) && (!encodeQueue.isPaused) && (encodeQueue.count() > 0))
\r
1765 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
1766 "Close HandBrake?", MessageBoxButtons.YesNo, MessageBoxIcon.Question);
\r
1767 if (result == DialogResult.No)
\r
1770 base.OnFormClosing(e);
\r
1774 #region In-GUI Encode Status (Experimental)
\r
1775 private Process HBProcess { get; set; }
\r
1777 private void encodeMonitorThread()
\r
1781 Parser encode = new Parser(HBProcess.StandardOutput.BaseStream);
\r
1782 encode.OnEncodeProgress += encode_OnEncodeProgress;
\r
1783 while (!encode.EndOfStream)
\r
1785 encode.readEncodeStatus();
\r
1788 catch (Exception exc)
\r
1790 MessageBox.Show(exc.ToString());
\r
1794 private void encode_OnEncodeProgress(object Sender, int CurrentTask, int TaskCount, float PercentComplete, float CurrentFps, float AverageFps, TimeSpan TimeRemaining)
\r
1796 if (this.InvokeRequired)
\r
1798 this.BeginInvoke(new EncodeProgressEventHandler(encode_OnEncodeProgress),
\r
1799 new object[] { Sender, CurrentTask, TaskCount, PercentComplete, CurrentFps, AverageFps, TimeRemaining });
\r
1802 lbl_encode.Text = string.Format("Encode Progress: {0}%, FPS: {1}, Avg FPS: {2}, Time Remaining: {3} ", PercentComplete, CurrentFps, AverageFps, TimeRemaining);
\r
1808 // This is the END of the road ****************************************
\r