3 This file is part of the HandBrake source code.
\r
4 Homepage: <http://handbrake.fr/>.
\r
5 It may be used under the terms of the GNU General Public License. */
\r
8 using System.Collections.Generic;
\r
9 using System.Drawing;
\r
10 using System.Globalization;
\r
11 using System.Windows.Forms;
\r
13 using System.Diagnostics;
\r
14 using System.Threading;
\r
15 using Handbrake.EncodeQueue;
\r
16 using Handbrake.Functions;
\r
17 using Handbrake.Presets;
\r
18 using Handbrake.Parsing;
\r
22 public partial class frmMain : Form
\r
24 // Objects which may be used by one or more other objects *************
\r
25 QueueHandler encodeQueue = new QueueHandler();
\r
26 PresetsHandler presetHandler = new PresetsHandler();
\r
27 QueryGenerator queryGen = new QueryGenerator();
\r
29 // Globals: Mainly used for tracking. *********************************
\r
30 public Title selectedTitle;
\r
31 private DVD thisDVD;
\r
32 private frmQueue queueWindow;
\r
33 private frmPreview qtpreview;
\r
34 private Form splash;
\r
35 public string sourcePath;
\r
37 // Delegates **********************************************************
\r
38 private delegate void UpdateWindowHandler();
\r
40 // Applicaiton Startup ************************************************
\r
42 #region Application Startup
\r
45 // Load and setup the splash screen in this thread
\r
46 splash = new frmSplashScreen();
\r
48 Label lblStatus = new Label { Size = new Size(150, 20), Location = new Point(182, 102) };
\r
49 splash.Controls.Add(lblStatus);
\r
51 InitializeComponent();
\r
53 // Update the users config file with the CLI version data.
\r
54 lblStatus.Text = "Setting Version Data ...";
\r
55 Application.DoEvents();
\r
56 Main.setCliVersionData();
\r
58 // Show the form, but leave disabled until preloading is complete then show the main form
\r
59 this.Enabled = false;
\r
61 Application.DoEvents(); // Forces frmMain to draw
\r
63 // Check for new versions, if update checking is enabled
\r
64 if (Properties.Settings.Default.updateStatus)
\r
66 DateTime now = DateTime.Now;
\r
67 DateTime lastCheck = Properties.Settings.Default.lastUpdateCheckDate;
\r
68 TimeSpan elapsed = now.Subtract(lastCheck);
\r
69 if (elapsed.TotalDays > Properties.Settings.Default.daysBetweenUpdateCheck)
\r
71 lblStatus.Text = "Checking for updates ...";
\r
72 Application.DoEvents();
\r
74 Main.BeginCheckForUpdates(new AsyncCallback(UpdateCheckDone), false);
\r
78 // Setup the GUI components
\r
79 lblStatus.Text = "Setting up the GUI ...";
\r
80 Application.DoEvents();
\r
81 loadPresetPanel(); // Load the Preset Panel
\r
82 treeView_presets.ExpandAll();
\r
83 lbl_encode.Text = "";
\r
84 queueWindow = new frmQueue(encodeQueue); // Prepare the Queue
\r
85 if (!Properties.Settings.Default.QueryEditorTab)
\r
86 tabs_panel.TabPages.RemoveAt(7); // Remove the query editor tab if the user does not want it enabled.
\r
88 // Load the user's default settings or Normal Preset
\r
89 if (Properties.Settings.Default.defaultSettings && Properties.Settings.Default.defaultPreset != "")
\r
91 if (presetHandler.getPreset(Properties.Settings.Default.defaultPreset) != null)
\r
93 string query = presetHandler.getPreset(Properties.Settings.Default.defaultPreset).Query;
\r
94 Boolean loadPictureSettings = presetHandler.getPreset(Properties.Settings.Default.defaultPreset).PictureSettings;
\r
98 //Ok, Reset all the H264 widgets before changing the preset
\r
99 x264Panel.reset2Defaults();
\r
101 // Send the query from the file to the Query Parser class, then load the preset
\r
102 QueryParser presetQuery = QueryParser.Parse(query);
\r
103 PresetLoader.presetLoader(this, presetQuery, Properties.Settings.Default.defaultPreset, loadPictureSettings);
\r
105 // The x264 widgets will need updated, so do this now:
\r
106 x264Panel.X264_StandardizeOptString();
\r
107 x264Panel.X264_SetCurrentSettingsInPanel();
\r
111 loadNormalPreset();
\r
114 loadNormalPreset();
\r
116 // Enabled GUI tooltip's if Required
\r
117 if (Properties.Settings.Default.tooltipEnable)
\r
118 ToolTip.Active = true;
\r
121 lblStatus.Text = "Loading Complete!";
\r
122 Application.DoEvents();
\r
125 this.Enabled = true;
\r
127 // Event Handlers and Queue Recovery
\r
132 private void UpdateCheckDone(IAsyncResult result)
\r
134 if (InvokeRequired)
\r
136 Invoke(new MethodInvoker(() => UpdateCheckDone(result)));
\r
140 UpdateCheckInformation info;
\r
144 info = Main.EndCheckForUpdates(result);
\r
146 if (info.NewVersionAvailable)
\r
148 frmUpdater updateWindow = new frmUpdater(info.BuildInformation);
\r
149 updateWindow.ShowDialog();
\r
152 catch (Exception ex)
\r
154 if ((bool)result.AsyncState)
\r
155 MessageBox.Show("Unable to check for updates, Please try again later. \n" + ex, "Error", MessageBoxButtons.OK, MessageBoxIcon.Error);
\r
159 // Startup Functions
\r
160 private void queueRecovery()
\r
162 if (Main.check_queue_recovery())
\r
164 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
166 if (result == DialogResult.Yes)
\r
167 encodeQueue.LoadQueueFromFile("hb_queue_recovery.xml"); // Start Recovery
\r
170 // Remove the Queue recovery file if the user doesn't want to recovery the last queue.
\r
171 string queuePath = Path.Combine(Path.GetTempPath(), "hb_queue_recovery.xml");
\r
172 if (File.Exists(queuePath))
\r
173 File.Delete(queuePath);
\r
180 // Encoding Events for setting up the GUI
\r
181 private void events()
\r
183 // Handle Widget changes when preset is selected.
\r
184 registerPresetEventHandler();
\r
186 // Handle Window Resize
\r
187 if (Properties.Settings.Default.MainWindowMinimize)
\r
188 this.Resize += new EventHandler(frmMain_Resize);
\r
190 // Handle Encode Start / Finish / Pause
\r
191 encodeQueue.CurrentJobCompleted += new EventHandler(encodeEnded);
\r
192 encodeQueue.QueuePauseRequested += new EventHandler(encodePaused);
\r
193 encodeQueue.NewJobStarted += new EventHandler(encodeStarted);
\r
195 // Handle a file being draged onto the GUI.
\r
196 this.DragEnter += new DragEventHandler(frmMain_DragEnter);
\r
197 this.DragDrop += new DragEventHandler(frmMain_DragDrop);
\r
200 // Change the preset label to custom when a user changes a setting. Don't want to give the impression that users can change settings and still be using a preset
\r
201 public void registerPresetEventHandler()
\r
204 drop_format.SelectedIndexChanged += new EventHandler(changePresetLabel);
\r
205 check_largeFile.CheckedChanged += new EventHandler(changePresetLabel);
\r
206 check_iPodAtom.CheckedChanged += new EventHandler(changePresetLabel);
\r
207 check_optimiseMP4.CheckedChanged += new EventHandler(changePresetLabel);
\r
209 // Picture Settings
\r
210 //PictureSettings.PictureSettingsChanged += new EventHandler(changePresetLabel);
\r
213 Filters.FilterSettingsChanged += new EventHandler(changePresetLabel);
\r
216 drp_videoEncoder.SelectedIndexChanged += new EventHandler(changePresetLabel);
\r
217 check_2PassEncode.CheckedChanged += new EventHandler(changePresetLabel);
\r
218 check_turbo.CheckedChanged += new EventHandler(changePresetLabel);
\r
219 text_filesize.TextChanged += new EventHandler(changePresetLabel);
\r
220 text_bitrate.TextChanged += new EventHandler(changePresetLabel);
\r
221 slider_videoQuality.ValueChanged += new EventHandler(changePresetLabel);
\r
224 AudioSettings.AudioListChanged += new EventHandler(changePresetLabel);
\r
227 x264Panel.rtf_x264Query.TextChanged += new EventHandler(changePresetLabel);
\r
229 public void unRegisterPresetEventHandler()
\r
231 // Output Settings
\r
232 drop_format.SelectedIndexChanged -= new EventHandler(changePresetLabel);
\r
233 check_largeFile.CheckedChanged -= new EventHandler(changePresetLabel);
\r
234 check_iPodAtom.CheckedChanged -= new EventHandler(changePresetLabel);
\r
235 check_optimiseMP4.CheckedChanged -= new EventHandler(changePresetLabel);
\r
237 // Picture Settings
\r
238 //PictureSettings.PictureSettingsChanged -= new EventHandler(changePresetLabel);
\r
241 Filters.FilterSettingsChanged -= new EventHandler(changePresetLabel);
\r
244 drp_videoEncoder.SelectedIndexChanged -= new EventHandler(changePresetLabel);
\r
245 check_2PassEncode.CheckedChanged -= new EventHandler(changePresetLabel);
\r
246 check_turbo.CheckedChanged -= new EventHandler(changePresetLabel);
\r
247 text_filesize.TextChanged -= new EventHandler(changePresetLabel);
\r
248 text_bitrate.TextChanged -= new EventHandler(changePresetLabel);
\r
249 slider_videoQuality.ValueChanged -= new EventHandler(changePresetLabel);
\r
252 AudioSettings.AudioListChanged -= new EventHandler(changePresetLabel);
\r
255 x264Panel.rtf_x264Query.TextChanged -= new EventHandler(changePresetLabel);
\r
257 private void changePresetLabel(object sender, EventArgs e)
\r
259 labelPreset.Text = "Output Settings (Preset: Custom)";
\r
262 private static void frmMain_DragEnter(object sender, DragEventArgs e)
\r
264 if (e.Data.GetDataPresent(DataFormats.FileDrop, false))
\r
265 e.Effect = DragDropEffects.All;
\r
267 private void frmMain_DragDrop(object sender, DragEventArgs e)
\r
269 string[] fileList = e.Data.GetData(DataFormats.FileDrop) as string[];
\r
270 sourcePath = string.Empty;
\r
272 if (fileList != null)
\r
274 if (fileList[0].StartsWith("\\"))
\r
277 "Sorry, HandBrake does not support UNC file paths. \nTry mounting the share as a network drive in My Computer",
\r
278 "Warning", MessageBoxButtons.OK, MessageBoxIcon.Warning);
\r
279 UpdateSourceLabel();
\r
283 if (fileList[0] != "")
\r
285 setupGUIforScan(fileList[0]);
\r
286 startScan(fileList[0]);
\r
289 UpdateSourceLabel();
\r
293 UpdateSourceLabel();
\r
295 private void encodeStarted(object sender, EventArgs e)
\r
297 lastAction = "encode";
\r
298 setEncodeStarted();
\r
300 // Experimental HBProc Process Monitoring.
\r
301 if (Properties.Settings.Default.enocdeStatusInGui)
\r
303 Thread encodeMon = new Thread(encodeMonitorThread);
\r
307 private void encodeEnded(object sender, EventArgs e)
\r
309 setEncodeFinished();
\r
311 private void encodePaused(object sender, EventArgs e)
\r
313 setEncodeFinished();
\r
317 // User Interface Menus / Tool Strips *********************************
\r
320 private void mnu_killCLI_Click(object sender, EventArgs e)
\r
324 private void mnu_exit_Click(object sender, EventArgs e)
\r
326 Application.Exit();
\r
331 private void mnu_encode_Click(object sender, EventArgs e)
\r
333 queueWindow.Show();
\r
335 private void mnu_encodeLog_Click(object sender, EventArgs e)
\r
337 String file = lastAction == "scan" ? "last_scan_log.txt" : "last_encode_log.txt";
\r
339 frmActivityWindow dvdInfoWindow = new frmActivityWindow(file, encodeQueue, this);
\r
340 dvdInfoWindow.Show();
\r
342 private void mnu_options_Click(object sender, EventArgs e)
\r
344 Form options = new frmOptions();
\r
345 options.ShowDialog();
\r
349 #region Presets Menu
\r
350 private void mnu_presetReset_Click(object sender, EventArgs e)
\r
352 presetHandler.updateBuiltInPresets();
\r
354 if (treeView_presets.Nodes.Count == 0)
\r
355 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
357 MessageBox.Show("Presets have been updated!", "Alert", MessageBoxButtons.OK, MessageBoxIcon.Information);
\r
359 treeView_presets.ExpandAll();
\r
361 private void mnu_delete_preset_Click(object sender, EventArgs e)
\r
363 presetHandler.removeBuiltInPresets();
\r
364 loadPresetPanel(); // Reload the preset panel
\r
366 private void mnu_SelectDefault_Click(object sender, EventArgs e)
\r
368 loadNormalPreset();
\r
370 private void btn_new_preset_Click(object sender, EventArgs e)
\r
372 Form preset = new frmAddPreset(this, queryGen.generateTheQuery(this), presetHandler);
\r
373 preset.ShowDialog();
\r
378 private void mnu_handbrake_forums_Click(object sender, EventArgs e)
\r
380 Process.Start("http://forum.handbrake.fr/");
\r
382 private void mnu_user_guide_Click(object sender, EventArgs e)
\r
384 Process.Start("http://trac.handbrake.fr/wiki/HandBrakeGuide");
\r
386 private void mnu_handbrake_home_Click(object sender, EventArgs e)
\r
388 Process.Start("http://handbrake.fr");
\r
390 private void mnu_UpdateCheck_Click(object sender, EventArgs e)
\r
392 lbl_updateCheck.Visible = true;
\r
393 Main.BeginCheckForUpdates(new AsyncCallback(updateCheckDoneMenu), false);
\r
395 private void updateCheckDoneMenu(IAsyncResult result)
\r
397 // Make sure it's running on the calling thread
\r
398 if (InvokeRequired)
\r
400 Invoke(new MethodInvoker(() => updateCheckDoneMenu(result)));
\r
403 UpdateCheckInformation info;
\r
406 // Get the information about the new build, if any, and close the window
\r
407 info = Main.EndCheckForUpdates(result);
\r
409 if (info.NewVersionAvailable && info.BuildInformation != null)
\r
411 frmUpdater updateWindow = new frmUpdater(info.BuildInformation);
\r
412 updateWindow.ShowDialog();
\r
415 MessageBox.Show("There are no new updates at this time.", "Update Check", MessageBoxButtons.OK, MessageBoxIcon.Information);
\r
416 lbl_updateCheck.Visible = false;
\r
419 catch (Exception ex)
\r
421 if ((bool)result.AsyncState)
\r
422 MessageBox.Show("Unable to check for updates, Please try again later. \n" + ex, "Error", MessageBoxButtons.OK, MessageBoxIcon.Error);
\r
425 private void mnu_about_Click(object sender, EventArgs e)
\r
427 using (frmAbout About = new frmAbout())
\r
429 About.ShowDialog();
\r
435 // Right Click Menu Code
\r
436 private void pmnu_expandAll_Click(object sender, EventArgs e)
\r
438 treeView_presets.ExpandAll();
\r
440 private void pmnu_collapse_Click(object sender, EventArgs e)
\r
442 treeView_presets.CollapseAll();
\r
444 private void pmnu_saveChanges_Click(object sender, EventArgs e)
\r
446 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
447 if (result == DialogResult.Yes)
\r
448 presetHandler.updatePreset(treeView_presets.SelectedNode.Text, QueryGenerator.generateTabbedComponentsQuery(this), true);
\r
449 else if (result == DialogResult.No)
\r
450 presetHandler.updatePreset(treeView_presets.SelectedNode.Text, QueryGenerator.generateTabbedComponentsQuery(this), false);
\r
452 private void pmnu_delete_click(object sender, EventArgs e)
\r
454 if (treeView_presets.SelectedNode != null)
\r
456 presetHandler.remove(treeView_presets.SelectedNode.Text);
\r
457 treeView_presets.Nodes.Remove(treeView_presets.SelectedNode);
\r
459 treeView_presets.Select();
\r
461 private void presets_menu_Opening(object sender, System.ComponentModel.CancelEventArgs e)
\r
463 // Make sure that the save menu is always disabled by default
\r
464 pmnu_saveChanges.Enabled = false;
\r
466 // Now enable the save menu if the selected preset is a user preset
\r
467 if (treeView_presets.SelectedNode != null)
\r
468 if (presetHandler.checkIfUserPresetExists(treeView_presets.SelectedNode.Text))
\r
469 pmnu_saveChanges.Enabled = true;
\r
471 treeView_presets.Select();
\r
474 // Presets Management
\r
475 private void btn_addPreset_Click(object sender, EventArgs e)
\r
477 Form preset = new frmAddPreset(this, QueryGenerator.generateTabbedComponentsQuery(this), presetHandler);
\r
478 preset.ShowDialog();
\r
480 private void btn_removePreset_Click(object sender, EventArgs e)
\r
482 DialogResult result = MessageBox.Show("Are you sure you wish to delete the selected preset?", "Preset", MessageBoxButtons.YesNo, MessageBoxIcon.Question);
\r
483 if (result == DialogResult.Yes)
\r
485 if (treeView_presets.SelectedNode != null)
\r
487 presetHandler.remove(treeView_presets.SelectedNode.Text);
\r
488 treeView_presets.Nodes.Remove(treeView_presets.SelectedNode);
\r
491 treeView_presets.Select();
\r
493 private void btn_setDefault_Click(object sender, EventArgs e)
\r
495 if (treeView_presets.SelectedNode != null)
\r
497 DialogResult result = MessageBox.Show("Are you sure you wish to set this preset as the default?", "Preset", MessageBoxButtons.YesNo, MessageBoxIcon.Question);
\r
498 if (result == DialogResult.Yes)
\r
500 Properties.Settings.Default.defaultPreset = treeView_presets.SelectedNode.Text;
\r
501 Properties.Settings.Default.Save();
\r
502 MessageBox.Show("New default preset set.", "Alert", MessageBoxButtons.OK, MessageBoxIcon.Information);
\r
506 MessageBox.Show("Please select a preset first.", "Warning", MessageBoxButtons.OK, MessageBoxIcon.Warning);
\r
508 private void treeview_presets_mouseUp(object sender, MouseEventArgs e)
\r
510 if (e.Button == MouseButtons.Right)
\r
511 treeView_presets.SelectedNode = treeView_presets.GetNodeAt(e.Location);
\r
512 else if (e.Button == MouseButtons.Left)
\r
514 if (treeView_presets.GetNodeAt(e.Location) != null)
\r
516 if (labelPreset.Text.Contains(treeView_presets.GetNodeAt(e.Location).Text))
\r
521 treeView_presets.Select();
\r
523 private void treeView_presets_AfterSelect(object sender, TreeViewEventArgs e)
\r
527 private void treeView_presets_deleteKey(object sender, KeyEventArgs e)
\r
529 if (e.KeyCode == Keys.Delete)
\r
531 DialogResult result = MessageBox.Show("Are you sure you wish to delete the selected preset?", "Preset", MessageBoxButtons.YesNo, MessageBoxIcon.Question);
\r
532 if (result == DialogResult.Yes)
\r
534 if (treeView_presets.SelectedNode != null)
\r
535 presetHandler.remove(treeView_presets.SelectedNode.Text);
\r
537 // Remember each nodes expanded status so we can reload it
\r
538 List<Boolean> nodeStatus = new List<Boolean>();
\r
539 foreach (TreeNode node in treeView_presets.Nodes)
\r
540 nodeStatus.Add(node.IsExpanded);
\r
542 // Now reload the preset panel
\r
545 // And finally, re-expand any of the nodes if required
\r
547 foreach (TreeNode node in treeView_presets.Nodes)
\r
557 private void selectPreset()
\r
559 if (treeView_presets.SelectedNode != null)
\r
561 // Ok, so, we've selected a preset. Now we want to load it.
\r
562 string presetName = treeView_presets.SelectedNode.Text;
\r
563 if (presetHandler.getPreset(presetName) != null)
\r
565 string query = presetHandler.getPreset(presetName).Query;
\r
566 Boolean loadPictureSettings = presetHandler.getPreset(presetName).PictureSettings;
\r
570 //Ok, Reset all the H264 widgets before changing the preset
\r
571 x264Panel.reset2Defaults();
\r
573 // Send the query from the file to the Query Parser class
\r
574 QueryParser presetQuery = QueryParser.Parse(query);
\r
576 // Now load the preset
\r
577 PresetLoader.presetLoader(this, presetQuery, presetName, loadPictureSettings);
\r
579 // The x264 widgets will need updated, so do this now:
\r
580 x264Panel.X264_StandardizeOptString();
\r
581 x264Panel.X264_SetCurrentSettingsInPanel();
\r
586 private void loadNormalPreset()
\r
588 foreach (TreeNode treenode in treeView_presets.Nodes)
\r
590 foreach (TreeNode node in treenode.Nodes)
\r
592 if (node.Text.Equals("Normal"))
\r
593 treeView_presets.SelectedNode = treeView_presets.Nodes[treenode.Index].Nodes[0];
\r
600 private void btn_source_Click(object sender, EventArgs e)
\r
602 if (Properties.Settings.Default.drive_detection)
\r
604 mnu_dvd_drive.Visible = true;
\r
605 Thread driveInfoThread = new Thread(getDriveInfoThread);
\r
606 driveInfoThread.Start();
\r
609 mnu_dvd_drive.Visible = false;
\r
611 private void btn_start_Click(object sender, EventArgs e)
\r
613 if (btn_start.Text == "Stop")
\r
615 DialogResult result = MessageBox.Show("Are you sure you wish to cancel the encode?", "Cancel Encode?", MessageBoxButtons.YesNo, MessageBoxIcon.Question);
\r
617 if (result == DialogResult.Yes)
\r
620 encodeQueue.RequestPause();
\r
622 // Allow the CLI to exit cleanly
\r
623 Win32.SetForegroundWindow((int)encodeQueue.encodeHandler.processHandle);
\r
624 SendKeys.Send("^C");
\r
627 setEncodeFinished();
\r
632 if (encodeQueue.Count != 0 || (!string.IsNullOrEmpty(sourcePath) && !string.IsNullOrEmpty(text_destination.Text)))
\r
634 string generatedQuery = queryGen.generateTheQuery(this);
\r
635 string specifiedQuery = rtf_query.Text != "" ? rtf_query.Text : queryGen.generateTheQuery(this);
\r
636 string query = string.Empty;
\r
638 // Check to make sure the generated query matches the GUI settings
\r
639 if (Properties.Settings.Default.PromptOnUnmatchingQueries && !string.IsNullOrEmpty(specifiedQuery) && generatedQuery != specifiedQuery)
\r
641 DialogResult result = MessageBox.Show("The query under the \"Query Editor\" tab " +
\r
642 "does not match the current GUI settings. Because the manual query takes " +
\r
643 "priority over the GUI, your recently updated settings will not be taken " +
\r
644 "into account when encoding this job." + Environment.NewLine + Environment.NewLine +
\r
645 "Do you want to replace the manual query with the GUI-generated query?",
\r
646 "Manual Query does not Match GUI",
\r
647 MessageBoxButtons.YesNoCancel, MessageBoxIcon.Asterisk,
\r
648 MessageBoxDefaultButton.Button3);
\r
652 case DialogResult.Yes:
\r
653 // Replace the manual query with the generated one
\r
654 query = generatedQuery;
\r
655 rtf_query.Text = generatedQuery;
\r
657 case DialogResult.No:
\r
658 // Use the manual query
\r
659 query = specifiedQuery;
\r
661 case DialogResult.Cancel:
\r
662 // Don't start the encode
\r
668 query = generatedQuery;
\r
671 DialogResult overwrite = DialogResult.Yes;
\r
672 if (text_destination.Text != "")
\r
673 if (File.Exists(text_destination.Text))
\r
674 overwrite = MessageBox.Show("The destination file already exists. Are you sure you want to overwrite it?", "Overwrite File?", MessageBoxButtons.YesNo, MessageBoxIcon.Question);
\r
676 if (overwrite == DialogResult.Yes)
\r
678 if (encodeQueue.Count == 0)
\r
679 encodeQueue.AddJob(query, sourcePath, text_destination.Text);
\r
681 queueWindow.setQueue();
\r
682 if (encodeQueue.Count > 1)
\r
683 queueWindow.Show(false);
\r
685 setEncodeStarted(); // Encode is running, so setup the GUI appropriately
\r
686 encodeQueue.StartEncodeQueue(); // Start The Queue Encoding Process
\r
687 lastAction = "encode"; // Set the last action to encode - Used for activity window.
\r
691 else if (string.IsNullOrEmpty(sourcePath) || string.IsNullOrEmpty(text_destination.Text))
\r
692 MessageBox.Show("No source or destination selected.", "Warning", MessageBoxButtons.OK, MessageBoxIcon.Warning);
\r
695 private void btn_add2Queue_Click(object sender, EventArgs e)
\r
697 if (string.IsNullOrEmpty(sourcePath) || string.IsNullOrEmpty(text_destination.Text))
\r
698 MessageBox.Show("No source or destination selected.", "Warning", MessageBoxButtons.OK, MessageBoxIcon.Warning);
\r
701 String query = queryGen.generateTheQuery(this);
\r
702 if (rtf_query.Text != "")
\r
703 query = rtf_query.Text;
\r
705 if (encodeQueue.CheckForDestinationDuplicate(text_destination.Text))
\r
707 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
708 "Warning", MessageBoxButtons.YesNo, MessageBoxIcon.Warning);
\r
709 if (result == DialogResult.Yes)
\r
710 encodeQueue.AddJob(query, sourcePath, text_destination.Text);
\r
714 encodeQueue.AddJob(query, sourcePath, text_destination.Text);
\r
716 queueWindow.Show();
\r
719 private void btn_showQueue_Click(object sender, EventArgs e)
\r
721 queueWindow.Show();
\r
723 private void tb_preview_Click(object sender, EventArgs e)
\r
725 if (string.IsNullOrEmpty(sourcePath) || string.IsNullOrEmpty(text_destination.Text))
\r
726 MessageBox.Show("No source or destination selected.", "Warning", MessageBoxButtons.OK, MessageBoxIcon.Warning);
\r
729 if (qtpreview == null)
\r
731 qtpreview = new frmPreview(this);
\r
734 else if (qtpreview.IsDisposed)
\r
736 qtpreview = new frmPreview(this);
\r
740 MessageBox.Show(qtpreview, "The preview window is already open!", "Warning", MessageBoxButtons.OK, MessageBoxIcon.Warning);
\r
743 private void btn_ActivityWindow_Click(object sender, EventArgs e)
\r
745 String file = lastAction == "scan" ? "last_scan_log.txt" : "last_encode_log.txt";
\r
747 frmActivityWindow ActivityWindow = new frmActivityWindow(file, encodeQueue, this);
\r
748 ActivityWindow.Show();
\r
752 #region System Tray Icon
\r
753 private void frmMain_Resize(object sender, EventArgs e)
\r
755 if (FormWindowState.Minimized == this.WindowState)
\r
757 notifyIcon.Visible = true;
\r
760 else if (FormWindowState.Normal == this.WindowState)
\r
761 notifyIcon.Visible = false;
\r
763 private void notifyIcon_MouseDoubleClick(object sender, MouseEventArgs e)
\r
765 this.Visible = true;
\r
767 this.WindowState = FormWindowState.Normal;
\r
768 notifyIcon.Visible = false;
\r
770 private void btn_restore_Click(object sender, EventArgs e)
\r
772 this.Visible = true;
\r
774 this.WindowState = FormWindowState.Normal;
\r
775 notifyIcon.Visible = false;
\r
779 #region Tab Control
\r
782 private void btn_dvd_source_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
790 sourcePath = string.Empty;
\r
792 if (DVD_Open.ShowDialog() == DialogResult.OK)
\r
794 String filename = DVD_Open.SelectedPath;
\r
796 if (filename.StartsWith("\\"))
\r
799 "Sorry, HandBrake does not support UNC file paths. \nTry mounting the share as a network drive in My Computer",
\r
800 "Warning", MessageBoxButtons.OK, MessageBoxIcon.Warning);
\r
801 UpdateSourceLabel();
\r
805 if (filename != "")
\r
807 sourcePath = Path.GetFullPath(filename);
\r
808 setupGUIforScan(filename);
\r
809 startScan(filename);
\r
811 UpdateSourceLabel();
\r
815 UpdateSourceLabel();
\r
817 private void btn_file_source_Click(object sender, EventArgs e)
\r
819 // Set the last action to scan.
\r
820 // This is used for tracking which file to load in the activity window
\r
821 lastAction = "scan";
\r
822 sourcePath = string.Empty;
\r
824 if (ISO_Open.ShowDialog() == DialogResult.OK)
\r
826 String filename = ISO_Open.FileName;
\r
827 if (filename.StartsWith("\\"))
\r
829 "Sorry, HandBrake does not support UNC file paths. \nTry mounting the share as a network drive in My Computer",
\r
830 "Warning", MessageBoxButtons.OK, MessageBoxIcon.Warning);
\r
833 if (filename != "")
\r
835 sourcePath = Path.GetFileName(filename);
\r
836 setupGUIforScan(filename);
\r
837 startScan(filename);
\r
839 UpdateSourceLabel();
\r
842 UpdateSourceLabel();
\r
844 private void mnu_dvd_drive_Click(object sender, EventArgs e)
\r
846 // Enable the creation of chapter markers.
\r
847 Check_ChapterMarkers.Enabled = true;
\r
849 // Set the last action to scan.
\r
850 // This is used for tracking which file to load in the activity window
\r
851 lastAction = "scan";
\r
852 sourcePath = string.Empty;
\r
854 if (mnu_dvd_drive.Text.Contains("VIDEO_TS"))
\r
856 string[] path = mnu_dvd_drive.Text.Split(' ');
\r
857 String filename = path[0];
\r
858 sourcePath = Path.GetFullPath(filename);
\r
859 setupGUIforScan(filename);
\r
860 startScan(filename);
\r
863 // If there are no titles in the dropdown menu then the scan has obviously failed. Display an error message explaining to the user.
\r
864 if (drp_dvdtitle.Items.Count == 0)
\r
865 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
867 UpdateSourceLabel();
\r
869 lbl_encode.Text = "";
\r
871 private void drp_dvdtitle_Click(object sender, EventArgs e)
\r
873 if ((drp_dvdtitle.Items.Count == 1) && (drp_dvdtitle.Items[0].ToString() == "Automatic"))
\r
874 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
876 private void drp_dvdtitle_SelectedIndexChanged(object sender, EventArgs e)
\r
878 unRegisterPresetEventHandler();
\r
879 // Reset some values on the form
\r
880 PictureSettings.lbl_Aspect.Text = "Select a Title";
\r
881 //lbl_RecomendedCrop.Text = "Select a Title";
\r
882 drop_chapterStart.Items.Clear();
\r
883 drop_chapterFinish.Items.Clear();
\r
885 // If the dropdown is set to automatic nothing else needs to be done.
\r
886 // Otheriwse if its not, title data has to be loased from parsing.
\r
887 if (drp_dvdtitle.Text != "Automatic")
\r
889 selectedTitle = drp_dvdtitle.SelectedItem as Title;
\r
890 lbl_duration.Text = selectedTitle.Duration.ToString();
\r
891 PictureSettings.Source = selectedTitle; // Setup Picture Settings Tab Control
\r
893 // Populate the Angles dropdown
\r
894 drop_angle.Items.Clear();
\r
895 if (Properties.Settings.Default.dvdnav)
\r
897 drop_angle.Visible = true;
\r
898 lbl_angle.Visible = true;
\r
899 drop_angle.Items.AddRange(selectedTitle.Angles.ToArray());
\r
900 if (drop_angle.Items.Count != 0)
\r
901 drop_angle.SelectedIndex = 0;
\r
905 drop_angle.Visible = false;
\r
906 lbl_angle.Visible = false;
\r
909 // Populate the Start chapter Dropdown
\r
910 drop_chapterStart.Items.Clear();
\r
911 drop_chapterStart.Items.AddRange(selectedTitle.Chapters.ToArray());
\r
912 if (drop_chapterStart.Items.Count > 0)
\r
913 drop_chapterStart.Text = drop_chapterStart.Items[0].ToString();
\r
915 // Populate the Final Chapter Dropdown
\r
916 drop_chapterFinish.Items.Clear();
\r
917 drop_chapterFinish.Items.AddRange(selectedTitle.Chapters.ToArray());
\r
918 if (drop_chapterFinish.Items.Count > 0)
\r
919 drop_chapterFinish.Text = drop_chapterFinish.Items[drop_chapterFinish.Items.Count - 1].ToString();
\r
921 // Populate the Audio Channels Dropdown
\r
922 AudioSettings.setTrackList(selectedTitle);
\r
924 // Populate the Subtitles dropdown
\r
925 Subtitles.drp_subtitleTracks.Items.Clear();
\r
926 Subtitles.drp_subtitleTracks.Items.Add("Foreign Audio Search (Bitmap)");
\r
927 Subtitles.drp_subtitleTracks.Items.AddRange(selectedTitle.Subtitles.ToArray());
\r
928 Subtitles.drp_subtitleTracks.SelectedIndex = 0;
\r
931 // Run the autoName & chapterNaming functions
\r
932 if (Properties.Settings.Default.autoNaming)
\r
934 string autoPath = Main.autoName(drp_dvdtitle, drop_chapterStart.Text, drop_chapterFinish.Text, sourcePath, text_destination.Text, drop_format.SelectedIndex);
\r
935 if (autoPath != null)
\r
936 text_destination.Text = autoPath;
\r
938 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
941 data_chpt.Rows.Clear();
\r
942 if (selectedTitle.Chapters.Count != 1)
\r
944 DataGridView chapterGridView = Main.chapterNaming(data_chpt, drop_chapterFinish.Text);
\r
945 if (chapterGridView != null)
\r
946 data_chpt = chapterGridView;
\r
950 Check_ChapterMarkers.Checked = false;
\r
951 Check_ChapterMarkers.Enabled = false;
\r
954 // Hack to force the redraw of the scrollbars which don't resize properly when the control is disabled.
\r
955 data_chpt.Columns[0].Width = 166;
\r
956 data_chpt.Columns[0].Width = 165;
\r
958 registerPresetEventHandler();
\r
960 private void drop_chapterStart_SelectedIndexChanged(object sender, EventArgs e)
\r
962 int c_start, c_end;
\r
964 if (drop_chapterFinish.Text == "Auto" && drop_chapterFinish.Items.Count != 0)
\r
965 drop_chapterFinish.SelectedIndex = drop_chapterFinish.Items.Count - 1;
\r
967 int.TryParse(drop_chapterStart.Text, out c_start);
\r
968 int.TryParse(drop_chapterFinish.Text, out c_end);
\r
972 if (c_start > c_end)
\r
973 drop_chapterFinish.Text = c_start.ToString();
\r
976 lbl_duration.Text = Main.calculateDuration(drop_chapterStart.Text, drop_chapterFinish.Text, selectedTitle).ToString();
\r
978 // Run the Autonaming function
\r
979 if (Properties.Settings.Default.autoNaming)
\r
980 text_destination.Text = Main.autoName(drp_dvdtitle, drop_chapterStart.Text, drop_chapterFinish.Text, sourcePath, text_destination.Text, drop_format.SelectedIndex);
\r
982 // Disable chapter markers if only 1 chapter is selected.
\r
983 if (c_start == c_end)
\r
985 Check_ChapterMarkers.Checked = false;
\r
986 Check_ChapterMarkers.Enabled = false;
\r
989 Check_ChapterMarkers.Enabled = true;
\r
991 private void drop_chapterFinish_SelectedIndexChanged(object sender, EventArgs e)
\r
993 int c_start, c_end;
\r
995 if (drop_chapterStart.Text == "Auto" && drop_chapterStart.Items.Count >= 1)
\r
996 drop_chapterStart.SelectedIndex = 1;
\r
998 int.TryParse(drop_chapterStart.Text, out c_start);
\r
999 int.TryParse(drop_chapterFinish.Text, out c_end);
\r
1003 if (c_end < c_start)
\r
1004 drop_chapterFinish.Text = c_start.ToString();
\r
1007 lbl_duration.Text = Main.calculateDuration(drop_chapterStart.Text, drop_chapterFinish.Text, selectedTitle).ToString();
\r
1009 // Run the Autonaming function
\r
1010 if (Properties.Settings.Default.autoNaming)
\r
1011 text_destination.Text = Main.autoName(drp_dvdtitle, drop_chapterStart.Text, drop_chapterFinish.Text, sourcePath, text_destination.Text, drop_format.SelectedIndex);
\r
1013 // Add more rows to the Chapter menu if needed.
\r
1014 if (Check_ChapterMarkers.Checked)
\r
1016 int i = data_chpt.Rows.Count, finish = 0;
\r
1018 if (drop_chapterFinish.Text != "Auto")
\r
1019 int.TryParse(drop_chapterFinish.Text, out finish);
\r
1021 while (i < finish)
\r
1023 int n = data_chpt.Rows.Add();
\r
1024 data_chpt.Rows[n].Cells[0].Value = (i + 1);
\r
1025 data_chpt.Rows[n].Cells[1].Value = "Chapter " + (i + 1);
\r
1026 data_chpt.Rows[n].Cells[0].ValueType = typeof(int);
\r
1027 data_chpt.Rows[n].Cells[1].ValueType = typeof(string);
\r
1032 // Disable chapter markers if only 1 chapter is selected.
\r
1033 if (c_start == c_end)
\r
1035 Check_ChapterMarkers.Checked = false;
\r
1036 Check_ChapterMarkers.Enabled = false;
\r
1039 Check_ChapterMarkers.Enabled = true;
\r
1043 private void btn_destBrowse_Click(object sender, EventArgs e)
\r
1045 // This removes the file extension from the filename box on the save file dialog.
\r
1046 // It's daft but some users don't realise that typing an extension overrides the dropdown extension selected.
\r
1047 DVD_Save.FileName = Path.GetFileNameWithoutExtension(text_destination.Text);
\r
1049 if (Path.IsPathRooted(text_destination.Text))
\r
1050 DVD_Save.InitialDirectory = Path.GetDirectoryName(text_destination.Text);
\r
1052 // Show the dialog and set the main form file path
\r
1053 if (drop_format.SelectedIndex.Equals(0))
\r
1054 DVD_Save.FilterIndex = 1;
\r
1055 else if (drop_format.SelectedIndex.Equals(1))
\r
1056 DVD_Save.FilterIndex = 2;
\r
1058 if (DVD_Save.ShowDialog() == DialogResult.OK)
\r
1060 if (DVD_Save.FileName.StartsWith("\\"))
\r
1061 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
1064 // Add a file extension manually, as FileDialog.AddExtension has issues with dots in filenames
\r
1065 switch (DVD_Save.FilterIndex)
\r
1068 if (!Path.GetExtension(DVD_Save.FileName).Equals(".mp4", StringComparison.InvariantCultureIgnoreCase))
\r
1069 if (Properties.Settings.Default.useM4v)
\r
1070 DVD_Save.FileName += ".m4v";
\r
1072 DVD_Save.FileName += ".mp4";
\r
1075 if (!Path.GetExtension(DVD_Save.FileName).Equals(".mkv", StringComparison.InvariantCultureIgnoreCase))
\r
1076 DVD_Save.FileName += ".mkv";
\r
1082 text_destination.Text = DVD_Save.FileName;
\r
1084 // Quicktime requires .m4v file for chapter markers to work. If checked, change the extension to .m4v (mp4 and m4v are the same thing)
\r
1085 if (Check_ChapterMarkers.Checked && DVD_Save.FilterIndex != 2)
\r
1086 setExtension(".m4v");
\r
1090 private void text_destination_TextChanged(object sender, EventArgs e)
\r
1092 string path = text_destination.Text;
\r
1093 if (path.EndsWith(".mp4") || path.EndsWith(".m4v"))
\r
1094 drop_format.SelectedIndex = 0;
\r
1095 else if (path.EndsWith(".mkv"))
\r
1096 drop_format.SelectedIndex = 1;
\r
1099 // Output Settings
\r
1100 private void drop_format_SelectedIndexChanged(object sender, EventArgs e)
\r
1102 switch (drop_format.SelectedIndex)
\r
1105 if (Properties.Settings.Default.useM4v)
\r
1106 setExtension(".m4v");
\r
1108 setExtension(".mp4");
\r
1111 setExtension(".mkv");
\r
1115 AudioSettings.setAudioByContainer(drop_format.Text);
\r
1116 Subtitles.setContainer(drop_format.SelectedIndex);
\r
1118 if ((drop_format.Text.Contains("MP4")) || (drop_format.Text.Contains("M4V")))
\r
1120 if (drp_videoEncoder.Items.Contains("VP3 (Theora)"))
\r
1122 drp_videoEncoder.Items.Remove("VP3 (Theora)");
\r
1123 drp_videoEncoder.SelectedIndex = 1;
\r
1126 else if (drop_format.Text.Contains("MKV"))
\r
1127 drp_videoEncoder.Items.Add("VP3 (Theora)");
\r
1129 private void setExtension(string newExtension)
\r
1131 text_destination.Text = text_destination.Text.Replace(".mp4", newExtension);
\r
1132 text_destination.Text = text_destination.Text.Replace(".m4v", newExtension);
\r
1133 text_destination.Text = text_destination.Text.Replace(".mkv", newExtension);
\r
1137 private void drp_videoEncoder_SelectedIndexChanged(object sender, EventArgs e)
\r
1139 setContainerOpts();
\r
1141 //Turn off some options which are H.264 only when the user selects a non h.264 encoder
\r
1142 if (drp_videoEncoder.Text.Contains("H.264"))
\r
1144 if (check_2PassEncode.CheckState == CheckState.Checked)
\r
1145 check_turbo.Enabled = true;
\r
1147 tab_advanced.Enabled = true;
\r
1148 if ((drop_format.Text.Contains("MP4")) || (drop_format.Text.Contains("M4V")))
\r
1149 check_iPodAtom.Enabled = true;
\r
1151 check_iPodAtom.Enabled = false;
\r
1155 check_turbo.CheckState = CheckState.Unchecked;
\r
1156 check_turbo.Enabled = false;
\r
1157 tab_advanced.Enabled = false;
\r
1158 x264Panel.x264Query = "";
\r
1159 check_iPodAtom.Enabled = false;
\r
1160 check_iPodAtom.Checked = false;
\r
1163 // Setup the CQ Slider
\r
1164 switch (drp_videoEncoder.Text)
\r
1166 case "MPEG-4 (FFmpeg)":
\r
1167 if (slider_videoQuality.Value > 31)
\r
1168 slider_videoQuality.Value = 20; // Just reset to 70% QP 10 on encode change.
\r
1169 slider_videoQuality.Minimum = 1;
\r
1170 slider_videoQuality.Maximum = 31;
\r
1172 case "H.264 (x264)":
\r
1173 slider_videoQuality.Minimum = 0;
\r
1174 slider_videoQuality.TickFrequency = 1;
\r
1176 CultureInfo culture = CultureInfo.CreateSpecificCulture("en-US");
\r
1177 double multiplier = 1.0 / Properties.Settings.Default.x264cqstep;
\r
1178 double value = slider_videoQuality.Value * multiplier;
\r
1180 switch (Properties.Settings.Default.x264cqstep.ToString(culture))
\r
1183 slider_videoQuality.Maximum = 255;
\r
1186 slider_videoQuality.Maximum = 204;
\r
1189 slider_videoQuality.Maximum = 40;
\r
1192 slider_videoQuality.Maximum = 51;
\r
1195 slider_videoQuality.Maximum = 51;
\r
1198 if (value < slider_videoQuality.Maximum)
\r
1199 slider_videoQuality.Value = slider_videoQuality.Maximum - (int)value;
\r
1202 case "VP3 (Theora)":
\r
1203 if (slider_videoQuality.Value > 63)
\r
1204 slider_videoQuality.Value = 45; // Just reset to 70% QP 45 on encode change.
\r
1205 slider_videoQuality.Minimum = 0;
\r
1206 slider_videoQuality.Maximum = 63;
\r
1211 /// Set the container format options
\r
1213 public void setContainerOpts()
\r
1215 if ((drop_format.Text.Contains("MP4")) || (drop_format.Text.Contains("M4V")))
\r
1217 check_largeFile.Enabled = true;
\r
1218 check_optimiseMP4.Enabled = true;
\r
1219 check_iPodAtom.Enabled = true;
\r
1223 check_largeFile.Enabled = false;
\r
1224 check_optimiseMP4.Enabled = false;
\r
1225 check_iPodAtom.Enabled = false;
\r
1226 check_largeFile.Checked = false;
\r
1227 check_optimiseMP4.Checked = false;
\r
1228 check_iPodAtom.Checked = false;
\r
1231 private void slider_videoQuality_Scroll(object sender, EventArgs e)
\r
1233 switch (drp_videoEncoder.Text)
\r
1235 case "MPEG-4 (FFmpeg)":
\r
1236 double rfValue = 31 - (slider_videoQuality.Value - 1);
\r
1237 double max = slider_videoQuality.Maximum;
\r
1238 double min = slider_videoQuality.Minimum;
\r
1239 double val = ((max - min) - (rfValue - min)) / (max - min);
\r
1240 SliderValue.Text = Math.Round((val * 100), 2) + "% QP:" + (32 - slider_videoQuality.Value);
\r
1242 case "H.264 (x264)":
\r
1243 rfValue = 51.0 - slider_videoQuality.Value * Properties.Settings.Default.x264cqstep;
\r
1244 max = slider_videoQuality.Maximum * Properties.Settings.Default.x264cqstep;
\r
1245 min = slider_videoQuality.Minimum;
\r
1246 val = ((max - min) - (rfValue - min)) / (max - min);
\r
1247 rfValue = Math.Round(rfValue, 2);
\r
1248 SliderValue.Text = Math.Round((val * 100), 2) + "% RF:" + rfValue;
\r
1250 case "VP3 (Theora)":
\r
1251 rfValue = slider_videoQuality.Value;
\r
1252 double value = rfValue / 63;
\r
1253 SliderValue.Text = Math.Round((value * 100), 2) + "% QP:" + slider_videoQuality.Value;
\r
1257 private void radio_targetFilesize_CheckedChanged(object sender, EventArgs e)
\r
1259 text_bitrate.Enabled = false;
\r
1260 text_filesize.Enabled = true;
\r
1261 slider_videoQuality.Enabled = false;
\r
1263 check_2PassEncode.Enabled = true;
\r
1265 private void radio_avgBitrate_CheckedChanged(object sender, EventArgs e)
\r
1267 text_bitrate.Enabled = true;
\r
1268 text_filesize.Enabled = false;
\r
1269 slider_videoQuality.Enabled = false;
\r
1271 check_2PassEncode.Enabled = true;
\r
1273 private void radio_cq_CheckedChanged(object sender, EventArgs e)
\r
1275 text_bitrate.Enabled = false;
\r
1276 text_filesize.Enabled = false;
\r
1277 slider_videoQuality.Enabled = true;
\r
1279 check_2PassEncode.Enabled = false;
\r
1280 check_2PassEncode.CheckState = CheckState.Unchecked;
\r
1282 private void check_2PassEncode_CheckedChanged(object sender, EventArgs e)
\r
1284 if (check_2PassEncode.CheckState.ToString() == "Checked")
\r
1286 if (drp_videoEncoder.Text.Contains("H.264"))
\r
1287 check_turbo.Enabled = true;
\r
1291 check_turbo.Enabled = false;
\r
1292 check_turbo.CheckState = CheckState.Unchecked;
\r
1296 // Chapter Marker Tab
\r
1297 private void Check_ChapterMarkers_CheckedChanged(object sender, EventArgs e)
\r
1299 if (Check_ChapterMarkers.Checked)
\r
1301 if (drop_format.SelectedIndex != 1)
\r
1302 setExtension(".m4v");
\r
1303 data_chpt.Rows.Clear();
\r
1304 data_chpt.Enabled = true;
\r
1305 DataGridView chapterGridView = Main.chapterNaming(data_chpt, drop_chapterFinish.Text);
\r
1306 if (chapterGridView != null)
\r
1307 data_chpt = chapterGridView;
\r
1311 if (drop_format.SelectedIndex != 1 && !Properties.Settings.Default.useM4v)
\r
1312 setExtension(".mp4");
\r
1313 data_chpt.Rows.Clear();
\r
1314 data_chpt.Enabled = false;
\r
1318 // Query Editor Tab
\r
1319 private void btn_generate_Query_Click(object sender, EventArgs e)
\r
1321 rtf_query.Text = queryGen.generateTheQuery(this);
\r
1323 private void btn_clear_Click(object sender, EventArgs e)
\r
1325 rtf_query.Clear();
\r
1329 // MainWindow Components, Actions and Functions ***********************
\r
1331 #region Source Scan
\r
1332 public Boolean isScanning { get; set; }
\r
1333 private static int scanProcessID { get; set; }
\r
1334 private void setupGUIforScan(String filename)
\r
1336 sourcePath = filename;
\r
1337 foreach (Control ctrl in Controls)
\r
1339 if (!(ctrl is StatusStrip || ctrl is MenuStrip || ctrl is ToolStrip))
\r
1340 ctrl.Enabled = false;
\r
1342 lbl_encode.Visible = true;
\r
1343 lbl_encode.Text = "Scanning ...";
\r
1344 //gb_source.Text = "Source: Scanning ...";
\r
1345 btn_source.Enabled = false;
\r
1346 btn_start.Enabled = false;
\r
1347 btn_showQueue.Enabled = false;
\r
1348 btn_add2Queue.Enabled = false;
\r
1349 tb_preview.Enabled = false;
\r
1350 mnu_killCLI.Visible = true;
\r
1352 private void startScan(String filename)
\r
1356 lbl_encode.Visible = true;
\r
1357 lbl_encode.Text = "Scanning...";
\r
1358 isScanning = true;
\r
1359 ThreadPool.QueueUserWorkItem(scanProcess, filename);
\r
1361 catch (Exception exc)
\r
1363 MessageBox.Show("frmMain.cs - startScan " + exc, "Error", MessageBoxButtons.OK, MessageBoxIcon.Error);
\r
1366 private void scanProcess(object state)
\r
1370 string inputFile = (string)state;
\r
1371 string handbrakeCLIPath = Path.Combine(Application.StartupPath, "HandBrakeCLI.exe");
\r
1372 string logDir = Environment.GetFolderPath(Environment.SpecialFolder.ApplicationData) + "\\HandBrake\\logs";
\r
1373 string dvdInfoPath = Path.Combine(logDir, "last_scan_log.txt");
\r
1375 // Make we don't pick up a stale last_encode_log.txt (and that we have rights to the file)
\r
1376 if (File.Exists(dvdInfoPath))
\r
1377 File.Delete(dvdInfoPath);
\r
1379 String dvdnav = string.Empty;
\r
1380 if (Properties.Settings.Default.dvdnav)
\r
1381 dvdnav = " --dvdnav";
\r
1382 string strCmdLine = String.Format(@"cmd /c """"{0}"" -i ""{1}"" -t0 {2} -v >""{3}"" 2>&1""", handbrakeCLIPath, inputFile, dvdnav, dvdInfoPath);
\r
1384 ProcessStartInfo hbParseDvd = new ProcessStartInfo("CMD.exe", strCmdLine) { WindowStyle = ProcessWindowStyle.Hidden };
\r
1386 Boolean cleanExit = true;
\r
1387 using (hbproc = Process.Start(hbParseDvd))
\r
1389 Process[] before = Process.GetProcesses(); // Get a list of running processes before starting.
\r
1390 scanProcessID = Main.getCliProcess(before);
\r
1391 hbproc.WaitForExit();
\r
1392 if (hbproc.ExitCode != 0)
\r
1393 cleanExit = false;
\r
1396 if (cleanExit) // If 0 exit code, CLI exited cleanly.
\r
1398 if (!File.Exists(dvdInfoPath))
\r
1400 throw new Exception(
\r
1401 "Unable to retrieve the DVD Info. last_scan_log.txt is missing. \nExpected location of last_scan_log.txt: \n" +
\r
1405 using (StreamReader sr = new StreamReader(dvdInfoPath))
\r
1407 thisDVD = DVD.Parse(sr);
\r
1412 updateUIafterScan();
\r
1415 catch (Exception exc)
\r
1417 MessageBox.Show("frmMain.cs - scanProcess() " + exc, "Error", MessageBoxButtons.OK, MessageBoxIcon.Error);
\r
1421 private void updateUIafterScan()
\r
1425 if (InvokeRequired)
\r
1427 BeginInvoke(new UpdateWindowHandler(updateUIafterScan));
\r
1431 // Setup some GUI components
\r
1432 drp_dvdtitle.Items.Clear();
\r
1433 if (thisDVD.Titles.Count != 0)
\r
1434 drp_dvdtitle.Items.AddRange(thisDVD.Titles.ToArray());
\r
1435 drp_dvdtitle.Text = "Automatic";
\r
1436 drop_chapterFinish.Text = "Auto";
\r
1437 drop_chapterStart.Text = "Auto";
\r
1439 // Now select the longest title
\r
1440 if (thisDVD.Titles.Count != 0)
\r
1441 drp_dvdtitle.SelectedItem = Main.selectLongestTitle(drp_dvdtitle);
\r
1443 // Enable the creation of chapter markers if the file is an image of a dvd.
\r
1444 if (sourcePath.ToLower().Contains(".iso") || sourcePath.ToLower().Contains("VIDEO_TS"))
\r
1445 Check_ChapterMarkers.Enabled = true;
\r
1448 Check_ChapterMarkers.Enabled = false;
\r
1449 Check_ChapterMarkers.Checked = false;
\r
1450 data_chpt.Rows.Clear();
\r
1453 // If no titles were found, Display an error message
\r
1454 if (drp_dvdtitle.Items.Count == 0)
\r
1457 "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).",
\r
1458 "Error", MessageBoxButtons.OK, MessageBoxIcon.Hand);
\r
1459 sourcePath = string.Empty;
\r
1461 UpdateSourceLabel();
\r
1463 // Enable the GUI components and enable any disabled components
\r
1466 catch (Exception exc)
\r
1468 MessageBox.Show("frmMain.cs - updateUIafterScan " + exc, "Error", MessageBoxButtons.OK, MessageBoxIcon.Error);
\r
1472 private void enableGUI()
\r
1476 if (InvokeRequired)
\r
1477 BeginInvoke(new UpdateWindowHandler(enableGUI));
\r
1478 lbl_encode.Text = "Scan Completed";
\r
1479 //gb_source.Text = "Source";
\r
1480 foreach (Control ctrl in Controls)
\r
1481 ctrl.Enabled = true;
\r
1482 btn_start.Enabled = true;
\r
1483 btn_showQueue.Enabled = true;
\r
1484 btn_add2Queue.Enabled = true;
\r
1485 tb_preview.Enabled = true;
\r
1486 btn_source.Enabled = true;
\r
1487 mnu_killCLI.Visible = false;
\r
1489 catch (Exception exc)
\r
1491 MessageBox.Show("frmMain.cs - enableGUI() " + exc, "Error", MessageBoxButtons.OK, MessageBoxIcon.Error);
\r
1494 private void killScan()
\r
1501 Process[] prs = Process.GetProcesses();
\r
1502 foreach (Process process in prs)
\r
1504 if (process.Id == scanProcessID)
\r
1506 process.Refresh();
\r
1507 if (!process.HasExited)
\r
1512 catch (Exception ex)
\r
1514 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
1517 private void resetGUI()
\r
1519 drp_dvdtitle.Items.Clear();
\r
1520 drp_dvdtitle.Text = "Automatic";
\r
1521 drop_chapterStart.Items.Clear();
\r
1522 drop_chapterStart.Text = "Auto";
\r
1523 drop_chapterFinish.Items.Clear();
\r
1524 drop_chapterFinish.Text = "Auto";
\r
1525 lbl_duration.Text = "Select a Title";
\r
1526 PictureSettings.lbl_src_res.Text = "Select a Title";
\r
1527 PictureSettings.lbl_Aspect.Text = "Select a Title";
\r
1528 sourcePath = "Source";
\r
1529 text_destination.Text = "";
\r
1531 selectedTitle = null;
\r
1532 isScanning = false;
\r
1535 private void UpdateSourceLabel()
\r
1537 labelSource.Text = string.IsNullOrEmpty(sourcePath) ? "Select \"Source\" to continue." : Path.GetFileName(sourcePath);
\r
1544 /// Set the GUI to it's finished encoding state.
\r
1546 private void setEncodeFinished()
\r
1550 if (InvokeRequired)
\r
1552 BeginInvoke(new UpdateWindowHandler(setEncodeFinished));
\r
1556 lbl_encode.Text = "Encoding Finished";
\r
1557 btn_start.Text = "Start";
\r
1558 btn_start.ToolTipText = "Start the encoding process";
\r
1559 btn_start.Image = Properties.Resources.Play;
\r
1561 // If the window is minimized, display the notification in a popup.
\r
1562 if (Properties.Settings.Default.trayIconAlerts)
\r
1563 if (FormWindowState.Minimized == this.WindowState)
\r
1565 notifyIcon.BalloonTipText = lbl_encode.Text;
\r
1566 notifyIcon.ShowBalloonTip(500);
\r
1569 catch (Exception exc)
\r
1571 MessageBox.Show(exc.ToString());
\r
1576 /// Set the GUI to it's started encoding state.
\r
1578 private void setEncodeStarted()
\r
1582 if (InvokeRequired)
\r
1584 BeginInvoke(new UpdateWindowHandler(setEncodeStarted));
\r
1588 lbl_encode.Visible = true;
\r
1589 lbl_encode.Text = "Encoding in Progress";
\r
1590 btn_start.Text = "Stop";
\r
1591 btn_start.ToolTipText = "Stop the encoding process.";
\r
1592 btn_start.Image = Properties.Resources.stop;
\r
1594 catch (Exception exc)
\r
1596 MessageBox.Show(exc.ToString());
\r
1601 #region DVD Drive Detection
\r
1602 private delegate void ProgressUpdateHandler();
\r
1603 private void getDriveInfoThread()
\r
1607 if (InvokeRequired)
\r
1609 BeginInvoke(new ProgressUpdateHandler(getDriveInfoThread));
\r
1613 Boolean foundDrive = false;
\r
1614 DriveInfo[] theCollectionOfDrives = DriveInfo.GetDrives();
\r
1615 foreach (DriveInfo curDrive in theCollectionOfDrives)
\r
1617 if (curDrive.DriveType == DriveType.CDRom && curDrive.IsReady)
\r
1619 if (File.Exists(curDrive.RootDirectory + "VIDEO_TS\\VIDEO_TS.IFO"))
\r
1621 mnu_dvd_drive.Text = curDrive.RootDirectory + "VIDEO_TS (" + curDrive.VolumeLabel + ")";
\r
1622 foundDrive = true;
\r
1628 if (foundDrive == false)
\r
1629 mnu_dvd_drive.Text = "[No DVD Drive Ready]";
\r
1633 mnu_dvd_drive.Text = "[No DVD Drive Ready / Found]";
\r
1638 #region Public Methods
\r
1640 /// Access the preset Handler and setup the preset panel.
\r
1642 public void loadPresetPanel()
\r
1644 if (presetHandler.checkIfPresetsAreOutOfDate())
\r
1645 if (!Properties.Settings.Default.presetNotification)
\r
1646 MessageBox.Show(splash,
\r
1647 "HandBrake has determined your built-in presets are out of date... These presets will now be updated.",
\r
1648 "Preset Update", MessageBoxButtons.OK, MessageBoxIcon.Information);
\r
1650 presetHandler.getPresetPanel(ref treeView_presets);
\r
1651 treeView_presets.Update();
\r
1655 /// Either Encode or Scan was last performed.
\r
1657 public string lastAction { get; set; }
\r
1662 /// If the queue is being processed, prompt the user to confirm application close.
\r
1664 /// <param name="e"></param>
\r
1665 protected override void OnFormClosing(FormClosingEventArgs e)
\r
1667 // If currently encoding, the queue isn't paused, and there are queue items to process, prompt to confirm close.
\r
1668 if ((encodeQueue.IsEncoding) && (!encodeQueue.PauseRequested) && (encodeQueue.Count > 0))
\r
1670 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
1671 "Close HandBrake?", MessageBoxButtons.YesNo, MessageBoxIcon.Question);
\r
1672 if (result == DialogResult.No)
\r
1675 base.OnFormClosing(e);
\r
1679 #region In-GUI Encode Status (Experimental)
\r
1681 private void encodeMonitorThread()
\r
1685 Parser encode = new Parser(encodeQueue.encodeHandler.hbProcess.StandardOutput.BaseStream);
\r
1686 encode.OnEncodeProgress += encodeOnEncodeProgress;
\r
1687 while (!encode.EndOfStream)
\r
1689 encode.readEncodeStatus();
\r
1692 catch (Exception exc)
\r
1694 MessageBox.Show(exc.ToString());
\r
1697 private void encodeOnEncodeProgress(object Sender, int CurrentTask, int TaskCount, float PercentComplete, float CurrentFps, float AverageFps, TimeSpan TimeRemaining)
\r
1699 if (this.InvokeRequired)
\r
1701 this.BeginInvoke(new EncodeProgressEventHandler(encodeOnEncodeProgress),
\r
1702 new object[] { Sender, CurrentTask, TaskCount, PercentComplete, CurrentFps, AverageFps, TimeRemaining });
\r
1705 lbl_encode.Text = string.Format("Encode Progress: {0}%, FPS: {1}, Avg FPS: {2}, Time Remaining: {3} ", PercentComplete, CurrentFps, AverageFps, TimeRemaining);
\r
1710 // This is the END of the road ****************************************
\r