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.EncodeQueue;
\r
15 using Handbrake.Functions;
\r
16 using Handbrake.Presets;
\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.encodeProcess.hbProcProcess;
\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
256 String file = lastAction == "scan" ? "last_scan_log.txt" : "last_encode_log.txt";
\r
258 frmActivityWindow dvdInfoWindow = new frmActivityWindow(file, encodeQueue, this);
\r
259 dvdInfoWindow.Show();
\r
261 private void mnu_options_Click(object sender, EventArgs e)
\r
263 Form Options = new frmOptions();
\r
264 Options.ShowDialog();
\r
268 #region Presets Menu
\r
269 private void mnu_presetReset_Click(object sender, EventArgs e)
\r
271 presetHandler.updateBuiltInPresets();
\r
273 if (treeView_presets.Nodes.Count == 0)
\r
274 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
276 MessageBox.Show("Presets have been updated!", "Alert", MessageBoxButtons.OK, MessageBoxIcon.Information);
\r
278 treeView_presets.ExpandAll();
\r
280 private void mnu_delete_preset_Click(object sender, EventArgs e)
\r
282 // Empty the preset file
\r
283 string presetsFile = Application.StartupPath + "\\presets.xml";
\r
284 if (File.Exists(presetsFile))
\r
285 File.Delete(presetsFile);
\r
289 FileStream strm = new FileStream(presetsFile, FileMode.Create, FileAccess.Write);
\r
293 catch (Exception exc)
\r
295 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
298 // Reload the preset panel
\r
301 private void mnu_SelectDefault_Click(object sender, EventArgs e)
\r
303 loadNormalPreset();
\r
305 private void btn_new_preset_Click(object sender, EventArgs e)
\r
307 // Remember each nodes expanded status so we can reload it
\r
308 List<Boolean> nodeStatus = saveTreeViewState();
\r
309 nodeStatus.Add(true);
\r
311 Form preset = new frmAddPreset(this, queryGen.GenerateTheQuery(this), presetHandler);
\r
312 preset.ShowDialog();
\r
314 // Now reload the TreeView states
\r
315 loadTreeViewStates(nodeStatus);
\r
320 private void mnu_handbrake_forums_Click(object sender, EventArgs e)
\r
322 Process.Start("http://forum.handbrake.fr/");
\r
324 private void mnu_user_guide_Click(object sender, EventArgs e)
\r
326 Process.Start("http://trac.handbrake.fr/wiki/HandBrakeGuide");
\r
328 private void mnu_handbrake_home_Click(object sender, EventArgs e)
\r
330 Process.Start("http://handbrake.fr");
\r
332 private void mnu_UpdateCheck_Click(object sender, EventArgs e)
\r
334 Boolean update = Main.updateCheck(true);
\r
337 frmUpdater updateWindow = new frmUpdater();
\r
338 updateWindow.Show();
\r
341 MessageBox.Show("There are no new updates at this time.", "Update Check", MessageBoxButtons.OK, MessageBoxIcon.Information);
\r
343 private void mnu_about_Click(object sender, EventArgs e)
\r
345 Form About = new frmAbout();
\r
346 About.ShowDialog();
\r
351 private void mnu_qptest_Click(object sender, EventArgs e)
\r
353 QueryParserTester qptest = new QueryParserTester();
\r
359 // Right Click Menu Code
\r
360 private void pmnu_expandAll_Click(object sender, EventArgs e)
\r
362 treeView_presets.ExpandAll();
\r
364 private void pmnu_collapse_Click(object sender, EventArgs e)
\r
366 treeView_presets.CollapseAll();
\r
368 private void pmnu_saveChanges_Click(object sender, EventArgs e)
\r
370 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
371 if (result == DialogResult.Yes)
\r
372 presetHandler.updatePreset(treeView_presets.SelectedNode.Text, QueryGenerator.generateTabbedComponentsQuery(this), true);
\r
373 else if (result == DialogResult.No)
\r
374 presetHandler.updatePreset(treeView_presets.SelectedNode.Text, QueryGenerator.generateTabbedComponentsQuery(this), false);
\r
376 private void pmnu_delete_click(object sender, EventArgs e)
\r
378 if (treeView_presets.SelectedNode != null)
\r
380 presetHandler.remove(treeView_presets.SelectedNode.Text);
\r
381 List<Boolean> nodeStatus = saveTreeViewState(); // Remember each nodes expanded status so we can reload it
\r
383 loadTreeViewStates(nodeStatus); // Now reload the TreeView states
\r
385 treeView_presets.Select();
\r
387 private void presets_menu_Opening(object sender, System.ComponentModel.CancelEventArgs e)
\r
389 // Make sure that the save menu is always disabled by default
\r
390 pmnu_saveChanges.Enabled = false;
\r
392 // Now enable the save menu if the selected preset is a user preset
\r
393 if (treeView_presets.SelectedNode != null)
\r
394 if (presetHandler.checkIfUserPresetExists(treeView_presets.SelectedNode.Text))
\r
395 pmnu_saveChanges.Enabled = true;
\r
397 treeView_presets.Select();
\r
400 // Presets Management
\r
401 private void btn_addPreset_Click(object sender, EventArgs e)
\r
403 // Remember each nodes expanded status so we can reload it
\r
404 List<Boolean> nodeStatus = saveTreeViewState();
\r
405 nodeStatus.Add(true);
\r
407 // Now add the new preset
\r
408 Form preset = new frmAddPreset(this, QueryGenerator.generateTabbedComponentsQuery(this), presetHandler);
\r
409 preset.ShowDialog();
\r
411 // Now reload the TreeView states
\r
412 loadTreeViewStates(nodeStatus);
\r
414 private void btn_removePreset_Click(object sender, EventArgs e)
\r
416 DialogResult result = MessageBox.Show("Are you sure you wish to delete the selected preset?", "Preset", MessageBoxButtons.YesNo, MessageBoxIcon.Question);
\r
417 if (result == DialogResult.Yes)
\r
419 if (treeView_presets.SelectedNode != null)
\r
420 presetHandler.remove(treeView_presets.SelectedNode.Text);
\r
422 List<Boolean> nodeStatus = saveTreeViewState(); // Remember each nodes expanded status so we can reload it
\r
424 loadTreeViewStates(nodeStatus); // Now reload the TreeView states
\r
426 treeView_presets.Select();
\r
428 private void btn_setDefault_Click(object sender, EventArgs e)
\r
430 if (treeView_presets.SelectedNode != null)
\r
432 DialogResult result = MessageBox.Show("Are you sure you wish to set this preset as the default?", "Preset", MessageBoxButtons.YesNo, MessageBoxIcon.Question);
\r
433 if (result == DialogResult.Yes)
\r
435 Properties.Settings.Default.defaultPreset = treeView_presets.SelectedNode.Text;
\r
436 Properties.Settings.Default.Save();
\r
437 MessageBox.Show("New default preset set.", "Alert", MessageBoxButtons.OK, MessageBoxIcon.Information);
\r
441 MessageBox.Show("Please select a preset first.", "Warning", MessageBoxButtons.OK, MessageBoxIcon.Warning);
\r
443 private void treeview_presets_mouseUp(object sender, MouseEventArgs e)
\r
445 if (e.Button == MouseButtons.Right)
\r
446 treeView_presets.SelectedNode = treeView_presets.GetNodeAt(e.Location);
\r
447 else if (e.Button == MouseButtons.Left)
\r
449 if (treeView_presets.GetNodeAt(e.Location) != null)
\r
451 if (groupBox_output.Text.Contains(treeView_presets.GetNodeAt(e.Location).Text))
\r
456 treeView_presets.Select();
\r
458 private void treeView_presets_AfterSelect(object sender, TreeViewEventArgs e)
\r
462 private void selectPreset()
\r
464 if (treeView_presets.SelectedNode != null)
\r
466 // Ok, so, we've selected a preset. Now we want to load it.
\r
467 string presetName = treeView_presets.SelectedNode.Text;
\r
468 if (presetHandler.getPreset(presetName) != null)
\r
470 string query = presetHandler.getPreset(presetName).Query;
\r
471 Boolean loadPictureSettings = presetHandler.getPreset(presetName).PictureSettings;
\r
475 //Ok, Reset all the H264 widgets before changing the preset
\r
476 x264Panel.reset2Defaults();
\r
478 // Send the query from the file to the Query Parser class
\r
479 QueryParser presetQuery = QueryParser.Parse(query);
\r
481 // Now load the preset
\r
482 PresetLoader.presetLoader(this, presetQuery, presetName, loadPictureSettings);
\r
484 // The x264 widgets will need updated, so do this now:
\r
485 x264Panel.X264_StandardizeOptString();
\r
486 x264Panel.X264_SetCurrentSettingsInPanel();
\r
488 if (maxWidth != 0 && maxHeight != 0)
\r
489 lbl_max.Text = "Max Width / Height";
\r
490 else if (maxWidth != 0)
\r
491 lbl_max.Text = "Max Width";
\r
498 private void treeView_presets_deleteKey(object sender, KeyEventArgs e)
\r
500 if (e.KeyCode == Keys.Delete)
\r
502 DialogResult result = MessageBox.Show("Are you sure you wish to delete the selected preset?", "Preset", MessageBoxButtons.YesNo, MessageBoxIcon.Question);
\r
503 if (result == DialogResult.Yes)
\r
505 if (treeView_presets.SelectedNode != null)
\r
506 presetHandler.remove(treeView_presets.SelectedNode.Text);
\r
508 // Remember each nodes expanded status so we can reload it
\r
509 List<Boolean> nodeStatus = new List<Boolean>();
\r
510 foreach (TreeNode node in treeView_presets.Nodes)
\r
511 nodeStatus.Add(node.IsExpanded);
\r
513 // Now reload the preset panel
\r
516 // And finally, re-expand any of the nodes if required
\r
518 foreach (TreeNode node in treeView_presets.Nodes)
\r
528 private List<Boolean> saveTreeViewState()
\r
530 // Remember each nodes expanded status so we can reload it
\r
531 List<Boolean> nodeStatus = new List<Boolean>();
\r
532 foreach (TreeNode node in treeView_presets.Nodes)
\r
534 nodeStatus.Add(node.IsExpanded);
\r
535 foreach (TreeNode subNode in node.Nodes)
\r
536 nodeStatus.Add(node.IsExpanded);
\r
540 private void loadTreeViewStates(List<Boolean> nodeStatus)
\r
542 // And finally, re-expand any of the nodes if required
\r
544 foreach (TreeNode node in treeView_presets.Nodes)
\r
549 foreach (TreeNode subNode in node.Nodes)
\r
558 private void loadNormalPreset()
\r
560 foreach (TreeNode treenode in treeView_presets.Nodes)
\r
562 foreach (TreeNode node in treenode.Nodes)
\r
564 if (node.Text.Equals("Normal"))
\r
565 treeView_presets.SelectedNode = treeView_presets.Nodes[treenode.Index].Nodes[0];
\r
572 private void btn_source_Click(object sender, EventArgs e)
\r
574 if (Properties.Settings.Default.drive_detection == "Checked")
\r
576 mnu_dvd_drive.Visible = true;
\r
577 Thread driveInfoThread = new Thread(getDriveInfoThread);
\r
578 driveInfoThread.Start();
\r
581 mnu_dvd_drive.Visible = false;
\r
583 private void btn_start_Click(object sender, EventArgs e)
\r
585 if (btn_start.Text == "Stop")
\r
587 DialogResult result = MessageBox.Show("Are you sure you wish to cancel the encode?", "Cancel Encode?", MessageBoxButtons.YesNo, MessageBoxIcon.Question);
\r
589 if (result == DialogResult.Yes)
\r
592 encodeQueue.pauseEncodeQueue();
\r
594 // Allow the CLI to exit cleanly
\r
595 Win32.SetForegroundWindow(encodeQueue.encodeProcess.processHandle);
\r
596 SendKeys.Send("^C");
\r
599 setEncodeFinished();
\r
604 if (encodeQueue.count() != 0 || (text_source.Text != string.Empty && text_source.Text != "Click 'Source' to continue" && text_destination.Text != string.Empty))
\r
606 // Set the last action to encode.
\r
607 // This is used for tracking which file to load in the activity window
\r
608 lastAction = "encode";
\r
610 String query = rtf_query.Text != "" ? rtf_query.Text : queryGen.GenerateTheQuery(this);
\r
612 if (encodeQueue.count() == 0)
\r
614 encodeQueue.add(query, text_source.Text, text_destination.Text);
\r
615 encodeQueue.write2disk("hb_queue_recovery.xml");
\r
617 queueWindow.setQueue();
\r
618 if (encodeQueue.count() > 1)
\r
619 queueWindow.Show(false);
\r
621 setEncodeStarted(); // Encode is running, so setup the GUI appropriately
\r
622 encodeQueue.startEncode(); // Start The Queue Encoding Process
\r
625 else if (text_source.Text == string.Empty || text_source.Text == "Click 'Source' to continue" || text_destination.Text == string.Empty)
\r
626 MessageBox.Show("No source OR destination selected.", "Warning", MessageBoxButtons.OK, MessageBoxIcon.Warning);
\r
629 private void btn_add2Queue_Click(object sender, EventArgs e)
\r
632 if (text_source.Text == string.Empty || text_source.Text == "Click 'Source' to continue" || text_destination.Text == string.Empty)
\r
633 MessageBox.Show("No source OR destination selected.", "Warning", MessageBoxButtons.OK, MessageBoxIcon.Warning);
\r
636 String query = queryGen.GenerateTheQuery(this);
\r
637 if (rtf_query.Text != "")
\r
638 query = rtf_query.Text;
\r
640 if (encodeQueue.checkDestinationPath(text_destination.Text))
\r
642 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
643 "Warning", MessageBoxButtons.YesNo, MessageBoxIcon.Warning);
\r
644 if (result == DialogResult.Yes)
\r
645 encodeQueue.add(query, text_source.Text, text_destination.Text);
\r
649 encodeQueue.add(query, text_source.Text, text_destination.Text);
\r
651 encodeQueue.write2disk("hb_queue_recovery.xml"); // Writes the queue to the recovery file, just incase the GUI crashes.
\r
652 queueWindow.Show();
\r
655 private void btn_showQueue_Click(object sender, EventArgs e)
\r
657 queueWindow.Show();
\r
659 private void tb_preview_Click(object sender, EventArgs e)
\r
661 if (text_source.Text == "" || text_source.Text == "Click 'Source' to continue" || text_destination.Text == "")
\r
662 MessageBox.Show("No source OR destination selected.", "Warning", MessageBoxButtons.OK, MessageBoxIcon.Warning);
\r
665 if (qtpreview == null)
\r
667 qtpreview = new frmPreview(this);
\r
670 else if (qtpreview.IsDisposed)
\r
672 qtpreview = new frmPreview(this);
\r
676 MessageBox.Show(qtpreview, "The preview window is already open!", "Warning", MessageBoxButtons.OK, MessageBoxIcon.Warning);
\r
679 private void btn_ActivityWindow_Click(object sender, EventArgs e)
\r
681 String file = lastAction == "scan" ? "last_scan_log.txt" : "last_encode_log.txt";
\r
683 frmActivityWindow ActivityWindow = new frmActivityWindow(file, encodeQueue, this);
\r
684 ActivityWindow.Show();
\r
688 #region System Tray Icon
\r
689 private void frmMain_Resize(object sender, EventArgs e)
\r
691 if (FormWindowState.Minimized == this.WindowState)
\r
693 notifyIcon.Visible = true;
\r
694 if (!encodeQueue.isEncoding)
\r
696 notifyIcon.BalloonTipText = lbl_encode.Text != "" ? lbl_encode.Text : "Not Encoding";
\r
697 if (Properties.Settings.Default.trayIconAlerts == "Checked")
\r
698 notifyIcon.ShowBalloonTip(500);
\r
702 else if (FormWindowState.Normal == this.WindowState)
\r
703 notifyIcon.Visible = false;
\r
705 private void notifyIcon_MouseDoubleClick(object sender, MouseEventArgs e)
\r
707 this.Visible = true;
\r
709 this.WindowState = FormWindowState.Normal;
\r
710 notifyIcon.Visible = false;
\r
712 private void btn_restore_Click(object sender, EventArgs e)
\r
714 this.Visible = true;
\r
716 this.WindowState = FormWindowState.Normal;
\r
717 notifyIcon.Visible = false;
\r
721 #region Tab Control
\r
724 private void btn_dvd_source_Click(object sender, EventArgs e)
\r
726 // Enable the creation of chapter markers.
\r
727 Check_ChapterMarkers.Enabled = true;
\r
729 // Set the last action to scan.
\r
730 // This is used for tracking which file to load in the activity window
\r
731 lastAction = "scan";
\r
732 text_source.Text = "";
\r
734 if (DVD_Open.ShowDialog() == DialogResult.OK)
\r
736 String filename = DVD_Open.SelectedPath;
\r
738 if (filename.StartsWith("\\"))
\r
739 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
742 if (filename != "")
\r
744 setupGUIforScan(filename);
\r
745 startScan(filename);
\r
748 text_source.Text = "Click 'Source' to continue";
\r
752 text_source.Text = "Click 'Source' to continue";
\r
754 private void btn_file_source_Click(object sender, EventArgs e)
\r
756 // Set the last action to scan.
\r
757 // This is used for tracking which file to load in the activity window
\r
758 lastAction = "scan";
\r
759 text_source.Text = "";
\r
761 if (ISO_Open.ShowDialog() == DialogResult.OK)
\r
763 String filename = ISO_Open.FileName;
\r
764 if (filename.StartsWith("\\"))
\r
766 "Sorry, HandBrake does not support UNC file paths. \nTry mounting the share as a network drive in My Computer",
\r
767 "Warning", MessageBoxButtons.OK, MessageBoxIcon.Warning);
\r
770 if (filename != "")
\r
772 setupGUIforScan(filename);
\r
773 startScan(filename);
\r
776 text_source.Text = "Click 'Source' to continue";
\r
780 text_source.Text = "Click 'Source' to continue";
\r
782 private void mnu_dvd_drive_Click(object sender, EventArgs e)
\r
784 // Enable the creation of chapter markers.
\r
785 Check_ChapterMarkers.Enabled = true;
\r
787 // Set the last action to scan.
\r
788 // This is used for tracking which file to load in the activity window
\r
789 lastAction = "scan";
\r
791 if (mnu_dvd_drive.Text.Contains("VIDEO_TS"))
\r
793 string[] path = mnu_dvd_drive.Text.Split(' ');
\r
794 String filename = path[0];
\r
795 setupGUIforScan(filename);
\r
796 startScan(filename);
\r
799 // If there are no titles in the dropdown menu then the scan has obviously failed. Display an error message explaining to the user.
\r
800 if (drp_dvdtitle.Items.Count == 0)
\r
801 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
803 lbl_encode.Text = "";
\r
805 private void drp_dvdtitle_Click(object sender, EventArgs e)
\r
807 if ((drp_dvdtitle.Items.Count == 1) && (drp_dvdtitle.Items[0].ToString() == "Automatic"))
\r
808 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
810 private void drp_dvdtitle_SelectedIndexChanged(object sender, EventArgs e)
\r
812 // Reset some values on the form
\r
813 lbl_Aspect.Text = "Select a Title";
\r
814 //lbl_RecomendedCrop.Text = "Select a Title";
\r
815 drop_chapterStart.Items.Clear();
\r
816 drop_chapterFinish.Items.Clear();
\r
818 // If the dropdown is set to automatic nothing else needs to be done.
\r
819 // Otheriwse if its not, title data has to be loased from parsing.
\r
820 if (drp_dvdtitle.Text != "Automatic")
\r
822 selectedTitle = drp_dvdtitle.SelectedItem as Parsing.Title;
\r
824 // Set the Aspect Ratio
\r
825 lbl_Aspect.Text = selectedTitle.AspectRatio.ToString();
\r
826 lbl_src_res.Text = selectedTitle.Resolution.Width + " x " + selectedTitle.Resolution.Height;
\r
827 lbl_duration.Text = selectedTitle.Duration.ToString();
\r
829 // Set the Recommended Cropping values
\r
830 text_top.Text = selectedTitle.AutoCropDimensions[0].ToString();
\r
831 text_bottom.Text = selectedTitle.AutoCropDimensions[1].ToString();
\r
832 text_left.Text = selectedTitle.AutoCropDimensions[2].ToString();
\r
833 text_right.Text = selectedTitle.AutoCropDimensions[3].ToString();
\r
835 // Populate the Angles dropdown
\r
836 drop_angle.Items.Clear();
\r
837 if (Properties.Settings.Default.dvdnav == "Checked")
\r
839 drop_angle.Visible = true;
\r
840 lbl_angle.Visible = true;
\r
841 drop_angle.Items.AddRange(selectedTitle.Angles.ToArray());
\r
842 if (drop_angle.Items.Count != 0)
\r
843 drop_angle.SelectedIndex = 0;
\r
847 drop_angle.Visible = false;
\r
848 lbl_angle.Visible = false;
\r
851 // Populate the Start chapter Dropdown
\r
852 drop_chapterStart.Items.Clear();
\r
853 drop_chapterStart.Items.AddRange(selectedTitle.Chapters.ToArray());
\r
854 if (drop_chapterStart.Items.Count > 0)
\r
855 drop_chapterStart.Text = drop_chapterStart.Items[0].ToString();
\r
857 // Populate the Final Chapter Dropdown
\r
858 drop_chapterFinish.Items.Clear();
\r
859 drop_chapterFinish.Items.AddRange(selectedTitle.Chapters.ToArray());
\r
860 if (drop_chapterFinish.Items.Count > 0)
\r
861 drop_chapterFinish.Text = drop_chapterFinish.Items[drop_chapterFinish.Items.Count - 1].ToString();
\r
863 // Populate the Audio Channels Dropdown
\r
864 audioPanel.setTrackList(selectedTitle);
\r
866 // Populate the Subtitles dropdown
\r
867 drp_subtitle.Items.Clear();
\r
868 drp_subtitle.Items.Add("None");
\r
869 drp_subtitle.Items.Add("Autoselect");
\r
870 drp_subtitle.Items.AddRange(selectedTitle.Subtitles.ToArray());
\r
871 if (drp_subtitle.Items.Count > 0)
\r
872 drp_subtitle.Text = drp_subtitle.Items[0].ToString();
\r
876 // Run the autoName & chapterNaming functions
\r
877 if (Properties.Settings.Default.autoNaming == "Checked")
\r
879 string autoPath = Main.autoName(drp_dvdtitle, drop_chapterStart.Text, drop_chapterFinish.Text, text_source.Text, text_destination.Text, drop_format.SelectedIndex);
\r
880 if (autoPath != null)
\r
881 text_destination.Text = autoPath;
\r
883 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
886 data_chpt.Rows.Clear();
\r
887 if (selectedTitle.Chapters.Count != 1)
\r
889 DataGridView chapterGridView = Main.chapterNaming(data_chpt, drop_chapterFinish.Text);
\r
890 if (chapterGridView != null)
\r
891 data_chpt = chapterGridView;
\r
895 Check_ChapterMarkers.Checked = false;
\r
896 Check_ChapterMarkers.Enabled = false;
\r
899 // Hack to force the redraw of the scrollbars which don't resize properly when the control is disabled.
\r
900 data_chpt.Columns[0].Width = 166;
\r
901 data_chpt.Columns[0].Width = 165;
\r
903 private void drop_chapterStart_SelectedIndexChanged(object sender, EventArgs e)
\r
905 int c_start, c_end;
\r
907 if (drop_chapterFinish.Text == "Auto" && drop_chapterFinish.Items.Count != 0)
\r
908 drop_chapterFinish.SelectedIndex = drop_chapterFinish.Items.Count - 1;
\r
910 int.TryParse(drop_chapterStart.Text, out c_start);
\r
911 int.TryParse(drop_chapterFinish.Text, out c_end);
\r
915 if (c_start > c_end)
\r
916 drop_chapterFinish.Text = c_start.ToString();
\r
919 lbl_duration.Text = Main.calculateDuration(drop_chapterStart.Text, drop_chapterFinish.Text, selectedTitle).ToString();
\r
921 // Run the Autonaming function
\r
922 if (Properties.Settings.Default.autoNaming == "Checked")
\r
923 text_destination.Text = Main.autoName(drp_dvdtitle, drop_chapterStart.Text, drop_chapterFinish.Text, text_source.Text, text_destination.Text, drop_format.SelectedIndex);
\r
925 // Disable chapter markers if only 1 chapter is selected.
\r
926 if (c_start == c_end)
\r
928 Check_ChapterMarkers.Checked = false;
\r
929 Check_ChapterMarkers.Enabled = false;
\r
932 Check_ChapterMarkers.Enabled = true;
\r
934 private void drop_chapterFinish_SelectedIndexChanged(object sender, EventArgs e)
\r
936 int c_start, c_end;
\r
938 if (drop_chapterStart.Text == "Auto" && drop_chapterStart.Items.Count >= 1)
\r
939 drop_chapterStart.SelectedIndex = 1;
\r
941 int.TryParse(drop_chapterStart.Text, out c_start);
\r
942 int.TryParse(drop_chapterFinish.Text, out c_end);
\r
946 if (c_end < c_start)
\r
947 drop_chapterFinish.Text = c_start.ToString();
\r
950 lbl_duration.Text = Main.calculateDuration(drop_chapterStart.Text, drop_chapterFinish.Text, selectedTitle).ToString();
\r
952 // Run the Autonaming function
\r
953 if (Properties.Settings.Default.autoNaming == "Checked")
\r
954 text_destination.Text = Main.autoName(drp_dvdtitle, drop_chapterStart.Text, drop_chapterFinish.Text, text_source.Text, text_destination.Text, drop_format.SelectedIndex);
\r
956 // Add more rows to the Chapter menu if needed.
\r
957 if (Check_ChapterMarkers.Checked)
\r
959 int i = data_chpt.Rows.Count, finish = 0;
\r
961 if (drop_chapterFinish.Text != "Auto")
\r
962 int.TryParse(drop_chapterFinish.Text, out finish);
\r
966 int n = data_chpt.Rows.Add();
\r
967 data_chpt.Rows[n].Cells[0].Value = (i + 1);
\r
968 data_chpt.Rows[n].Cells[1].Value = "Chapter " + (i + 1);
\r
969 data_chpt.Rows[n].Cells[0].ValueType = typeof(int);
\r
970 data_chpt.Rows[n].Cells[1].ValueType = typeof(string);
\r
975 // Disable chapter markers if only 1 chapter is selected.
\r
976 if (c_start == c_end)
\r
978 Check_ChapterMarkers.Checked = false;
\r
979 Check_ChapterMarkers.Enabled = false;
\r
982 Check_ChapterMarkers.Enabled = true;
\r
986 private void btn_destBrowse_Click(object sender, EventArgs e)
\r
988 // This removes the file extension from the filename box on the save file dialog.
\r
989 // It's daft but some users don't realise that typing an extension overrides the dropdown extension selected.
\r
990 DVD_Save.FileName = Path.GetFileNameWithoutExtension(text_destination.Text);
\r
992 if (Path.IsPathRooted(text_destination.Text))
\r
993 DVD_Save.InitialDirectory = Path.GetDirectoryName(text_destination.Text);
\r
995 // Show the dialog and set the main form file path
\r
996 if (drop_format.SelectedIndex.Equals(0))
\r
997 DVD_Save.FilterIndex = 1;
\r
998 else if (drop_format.SelectedIndex.Equals(1))
\r
999 DVD_Save.FilterIndex = 2;
\r
1000 else if (drop_format.SelectedIndex.Equals(2))
\r
1001 DVD_Save.FilterIndex = 3;
\r
1003 if (DVD_Save.ShowDialog() == DialogResult.OK)
\r
1005 if (DVD_Save.FileName.StartsWith("\\"))
\r
1006 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
1009 // Add a file extension manually, as FileDialog.AddExtension has issues with dots in filenames
\r
1010 switch (DVD_Save.FilterIndex)
\r
1013 if (!Path.GetExtension(DVD_Save.FileName).Equals(".mp4", StringComparison.InvariantCultureIgnoreCase))
\r
1014 DVD_Save.FileName += ".mp4";
\r
1017 if (!Path.GetExtension(DVD_Save.FileName).Equals(".m4v", StringComparison.InvariantCultureIgnoreCase))
\r
1018 DVD_Save.FileName += ".m4v";
\r
1021 if (!Path.GetExtension(DVD_Save.FileName).Equals(".mkv", StringComparison.InvariantCultureIgnoreCase))
\r
1022 DVD_Save.FileName += ".mkv";
\r
1028 text_destination.Text = DVD_Save.FileName;
\r
1030 // Quicktime requires .m4v file for chapter markers to work. If checked, change the extension to .m4v (mp4 and m4v are the same thing)
\r
1031 if (Check_ChapterMarkers.Checked)
\r
1032 drop_format.SelectedIndex = 1;
\r
1036 private void text_destination_TextChanged(object sender, EventArgs e)
\r
1038 string path = text_destination.Text;
\r
1039 if (path.EndsWith(".mp4"))
\r
1040 drop_format.SelectedIndex = 0;
\r
1041 else if (path.EndsWith(".m4v"))
\r
1042 drop_format.SelectedIndex = 1;
\r
1043 else if (path.EndsWith(".mkv"))
\r
1044 drop_format.SelectedIndex = 2;
\r
1047 // Output Settings
\r
1048 private void drop_format_SelectedIndexChanged(object sender, EventArgs e)
\r
1050 if (drop_format.SelectedIndex == 0)
\r
1051 setExtension(".mp4");
\r
1052 else if (drop_format.SelectedIndex == 1)
\r
1053 setExtension(".m4v");
\r
1054 else if (drop_format.SelectedIndex == 2)
\r
1055 setExtension(".mkv");
\r
1057 audioPanel.setAudioByContainer(drop_format.Text);
\r
1060 if ((drop_format.Text.Contains("MP4")) || (drop_format.Text.Contains("M4V")))
\r
1062 oldval = drp_videoEncoder.Text;
\r
1063 drp_videoEncoder.Items.Clear();
\r
1064 drp_videoEncoder.Items.Add("MPEG-4 (FFmpeg)");
\r
1065 drp_videoEncoder.Items.Add("H.264 (x264)");
\r
1066 if (oldval == "VP3 (Theora)")
\r
1067 drp_videoEncoder.SelectedIndex = 1;
\r
1069 drp_videoEncoder.Text = oldval;
\r
1071 else if (drop_format.Text.Contains("MKV"))
\r
1073 oldval = drp_videoEncoder.Text;
\r
1074 drp_videoEncoder.Items.Clear();
\r
1075 drp_videoEncoder.Items.Add("MPEG-4 (FFmpeg)");
\r
1076 drp_videoEncoder.Items.Add("H.264 (x264)");
\r
1077 drp_videoEncoder.Items.Add("VP3 (Theora)");
\r
1078 drp_videoEncoder.Text = oldval;
\r
1081 private void setExtension(string newExtension)
\r
1083 text_destination.Text = text_destination.Text.Replace(".mp4", newExtension);
\r
1084 text_destination.Text = text_destination.Text.Replace(".m4v", newExtension);
\r
1085 text_destination.Text = text_destination.Text.Replace(".mkv", newExtension);
\r
1089 private void drp_videoEncoder_SelectedIndexChanged(object sender, EventArgs e)
\r
1091 setContainerOpts();
\r
1093 //Turn off some options which are H.264 only when the user selects a non h.264 encoder
\r
1094 if (drp_videoEncoder.Text.Contains("H.264"))
\r
1096 if (check_2PassEncode.CheckState == CheckState.Checked)
\r
1097 check_turbo.Enabled = true;
\r
1099 tab_advanced.Enabled = true;
\r
1100 if ((drop_format.Text.Contains("MP4")) || (drop_format.Text.Contains("M4V")))
\r
1101 check_iPodAtom.Enabled = true;
\r
1103 check_iPodAtom.Enabled = false;
\r
1107 check_turbo.CheckState = CheckState.Unchecked;
\r
1108 check_turbo.Enabled = false;
\r
1109 tab_advanced.Enabled = false;
\r
1110 x264Panel.x264Query = "";
\r
1111 check_iPodAtom.Enabled = false;
\r
1112 check_iPodAtom.Checked = false;
\r
1115 // Setup the CQ Slider
\r
1116 switch (drp_videoEncoder.Text)
\r
1118 case "MPEG-4 (FFmpeg)":
\r
1119 slider_videoQuality.Minimum = 1;
\r
1120 slider_videoQuality.Maximum = 31;
\r
1121 slider_videoQuality.Value = 1;
\r
1122 SliderValue.Text = "0% QP: 31.00";
\r
1124 case "H.264 (x264)":
\r
1125 slider_videoQuality.Minimum = 0;
\r
1126 slider_videoQuality.Value = 0;
\r
1127 slider_videoQuality.TickFrequency = 1;
\r
1128 SliderValue.Text = "0% RF: 51.00";
\r
1129 String step = Properties.Settings.Default.x264cqstep;
\r
1133 slider_videoQuality.Maximum = 255;
\r
1136 slider_videoQuality.Maximum = 204;
\r
1139 slider_videoQuality.Maximum = 155;
\r
1142 slider_videoQuality.Maximum = 102;
\r
1145 slider_videoQuality.Maximum = 51;
\r
1148 slider_videoQuality.Maximum = 51;
\r
1152 case "VP3 (Theora)":
\r
1153 slider_videoQuality.Minimum = 0;
\r
1154 slider_videoQuality.Maximum = 63;
\r
1155 slider_videoQuality.Value = 0;
\r
1156 SliderValue.Text = "0% QP: 0.00";
\r
1161 /// Set the container format options
\r
1163 public void setContainerOpts()
\r
1165 if ((drop_format.Text.Contains("MP4")) || (drop_format.Text.Contains("M4V")))
\r
1167 check_largeFile.Enabled = true;
\r
1168 check_optimiseMP4.Enabled = true;
\r
1169 check_iPodAtom.Enabled = true;
\r
1173 check_largeFile.Enabled = false;
\r
1174 check_optimiseMP4.Enabled = false;
\r
1175 check_iPodAtom.Enabled = false;
\r
1176 check_largeFile.Checked = false;
\r
1177 check_optimiseMP4.Checked = false;
\r
1178 check_iPodAtom.Checked = false;
\r
1181 private void slider_videoQuality_Scroll(object sender, EventArgs e)
\r
1183 switch (drp_videoEncoder.Text)
\r
1185 case "MPEG-4 (FFmpeg)":
\r
1186 double rfValue = 31 - (slider_videoQuality.Value - 1);
\r
1187 double max = slider_videoQuality.Maximum;
\r
1188 double min = slider_videoQuality.Minimum;
\r
1189 double val = ((max - min) - (rfValue - min)) / (max - min);
\r
1190 SliderValue.Text = Math.Round((val * 100), 2) + "% QP:" + (32 - slider_videoQuality.Value);
\r
1192 case "H.264 (x264)":
\r
1194 System.Globalization.CultureInfo culture = System.Globalization.CultureInfo.CreateSpecificCulture("en-US");
\r
1195 double.TryParse(Properties.Settings.Default.x264cqstep,
\r
1196 System.Globalization.NumberStyles.Number,
\r
1199 rfValue = 51.0 - slider_videoQuality.Value * divided;
\r
1200 max = slider_videoQuality.Maximum * divided;
\r
1201 min = slider_videoQuality.Minimum;
\r
1202 val = ((max - min) - (rfValue - min)) / (max - min);
\r
1203 rfValue = Math.Round(rfValue, 2);
\r
1204 SliderValue.Text = Math.Round((val * 100), 2) + "% RF:" + rfValue;
\r
1206 case "VP3 (Theora)":
\r
1207 rfValue = slider_videoQuality.Value;
\r
1208 double value = rfValue / 63;
\r
1209 SliderValue.Text = Math.Round((value * 100), 2) + "% QP:" + slider_videoQuality.Value;
\r
1213 private void radio_targetFilesize_CheckedChanged(object sender, EventArgs e)
\r
1215 text_bitrate.Enabled = false;
\r
1216 text_filesize.Enabled = true;
\r
1217 slider_videoQuality.Enabled = false;
\r
1219 check_2PassEncode.Enabled = true;
\r
1221 private void radio_avgBitrate_CheckedChanged(object sender, EventArgs e)
\r
1223 text_bitrate.Enabled = true;
\r
1224 text_filesize.Enabled = false;
\r
1225 slider_videoQuality.Enabled = false;
\r
1227 check_2PassEncode.Enabled = true;
\r
1229 private void radio_cq_CheckedChanged(object sender, EventArgs e)
\r
1231 text_bitrate.Enabled = false;
\r
1232 text_filesize.Enabled = false;
\r
1233 slider_videoQuality.Enabled = true;
\r
1235 check_2PassEncode.Enabled = false;
\r
1236 check_2PassEncode.CheckState = CheckState.Unchecked;
\r
1238 private void check_2PassEncode_CheckedChanged(object sender, EventArgs e)
\r
1240 if (check_2PassEncode.CheckState.ToString() == "Checked")
\r
1242 if (drp_videoEncoder.Text.Contains("H.264"))
\r
1243 check_turbo.Enabled = true;
\r
1247 check_turbo.Enabled = false;
\r
1248 check_turbo.CheckState = CheckState.Unchecked;
\r
1253 private void text_width_TextChanged(object sender, EventArgs e)
\r
1255 if (text_width.Text == "")
\r
1256 text_width.BackColor = Color.White;
\r
1258 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
1259 lbl_max.Text = "";
\r
1262 Boolean parsed = int.TryParse(text_width.Text, out width);
\r
1265 text_width.BackColor = (width % 16) != 0 ? Color.LightCoral : Color.LightGreen;
\r
1267 if (lbl_Aspect.Text != "Select a Title" && maxWidth == 0 && maxHeight == 0)
\r
1269 if (drp_anamorphic.Text == "None")
\r
1271 int height = Main.cacluateNonAnamorphicHeight(width, text_top.Value, text_bottom.Value, text_left.Value, text_right.Value, selectedTitle);
\r
1273 text_height.Text = height.ToString();
\r
1278 private void text_height_TextChanged(object sender, EventArgs e)
\r
1280 if (text_height.Text == "")
\r
1281 text_height.BackColor = Color.White;
\r
1283 maxHeight = 0; // Reset max height so that it's not using the MaxHeight -Y. Quick hack to allow -Y for preset usage.
\r
1284 lbl_max.Text = maxWidth != 0 ? "Max Width" : "";
\r
1287 Boolean parsed = int.TryParse(text_height.Text, out height);
\r
1289 text_height.BackColor = (height % 16) != 0 ? Color.LightCoral : Color.LightGreen;
\r
1291 private void check_customCrop_CheckedChanged(object sender, EventArgs e)
\r
1293 text_left.Enabled = true;
\r
1294 text_right.Enabled = true;
\r
1295 text_top.Enabled = true;
\r
1296 text_bottom.Enabled = true;
\r
1297 if (selectedTitle != null)
\r
1299 text_top.Text = selectedTitle.AutoCropDimensions[0].ToString();
\r
1300 text_bottom.Text = selectedTitle.AutoCropDimensions[1].ToString();
\r
1301 text_left.Text = selectedTitle.AutoCropDimensions[2].ToString();
\r
1302 text_right.Text = selectedTitle.AutoCropDimensions[3].ToString();
\r
1306 text_left.Text = "0";
\r
1307 text_right.Text = "0";
\r
1308 text_top.Text = "0";
\r
1309 text_bottom.Text = "0";
\r
1312 private void check_autoCrop_CheckedChanged(object sender, EventArgs e)
\r
1314 text_left.Enabled = false;
\r
1315 text_right.Enabled = false;
\r
1316 text_top.Enabled = false;
\r
1317 text_bottom.Enabled = false;
\r
1319 private void drp_anamorphic_SelectedIndexChanged(object sender, EventArgs e)
\r
1321 if (drp_anamorphic.SelectedIndex == 1)
\r
1323 text_height.BackColor = Color.LightGray;
\r
1324 text_width.BackColor = Color.LightGray;
\r
1325 text_height.Text = "";
\r
1326 text_width.Text = "";
\r
1327 text_height.Enabled = false;
\r
1328 text_width.Enabled = false;
\r
1331 if (drp_anamorphic.SelectedIndex == 2)
\r
1333 text_height.Text = "";
\r
1334 text_height.Enabled = false;
\r
1335 text_height.BackColor = Color.LightGray;
\r
1337 text_width.Enabled = true;
\r
1338 text_width.BackColor = Color.White;
\r
1341 if (drp_anamorphic.SelectedIndex == 0)
\r
1343 text_height.BackColor = Color.White;
\r
1344 text_width.BackColor = Color.White;
\r
1345 text_height.Enabled = true;
\r
1346 text_width.Enabled = true;
\r
1351 private void ctl_decomb_changed(object sender, EventArgs e)
\r
1353 if (ctl_decomb.getDropValue != "Off")
\r
1354 if (ctl_deinterlace.getDropValue != "None")
\r
1355 ctl_deinterlace.setOption("None");
\r
1357 private void ctl_deinterlace_changed(object sender, EventArgs e)
\r
1359 if (ctl_detelecine.getDropValue != "None")
\r
1360 if (ctl_decomb.getDropValue != "Off")
\r
1361 ctl_decomb.setOption("Off");
\r
1363 private void slider_deblock_Scroll(object sender, EventArgs e)
\r
1365 lbl_deblockVal.Text = slider_deblock.Value == 4 ? "Off" : slider_deblock.Value.ToString();
\r
1369 private void drp_subtitle_SelectedIndexChanged(object sender, EventArgs e)
\r
1371 if (drp_subtitle.Text.Contains("None"))
\r
1373 check_forced.Enabled = false;
\r
1374 check_forced.Checked = false;
\r
1377 check_forced.Enabled = true;
\r
1380 // Chapter Marker Tab
\r
1381 private void Check_ChapterMarkers_CheckedChanged(object sender, EventArgs e)
\r
1383 if (Check_ChapterMarkers.Checked)
\r
1385 drop_format.SelectedIndex = 1;
\r
1386 data_chpt.Rows.Clear();
\r
1387 data_chpt.Enabled = true;
\r
1388 DataGridView chapterGridView = Main.chapterNaming(data_chpt, drop_chapterFinish.Text);
\r
1389 if (chapterGridView != null)
\r
1390 data_chpt = chapterGridView;
\r
1394 drop_format.SelectedIndex = 0;
\r
1395 data_chpt.Rows.Clear();
\r
1396 data_chpt.Enabled = false;
\r
1400 // Query Editor Tab
\r
1401 private void btn_generate_Query_Click(object sender, EventArgs e)
\r
1403 rtf_query.Text = queryGen.GenerateTheQuery(this);
\r
1405 private void btn_clear_Click(object sender, EventArgs e)
\r
1407 rtf_query.Clear();
\r
1411 // MainWindow Components, Actions and Functions ***********************
\r
1413 #region Source Scan
\r
1414 public Boolean isScanning { get; set; }
\r
1415 private static int scanProcessID { get; set; }
\r
1416 private void setupGUIforScan(String filename)
\r
1418 text_source.Text = filename;
\r
1420 foreach (Control ctrl in Controls)
\r
1422 if (!(ctrl is StatusStrip || ctrl is MenuStrip || ctrl is ToolStrip))
\r
1423 ctrl.Enabled = false;
\r
1425 lbl_encode.Visible = true;
\r
1426 lbl_encode.Text = "Scanning ...";
\r
1427 gb_source.Text = "Source: Scanning ...";
\r
1428 btn_source.Enabled = false;
\r
1429 btn_start.Enabled = false;
\r
1430 btn_showQueue.Enabled = false;
\r
1431 btn_add2Queue.Enabled = false;
\r
1432 tb_preview.Enabled = false;
\r
1433 mnu_killCLI.Visible = true;
\r
1435 private void startScan(String filename)
\r
1439 lbl_encode.Visible = true;
\r
1440 lbl_encode.Text = "Scanning...";
\r
1441 isScanning = true;
\r
1442 ThreadPool.QueueUserWorkItem(scanProcess, filename);
\r
1444 catch (Exception exc)
\r
1446 MessageBox.Show("frmMain.cs - startScan " + exc, "Error", MessageBoxButtons.OK, MessageBoxIcon.Error);
\r
1449 private void scanProcess(object state)
\r
1453 string inputFile = (string)state;
\r
1454 string handbrakeCLIPath = Path.Combine(Application.StartupPath, "HandBrakeCLI.exe");
\r
1455 string logDir = Environment.GetFolderPath(Environment.SpecialFolder.ApplicationData) + "\\HandBrake\\logs";
\r
1456 string dvdInfoPath = Path.Combine(logDir, "last_scan_log.txt");
\r
1458 // Make we don't pick up a stale last_encode_log.txt (and that we have rights to the file)
\r
1459 if (File.Exists(dvdInfoPath))
\r
1460 File.Delete(dvdInfoPath);
\r
1462 String dvdnav = string.Empty;
\r
1463 if (Properties.Settings.Default.dvdnav == "Checked")
\r
1464 dvdnav = " --dvdnav";
\r
1465 string strCmdLine = String.Format(@"cmd /c """"{0}"" -i ""{1}"" -t0 {2} -v >""{3}"" 2>&1""", handbrakeCLIPath, inputFile, dvdnav, dvdInfoPath);
\r
1467 ProcessStartInfo hbParseDvd = new ProcessStartInfo("CMD.exe", strCmdLine) { WindowStyle = ProcessWindowStyle.Hidden };
\r
1469 Boolean cleanExit = true;
\r
1470 using (hbproc = Process.Start(hbParseDvd))
\r
1472 Process[] before = Process.GetProcesses(); // Get a list of running processes before starting.
\r
1473 scanProcessID = Main.getCliProcess(before);
\r
1474 hbproc.WaitForExit();
\r
1475 if (hbproc.ExitCode != 0)
\r
1476 cleanExit = false;
\r
1479 if (cleanExit) // If 0 exit code, CLI exited cleanly.
\r
1481 if (!File.Exists(dvdInfoPath))
\r
1483 throw new Exception(
\r
1484 "Unable to retrieve the DVD Info. last_scan_log.txt is missing. \nExpected location of last_scan_log.txt: \n" +
\r
1488 using (StreamReader sr = new StreamReader(dvdInfoPath))
\r
1490 thisDVD = DVD.Parse(sr);
\r
1495 updateUIafterScan();
\r
1498 catch (Exception exc)
\r
1500 MessageBox.Show("frmMain.cs - scanProcess() " + exc, "Error", MessageBoxButtons.OK, MessageBoxIcon.Error);
\r
1504 private void updateUIafterScan()
\r
1508 if (InvokeRequired)
\r
1510 BeginInvoke(new UpdateWindowHandler(updateUIafterScan));
\r
1514 // Setup some GUI components
\r
1515 drp_dvdtitle.Items.Clear();
\r
1516 if (thisDVD.Titles.Count != 0)
\r
1517 drp_dvdtitle.Items.AddRange(thisDVD.Titles.ToArray());
\r
1518 drp_dvdtitle.Text = "Automatic";
\r
1519 drop_chapterFinish.Text = "Auto";
\r
1520 drop_chapterStart.Text = "Auto";
\r
1522 // Now select the longest title
\r
1523 if (thisDVD.Titles.Count != 0)
\r
1524 drp_dvdtitle.SelectedItem = Main.selectLongestTitle(drp_dvdtitle);
\r
1526 // Enable the creation of chapter markers if the file is an image of a dvd.
\r
1527 if (text_source.Text.ToLower().Contains(".iso") || text_source.Text.ToLower().Contains("VIDEO_TS"))
\r
1528 Check_ChapterMarkers.Enabled = true;
\r
1531 Check_ChapterMarkers.Enabled = false;
\r
1532 Check_ChapterMarkers.Checked = false;
\r
1533 data_chpt.Rows.Clear();
\r
1536 // If no titles were found, Display an error message
\r
1537 if (drp_dvdtitle.Items.Count == 0)
\r
1538 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
1540 // Enable the GUI components and enable any disabled components
\r
1543 catch (Exception exc)
\r
1545 MessageBox.Show("frmMain.cs - updateUIafterScan " + exc, "Error", MessageBoxButtons.OK, MessageBoxIcon.Error);
\r
1549 private void enableGUI()
\r
1553 if (InvokeRequired)
\r
1554 BeginInvoke(new UpdateWindowHandler(enableGUI));
\r
1555 lbl_encode.Text = "Scan Completed";
\r
1556 gb_source.Text = "Source";
\r
1557 foreach (Control ctrl in Controls)
\r
1558 ctrl.Enabled = true;
\r
1559 btn_start.Enabled = true;
\r
1560 btn_showQueue.Enabled = true;
\r
1561 btn_add2Queue.Enabled = true;
\r
1562 tb_preview.Enabled = true;
\r
1563 btn_source.Enabled = true;
\r
1564 mnu_killCLI.Visible = false;
\r
1566 catch (Exception exc)
\r
1568 MessageBox.Show("frmMain.cs - enableGUI() " + exc, "Error", MessageBoxButtons.OK, MessageBoxIcon.Error);
\r
1571 private void killScan()
\r
1578 Process[] prs = Process.GetProcesses();
\r
1579 foreach (Process process in prs)
\r
1581 if (process.Id == scanProcessID)
\r
1583 process.Refresh();
\r
1584 if (!process.HasExited)
\r
1589 catch (Exception ex)
\r
1591 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
1594 private void resetGUI()
\r
1596 drp_dvdtitle.Items.Clear();
\r
1597 drp_dvdtitle.Text = "Automatic";
\r
1598 drop_chapterStart.Items.Clear();
\r
1599 drop_chapterStart.Text = "Auto";
\r
1600 drop_chapterFinish.Items.Clear();
\r
1601 drop_chapterFinish.Text = "Auto";
\r
1602 lbl_duration.Text = "Select a Title";
\r
1603 lbl_src_res.Text = "Select a Title";
\r
1604 lbl_Aspect.Text = "Select a Title";
\r
1605 text_source.Text = "Click 'Source' to continue";
\r
1606 text_destination.Text = "";
\r
1608 selectedTitle = null;
\r
1609 isScanning = false;
\r
1615 /// Set the GUI to it's finished encoding state.
\r
1617 private void setEncodeFinished()
\r
1621 if (InvokeRequired)
\r
1623 BeginInvoke(new UpdateWindowHandler(setEncodeFinished));
\r
1627 lbl_encode.Text = "Encoding Finished";
\r
1628 btn_start.Text = "Start";
\r
1629 btn_start.ToolTipText = "Start the encoding process";
\r
1630 btn_start.Image = Properties.Resources.Play;
\r
1632 // If the window is minimized, display the notification in a popup.
\r
1633 if (FormWindowState.Minimized == this.WindowState)
\r
1635 notifyIcon.BalloonTipText = lbl_encode.Text;
\r
1636 notifyIcon.ShowBalloonTip(500);
\r
1639 catch (Exception exc)
\r
1641 MessageBox.Show(exc.ToString());
\r
1646 /// Set the GUI to it's started encoding state.
\r
1648 private void setEncodeStarted()
\r
1652 if (InvokeRequired)
\r
1654 BeginInvoke(new UpdateWindowHandler(setEncodeStarted));
\r
1658 lbl_encode.Visible = true;
\r
1659 lbl_encode.Text = "Encoding in Progress";
\r
1660 btn_start.Text = "Stop";
\r
1661 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
1662 btn_start.Image = Properties.Resources.stop;
\r
1664 catch (Exception exc)
\r
1666 MessageBox.Show(exc.ToString());
\r
1671 #region DVD Drive Detection
\r
1672 private delegate void ProgressUpdateHandler();
\r
1673 private void getDriveInfoThread()
\r
1677 if (InvokeRequired)
\r
1679 BeginInvoke(new ProgressUpdateHandler(getDriveInfoThread));
\r
1683 Boolean foundDrive = false;
\r
1684 DriveInfo[] theCollectionOfDrives = DriveInfo.GetDrives();
\r
1685 foreach (DriveInfo curDrive in theCollectionOfDrives)
\r
1687 if (curDrive.DriveType == DriveType.CDRom && curDrive.IsReady)
\r
1689 if (File.Exists(curDrive.RootDirectory + "VIDEO_TS\\VIDEO_TS.IFO"))
\r
1691 mnu_dvd_drive.Text = curDrive.RootDirectory + "VIDEO_TS (" + curDrive.VolumeLabel + ")";
\r
1692 foundDrive = true;
\r
1698 if (foundDrive == false)
\r
1699 mnu_dvd_drive.Text = "[No DVD Drive Ready]";
\r
1703 mnu_dvd_drive.Text = "[No DVD Drive Ready / Found]";
\r
1708 #region Public Methods
\r
1710 /// Access the preset Handler and setup the preset panel.
\r
1712 public void loadPresetPanel()
\r
1714 if (presetHandler.checkIfPresetsAreOutOfDate())
\r
1715 if (Properties.Settings.Default.presetNotification == "Unchecked")
\r
1717 "HandBrake has determined your built-in presets are out of date... These presets will now be updated.",
\r
1718 "Preset Update", MessageBoxButtons.OK, MessageBoxIcon.Information);
\r
1720 presetHandler.getPresetPanel(ref treeView_presets);
\r
1721 treeView_presets.Update();
\r
1725 /// Either Encode or Scan was last performed.
\r
1727 public string lastAction { get; set; }
\r
1732 /// If the queue is being processed, prompt the user to confirm application close.
\r
1734 /// <param name="e"></param>
\r
1735 protected override void OnFormClosing(FormClosingEventArgs e)
\r
1737 // If currently encoding, the queue isn't paused, and there are queue items to process, prompt to confirm close.
\r
1738 if ((encodeQueue.isEncoding) && (!encodeQueue.isPaused) && (encodeQueue.count() > 0))
\r
1740 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
1741 "Close HandBrake?", MessageBoxButtons.YesNo, MessageBoxIcon.Question);
\r
1742 if (result == DialogResult.No)
\r
1745 base.OnFormClosing(e);
\r
1749 #region In-GUI Encode Status (Experimental)
\r
1750 private Process HBProcess { get; set; }
\r
1752 private void encodeMonitorThread()
\r
1756 Parser encode = new Parser(HBProcess.StandardOutput.BaseStream);
\r
1757 encode.OnEncodeProgress += encode_OnEncodeProgress;
\r
1758 while (!encode.EndOfStream)
\r
1760 encode.readEncodeStatus();
\r
1763 catch (Exception exc)
\r
1765 MessageBox.Show(exc.ToString());
\r
1769 private void encode_OnEncodeProgress(object Sender, int CurrentTask, int TaskCount, float PercentComplete, float CurrentFps, float AverageFps, TimeSpan TimeRemaining)
\r
1771 if (this.InvokeRequired)
\r
1773 this.BeginInvoke(new EncodeProgressEventHandler(encode_OnEncodeProgress),
\r
1774 new object[] { Sender, CurrentTask, TaskCount, PercentComplete, CurrentFps, AverageFps, TimeRemaining });
\r
1777 lbl_encode.Text = string.Format("Encode Progress: {0}%, FPS: {1}, Avg FPS: {2}, Time Remaining: {3} ", PercentComplete, CurrentFps, AverageFps, TimeRemaining);
\r
1781 // This is the END of the road ****************************************
\r