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
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? 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
589 if (result == DialogResult.Yes)
\r
592 encodeQueue.pauseEncode();
\r
593 encodeQueue.endEncode();
\r
596 setEncodeFinished();
\r
601 if (encodeQueue.count() != 0 || (text_source.Text != string.Empty && text_source.Text != "Click 'Source' to continue" && text_destination.Text != string.Empty))
\r
603 // Set the last action to encode.
\r
604 // This is used for tracking which file to load in the activity window
\r
605 lastAction = "encode";
\r
607 String query = rtf_query.Text != "" ? rtf_query.Text : queryGen.GenerateTheQuery(this);
\r
609 if (encodeQueue.count() == 0)
\r
611 encodeQueue.add(query, text_source.Text, text_destination.Text);
\r
612 encodeQueue.write2disk("hb_queue_recovery.xml");
\r
614 queueWindow.setQueue();
\r
615 if (encodeQueue.count() > 1)
\r
616 queueWindow.Show(false);
\r
618 setEncodeStarted(); // Encode is running, so setup the GUI appropriately
\r
619 encodeQueue.startEncode(); // Start The Queue Encoding Process
\r
622 else if (text_source.Text == string.Empty || text_source.Text == "Click 'Source' to continue" || text_destination.Text == string.Empty)
\r
623 MessageBox.Show("No source OR destination selected.", "Warning", MessageBoxButtons.OK, MessageBoxIcon.Warning);
\r
626 private void btn_add2Queue_Click(object sender, EventArgs e)
\r
629 if (text_source.Text == string.Empty || text_source.Text == "Click 'Source' to continue" || text_destination.Text == string.Empty)
\r
630 MessageBox.Show("No source OR destination selected.", "Warning", MessageBoxButtons.OK, MessageBoxIcon.Warning);
\r
633 String query = queryGen.GenerateTheQuery(this);
\r
634 if (rtf_query.Text != "")
\r
635 query = rtf_query.Text;
\r
637 if (encodeQueue.checkDestinationPath(text_destination.Text))
\r
639 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
640 "Warning", MessageBoxButtons.YesNo, MessageBoxIcon.Warning);
\r
641 if (result == DialogResult.Yes)
\r
642 encodeQueue.add(query, text_source.Text, text_destination.Text);
\r
646 encodeQueue.add(query, text_source.Text, text_destination.Text);
\r
648 encodeQueue.write2disk("hb_queue_recovery.xml"); // Writes the queue to the recovery file, just incase the GUI crashes.
\r
649 queueWindow.Show();
\r
652 private void btn_showQueue_Click(object sender, EventArgs e)
\r
654 queueWindow.Show();
\r
656 private void tb_preview_Click(object sender, EventArgs e)
\r
658 if (text_source.Text == "" || text_source.Text == "Click 'Source' to continue" || text_destination.Text == "")
\r
659 MessageBox.Show("No source OR destination selected.", "Warning", MessageBoxButtons.OK, MessageBoxIcon.Warning);
\r
662 if (qtpreview == null)
\r
664 qtpreview = new frmPreview(this);
\r
667 else if (qtpreview.IsDisposed)
\r
669 qtpreview = new frmPreview(this);
\r
673 MessageBox.Show(qtpreview, "The preview window is already open!", "Warning", MessageBoxButtons.OK, MessageBoxIcon.Warning);
\r
676 private void btn_ActivityWindow_Click(object sender, EventArgs e)
\r
678 String file = lastAction == "scan" ? "last_scan_log.txt" : "last_encode_log.txt";
\r
680 frmActivityWindow ActivityWindow = new frmActivityWindow(file, encodeQueue, this);
\r
681 ActivityWindow.Show();
\r
685 #region System Tray Icon
\r
686 private void frmMain_Resize(object sender, EventArgs e)
\r
688 if (FormWindowState.Minimized == this.WindowState)
\r
690 notifyIcon.Visible = true;
\r
691 if (!encodeQueue.isEncoding)
\r
693 notifyIcon.BalloonTipText = lbl_encode.Text != "" ? lbl_encode.Text : "Not Encoding";
\r
694 if (Properties.Settings.Default.trayIconAlerts == "Checked")
\r
695 notifyIcon.ShowBalloonTip(500);
\r
699 else if (FormWindowState.Normal == this.WindowState)
\r
700 notifyIcon.Visible = false;
\r
702 private void notifyIcon_MouseDoubleClick(object sender, MouseEventArgs e)
\r
704 this.Visible = true;
\r
706 this.WindowState = FormWindowState.Normal;
\r
707 notifyIcon.Visible = false;
\r
709 private void btn_restore_Click(object sender, EventArgs e)
\r
711 this.Visible = true;
\r
713 this.WindowState = FormWindowState.Normal;
\r
714 notifyIcon.Visible = false;
\r
718 #region Tab Control
\r
721 private void btn_dvd_source_Click(object sender, EventArgs e)
\r
723 // Enable the creation of chapter markers.
\r
724 Check_ChapterMarkers.Enabled = true;
\r
726 // Set the last action to scan.
\r
727 // This is used for tracking which file to load in the activity window
\r
728 lastAction = "scan";
\r
729 text_source.Text = "";
\r
731 if (DVD_Open.ShowDialog() == DialogResult.OK)
\r
733 String filename = DVD_Open.SelectedPath;
\r
735 if (filename.StartsWith("\\"))
\r
736 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
739 if (filename != "")
\r
741 setupGUIforScan(filename);
\r
742 startScan(filename);
\r
745 text_source.Text = "Click 'Source' to continue";
\r
749 text_source.Text = "Click 'Source' to continue";
\r
751 private void btn_file_source_Click(object sender, EventArgs e)
\r
753 // Set the last action to scan.
\r
754 // This is used for tracking which file to load in the activity window
\r
755 lastAction = "scan";
\r
756 text_source.Text = "";
\r
758 if (ISO_Open.ShowDialog() == DialogResult.OK)
\r
760 String filename = ISO_Open.FileName;
\r
761 if (filename.StartsWith("\\"))
\r
763 "Sorry, HandBrake does not support UNC file paths. \nTry mounting the share as a network drive in My Computer",
\r
764 "Warning", MessageBoxButtons.OK, MessageBoxIcon.Warning);
\r
767 if (filename != "")
\r
769 setupGUIforScan(filename);
\r
770 startScan(filename);
\r
773 text_source.Text = "Click 'Source' to continue";
\r
777 text_source.Text = "Click 'Source' to continue";
\r
779 private void mnu_dvd_drive_Click(object sender, EventArgs e)
\r
781 // Enable the creation of chapter markers.
\r
782 Check_ChapterMarkers.Enabled = true;
\r
784 // Set the last action to scan.
\r
785 // This is used for tracking which file to load in the activity window
\r
786 lastAction = "scan";
\r
788 if (mnu_dvd_drive.Text.Contains("VIDEO_TS"))
\r
790 string[] path = mnu_dvd_drive.Text.Split(' ');
\r
791 String filename = path[0];
\r
792 setupGUIforScan(filename);
\r
793 startScan(filename);
\r
796 // If there are no titles in the dropdown menu then the scan has obviously failed. Display an error message explaining to the user.
\r
797 if (drp_dvdtitle.Items.Count == 0)
\r
798 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
800 lbl_encode.Text = "";
\r
802 private void drp_dvdtitle_Click(object sender, EventArgs e)
\r
804 if ((drp_dvdtitle.Items.Count == 1) && (drp_dvdtitle.Items[0].ToString() == "Automatic"))
\r
805 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
807 private void drp_dvdtitle_SelectedIndexChanged(object sender, EventArgs e)
\r
809 // Reset some values on the form
\r
810 lbl_Aspect.Text = "Select a Title";
\r
811 //lbl_RecomendedCrop.Text = "Select a Title";
\r
812 drop_chapterStart.Items.Clear();
\r
813 drop_chapterFinish.Items.Clear();
\r
815 // If the dropdown is set to automatic nothing else needs to be done.
\r
816 // Otheriwse if its not, title data has to be loased from parsing.
\r
817 if (drp_dvdtitle.Text != "Automatic")
\r
819 selectedTitle = drp_dvdtitle.SelectedItem as Parsing.Title;
\r
821 // Set the Aspect Ratio
\r
822 lbl_Aspect.Text = selectedTitle.AspectRatio.ToString();
\r
823 lbl_src_res.Text = selectedTitle.Resolution.Width + " x " + selectedTitle.Resolution.Height;
\r
824 lbl_duration.Text = selectedTitle.Duration.ToString();
\r
826 // Set the Recommended Cropping values
\r
827 text_top.Text = selectedTitle.AutoCropDimensions[0].ToString();
\r
828 text_bottom.Text = selectedTitle.AutoCropDimensions[1].ToString();
\r
829 text_left.Text = selectedTitle.AutoCropDimensions[2].ToString();
\r
830 text_right.Text = selectedTitle.AutoCropDimensions[3].ToString();
\r
832 // Populate the Angles dropdown
\r
833 drop_angle.Items.Clear();
\r
834 if (Properties.Settings.Default.dvdnav == "Checked")
\r
836 drop_angle.Visible = true;
\r
837 lbl_angle.Visible = true;
\r
838 drop_angle.Items.AddRange(selectedTitle.Angles.ToArray());
\r
839 if (drop_angle.Items.Count != 0)
\r
840 drop_angle.SelectedIndex = 0;
\r
844 drop_angle.Visible = false;
\r
845 lbl_angle.Visible = false;
\r
848 // Populate the Start chapter Dropdown
\r
849 drop_chapterStart.Items.Clear();
\r
850 drop_chapterStart.Items.AddRange(selectedTitle.Chapters.ToArray());
\r
851 if (drop_chapterStart.Items.Count > 0)
\r
852 drop_chapterStart.Text = drop_chapterStart.Items[0].ToString();
\r
854 // Populate the Final Chapter Dropdown
\r
855 drop_chapterFinish.Items.Clear();
\r
856 drop_chapterFinish.Items.AddRange(selectedTitle.Chapters.ToArray());
\r
857 if (drop_chapterFinish.Items.Count > 0)
\r
858 drop_chapterFinish.Text = drop_chapterFinish.Items[drop_chapterFinish.Items.Count - 1].ToString();
\r
860 // Populate the Audio Channels Dropdown
\r
861 audioPanel.setTrackList(selectedTitle);
\r
863 // Populate the Subtitles dropdown
\r
864 drp_subtitle.Items.Clear();
\r
865 drp_subtitle.Items.Add("None");
\r
866 drp_subtitle.Items.Add("Autoselect");
\r
867 drp_subtitle.Items.AddRange(selectedTitle.Subtitles.ToArray());
\r
868 if (drp_subtitle.Items.Count > 0)
\r
869 drp_subtitle.Text = drp_subtitle.Items[0].ToString();
\r
873 // Run the autoName & chapterNaming functions
\r
874 if (Properties.Settings.Default.autoNaming == "Checked")
\r
876 string autoPath = Main.autoName(drp_dvdtitle, drop_chapterStart.Text, drop_chapterFinish.Text, text_source.Text, text_destination.Text, drop_format.SelectedIndex);
\r
877 if (autoPath != null)
\r
878 text_destination.Text = autoPath;
\r
880 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
883 data_chpt.Rows.Clear();
\r
884 if (selectedTitle.Chapters.Count != 1)
\r
886 DataGridView chapterGridView = Main.chapterNaming(data_chpt, drop_chapterFinish.Text);
\r
887 if (chapterGridView != null)
\r
888 data_chpt = chapterGridView;
\r
892 Check_ChapterMarkers.Checked = false;
\r
893 Check_ChapterMarkers.Enabled = false;
\r
896 // Hack to force the redraw of the scrollbars which don't resize properly when the control is disabled.
\r
897 data_chpt.Columns[0].Width = 166;
\r
898 data_chpt.Columns[0].Width = 165;
\r
900 private void drop_chapterStart_SelectedIndexChanged(object sender, EventArgs e)
\r
902 int c_start, c_end;
\r
904 if (drop_chapterFinish.Text == "Auto" && drop_chapterFinish.Items.Count != 0)
\r
905 drop_chapterFinish.SelectedIndex = drop_chapterFinish.Items.Count - 1;
\r
907 int.TryParse(drop_chapterStart.Text, out c_start);
\r
908 int.TryParse(drop_chapterFinish.Text, out c_end);
\r
912 if (c_start > c_end)
\r
913 drop_chapterFinish.Text = c_start.ToString();
\r
916 lbl_duration.Text = Main.calculateDuration(drop_chapterStart.Text, drop_chapterFinish.Text, selectedTitle).ToString();
\r
918 // Run the Autonaming function
\r
919 if (Properties.Settings.Default.autoNaming == "Checked")
\r
920 text_destination.Text = Main.autoName(drp_dvdtitle, drop_chapterStart.Text, drop_chapterFinish.Text, text_source.Text, text_destination.Text, drop_format.SelectedIndex);
\r
922 // Disable chapter markers if only 1 chapter is selected.
\r
923 if (c_start == c_end)
\r
925 Check_ChapterMarkers.Checked = false;
\r
926 Check_ChapterMarkers.Enabled = false;
\r
929 Check_ChapterMarkers.Enabled = true;
\r
931 private void drop_chapterFinish_SelectedIndexChanged(object sender, EventArgs e)
\r
933 int c_start, c_end;
\r
935 if (drop_chapterStart.Text == "Auto" && drop_chapterStart.Items.Count >= 1)
\r
936 drop_chapterStart.SelectedIndex = 1;
\r
938 int.TryParse(drop_chapterStart.Text, out c_start);
\r
939 int.TryParse(drop_chapterFinish.Text, out c_end);
\r
943 if (c_end < c_start)
\r
944 drop_chapterFinish.Text = c_start.ToString();
\r
947 lbl_duration.Text = Main.calculateDuration(drop_chapterStart.Text, drop_chapterFinish.Text, selectedTitle).ToString();
\r
949 // Run the Autonaming function
\r
950 if (Properties.Settings.Default.autoNaming == "Checked")
\r
951 text_destination.Text = Main.autoName(drp_dvdtitle, drop_chapterStart.Text, drop_chapterFinish.Text, text_source.Text, text_destination.Text, drop_format.SelectedIndex);
\r
953 // Add more rows to the Chapter menu if needed.
\r
954 if (Check_ChapterMarkers.Checked)
\r
956 int i = data_chpt.Rows.Count, finish = 0;
\r
958 if (drop_chapterFinish.Text != "Auto")
\r
959 int.TryParse(drop_chapterFinish.Text, out finish);
\r
963 int n = data_chpt.Rows.Add();
\r
964 data_chpt.Rows[n].Cells[0].Value = (i + 1);
\r
965 data_chpt.Rows[n].Cells[1].Value = "Chapter " + (i + 1);
\r
966 data_chpt.Rows[n].Cells[0].ValueType = typeof(int);
\r
967 data_chpt.Rows[n].Cells[1].ValueType = typeof(string);
\r
972 // Disable chapter markers if only 1 chapter is selected.
\r
973 if (c_start == c_end)
\r
975 Check_ChapterMarkers.Checked = false;
\r
976 Check_ChapterMarkers.Enabled = false;
\r
979 Check_ChapterMarkers.Enabled = true;
\r
983 private void btn_destBrowse_Click(object sender, EventArgs e)
\r
985 // This removes the file extension from the filename box on the save file dialog.
\r
986 // It's daft but some users don't realise that typing an extension overrides the dropdown extension selected.
\r
987 DVD_Save.FileName = Path.GetFileNameWithoutExtension(text_destination.Text);
\r
989 if (Path.IsPathRooted(text_destination.Text))
\r
990 DVD_Save.InitialDirectory = Path.GetDirectoryName(text_destination.Text);
\r
992 // Show the dialog and set the main form file path
\r
993 if (drop_format.SelectedIndex.Equals(0))
\r
994 DVD_Save.FilterIndex = 1;
\r
995 else if (drop_format.SelectedIndex.Equals(1))
\r
996 DVD_Save.FilterIndex = 2;
\r
997 else if (drop_format.SelectedIndex.Equals(2))
\r
998 DVD_Save.FilterIndex = 3;
\r
1000 if (DVD_Save.ShowDialog() == DialogResult.OK)
\r
1002 if (DVD_Save.FileName.StartsWith("\\"))
\r
1003 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
1006 // Add a file extension manually, as FileDialog.AddExtension has issues with dots in filenames
\r
1007 switch (DVD_Save.FilterIndex)
\r
1010 if (!Path.GetExtension(DVD_Save.FileName).Equals(".mp4", StringComparison.InvariantCultureIgnoreCase))
\r
1011 DVD_Save.FileName += ".mp4";
\r
1014 if (!Path.GetExtension(DVD_Save.FileName).Equals(".m4v", StringComparison.InvariantCultureIgnoreCase))
\r
1015 DVD_Save.FileName += ".m4v";
\r
1018 if (!Path.GetExtension(DVD_Save.FileName).Equals(".mkv", StringComparison.InvariantCultureIgnoreCase))
\r
1019 DVD_Save.FileName += ".mkv";
\r
1025 text_destination.Text = DVD_Save.FileName;
\r
1027 // Quicktime requires .m4v file for chapter markers to work. If checked, change the extension to .m4v (mp4 and m4v are the same thing)
\r
1028 if (Check_ChapterMarkers.Checked)
\r
1029 drop_format.SelectedIndex = 1;
\r
1033 private void text_destination_TextChanged(object sender, EventArgs e)
\r
1035 string path = text_destination.Text;
\r
1036 if (path.EndsWith(".mp4"))
\r
1037 drop_format.SelectedIndex = 0;
\r
1038 else if (path.EndsWith(".m4v"))
\r
1039 drop_format.SelectedIndex = 1;
\r
1040 else if (path.EndsWith(".mkv"))
\r
1041 drop_format.SelectedIndex = 2;
\r
1044 // Output Settings
\r
1045 private void drop_format_SelectedIndexChanged(object sender, EventArgs e)
\r
1047 if (drop_format.SelectedIndex == 0)
\r
1048 setExtension(".mp4");
\r
1049 else if (drop_format.SelectedIndex == 1)
\r
1050 setExtension(".m4v");
\r
1051 else if (drop_format.SelectedIndex == 2)
\r
1052 setExtension(".mkv");
\r
1054 audioPanel.setAudioByContainer(drop_format.Text);
\r
1057 if ((drop_format.Text.Contains("MP4")) || (drop_format.Text.Contains("M4V")))
\r
1059 oldval = drp_videoEncoder.Text;
\r
1060 drp_videoEncoder.Items.Clear();
\r
1061 drp_videoEncoder.Items.Add("MPEG-4 (FFmpeg)");
\r
1062 drp_videoEncoder.Items.Add("H.264 (x264)");
\r
1063 if (oldval == "VP3 (Theora)")
\r
1064 drp_videoEncoder.SelectedIndex = 1;
\r
1066 drp_videoEncoder.Text = oldval;
\r
1068 else if (drop_format.Text.Contains("MKV"))
\r
1070 oldval = drp_videoEncoder.Text;
\r
1071 drp_videoEncoder.Items.Clear();
\r
1072 drp_videoEncoder.Items.Add("MPEG-4 (FFmpeg)");
\r
1073 drp_videoEncoder.Items.Add("H.264 (x264)");
\r
1074 drp_videoEncoder.Items.Add("VP3 (Theora)");
\r
1075 drp_videoEncoder.Text = oldval;
\r
1078 private void setExtension(string newExtension)
\r
1080 text_destination.Text = text_destination.Text.Replace(".mp4", newExtension);
\r
1081 text_destination.Text = text_destination.Text.Replace(".m4v", newExtension);
\r
1082 text_destination.Text = text_destination.Text.Replace(".mkv", newExtension);
\r
1086 private void drp_videoEncoder_SelectedIndexChanged(object sender, EventArgs e)
\r
1088 setContainerOpts();
\r
1090 //Turn off some options which are H.264 only when the user selects a non h.264 encoder
\r
1091 if (drp_videoEncoder.Text.Contains("H.264"))
\r
1093 if (check_2PassEncode.CheckState == CheckState.Checked)
\r
1094 check_turbo.Enabled = true;
\r
1096 tab_advanced.Enabled = true;
\r
1097 if ((drop_format.Text.Contains("MP4")) || (drop_format.Text.Contains("M4V")))
\r
1098 check_iPodAtom.Enabled = true;
\r
1100 check_iPodAtom.Enabled = false;
\r
1104 check_turbo.CheckState = CheckState.Unchecked;
\r
1105 check_turbo.Enabled = false;
\r
1106 tab_advanced.Enabled = false;
\r
1107 x264Panel.x264Query = "";
\r
1108 check_iPodAtom.Enabled = false;
\r
1109 check_iPodAtom.Checked = false;
\r
1112 // Setup the CQ Slider
\r
1113 switch (drp_videoEncoder.Text)
\r
1115 case "MPEG-4 (FFmpeg)":
\r
1116 slider_videoQuality.Minimum = 1;
\r
1117 slider_videoQuality.Maximum = 31;
\r
1118 slider_videoQuality.Value = 1;
\r
1119 SliderValue.Text = "0% QP: 31.00";
\r
1121 case "H.264 (x264)":
\r
1122 slider_videoQuality.Minimum = 0;
\r
1123 slider_videoQuality.Value = 0;
\r
1124 slider_videoQuality.TickFrequency = 1;
\r
1125 SliderValue.Text = "0% RF: 51.00";
\r
1126 String step = Properties.Settings.Default.x264cqstep;
\r
1130 slider_videoQuality.Maximum = 255;
\r
1133 slider_videoQuality.Maximum = 204;
\r
1136 slider_videoQuality.Maximum = 155;
\r
1139 slider_videoQuality.Maximum = 102;
\r
1142 slider_videoQuality.Maximum = 51;
\r
1145 slider_videoQuality.Maximum = 51;
\r
1149 case "VP3 (Theora)":
\r
1150 slider_videoQuality.Minimum = 0;
\r
1151 slider_videoQuality.Maximum = 63;
\r
1152 slider_videoQuality.Value = 0;
\r
1153 SliderValue.Text = "0% QP: 0.00";
\r
1158 /// Set the container format options
\r
1160 public void setContainerOpts()
\r
1162 if ((drop_format.Text.Contains("MP4")) || (drop_format.Text.Contains("M4V")))
\r
1164 check_largeFile.Enabled = true;
\r
1165 check_optimiseMP4.Enabled = true;
\r
1166 check_iPodAtom.Enabled = true;
\r
1170 check_largeFile.Enabled = false;
\r
1171 check_optimiseMP4.Enabled = false;
\r
1172 check_iPodAtom.Enabled = false;
\r
1173 check_largeFile.Checked = false;
\r
1174 check_optimiseMP4.Checked = false;
\r
1175 check_iPodAtom.Checked = false;
\r
1178 private void slider_videoQuality_Scroll(object sender, EventArgs e)
\r
1180 switch (drp_videoEncoder.Text)
\r
1182 case "MPEG-4 (FFmpeg)":
\r
1183 double rfValue = 31 - (slider_videoQuality.Value - 1);
\r
1184 double max = slider_videoQuality.Maximum;
\r
1185 double min = slider_videoQuality.Minimum;
\r
1186 double val = ((max - min) - (rfValue - min)) / (max - min);
\r
1187 SliderValue.Text = Math.Round((val * 100), 2) + "% QP:" + (32 - slider_videoQuality.Value);
\r
1189 case "H.264 (x264)":
\r
1191 System.Globalization.CultureInfo culture = System.Globalization.CultureInfo.CreateSpecificCulture("en-US");
\r
1192 double.TryParse(Properties.Settings.Default.x264cqstep,
\r
1193 System.Globalization.NumberStyles.Number,
\r
1196 rfValue = 51.0 - slider_videoQuality.Value * divided;
\r
1197 max = slider_videoQuality.Maximum * divided;
\r
1198 min = slider_videoQuality.Minimum;
\r
1199 val = ((max - min) - (rfValue - min)) / (max - min);
\r
1200 rfValue = Math.Round(rfValue, 2);
\r
1201 SliderValue.Text = Math.Round((val * 100), 2) + "% RF:" + rfValue;
\r
1203 case "VP3 (Theora)":
\r
1204 rfValue = slider_videoQuality.Value;
\r
1205 double value = rfValue / 63;
\r
1206 SliderValue.Text = Math.Round((value * 100), 2) + "% QP:" + slider_videoQuality.Value;
\r
1210 private void radio_targetFilesize_CheckedChanged(object sender, EventArgs e)
\r
1212 text_bitrate.Enabled = false;
\r
1213 text_filesize.Enabled = true;
\r
1214 slider_videoQuality.Enabled = false;
\r
1216 check_2PassEncode.Enabled = true;
\r
1218 private void radio_avgBitrate_CheckedChanged(object sender, EventArgs e)
\r
1220 text_bitrate.Enabled = true;
\r
1221 text_filesize.Enabled = false;
\r
1222 slider_videoQuality.Enabled = false;
\r
1224 check_2PassEncode.Enabled = true;
\r
1226 private void radio_cq_CheckedChanged(object sender, EventArgs e)
\r
1228 text_bitrate.Enabled = false;
\r
1229 text_filesize.Enabled = false;
\r
1230 slider_videoQuality.Enabled = true;
\r
1232 check_2PassEncode.Enabled = false;
\r
1233 check_2PassEncode.CheckState = CheckState.Unchecked;
\r
1235 private void check_2PassEncode_CheckedChanged(object sender, EventArgs e)
\r
1237 if (check_2PassEncode.CheckState.ToString() == "Checked")
\r
1239 if (drp_videoEncoder.Text.Contains("H.264"))
\r
1240 check_turbo.Enabled = true;
\r
1244 check_turbo.Enabled = false;
\r
1245 check_turbo.CheckState = CheckState.Unchecked;
\r
1250 private void text_width_TextChanged(object sender, EventArgs e)
\r
1252 if (text_width.Text == "")
\r
1253 text_width.BackColor = Color.White;
\r
1255 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
1256 lbl_max.Text = "";
\r
1259 Boolean parsed = int.TryParse(text_width.Text, out width);
\r
1262 text_width.BackColor = (width % 16) != 0 ? Color.LightCoral : Color.LightGreen;
\r
1264 if (lbl_Aspect.Text != "Select a Title" && maxWidth == 0 && maxHeight == 0)
\r
1266 if (drp_anamorphic.Text == "None")
\r
1268 int height = Main.cacluateNonAnamorphicHeight(width, text_top.Value, text_bottom.Value, text_left.Value, text_right.Value, selectedTitle);
\r
1270 text_height.Text = height.ToString();
\r
1275 private void text_height_TextChanged(object sender, EventArgs e)
\r
1277 if (text_height.Text == "")
\r
1278 text_height.BackColor = Color.White;
\r
1280 maxHeight = 0; // Reset max height so that it's not using the MaxHeight -Y. Quick hack to allow -Y for preset usage.
\r
1281 lbl_max.Text = maxWidth != 0 ? "Max Width" : "";
\r
1284 Boolean parsed = int.TryParse(text_height.Text, out height);
\r
1286 text_height.BackColor = (height % 16) != 0 ? Color.LightCoral : Color.LightGreen;
\r
1288 private void check_customCrop_CheckedChanged(object sender, EventArgs e)
\r
1290 text_left.Enabled = true;
\r
1291 text_right.Enabled = true;
\r
1292 text_top.Enabled = true;
\r
1293 text_bottom.Enabled = true;
\r
1294 if (selectedTitle != null)
\r
1296 text_top.Text = selectedTitle.AutoCropDimensions[0].ToString();
\r
1297 text_bottom.Text = selectedTitle.AutoCropDimensions[1].ToString();
\r
1298 text_left.Text = selectedTitle.AutoCropDimensions[2].ToString();
\r
1299 text_right.Text = selectedTitle.AutoCropDimensions[3].ToString();
\r
1303 text_left.Text = "0";
\r
1304 text_right.Text = "0";
\r
1305 text_top.Text = "0";
\r
1306 text_bottom.Text = "0";
\r
1309 private void check_autoCrop_CheckedChanged(object sender, EventArgs e)
\r
1311 text_left.Enabled = false;
\r
1312 text_right.Enabled = false;
\r
1313 text_top.Enabled = false;
\r
1314 text_bottom.Enabled = false;
\r
1316 private void drp_anamorphic_SelectedIndexChanged(object sender, EventArgs e)
\r
1318 if (drp_anamorphic.SelectedIndex == 1)
\r
1320 text_height.BackColor = Color.LightGray;
\r
1321 text_width.BackColor = Color.LightGray;
\r
1322 text_height.Text = "";
\r
1323 text_width.Text = "";
\r
1324 text_height.Enabled = false;
\r
1325 text_width.Enabled = false;
\r
1328 if (drp_anamorphic.SelectedIndex == 2)
\r
1330 text_height.Text = "";
\r
1331 text_height.Enabled = false;
\r
1332 text_height.BackColor = Color.LightGray;
\r
1334 text_width.Enabled = true;
\r
1335 text_width.BackColor = Color.White;
\r
1338 if (drp_anamorphic.SelectedIndex == 0)
\r
1340 text_height.BackColor = Color.White;
\r
1341 text_width.BackColor = Color.White;
\r
1342 text_height.Enabled = true;
\r
1343 text_width.Enabled = true;
\r
1348 private void ctl_decomb_changed(object sender, EventArgs e)
\r
1350 if (ctl_decomb.getDropValue != "Off")
\r
1351 if (ctl_deinterlace.getDropValue != "None")
\r
1352 ctl_deinterlace.setOption("None");
\r
1354 private void ctl_deinterlace_changed(object sender, EventArgs e)
\r
1356 if (ctl_detelecine.getDropValue != "None")
\r
1357 if (ctl_decomb.getDropValue != "Off")
\r
1358 ctl_decomb.setOption("Off");
\r
1360 private void slider_deblock_Scroll(object sender, EventArgs e)
\r
1362 lbl_deblockVal.Text = slider_deblock.Value == 4 ? "Off" : slider_deblock.Value.ToString();
\r
1366 private void drp_subtitle_SelectedIndexChanged(object sender, EventArgs e)
\r
1368 if (drp_subtitle.Text.Contains("None"))
\r
1370 check_forced.Enabled = false;
\r
1371 check_forced.Checked = false;
\r
1374 check_forced.Enabled = true;
\r
1377 // Chapter Marker Tab
\r
1378 private void Check_ChapterMarkers_CheckedChanged(object sender, EventArgs e)
\r
1380 if (Check_ChapterMarkers.Checked)
\r
1382 drop_format.SelectedIndex = 1;
\r
1383 data_chpt.Rows.Clear();
\r
1384 data_chpt.Enabled = true;
\r
1385 DataGridView chapterGridView = Main.chapterNaming(data_chpt, drop_chapterFinish.Text);
\r
1386 if (chapterGridView != null)
\r
1387 data_chpt = chapterGridView;
\r
1391 drop_format.SelectedIndex = 0;
\r
1392 data_chpt.Rows.Clear();
\r
1393 data_chpt.Enabled = false;
\r
1397 // Query Editor Tab
\r
1398 private void btn_generate_Query_Click(object sender, EventArgs e)
\r
1400 rtf_query.Text = queryGen.GenerateTheQuery(this);
\r
1402 private void btn_clear_Click(object sender, EventArgs e)
\r
1404 rtf_query.Clear();
\r
1408 // MainWindow Components, Actions and Functions ***********************
\r
1410 #region Source Scan
\r
1411 public Boolean isScanning { get; set; }
\r
1412 private static int scanProcessID { get; set; }
\r
1413 private void setupGUIforScan(String filename)
\r
1415 text_source.Text = filename;
\r
1417 foreach (Control ctrl in Controls)
\r
1419 if (!(ctrl is StatusStrip || ctrl is MenuStrip || ctrl is ToolStrip))
\r
1420 ctrl.Enabled = false;
\r
1422 lbl_encode.Visible = true;
\r
1423 lbl_encode.Text = "Scanning ...";
\r
1424 gb_source.Text = "Source: Scanning ...";
\r
1425 btn_source.Enabled = false;
\r
1426 btn_start.Enabled = false;
\r
1427 btn_showQueue.Enabled = false;
\r
1428 btn_add2Queue.Enabled = false;
\r
1429 tb_preview.Enabled = false;
\r
1430 mnu_killCLI.Visible = true;
\r
1432 private void startScan(String filename)
\r
1436 lbl_encode.Visible = true;
\r
1437 lbl_encode.Text = "Scanning...";
\r
1438 isScanning = true;
\r
1439 ThreadPool.QueueUserWorkItem(scanProcess, filename);
\r
1441 catch (Exception exc)
\r
1443 MessageBox.Show("frmMain.cs - startScan " + exc, "Error", MessageBoxButtons.OK, MessageBoxIcon.Error);
\r
1446 private void scanProcess(object state)
\r
1450 string inputFile = (string)state;
\r
1451 string handbrakeCLIPath = Path.Combine(Application.StartupPath, "HandBrakeCLI.exe");
\r
1452 string logDir = Environment.GetFolderPath(Environment.SpecialFolder.ApplicationData) + "\\HandBrake\\logs";
\r
1453 string dvdInfoPath = Path.Combine(logDir, "last_scan_log.txt");
\r
1455 // Make we don't pick up a stale last_encode_log.txt (and that we have rights to the file)
\r
1456 if (File.Exists(dvdInfoPath))
\r
1457 File.Delete(dvdInfoPath);
\r
1459 String dvdnav = string.Empty;
\r
1460 if (Properties.Settings.Default.dvdnav == "Checked")
\r
1461 dvdnav = " --dvdnav";
\r
1462 string strCmdLine = String.Format(@"cmd /c """"{0}"" -i ""{1}"" -t0 {2} -v >""{3}"" 2>&1""", handbrakeCLIPath, inputFile, dvdnav, dvdInfoPath);
\r
1464 ProcessStartInfo hbParseDvd = new ProcessStartInfo("CMD.exe", strCmdLine) { WindowStyle = ProcessWindowStyle.Hidden };
\r
1466 Boolean cleanExit = true;
\r
1467 using (hbproc = Process.Start(hbParseDvd))
\r
1469 Process[] before = Process.GetProcesses(); // Get a list of running processes before starting.
\r
1470 scanProcessID = Main.getCliProcess(before);
\r
1471 hbproc.WaitForExit();
\r
1472 if (hbproc.ExitCode != 0)
\r
1473 cleanExit = false;
\r
1476 if (cleanExit) // If 0 exit code, CLI exited cleanly.
\r
1478 if (!File.Exists(dvdInfoPath))
\r
1480 throw new Exception(
\r
1481 "Unable to retrieve the DVD Info. last_scan_log.txt is missing. \nExpected location of last_scan_log.txt: \n" +
\r
1485 using (StreamReader sr = new StreamReader(dvdInfoPath))
\r
1487 thisDVD = DVD.Parse(sr);
\r
1492 updateUIafterScan();
\r
1495 catch (Exception exc)
\r
1497 MessageBox.Show("frmMain.cs - scanProcess() " + exc, "Error", MessageBoxButtons.OK, MessageBoxIcon.Error);
\r
1501 private void updateUIafterScan()
\r
1505 if (InvokeRequired)
\r
1507 BeginInvoke(new UpdateWindowHandler(updateUIafterScan));
\r
1511 // Setup some GUI components
\r
1512 drp_dvdtitle.Items.Clear();
\r
1513 if (thisDVD.Titles.Count != 0)
\r
1514 drp_dvdtitle.Items.AddRange(thisDVD.Titles.ToArray());
\r
1515 drp_dvdtitle.Text = "Automatic";
\r
1516 drop_chapterFinish.Text = "Auto";
\r
1517 drop_chapterStart.Text = "Auto";
\r
1519 // Now select the longest title
\r
1520 if (thisDVD.Titles.Count != 0)
\r
1521 drp_dvdtitle.SelectedItem = Main.selectLongestTitle(drp_dvdtitle);
\r
1523 // Enable the creation of chapter markers if the file is an image of a dvd.
\r
1524 if (text_source.Text.ToLower().Contains(".iso") || text_source.Text.ToLower().Contains("VIDEO_TS"))
\r
1525 Check_ChapterMarkers.Enabled = true;
\r
1528 Check_ChapterMarkers.Enabled = false;
\r
1529 Check_ChapterMarkers.Checked = false;
\r
1530 data_chpt.Rows.Clear();
\r
1533 // If no titles were found, Display an error message
\r
1534 if (drp_dvdtitle.Items.Count == 0)
\r
1535 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
1537 // Enable the GUI components and enable any disabled components
\r
1540 catch (Exception exc)
\r
1542 MessageBox.Show("frmMain.cs - updateUIafterScan " + exc, "Error", MessageBoxButtons.OK, MessageBoxIcon.Error);
\r
1546 private void enableGUI()
\r
1550 if (InvokeRequired)
\r
1551 BeginInvoke(new UpdateWindowHandler(enableGUI));
\r
1552 lbl_encode.Text = "Scan Completed";
\r
1553 gb_source.Text = "Source";
\r
1554 foreach (Control ctrl in Controls)
\r
1555 ctrl.Enabled = true;
\r
1556 btn_start.Enabled = true;
\r
1557 btn_showQueue.Enabled = true;
\r
1558 btn_add2Queue.Enabled = true;
\r
1559 tb_preview.Enabled = true;
\r
1560 btn_source.Enabled = true;
\r
1561 mnu_killCLI.Visible = false;
\r
1563 catch (Exception exc)
\r
1565 MessageBox.Show("frmMain.cs - enableGUI() " + exc, "Error", MessageBoxButtons.OK, MessageBoxIcon.Error);
\r
1568 private void killScan()
\r
1575 Process[] prs = Process.GetProcesses();
\r
1576 foreach (Process process in prs)
\r
1578 if (process.Id == scanProcessID)
\r
1580 process.Refresh();
\r
1581 if (!process.HasExited)
\r
1586 catch (Exception ex)
\r
1588 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
1591 private void resetGUI()
\r
1593 drp_dvdtitle.Items.Clear();
\r
1594 drp_dvdtitle.Text = "Automatic";
\r
1595 drop_chapterStart.Items.Clear();
\r
1596 drop_chapterStart.Text = "Auto";
\r
1597 drop_chapterFinish.Items.Clear();
\r
1598 drop_chapterFinish.Text = "Auto";
\r
1599 lbl_duration.Text = "Select a Title";
\r
1600 lbl_src_res.Text = "Select a Title";
\r
1601 lbl_Aspect.Text = "Select a Title";
\r
1602 text_source.Text = "Click 'Source' to continue";
\r
1603 text_destination.Text = "";
\r
1605 selectedTitle = null;
\r
1606 isScanning = false;
\r
1612 /// Set the GUI to it's finished encoding state.
\r
1614 private void setEncodeFinished()
\r
1618 if (InvokeRequired)
\r
1620 BeginInvoke(new UpdateWindowHandler(setEncodeFinished));
\r
1624 lbl_encode.Text = "Encoding Finished";
\r
1625 btn_start.Text = "Start";
\r
1626 btn_start.ToolTipText = "Start the encoding process";
\r
1627 btn_start.Image = Properties.Resources.Play;
\r
1629 // If the window is minimized, display the notification in a popup.
\r
1630 if (FormWindowState.Minimized == this.WindowState)
\r
1632 notifyIcon.BalloonTipText = lbl_encode.Text;
\r
1633 notifyIcon.ShowBalloonTip(500);
\r
1636 catch (Exception exc)
\r
1638 MessageBox.Show(exc.ToString());
\r
1643 /// Set the GUI to it's started encoding state.
\r
1645 private void setEncodeStarted()
\r
1649 if (InvokeRequired)
\r
1651 BeginInvoke(new UpdateWindowHandler(setEncodeStarted));
\r
1655 lbl_encode.Visible = true;
\r
1656 lbl_encode.Text = "Encoding in Progress";
\r
1657 btn_start.Text = "Stop";
\r
1658 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
1659 btn_start.Image = Properties.Resources.stop;
\r
1661 catch (Exception exc)
\r
1663 MessageBox.Show(exc.ToString());
\r
1668 #region DVD Drive Detection
\r
1669 private delegate void ProgressUpdateHandler();
\r
1670 private void getDriveInfoThread()
\r
1674 if (InvokeRequired)
\r
1676 BeginInvoke(new ProgressUpdateHandler(getDriveInfoThread));
\r
1680 Boolean foundDrive = false;
\r
1681 DriveInfo[] theCollectionOfDrives = DriveInfo.GetDrives();
\r
1682 foreach (DriveInfo curDrive in theCollectionOfDrives)
\r
1684 if (curDrive.DriveType == DriveType.CDRom && curDrive.IsReady)
\r
1686 if (File.Exists(curDrive.RootDirectory + "VIDEO_TS\\VIDEO_TS.IFO"))
\r
1688 mnu_dvd_drive.Text = curDrive.RootDirectory + "VIDEO_TS (" + curDrive.VolumeLabel + ")";
\r
1689 foundDrive = true;
\r
1695 if (foundDrive == false)
\r
1696 mnu_dvd_drive.Text = "[No DVD Drive Ready]";
\r
1700 mnu_dvd_drive.Text = "[No DVD Drive Ready / Found]";
\r
1705 #region Public Methods
\r
1707 /// Access the preset Handler and setup the preset panel.
\r
1709 public void loadPresetPanel()
\r
1711 if (presetHandler.checkIfPresetsAreOutOfDate())
\r
1712 if (Properties.Settings.Default.presetNotification == "Unchecked")
\r
1714 "HandBrake has determined your built-in presets are out of date... These presets will now be updated.",
\r
1715 "Preset Update", MessageBoxButtons.OK, MessageBoxIcon.Information);
\r
1717 presetHandler.getPresetPanel(ref treeView_presets);
\r
1718 treeView_presets.Update();
\r
1722 /// Either Encode or Scan was last performed.
\r
1724 public string lastAction { get; set; }
\r
1729 /// If the queue is being processed, prompt the user to confirm application close.
\r
1731 /// <param name="e"></param>
\r
1732 protected override void OnFormClosing(FormClosingEventArgs e)
\r
1734 // If currently encoding, the queue isn't paused, and there are queue items to process, prompt to confirm close.
\r
1735 if ((encodeQueue.isEncoding) && (!encodeQueue.isPaused) && (encodeQueue.count() > 0))
\r
1737 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
1738 "Close HandBrake?", MessageBoxButtons.YesNo, MessageBoxIcon.Question);
\r
1739 if (result == DialogResult.No)
\r
1742 base.OnFormClosing(e);
\r
1746 #region In-GUI Encode Status (Experimental)
\r
1747 private Process HBProcess { get; set; }
\r
1749 private void encodeMonitorThread()
\r
1753 Parser encode = new Parser(HBProcess.StandardOutput.BaseStream);
\r
1754 encode.OnEncodeProgress += encode_OnEncodeProgress;
\r
1755 while (!encode.EndOfStream)
\r
1757 encode.readEncodeStatus();
\r
1760 catch (Exception exc)
\r
1762 MessageBox.Show(exc.ToString());
\r
1766 private void encode_OnEncodeProgress(object Sender, int CurrentTask, int TaskCount, float PercentComplete, float CurrentFps, float AverageFps, TimeSpan TimeRemaining)
\r
1768 if (this.InvokeRequired)
\r
1770 this.BeginInvoke(new EncodeProgressEventHandler(encode_OnEncodeProgress),
\r
1771 new object[] { Sender, CurrentTask, TaskCount, PercentComplete, CurrentFps, AverageFps, TimeRemaining });
\r
1774 lbl_encode.Text = string.Format("Encode Progress: {0}%, FPS: {1}, Avg FPS: {2}, Time Remaining: {3} ", PercentComplete, CurrentFps, AverageFps, TimeRemaining);
\r
1778 // This is the END of the road ****************************************
\r