3 This file is part of the HandBrake source code.
\r
4 Homepage: <http://handbrake.fr/>.
\r
5 It may be used under the terms of the GNU General Public License. */
\r
8 using System.Collections.Generic;
\r
9 using System.Drawing;
\r
10 using System.Globalization;
\r
11 using System.Windows.Forms;
\r
13 using System.Diagnostics;
\r
14 using System.Threading;
\r
15 using Handbrake.EncodeQueue;
\r
16 using Handbrake.Functions;
\r
17 using Handbrake.Presets;
\r
18 using Handbrake.Parsing;
\r
22 public partial class frmMain : Form
\r
24 // Objects which may be used by one or more other objects *************
\r
25 EncodeAndQueueHandler encodeQueue = new EncodeAndQueueHandler();
\r
26 PresetsHandler presetHandler = new PresetsHandler();
\r
27 QueryGenerator queryGen = new QueryGenerator();
\r
29 // Globals: Mainly used for tracking. *********************************
\r
30 public Title selectedTitle;
\r
31 private DVD thisDVD;
\r
32 private frmQueue queueWindow;
\r
33 private frmPreview qtpreview;
\r
34 private frmActivityWindow ActivityWindow;
\r
35 private Form splash;
\r
36 public string sourcePath;
\r
37 private string lastAction;
\r
39 // Delegates **********************************************************
\r
40 private delegate void UpdateWindowHandler();
\r
42 // Applicaiton Startup ************************************************
\r
44 #region Application Startup
\r
47 // Load and setup the splash screen in this thread
\r
48 splash = new frmSplashScreen();
\r
50 Label lblStatus = new Label { Size = new Size(150, 20), Location = new Point(182, 102) };
\r
51 splash.Controls.Add(lblStatus);
\r
53 InitializeComponent();
\r
55 // Update the users config file with the CLI version data.
\r
56 lblStatus.Text = "Setting Version Data ...";
\r
57 Application.DoEvents();
\r
58 Main.setCliVersionData();
\r
60 // Show the form, but leave disabled until preloading is complete then show the main form
\r
61 this.Enabled = false;
\r
63 Application.DoEvents(); // Forces frmMain to draw
\r
65 // Check for new versions, if update checking is enabled
\r
66 if (Properties.Settings.Default.updateStatus)
\r
68 DateTime now = DateTime.Now;
\r
69 DateTime lastCheck = Properties.Settings.Default.lastUpdateCheckDate;
\r
70 TimeSpan elapsed = now.Subtract(lastCheck);
\r
71 if (elapsed.TotalDays > Properties.Settings.Default.daysBetweenUpdateCheck)
\r
73 lblStatus.Text = "Checking for updates ...";
\r
74 Application.DoEvents();
\r
76 Main.BeginCheckForUpdates(new AsyncCallback(UpdateCheckDone), false);
\r
80 // Setup the GUI components
\r
81 lblStatus.Text = "Setting up the GUI ...";
\r
82 Application.DoEvents();
\r
83 loadPresetPanel(); // Load the Preset Panel
\r
84 treeView_presets.ExpandAll();
\r
85 lbl_encode.Text = "";
\r
86 queueWindow = new frmQueue(encodeQueue); // Prepare the Queue
\r
87 if (!Properties.Settings.Default.QueryEditorTab)
\r
88 tabs_panel.TabPages.RemoveAt(7); // Remove the query editor tab if the user does not want it enabled.
\r
90 // Load the user's default settings or Normal Preset
\r
91 if (Properties.Settings.Default.defaultSettings && Properties.Settings.Default.defaultPreset != "")
\r
93 if (presetHandler.getPreset(Properties.Settings.Default.defaultPreset) != null)
\r
95 string query = presetHandler.getPreset(Properties.Settings.Default.defaultPreset).Query;
\r
96 Boolean loadPictureSettings = presetHandler.getPreset(Properties.Settings.Default.defaultPreset).PictureSettings;
\r
100 //Ok, Reset all the H264 widgets before changing the preset
\r
101 x264Panel.reset2Defaults();
\r
103 // Send the query from the file to the Query Parser class, then load the preset
\r
104 QueryParser presetQuery = QueryParser.Parse(query);
\r
105 PresetLoader.presetLoader(this, presetQuery, Properties.Settings.Default.defaultPreset, loadPictureSettings);
\r
107 // The x264 widgets will need updated, so do this now:
\r
108 x264Panel.X264_StandardizeOptString();
\r
109 x264Panel.X264_SetCurrentSettingsInPanel();
\r
113 loadNormalPreset();
\r
116 loadNormalPreset();
\r
118 // Enabled GUI tooltip's if Required
\r
119 if (Properties.Settings.Default.tooltipEnable)
\r
120 ToolTip.Active = true;
\r
123 lblStatus.Text = "Loading Complete!";
\r
124 Application.DoEvents();
\r
127 this.Enabled = true;
\r
129 // Event Handlers and Queue Recovery
\r
134 private void UpdateCheckDone(IAsyncResult result)
\r
136 if (InvokeRequired)
\r
138 Invoke(new MethodInvoker(() => UpdateCheckDone(result)));
\r
142 UpdateCheckInformation info;
\r
146 info = Main.EndCheckForUpdates(result);
\r
148 if (info.NewVersionAvailable)
\r
150 frmUpdater updateWindow = new frmUpdater(info.BuildInformation);
\r
151 updateWindow.ShowDialog();
\r
154 catch (Exception ex)
\r
156 if ((bool)result.AsyncState)
\r
157 MessageBox.Show("Unable to check for updates, Please try again later. \n" + ex, "Error", MessageBoxButtons.OK, MessageBoxIcon.Error);
\r
161 // Startup Functions
\r
162 private void queueRecovery()
\r
164 if (Main.check_queue_recovery())
\r
166 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
168 if (result == DialogResult.Yes)
\r
169 encodeQueue.LoadQueueFromFile("hb_queue_recovery.xml"); // Start Recovery
\r
172 // Remove the Queue recovery file if the user doesn't want to recovery the last queue.
\r
173 string queuePath = Path.Combine(Path.GetTempPath(), "hb_queue_recovery.xml");
\r
174 if (File.Exists(queuePath))
\r
175 File.Delete(queuePath);
\r
182 // Encoding Events for setting up the GUI
\r
183 private void events()
\r
185 // Handle Widget changes when preset is selected.
\r
186 registerPresetEventHandler();
\r
188 // Handle Window Resize
\r
189 if (Properties.Settings.Default.MainWindowMinimize)
\r
190 this.Resize += new EventHandler(frmMain_Resize);
\r
192 // Handle Encode Start / Finish / Pause
\r
193 encodeQueue.CurrentJobCompleted += new EventHandler(encodeEnded);
\r
194 encodeQueue.QueuePauseRequested += new EventHandler(encodePaused);
\r
195 encodeQueue.NewJobStarted += new EventHandler(encodeStarted);
\r
197 // Handle a file being draged onto the GUI.
\r
198 this.DragEnter += new DragEventHandler(frmMain_DragEnter);
\r
199 this.DragDrop += new DragEventHandler(frmMain_DragDrop);
\r
202 // 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
203 public void registerPresetEventHandler()
\r
206 drop_format.SelectedIndexChanged += new EventHandler(changePresetLabel);
\r
207 check_largeFile.CheckedChanged += new EventHandler(changePresetLabel);
\r
208 check_iPodAtom.CheckedChanged += new EventHandler(changePresetLabel);
\r
209 check_optimiseMP4.CheckedChanged += new EventHandler(changePresetLabel);
\r
211 // Picture Settings
\r
212 //PictureSettings.PictureSettingsChanged += new EventHandler(changePresetLabel);
\r
215 Filters.FilterSettingsChanged += new EventHandler(changePresetLabel);
\r
218 drp_videoEncoder.SelectedIndexChanged += new EventHandler(changePresetLabel);
\r
219 check_2PassEncode.CheckedChanged += new EventHandler(changePresetLabel);
\r
220 check_turbo.CheckedChanged += new EventHandler(changePresetLabel);
\r
221 text_filesize.TextChanged += new EventHandler(changePresetLabel);
\r
222 text_bitrate.TextChanged += new EventHandler(changePresetLabel);
\r
223 slider_videoQuality.ValueChanged += new EventHandler(changePresetLabel);
\r
226 AudioSettings.AudioListChanged += new EventHandler(changePresetLabel);
\r
229 x264Panel.rtf_x264Query.TextChanged += new EventHandler(changePresetLabel);
\r
231 public void unRegisterPresetEventHandler()
\r
233 // Output Settings
\r
234 drop_format.SelectedIndexChanged -= new EventHandler(changePresetLabel);
\r
235 check_largeFile.CheckedChanged -= new EventHandler(changePresetLabel);
\r
236 check_iPodAtom.CheckedChanged -= new EventHandler(changePresetLabel);
\r
237 check_optimiseMP4.CheckedChanged -= new EventHandler(changePresetLabel);
\r
239 // Picture Settings
\r
240 //PictureSettings.PictureSettingsChanged -= new EventHandler(changePresetLabel);
\r
243 Filters.FilterSettingsChanged -= new EventHandler(changePresetLabel);
\r
246 drp_videoEncoder.SelectedIndexChanged -= new EventHandler(changePresetLabel);
\r
247 check_2PassEncode.CheckedChanged -= new EventHandler(changePresetLabel);
\r
248 check_turbo.CheckedChanged -= new EventHandler(changePresetLabel);
\r
249 text_filesize.TextChanged -= new EventHandler(changePresetLabel);
\r
250 text_bitrate.TextChanged -= new EventHandler(changePresetLabel);
\r
251 slider_videoQuality.ValueChanged -= new EventHandler(changePresetLabel);
\r
254 AudioSettings.AudioListChanged -= new EventHandler(changePresetLabel);
\r
257 x264Panel.rtf_x264Query.TextChanged -= new EventHandler(changePresetLabel);
\r
259 private void changePresetLabel(object sender, EventArgs e)
\r
261 labelPreset.Text = "Output Settings (Preset: Custom)";
\r
264 private static void frmMain_DragEnter(object sender, DragEventArgs e)
\r
266 if (e.Data.GetDataPresent(DataFormats.FileDrop, false))
\r
267 e.Effect = DragDropEffects.All;
\r
269 private void frmMain_DragDrop(object sender, DragEventArgs e)
\r
271 string[] fileList = e.Data.GetData(DataFormats.FileDrop) as string[];
\r
272 sourcePath = string.Empty;
\r
274 if (fileList != null)
\r
276 if (fileList[0].StartsWith("\\"))
\r
279 "Sorry, HandBrake does not support UNC file paths. \nTry mounting the share as a network drive in My Computer",
\r
280 "Warning", MessageBoxButtons.OK, MessageBoxIcon.Warning);
\r
281 UpdateSourceLabel();
\r
285 if (fileList[0] != "")
\r
287 setupGUIforScan(fileList[0]);
\r
288 startScan(fileList[0]);
\r
291 UpdateSourceLabel();
\r
295 UpdateSourceLabel();
\r
297 private void encodeStarted(object sender, EventArgs e)
\r
299 lastAction = "encode";
\r
300 setEncodeStarted();
\r
302 // Experimental HBProc Process Monitoring.
\r
303 if (Properties.Settings.Default.enocdeStatusInGui)
\r
305 Thread encodeMon = new Thread(encodeMonitorThread);
\r
309 private void encodeEnded(object sender, EventArgs e)
\r
311 setEncodeFinished();
\r
313 private void encodePaused(object sender, EventArgs e)
\r
315 setEncodeFinished();
\r
319 // User Interface Menus / Tool Strips *********************************
\r
322 private void mnu_killCLI_Click(object sender, EventArgs e)
\r
326 private void mnu_exit_Click(object sender, EventArgs e)
\r
328 Application.Exit();
\r
333 private void mnu_encode_Click(object sender, EventArgs e)
\r
335 queueWindow.Show();
\r
337 private void mnu_encodeLog_Click(object sender, EventArgs e)
\r
339 String file = lastAction == "scan" ? "last_scan_log.txt" : "last_encode_log.txt";
\r
341 frmActivityWindow dvdInfoWindow = new frmActivityWindow(file, encodeQueue, this);
\r
342 dvdInfoWindow.Show();
\r
344 private void mnu_options_Click(object sender, EventArgs e)
\r
346 Form options = new frmOptions();
\r
347 options.ShowDialog();
\r
351 #region Presets Menu
\r
352 private void mnu_presetReset_Click(object sender, EventArgs e)
\r
354 presetHandler.updateBuiltInPresets();
\r
356 if (treeView_presets.Nodes.Count == 0)
\r
357 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
359 MessageBox.Show("Presets have been updated!", "Alert", MessageBoxButtons.OK, MessageBoxIcon.Information);
\r
361 treeView_presets.ExpandAll();
\r
363 private void mnu_delete_preset_Click(object sender, EventArgs e)
\r
365 presetHandler.removeBuiltInPresets();
\r
366 loadPresetPanel(); // Reload the preset panel
\r
368 private void mnu_SelectDefault_Click(object sender, EventArgs e)
\r
370 loadNormalPreset();
\r
372 private void mnu_importMacPreset_Click(object sender, EventArgs e)
\r
374 Import imp = new Import();
\r
375 if (openPreset.ShowDialog() == DialogResult.OK)
\r
377 QueryParser parsed = imp.importMacPreset(openPreset.FileName);
\r
378 if (presetHandler.checkIfUserPresetExists(parsed.PresetName + " (Imported)"))
\r
380 DialogResult result = MessageBox.Show("This preset appears to already exist. Would you like to overwrite it?", "Overwrite preset?",
\r
381 MessageBoxButtons.YesNo, MessageBoxIcon.Warning);
\r
382 if (result == DialogResult.Yes)
\r
384 PresetLoader.presetLoader(this, parsed, parsed.PresetName, parsed.UsesPictureSettings);
\r
385 presetHandler.updatePreset(parsed.PresetName + " (Imported)", queryGen.generateTheQuery(this),
\r
386 parsed.UsesPictureSettings);
\r
391 PresetLoader.presetLoader(this, parsed, parsed.PresetName, parsed.UsesPictureSettings);
\r
392 presetHandler.addPreset(parsed.PresetName, queryGen.generateTheQuery(this), parsed.UsesPictureSettings);
\r
394 if (presetHandler.addPreset(parsed.PresetName + " (Imported)", queryGen.generateTheQuery(this), parsed.UsesPictureSettings))
\r
396 TreeNode preset_treeview = new TreeNode(parsed.PresetName + " (Imported)") { ForeColor = Color.Black };
\r
397 treeView_presets.Nodes.Add(preset_treeview);
\r
402 private void btn_new_preset_Click(object sender, EventArgs e)
\r
404 Form preset = new frmAddPreset(this, queryGen.generateTheQuery(this), presetHandler);
\r
405 preset.ShowDialog();
\r
410 private void mnu_handbrake_forums_Click(object sender, EventArgs e)
\r
412 Process.Start("http://forum.handbrake.fr/");
\r
414 private void mnu_user_guide_Click(object sender, EventArgs e)
\r
416 Process.Start("http://trac.handbrake.fr/wiki/HandBrakeGuide");
\r
418 private void mnu_handbrake_home_Click(object sender, EventArgs e)
\r
420 Process.Start("http://handbrake.fr");
\r
422 private void mnu_UpdateCheck_Click(object sender, EventArgs e)
\r
424 lbl_updateCheck.Visible = true;
\r
425 Main.BeginCheckForUpdates(new AsyncCallback(updateCheckDoneMenu), false);
\r
427 private void updateCheckDoneMenu(IAsyncResult result)
\r
429 // Make sure it's running on the calling thread
\r
430 if (InvokeRequired)
\r
432 Invoke(new MethodInvoker(() => updateCheckDoneMenu(result)));
\r
435 UpdateCheckInformation info;
\r
438 // Get the information about the new build, if any, and close the window
\r
439 info = Main.EndCheckForUpdates(result);
\r
441 if (info.NewVersionAvailable && info.BuildInformation != null)
\r
443 frmUpdater updateWindow = new frmUpdater(info.BuildInformation);
\r
444 updateWindow.ShowDialog();
\r
447 MessageBox.Show("There are no new updates at this time.", "Update Check", MessageBoxButtons.OK, MessageBoxIcon.Information);
\r
448 lbl_updateCheck.Visible = false;
\r
451 catch (Exception ex)
\r
453 if ((bool)result.AsyncState)
\r
454 MessageBox.Show("Unable to check for updates, Please try again later. \n" + ex, "Error", MessageBoxButtons.OK, MessageBoxIcon.Error);
\r
457 private void mnu_about_Click(object sender, EventArgs e)
\r
459 using (frmAbout About = new frmAbout())
\r
461 About.ShowDialog();
\r
467 // Right Click Menu Code
\r
468 private void pmnu_expandAll_Click(object sender, EventArgs e)
\r
470 treeView_presets.ExpandAll();
\r
472 private void pmnu_collapse_Click(object sender, EventArgs e)
\r
474 treeView_presets.CollapseAll();
\r
476 private void pmnu_saveChanges_Click(object sender, EventArgs e)
\r
478 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
479 if (result == DialogResult.Yes)
\r
480 presetHandler.updatePreset(treeView_presets.SelectedNode.Text, QueryGenerator.generateTabbedComponentsQuery(this), true);
\r
481 else if (result == DialogResult.No)
\r
482 presetHandler.updatePreset(treeView_presets.SelectedNode.Text, QueryGenerator.generateTabbedComponentsQuery(this), false);
\r
484 private void pmnu_delete_click(object sender, EventArgs e)
\r
486 if (treeView_presets.SelectedNode != null)
\r
488 presetHandler.remove(treeView_presets.SelectedNode.Text);
\r
489 treeView_presets.Nodes.Remove(treeView_presets.SelectedNode);
\r
491 treeView_presets.Select();
\r
493 private void presets_menu_Opening(object sender, System.ComponentModel.CancelEventArgs e)
\r
495 // Make sure that the save menu is always disabled by default
\r
496 pmnu_saveChanges.Enabled = false;
\r
498 // Now enable the save menu if the selected preset is a user preset
\r
499 if (treeView_presets.SelectedNode != null)
\r
500 if (presetHandler.checkIfUserPresetExists(treeView_presets.SelectedNode.Text))
\r
501 pmnu_saveChanges.Enabled = true;
\r
503 treeView_presets.Select();
\r
506 // Presets Management
\r
507 private void btn_addPreset_Click(object sender, EventArgs e)
\r
509 Form preset = new frmAddPreset(this, QueryGenerator.generateTabbedComponentsQuery(this), presetHandler);
\r
510 preset.ShowDialog();
\r
512 private void btn_removePreset_Click(object sender, EventArgs e)
\r
514 DialogResult result = MessageBox.Show("Are you sure you wish to delete the selected preset?", "Preset", MessageBoxButtons.YesNo, MessageBoxIcon.Question);
\r
515 if (result == DialogResult.Yes)
\r
517 if (treeView_presets.SelectedNode != null)
\r
519 presetHandler.remove(treeView_presets.SelectedNode.Text);
\r
520 treeView_presets.Nodes.Remove(treeView_presets.SelectedNode);
\r
523 treeView_presets.Select();
\r
525 private void btn_setDefault_Click(object sender, EventArgs e)
\r
527 if (treeView_presets.SelectedNode != null)
\r
529 DialogResult result = MessageBox.Show("Are you sure you wish to set this preset as the default?", "Preset", MessageBoxButtons.YesNo, MessageBoxIcon.Question);
\r
530 if (result == DialogResult.Yes)
\r
532 Properties.Settings.Default.defaultPreset = treeView_presets.SelectedNode.Text;
\r
533 Properties.Settings.Default.Save();
\r
534 MessageBox.Show("New default preset set.", "Alert", MessageBoxButtons.OK, MessageBoxIcon.Information);
\r
538 MessageBox.Show("Please select a preset first.", "Warning", MessageBoxButtons.OK, MessageBoxIcon.Warning);
\r
540 private void treeview_presets_mouseUp(object sender, MouseEventArgs e)
\r
542 if (e.Button == MouseButtons.Right)
\r
543 treeView_presets.SelectedNode = treeView_presets.GetNodeAt(e.Location);
\r
544 else if (e.Button == MouseButtons.Left)
\r
546 if (treeView_presets.GetNodeAt(e.Location) != null)
\r
548 if (labelPreset.Text.Contains(treeView_presets.GetNodeAt(e.Location).Text))
\r
553 treeView_presets.Select();
\r
555 private void treeView_presets_AfterSelect(object sender, TreeViewEventArgs e)
\r
559 private void treeView_presets_deleteKey(object sender, KeyEventArgs e)
\r
561 if (e.KeyCode == Keys.Delete)
\r
563 DialogResult result = MessageBox.Show("Are you sure you wish to delete the selected preset?", "Preset", MessageBoxButtons.YesNo, MessageBoxIcon.Question);
\r
564 if (result == DialogResult.Yes)
\r
566 if (treeView_presets.SelectedNode != null)
\r
567 presetHandler.remove(treeView_presets.SelectedNode.Text);
\r
569 // Remember each nodes expanded status so we can reload it
\r
570 List<Boolean> nodeStatus = new List<Boolean>();
\r
571 foreach (TreeNode node in treeView_presets.Nodes)
\r
572 nodeStatus.Add(node.IsExpanded);
\r
574 // Now reload the preset panel
\r
577 // And finally, re-expand any of the nodes if required
\r
579 foreach (TreeNode node in treeView_presets.Nodes)
\r
589 private void selectPreset()
\r
591 if (treeView_presets.SelectedNode != null)
\r
593 // Ok, so, we've selected a preset. Now we want to load it.
\r
594 string presetName = treeView_presets.SelectedNode.Text;
\r
595 if (presetHandler.getPreset(presetName) != null)
\r
597 string query = presetHandler.getPreset(presetName).Query;
\r
598 Boolean loadPictureSettings = presetHandler.getPreset(presetName).PictureSettings;
\r
602 //Ok, Reset all the H264 widgets before changing the preset
\r
603 x264Panel.reset2Defaults();
\r
605 // Send the query from the file to the Query Parser class
\r
606 QueryParser presetQuery = QueryParser.Parse(query);
\r
608 // Now load the preset
\r
609 PresetLoader.presetLoader(this, presetQuery, presetName, loadPictureSettings);
\r
611 // The x264 widgets will need updated, so do this now:
\r
612 x264Panel.X264_StandardizeOptString();
\r
613 x264Panel.X264_SetCurrentSettingsInPanel();
\r
618 private void loadNormalPreset()
\r
620 foreach (TreeNode treenode in treeView_presets.Nodes)
\r
622 foreach (TreeNode node in treenode.Nodes)
\r
624 if (node.Text.Equals("Normal"))
\r
625 treeView_presets.SelectedNode = treeView_presets.Nodes[treenode.Index].Nodes[0];
\r
632 private void btn_source_Click(object sender, EventArgs e)
\r
634 if (Properties.Settings.Default.drive_detection)
\r
636 mnu_dvd_drive.Visible = true;
\r
637 Thread driveInfoThread = new Thread(getDriveInfoThread);
\r
638 driveInfoThread.Start();
\r
641 mnu_dvd_drive.Visible = false;
\r
643 private void btn_start_Click(object sender, EventArgs e)
\r
645 if (btn_start.Text == "Stop")
\r
647 DialogResult result = MessageBox.Show("Are you sure you wish to cancel the encode?", "Cancel Encode?", MessageBoxButtons.YesNo, MessageBoxIcon.Question);
\r
649 if (result == DialogResult.Yes)
\r
652 encodeQueue.RequestPause();
\r
654 // Allow the CLI to exit cleanly
\r
655 Win32.SetForegroundWindow((int)encodeQueue.processHandle);
\r
656 SendKeys.Send("^C");
\r
659 setEncodeFinished();
\r
664 if (encodeQueue.Count != 0 || (!string.IsNullOrEmpty(sourcePath) && !string.IsNullOrEmpty(text_destination.Text)))
\r
666 string generatedQuery = queryGen.generateTheQuery(this);
\r
667 string specifiedQuery = rtf_query.Text != "" ? rtf_query.Text : queryGen.generateTheQuery(this);
\r
668 string query = string.Empty;
\r
670 // Check to make sure the generated query matches the GUI settings
\r
671 if (Properties.Settings.Default.PromptOnUnmatchingQueries && !string.IsNullOrEmpty(specifiedQuery) && generatedQuery != specifiedQuery)
\r
673 DialogResult result = MessageBox.Show("The query under the \"Query Editor\" tab " +
\r
674 "does not match the current GUI settings. Because the manual query takes " +
\r
675 "priority over the GUI, your recently updated settings will not be taken " +
\r
676 "into account when encoding this job." + Environment.NewLine + Environment.NewLine +
\r
677 "Do you want to replace the manual query with the GUI-generated query?",
\r
678 "Manual Query does not Match GUI",
\r
679 MessageBoxButtons.YesNoCancel, MessageBoxIcon.Asterisk,
\r
680 MessageBoxDefaultButton.Button3);
\r
684 case DialogResult.Yes:
\r
685 // Replace the manual query with the generated one
\r
686 query = generatedQuery;
\r
687 rtf_query.Text = generatedQuery;
\r
689 case DialogResult.No:
\r
690 // Use the manual query
\r
691 query = specifiedQuery;
\r
693 case DialogResult.Cancel:
\r
694 // Don't start the encode
\r
700 query = generatedQuery;
\r
703 DialogResult overwrite = DialogResult.Yes;
\r
704 if (text_destination.Text != "")
\r
705 if (File.Exists(text_destination.Text))
\r
706 overwrite = MessageBox.Show("The destination file already exists. Are you sure you want to overwrite it?", "Overwrite File?", MessageBoxButtons.YesNo, MessageBoxIcon.Question);
\r
708 if (overwrite == DialogResult.Yes)
\r
710 if (encodeQueue.Count == 0)
\r
711 encodeQueue.AddJob(query, sourcePath, text_destination.Text);
\r
713 queueWindow.setQueue();
\r
714 if (encodeQueue.Count > 1)
\r
715 queueWindow.Show(false);
\r
717 setEncodeStarted(); // Encode is running, so setup the GUI appropriately
\r
718 if (ActivityWindow != null)
\r
719 ActivityWindow.setLogView(false);
\r
720 encodeQueue.StartEncodeQueue(); // Start The Queue Encoding Process
\r
721 lastAction = "encode"; // Set the last action to encode - Used for activity window.
\r
725 else 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 private void btn_add2Queue_Click(object sender, EventArgs e)
\r
731 if (string.IsNullOrEmpty(sourcePath) || string.IsNullOrEmpty(text_destination.Text))
\r
732 MessageBox.Show("No source or destination selected.", "Warning", MessageBoxButtons.OK, MessageBoxIcon.Warning);
\r
735 String query = queryGen.generateTheQuery(this);
\r
736 if (rtf_query.Text != "")
\r
737 query = rtf_query.Text;
\r
739 if (encodeQueue.CheckForDestinationDuplicate(text_destination.Text))
\r
741 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
742 "Warning", MessageBoxButtons.YesNo, MessageBoxIcon.Warning);
\r
743 if (result == DialogResult.Yes)
\r
744 encodeQueue.AddJob(query, sourcePath, text_destination.Text);
\r
748 encodeQueue.AddJob(query, sourcePath, text_destination.Text);
\r
750 queueWindow.Show();
\r
753 private void btn_showQueue_Click(object sender, EventArgs e)
\r
755 queueWindow.Show();
\r
757 private void tb_preview_Click(object sender, EventArgs e)
\r
759 if (string.IsNullOrEmpty(sourcePath) || string.IsNullOrEmpty(text_destination.Text))
\r
760 MessageBox.Show("No source or destination selected.", "Warning", MessageBoxButtons.OK, MessageBoxIcon.Warning);
\r
763 if (qtpreview == null)
\r
765 qtpreview = new frmPreview(this);
\r
768 else if (qtpreview.IsDisposed)
\r
770 qtpreview = new frmPreview(this);
\r
774 MessageBox.Show(qtpreview, "The preview window is already open!", "Warning", MessageBoxButtons.OK, MessageBoxIcon.Warning);
\r
777 private void btn_ActivityWindow_Click(object sender, EventArgs e)
\r
779 String file = lastAction == "scan" ? "last_scan_log.txt" : "last_encode_log.txt";
\r
780 if (ActivityWindow == null)
\r
781 ActivityWindow = new frmActivityWindow(file, encodeQueue, this);
\r
783 ActivityWindow.Show();
\r
787 #region System Tray Icon
\r
788 private void frmMain_Resize(object sender, EventArgs e)
\r
790 if (FormWindowState.Minimized == this.WindowState)
\r
792 notifyIcon.Visible = true;
\r
795 else if (FormWindowState.Normal == this.WindowState)
\r
796 notifyIcon.Visible = false;
\r
798 private void notifyIcon_MouseDoubleClick(object sender, MouseEventArgs e)
\r
800 this.Visible = true;
\r
802 this.WindowState = FormWindowState.Normal;
\r
803 notifyIcon.Visible = false;
\r
805 private void btn_restore_Click(object sender, EventArgs e)
\r
807 this.Visible = true;
\r
809 this.WindowState = FormWindowState.Normal;
\r
810 notifyIcon.Visible = false;
\r
814 #region Tab Control
\r
817 private void btn_dvd_source_Click(object sender, EventArgs e)
\r
819 // Enable the creation of chapter markers.
\r
820 Check_ChapterMarkers.Enabled = true;
\r
822 // Set the last action to scan.
\r
823 // This is used for tracking which file to load in the activity window
\r
824 lastAction = "scan";
\r
825 sourcePath = string.Empty;
\r
827 if (DVD_Open.ShowDialog() == DialogResult.OK)
\r
829 String filename = DVD_Open.SelectedPath;
\r
831 if (filename.StartsWith("\\"))
\r
834 "Sorry, HandBrake does not support UNC file paths. \nTry mounting the share as a network drive in My Computer",
\r
835 "Warning", MessageBoxButtons.OK, MessageBoxIcon.Warning);
\r
836 UpdateSourceLabel();
\r
840 if (filename != "")
\r
842 sourcePath = Path.GetFullPath(filename);
\r
843 setupGUIforScan(filename);
\r
844 startScan(filename);
\r
846 UpdateSourceLabel();
\r
850 UpdateSourceLabel();
\r
852 private void btn_file_source_Click(object sender, EventArgs e)
\r
854 // Set the last action to scan.
\r
855 // This is used for tracking which file to load in the activity window
\r
856 lastAction = "scan";
\r
857 sourcePath = string.Empty;
\r
859 if (ISO_Open.ShowDialog() == DialogResult.OK)
\r
861 String filename = ISO_Open.FileName;
\r
862 if (filename.StartsWith("\\"))
\r
864 "Sorry, HandBrake does not support UNC file paths. \nTry mounting the share as a network drive in My Computer",
\r
865 "Warning", MessageBoxButtons.OK, MessageBoxIcon.Warning);
\r
868 if (filename != "")
\r
870 sourcePath = Path.GetFileName(filename);
\r
871 setupGUIforScan(filename);
\r
872 startScan(filename);
\r
874 UpdateSourceLabel();
\r
877 UpdateSourceLabel();
\r
879 private void mnu_dvd_drive_Click(object sender, EventArgs e)
\r
881 // Enable the creation of chapter markers.
\r
882 Check_ChapterMarkers.Enabled = true;
\r
884 // Set the last action to scan.
\r
885 // This is used for tracking which file to load in the activity window
\r
886 lastAction = "scan";
\r
887 sourcePath = string.Empty;
\r
889 if (mnu_dvd_drive.Text.Contains("VIDEO_TS"))
\r
891 string[] path = mnu_dvd_drive.Text.Split(' ');
\r
892 String filename = path[0];
\r
893 sourcePath = Path.GetFullPath(filename);
\r
894 setupGUIforScan(filename);
\r
895 startScan(filename);
\r
898 // If there are no titles in the dropdown menu then the scan has obviously failed. Display an error message explaining to the user.
\r
899 if (drp_dvdtitle.Items.Count == 0)
\r
900 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
902 UpdateSourceLabel();
\r
904 lbl_encode.Text = "";
\r
906 private void drp_dvdtitle_Click(object sender, EventArgs e)
\r
908 if ((drp_dvdtitle.Items.Count == 1) && (drp_dvdtitle.Items[0].ToString() == "Automatic"))
\r
909 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
911 private void drp_dvdtitle_SelectedIndexChanged(object sender, EventArgs e)
\r
913 unRegisterPresetEventHandler();
\r
914 // Reset some values on the form
\r
915 PictureSettings.lbl_Aspect.Text = "Select a Title";
\r
916 //lbl_RecomendedCrop.Text = "Select a Title";
\r
917 drop_chapterStart.Items.Clear();
\r
918 drop_chapterFinish.Items.Clear();
\r
920 // If the dropdown is set to automatic nothing else needs to be done.
\r
921 // Otheriwse if its not, title data has to be loased from parsing.
\r
922 if (drp_dvdtitle.Text != "Automatic")
\r
924 selectedTitle = drp_dvdtitle.SelectedItem as Title;
\r
925 lbl_duration.Text = selectedTitle.Duration.ToString();
\r
926 PictureSettings.Source = selectedTitle; // Setup Picture Settings Tab Control
\r
928 // Populate the Angles dropdown
\r
929 drop_angle.Items.Clear();
\r
930 if (Properties.Settings.Default.dvdnav)
\r
932 drop_angle.Visible = true;
\r
933 lbl_angle.Visible = true;
\r
934 drop_angle.Items.AddRange(selectedTitle.Angles.ToArray());
\r
935 if (drop_angle.Items.Count != 0)
\r
936 drop_angle.SelectedIndex = 0;
\r
940 drop_angle.Visible = false;
\r
941 lbl_angle.Visible = false;
\r
944 // Populate the Start chapter Dropdown
\r
945 drop_chapterStart.Items.Clear();
\r
946 drop_chapterStart.Items.AddRange(selectedTitle.Chapters.ToArray());
\r
947 if (drop_chapterStart.Items.Count > 0)
\r
948 drop_chapterStart.Text = drop_chapterStart.Items[0].ToString();
\r
950 // Populate the Final Chapter Dropdown
\r
951 drop_chapterFinish.Items.Clear();
\r
952 drop_chapterFinish.Items.AddRange(selectedTitle.Chapters.ToArray());
\r
953 if (drop_chapterFinish.Items.Count > 0)
\r
954 drop_chapterFinish.Text = drop_chapterFinish.Items[drop_chapterFinish.Items.Count - 1].ToString();
\r
956 // Populate the Audio Channels Dropdown
\r
957 AudioSettings.setTrackList(selectedTitle);
\r
959 // Populate the Subtitles dropdown
\r
960 Subtitles.drp_subtitleTracks.Items.Clear();
\r
961 Subtitles.drp_subtitleTracks.Items.Add("Foreign Audio Search (Bitmap)");
\r
962 Subtitles.drp_subtitleTracks.Items.AddRange(selectedTitle.Subtitles.ToArray());
\r
963 Subtitles.drp_subtitleTracks.SelectedIndex = 0;
\r
964 Subtitles.setSubtitleTrackAuto();
\r
967 // Run the autoName & chapterNaming functions
\r
968 if (Properties.Settings.Default.autoNaming)
\r
970 string autoPath = Main.autoName(drp_dvdtitle, drop_chapterStart.Text, drop_chapterFinish.Text, sourcePath, text_destination.Text, drop_format.SelectedIndex);
\r
971 if (autoPath != null)
\r
972 text_destination.Text = autoPath;
\r
974 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
977 data_chpt.Rows.Clear();
\r
978 if (selectedTitle.Chapters.Count != 1)
\r
980 DataGridView chapterGridView = Main.chapterNaming(data_chpt, drop_chapterFinish.Text);
\r
981 if (chapterGridView != null)
\r
982 data_chpt = chapterGridView;
\r
986 Check_ChapterMarkers.Checked = false;
\r
987 Check_ChapterMarkers.Enabled = false;
\r
990 // Hack to force the redraw of the scrollbars which don't resize properly when the control is disabled.
\r
991 data_chpt.Columns[0].Width = 166;
\r
992 data_chpt.Columns[0].Width = 165;
\r
994 registerPresetEventHandler();
\r
996 private void drop_chapterStart_SelectedIndexChanged(object sender, EventArgs e)
\r
998 int c_start, c_end;
\r
1000 if (drop_chapterFinish.Text == "Auto" && drop_chapterFinish.Items.Count != 0)
\r
1001 drop_chapterFinish.SelectedIndex = drop_chapterFinish.Items.Count - 1;
\r
1003 int.TryParse(drop_chapterStart.Text, out c_start);
\r
1004 int.TryParse(drop_chapterFinish.Text, out c_end);
\r
1008 if (c_start > c_end)
\r
1009 drop_chapterFinish.Text = c_start.ToString();
\r
1012 lbl_duration.Text = Main.calculateDuration(drop_chapterStart.SelectedIndex, drop_chapterFinish.SelectedIndex, selectedTitle).ToString();
\r
1014 // Run the Autonaming function
\r
1015 if (Properties.Settings.Default.autoNaming)
\r
1016 text_destination.Text = Main.autoName(drp_dvdtitle, drop_chapterStart.Text, drop_chapterFinish.Text, sourcePath, text_destination.Text, drop_format.SelectedIndex);
\r
1018 // Disable chapter markers if only 1 chapter is selected.
\r
1019 if (c_start == c_end)
\r
1021 Check_ChapterMarkers.Checked = false;
\r
1022 Check_ChapterMarkers.Enabled = false;
\r
1025 Check_ChapterMarkers.Enabled = true;
\r
1027 private void drop_chapterFinish_SelectedIndexChanged(object sender, EventArgs e)
\r
1029 int c_start, c_end;
\r
1031 if (drop_chapterStart.Text == "Auto" && drop_chapterStart.Items.Count >= 1)
\r
1032 drop_chapterStart.SelectedIndex = 1;
\r
1034 int.TryParse(drop_chapterStart.Text, out c_start);
\r
1035 int.TryParse(drop_chapterFinish.Text, out c_end);
\r
1039 if (c_end < c_start)
\r
1040 drop_chapterFinish.Text = c_start.ToString();
\r
1043 lbl_duration.Text = Main.calculateDuration(drop_chapterStart.SelectedIndex, drop_chapterFinish.SelectedIndex, selectedTitle).ToString();
\r
1045 // Run the Autonaming function
\r
1046 if (Properties.Settings.Default.autoNaming)
\r
1047 text_destination.Text = Main.autoName(drp_dvdtitle, drop_chapterStart.Text, drop_chapterFinish.Text, sourcePath, text_destination.Text, drop_format.SelectedIndex);
\r
1049 // Add more rows to the Chapter menu if needed.
\r
1050 if (Check_ChapterMarkers.Checked)
\r
1052 int i = data_chpt.Rows.Count, finish = 0;
\r
1054 if (drop_chapterFinish.Text != "Auto")
\r
1055 int.TryParse(drop_chapterFinish.Text, out finish);
\r
1057 while (i < finish)
\r
1059 int n = data_chpt.Rows.Add();
\r
1060 data_chpt.Rows[n].Cells[0].Value = (i + 1);
\r
1061 data_chpt.Rows[n].Cells[1].Value = "Chapter " + (i + 1);
\r
1062 data_chpt.Rows[n].Cells[0].ValueType = typeof(int);
\r
1063 data_chpt.Rows[n].Cells[1].ValueType = typeof(string);
\r
1068 // Disable chapter markers if only 1 chapter is selected.
\r
1069 if (c_start == c_end)
\r
1071 Check_ChapterMarkers.Checked = false;
\r
1072 Check_ChapterMarkers.Enabled = false;
\r
1075 Check_ChapterMarkers.Enabled = true;
\r
1079 private void btn_destBrowse_Click(object sender, EventArgs e)
\r
1081 // This removes the file extension from the filename box on the save file dialog.
\r
1082 // It's daft but some users don't realise that typing an extension overrides the dropdown extension selected.
\r
1083 DVD_Save.FileName = Path.GetFileNameWithoutExtension(text_destination.Text);
\r
1085 if (Path.IsPathRooted(text_destination.Text))
\r
1086 DVD_Save.InitialDirectory = Path.GetDirectoryName(text_destination.Text);
\r
1088 // Show the dialog and set the main form file path
\r
1089 if (drop_format.SelectedIndex.Equals(0))
\r
1090 DVD_Save.FilterIndex = 1;
\r
1091 else if (drop_format.SelectedIndex.Equals(1))
\r
1092 DVD_Save.FilterIndex = 2;
\r
1094 if (DVD_Save.ShowDialog() == DialogResult.OK)
\r
1096 if (DVD_Save.FileName.StartsWith("\\"))
\r
1097 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
1100 // Add a file extension manually, as FileDialog.AddExtension has issues with dots in filenames
\r
1101 switch (DVD_Save.FilterIndex)
\r
1104 if (!Path.GetExtension(DVD_Save.FileName).Equals(".mp4", StringComparison.InvariantCultureIgnoreCase))
\r
1105 if (Properties.Settings.Default.useM4v)
\r
1106 DVD_Save.FileName += ".m4v";
\r
1108 DVD_Save.FileName += ".mp4";
\r
1111 if (!Path.GetExtension(DVD_Save.FileName).Equals(".mkv", StringComparison.InvariantCultureIgnoreCase))
\r
1112 DVD_Save.FileName += ".mkv";
\r
1118 text_destination.Text = DVD_Save.FileName;
\r
1120 // Quicktime requires .m4v file for chapter markers to work. If checked, change the extension to .m4v (mp4 and m4v are the same thing)
\r
1121 if (Check_ChapterMarkers.Checked && DVD_Save.FilterIndex != 2)
\r
1122 setExtension(".m4v");
\r
1126 private void text_destination_TextChanged(object sender, EventArgs e)
\r
1128 string path = text_destination.Text;
\r
1129 if (path.EndsWith(".mp4") || path.EndsWith(".m4v"))
\r
1130 drop_format.SelectedIndex = 0;
\r
1131 else if (path.EndsWith(".mkv"))
\r
1132 drop_format.SelectedIndex = 1;
\r
1135 // Output Settings
\r
1136 private void drop_format_SelectedIndexChanged(object sender, EventArgs e)
\r
1138 switch (drop_format.SelectedIndex)
\r
1141 if (Properties.Settings.Default.useM4v)
\r
1142 setExtension(".m4v");
\r
1144 setExtension(".mp4");
\r
1147 setExtension(".mkv");
\r
1151 AudioSettings.setAudioByContainer(drop_format.Text);
\r
1152 Subtitles.setContainer(drop_format.SelectedIndex);
\r
1154 if ((drop_format.Text.Contains("MP4")) || (drop_format.Text.Contains("M4V")))
\r
1156 if (drp_videoEncoder.Items.Contains("VP3 (Theora)"))
\r
1158 drp_videoEncoder.Items.Remove("VP3 (Theora)");
\r
1159 drp_videoEncoder.SelectedIndex = 1;
\r
1162 else if (drop_format.Text.Contains("MKV"))
\r
1163 drp_videoEncoder.Items.Add("VP3 (Theora)");
\r
1165 private void setExtension(string newExtension)
\r
1167 text_destination.Text = text_destination.Text.Replace(".mp4", newExtension);
\r
1168 text_destination.Text = text_destination.Text.Replace(".m4v", newExtension);
\r
1169 text_destination.Text = text_destination.Text.Replace(".mkv", newExtension);
\r
1173 private void drp_videoEncoder_SelectedIndexChanged(object sender, EventArgs e)
\r
1175 setContainerOpts();
\r
1177 //Turn off some options which are H.264 only when the user selects a non h.264 encoder
\r
1178 if (drp_videoEncoder.Text.Contains("H.264"))
\r
1180 if (check_2PassEncode.CheckState == CheckState.Checked)
\r
1181 check_turbo.Enabled = true;
\r
1183 tab_advanced.Enabled = true;
\r
1184 if ((drop_format.Text.Contains("MP4")) || (drop_format.Text.Contains("M4V")))
\r
1185 check_iPodAtom.Enabled = true;
\r
1187 check_iPodAtom.Enabled = false;
\r
1191 check_turbo.CheckState = CheckState.Unchecked;
\r
1192 check_turbo.Enabled = false;
\r
1193 tab_advanced.Enabled = false;
\r
1194 x264Panel.x264Query = "";
\r
1195 check_iPodAtom.Enabled = false;
\r
1196 check_iPodAtom.Checked = false;
\r
1199 // Setup the CQ Slider
\r
1200 switch (drp_videoEncoder.Text)
\r
1202 case "MPEG-4 (FFmpeg)":
\r
1203 if (slider_videoQuality.Value > 31)
\r
1204 slider_videoQuality.Value = 20; // Just reset to 70% QP 10 on encode change.
\r
1205 slider_videoQuality.Minimum = 1;
\r
1206 slider_videoQuality.Maximum = 31;
\r
1208 case "H.264 (x264)":
\r
1209 slider_videoQuality.Minimum = 0;
\r
1210 slider_videoQuality.TickFrequency = 1;
\r
1212 CultureInfo culture = CultureInfo.CreateSpecificCulture("en-US");
\r
1213 double multiplier = 1.0 / Properties.Settings.Default.x264cqstep;
\r
1214 double value = slider_videoQuality.Value * multiplier;
\r
1216 switch (Properties.Settings.Default.x264cqstep.ToString(culture))
\r
1219 slider_videoQuality.Maximum = 255;
\r
1222 slider_videoQuality.Maximum = 204;
\r
1225 slider_videoQuality.Maximum = 40;
\r
1228 slider_videoQuality.Maximum = 51;
\r
1231 slider_videoQuality.Maximum = 51;
\r
1234 if (value < slider_videoQuality.Maximum)
\r
1235 slider_videoQuality.Value = slider_videoQuality.Maximum - (int)value;
\r
1238 case "VP3 (Theora)":
\r
1239 if (slider_videoQuality.Value > 63)
\r
1240 slider_videoQuality.Value = 45; // Just reset to 70% QP 45 on encode change.
\r
1241 slider_videoQuality.Minimum = 0;
\r
1242 slider_videoQuality.Maximum = 63;
\r
1247 /// Set the container format options
\r
1249 public void setContainerOpts()
\r
1251 if ((drop_format.Text.Contains("MP4")) || (drop_format.Text.Contains("M4V")))
\r
1253 check_largeFile.Enabled = true;
\r
1254 check_optimiseMP4.Enabled = true;
\r
1255 check_iPodAtom.Enabled = true;
\r
1259 check_largeFile.Enabled = false;
\r
1260 check_optimiseMP4.Enabled = false;
\r
1261 check_iPodAtom.Enabled = false;
\r
1262 check_largeFile.Checked = false;
\r
1263 check_optimiseMP4.Checked = false;
\r
1264 check_iPodAtom.Checked = false;
\r
1267 private void slider_videoQuality_Scroll(object sender, EventArgs e)
\r
1269 switch (drp_videoEncoder.Text)
\r
1271 case "MPEG-4 (FFmpeg)":
\r
1272 double rfValue = 31 - (slider_videoQuality.Value - 1);
\r
1273 double max = slider_videoQuality.Maximum;
\r
1274 double min = slider_videoQuality.Minimum;
\r
1275 double val = ((max - min) - (rfValue - min)) / (max - min);
\r
1276 SliderValue.Text = Math.Round((val * 100), 2) + "% QP:" + (32 - slider_videoQuality.Value);
\r
1278 case "H.264 (x264)":
\r
1279 rfValue = 51.0 - slider_videoQuality.Value * Properties.Settings.Default.x264cqstep;
\r
1280 max = slider_videoQuality.Maximum * Properties.Settings.Default.x264cqstep;
\r
1281 min = slider_videoQuality.Minimum;
\r
1282 val = ((max - min) - (rfValue - min)) / (max - min);
\r
1283 rfValue = Math.Round(rfValue, 2);
\r
1284 SliderValue.Text = Math.Round((val * 100), 2) + "% RF:" + rfValue;
\r
1286 case "VP3 (Theora)":
\r
1287 rfValue = slider_videoQuality.Value;
\r
1288 double value = rfValue / 63;
\r
1289 SliderValue.Text = Math.Round((value * 100), 2) + "% QP:" + slider_videoQuality.Value;
\r
1293 private void radio_targetFilesize_CheckedChanged(object sender, EventArgs e)
\r
1295 text_bitrate.Enabled = false;
\r
1296 text_filesize.Enabled = true;
\r
1297 slider_videoQuality.Enabled = false;
\r
1299 check_2PassEncode.Enabled = true;
\r
1301 private void radio_avgBitrate_CheckedChanged(object sender, EventArgs e)
\r
1303 text_bitrate.Enabled = true;
\r
1304 text_filesize.Enabled = false;
\r
1305 slider_videoQuality.Enabled = false;
\r
1307 check_2PassEncode.Enabled = true;
\r
1309 private void radio_cq_CheckedChanged(object sender, EventArgs e)
\r
1311 text_bitrate.Enabled = false;
\r
1312 text_filesize.Enabled = false;
\r
1313 slider_videoQuality.Enabled = true;
\r
1315 check_2PassEncode.Enabled = false;
\r
1316 check_2PassEncode.CheckState = CheckState.Unchecked;
\r
1318 private void check_2PassEncode_CheckedChanged(object sender, EventArgs e)
\r
1320 if (check_2PassEncode.CheckState.ToString() == "Checked")
\r
1322 if (drp_videoEncoder.Text.Contains("H.264"))
\r
1323 check_turbo.Enabled = true;
\r
1327 check_turbo.Enabled = false;
\r
1328 check_turbo.CheckState = CheckState.Unchecked;
\r
1332 // Chapter Marker Tab
\r
1333 private void Check_ChapterMarkers_CheckedChanged(object sender, EventArgs e)
\r
1335 if (Check_ChapterMarkers.Checked)
\r
1337 if (drop_format.SelectedIndex != 1)
\r
1338 setExtension(".m4v");
\r
1339 data_chpt.Rows.Clear();
\r
1340 data_chpt.Enabled = true;
\r
1341 DataGridView chapterGridView = Main.chapterNaming(data_chpt, drop_chapterFinish.Text);
\r
1342 if (chapterGridView != null)
\r
1343 data_chpt = chapterGridView;
\r
1347 if (drop_format.SelectedIndex != 1 && !Properties.Settings.Default.useM4v)
\r
1348 setExtension(".mp4");
\r
1349 data_chpt.Rows.Clear();
\r
1350 data_chpt.Enabled = false;
\r
1354 // Query Editor Tab
\r
1355 private void btn_generate_Query_Click(object sender, EventArgs e)
\r
1357 rtf_query.Text = queryGen.generateTheQuery(this);
\r
1359 private void btn_clear_Click(object sender, EventArgs e)
\r
1361 rtf_query.Clear();
\r
1365 // MainWindow Components, Actions and Functions ***********************
\r
1367 #region Source Scan
\r
1368 public Boolean isScanning { get; set; }
\r
1369 private static int scanProcessID { get; set; }
\r
1370 private void setupGUIforScan(String filename)
\r
1372 sourcePath = filename;
\r
1373 foreach (Control ctrl in Controls)
\r
1375 if (!(ctrl is StatusStrip || ctrl is MenuStrip || ctrl is ToolStrip))
\r
1376 ctrl.Enabled = false;
\r
1378 lbl_encode.Visible = true;
\r
1379 lbl_encode.Text = "Scanning ...";
\r
1380 //gb_source.Text = "Source: Scanning ...";
\r
1381 btn_source.Enabled = false;
\r
1382 btn_start.Enabled = false;
\r
1383 btn_showQueue.Enabled = false;
\r
1384 btn_add2Queue.Enabled = false;
\r
1385 tb_preview.Enabled = false;
\r
1386 mnu_killCLI.Visible = true;
\r
1388 private void startScan(String filename)
\r
1392 lbl_encode.Visible = true;
\r
1393 lbl_encode.Text = "Scanning...";
\r
1394 if (ActivityWindow != null)
\r
1395 ActivityWindow.setLogView(true);
\r
1396 isScanning = true;
\r
1397 ThreadPool.QueueUserWorkItem(scanProcess, filename);
\r
1399 catch (Exception exc)
\r
1401 MessageBox.Show("frmMain.cs - startScan " + exc, "Error", MessageBoxButtons.OK, MessageBoxIcon.Error);
\r
1404 private void scanProcess(object state)
\r
1408 string inputFile = (string)state;
\r
1409 string handbrakeCLIPath = Path.Combine(Application.StartupPath, "HandBrakeCLI.exe");
\r
1410 string logDir = Environment.GetFolderPath(Environment.SpecialFolder.ApplicationData) + "\\HandBrake\\logs";
\r
1411 string dvdInfoPath = Path.Combine(logDir, "last_scan_log.txt");
\r
1413 // Make we don't pick up a stale last_encode_log.txt (and that we have rights to the file)
\r
1414 if (File.Exists(dvdInfoPath))
\r
1415 File.Delete(dvdInfoPath);
\r
1417 String dvdnav = string.Empty;
\r
1418 if (Properties.Settings.Default.dvdnav)
\r
1419 dvdnav = " --dvdnav";
\r
1420 string strCmdLine = String.Format(@"cmd /c """"{0}"" -i ""{1}"" -t0 {2} -v >""{3}"" 2>&1""", handbrakeCLIPath, inputFile, dvdnav, dvdInfoPath);
\r
1422 ProcessStartInfo hbParseDvd = new ProcessStartInfo("CMD.exe", strCmdLine) { WindowStyle = ProcessWindowStyle.Hidden };
\r
1424 Boolean cleanExit = true;
\r
1425 using (hbproc = Process.Start(hbParseDvd))
\r
1427 Process[] before = Process.GetProcesses(); // Get a list of running processes before starting.
\r
1428 scanProcessID = Main.getCliProcess(before);
\r
1429 hbproc.WaitForExit();
\r
1430 if (hbproc.ExitCode != 0)
\r
1431 cleanExit = false;
\r
1434 if (cleanExit) // If 0 exit code, CLI exited cleanly.
\r
1436 if (!File.Exists(dvdInfoPath))
\r
1438 throw new Exception(
\r
1439 "Unable to retrieve the DVD Info. last_scan_log.txt is missing. \nExpected location of last_scan_log.txt: \n" +
\r
1443 using (StreamReader sr = new StreamReader(dvdInfoPath))
\r
1445 thisDVD = DVD.Parse(sr);
\r
1450 updateUIafterScan();
\r
1453 catch (Exception exc)
\r
1455 MessageBox.Show("frmMain.cs - scanProcess() " + exc, "Error", MessageBoxButtons.OK, MessageBoxIcon.Error);
\r
1459 private void updateUIafterScan()
\r
1463 if (InvokeRequired)
\r
1465 BeginInvoke(new UpdateWindowHandler(updateUIafterScan));
\r
1469 // Setup some GUI components
\r
1470 drp_dvdtitle.Items.Clear();
\r
1471 if (thisDVD.Titles.Count != 0)
\r
1472 drp_dvdtitle.Items.AddRange(thisDVD.Titles.ToArray());
\r
1473 drp_dvdtitle.Text = "Automatic";
\r
1474 drop_chapterFinish.Text = "Auto";
\r
1475 drop_chapterStart.Text = "Auto";
\r
1477 // Now select the longest title
\r
1478 if (thisDVD.Titles.Count != 0)
\r
1479 drp_dvdtitle.SelectedItem = Main.selectLongestTitle(thisDVD);
\r
1481 // Enable the creation of chapter markers if the file is an image of a dvd.
\r
1482 if (sourcePath.ToLower().Contains(".iso") || sourcePath.ToLower().Contains("VIDEO_TS"))
\r
1483 Check_ChapterMarkers.Enabled = true;
\r
1486 Check_ChapterMarkers.Enabled = false;
\r
1487 Check_ChapterMarkers.Checked = false;
\r
1488 data_chpt.Rows.Clear();
\r
1491 // If no titles were found, Display an error message
\r
1492 if (drp_dvdtitle.Items.Count == 0)
\r
1495 "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
1496 "Error", MessageBoxButtons.OK, MessageBoxIcon.Hand);
\r
1497 sourcePath = string.Empty;
\r
1499 UpdateSourceLabel();
\r
1501 // Enable the GUI components and enable any disabled components
\r
1504 catch (Exception exc)
\r
1506 MessageBox.Show("frmMain.cs - updateUIafterScan " + exc, "Error", MessageBoxButtons.OK, MessageBoxIcon.Error);
\r
1510 private void enableGUI()
\r
1514 if (InvokeRequired)
\r
1515 BeginInvoke(new UpdateWindowHandler(enableGUI));
\r
1516 lbl_encode.Text = "Scan Completed";
\r
1517 //gb_source.Text = "Source";
\r
1518 foreach (Control ctrl in Controls)
\r
1519 ctrl.Enabled = true;
\r
1520 btn_start.Enabled = true;
\r
1521 btn_showQueue.Enabled = true;
\r
1522 btn_add2Queue.Enabled = true;
\r
1523 tb_preview.Enabled = true;
\r
1524 btn_source.Enabled = true;
\r
1525 mnu_killCLI.Visible = false;
\r
1527 catch (Exception exc)
\r
1529 MessageBox.Show("frmMain.cs - enableGUI() " + exc, "Error", MessageBoxButtons.OK, MessageBoxIcon.Error);
\r
1532 private void killScan()
\r
1539 Process[] prs = Process.GetProcesses();
\r
1540 foreach (Process process in prs)
\r
1542 if (process.Id == scanProcessID)
\r
1544 process.Refresh();
\r
1545 if (!process.HasExited)
\r
1550 catch (Exception ex)
\r
1552 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
1555 private void resetGUI()
\r
1557 drp_dvdtitle.Items.Clear();
\r
1558 drp_dvdtitle.Text = "Automatic";
\r
1559 drop_chapterStart.Items.Clear();
\r
1560 drop_chapterStart.Text = "Auto";
\r
1561 drop_chapterFinish.Items.Clear();
\r
1562 drop_chapterFinish.Text = "Auto";
\r
1563 lbl_duration.Text = "Select a Title";
\r
1564 PictureSettings.lbl_src_res.Text = "Select a Title";
\r
1565 PictureSettings.lbl_Aspect.Text = "Select a Title";
\r
1566 sourcePath = "Source";
\r
1567 text_destination.Text = "";
\r
1569 selectedTitle = null;
\r
1570 isScanning = false;
\r
1573 private void UpdateSourceLabel()
\r
1575 labelSource.Text = string.IsNullOrEmpty(sourcePath) ? "Select \"Source\" to continue." : Path.GetFileName(sourcePath);
\r
1582 /// Set the GUI to it's finished encoding state.
\r
1584 private void setEncodeFinished()
\r
1588 if (InvokeRequired)
\r
1590 BeginInvoke(new UpdateWindowHandler(setEncodeFinished));
\r
1594 lbl_encode.Text = "Encoding Finished";
\r
1595 btn_start.Text = "Start";
\r
1596 btn_start.ToolTipText = "Start the encoding process";
\r
1597 btn_start.Image = Properties.Resources.Play;
\r
1599 // If the window is minimized, display the notification in a popup.
\r
1600 if (Properties.Settings.Default.trayIconAlerts)
\r
1601 if (FormWindowState.Minimized == this.WindowState)
\r
1603 notifyIcon.BalloonTipText = lbl_encode.Text;
\r
1604 notifyIcon.ShowBalloonTip(500);
\r
1607 catch (Exception exc)
\r
1609 MessageBox.Show(exc.ToString());
\r
1614 /// Set the GUI to it's started encoding state.
\r
1616 private void setEncodeStarted()
\r
1620 if (InvokeRequired)
\r
1622 BeginInvoke(new UpdateWindowHandler(setEncodeStarted));
\r
1626 lbl_encode.Visible = true;
\r
1627 lbl_encode.Text = "Encoding in Progress";
\r
1628 btn_start.Text = "Stop";
\r
1629 btn_start.ToolTipText = "Stop the encoding process.";
\r
1630 btn_start.Image = Properties.Resources.stop;
\r
1632 catch (Exception exc)
\r
1634 MessageBox.Show(exc.ToString());
\r
1639 #region DVD Drive Detection
\r
1640 private delegate void ProgressUpdateHandler();
\r
1641 private void getDriveInfoThread()
\r
1645 if (InvokeRequired)
\r
1647 BeginInvoke(new ProgressUpdateHandler(getDriveInfoThread));
\r
1651 Boolean foundDrive = false;
\r
1652 DriveInfo[] theCollectionOfDrives = DriveInfo.GetDrives();
\r
1653 foreach (DriveInfo curDrive in theCollectionOfDrives)
\r
1655 if (curDrive.DriveType == DriveType.CDRom && curDrive.IsReady)
\r
1657 if (File.Exists(curDrive.RootDirectory + "VIDEO_TS\\VIDEO_TS.IFO"))
\r
1659 mnu_dvd_drive.Text = curDrive.RootDirectory + "VIDEO_TS (" + curDrive.VolumeLabel + ")";
\r
1660 foundDrive = true;
\r
1666 if (foundDrive == false)
\r
1667 mnu_dvd_drive.Text = "[No DVD Drive Ready]";
\r
1671 mnu_dvd_drive.Text = "[No DVD Drive Ready / Found]";
\r
1676 #region Public Methods
\r
1678 /// Access the preset Handler and setup the preset panel.
\r
1680 public void loadPresetPanel()
\r
1682 if (presetHandler.checkIfPresetsAreOutOfDate())
\r
1683 if (!Properties.Settings.Default.presetNotification)
\r
1684 MessageBox.Show(splash,
\r
1685 "HandBrake has determined your built-in presets are out of date... These presets will now be updated.",
\r
1686 "Preset Update", MessageBoxButtons.OK, MessageBoxIcon.Information);
\r
1688 presetHandler.getPresetPanel(ref treeView_presets);
\r
1689 treeView_presets.Update();
\r
1695 /// If the queue is being processed, prompt the user to confirm application close.
\r
1697 /// <param name="e"></param>
\r
1698 protected override void OnFormClosing(FormClosingEventArgs e)
\r
1700 // If currently encoding, the queue isn't paused, and there are queue items to process, prompt to confirm close.
\r
1701 if ((encodeQueue.isEncoding) && (!encodeQueue.PauseRequested) && (encodeQueue.Count > 0))
\r
1703 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
1704 "Close HandBrake?", MessageBoxButtons.YesNo, MessageBoxIcon.Question);
\r
1705 if (result == DialogResult.No)
\r
1708 base.OnFormClosing(e);
\r
1712 #region In-GUI Encode Status (Experimental)
\r
1714 private void encodeMonitorThread()
\r
1718 Parser encode = new Parser(encodeQueue.hbProcess.StandardOutput.BaseStream);
\r
1719 encode.OnEncodeProgress += encodeOnEncodeProgress;
\r
1720 while (!encode.EndOfStream)
\r
1722 encode.readEncodeStatus();
\r
1725 catch (Exception exc)
\r
1727 MessageBox.Show(exc.ToString());
\r
1730 private void encodeOnEncodeProgress(object Sender, int CurrentTask, int TaskCount, float PercentComplete, float CurrentFps, float AverageFps, TimeSpan TimeRemaining)
\r
1732 if (this.InvokeRequired)
\r
1734 this.BeginInvoke(new EncodeProgressEventHandler(encodeOnEncodeProgress),
\r
1735 new object[] { Sender, CurrentTask, TaskCount, PercentComplete, CurrentFps, AverageFps, TimeRemaining });
\r
1738 lbl_encode.Text = string.Format("Encode Progress: {0}%, FPS: {1}, Avg FPS: {2}, Time Remaining: {3} ", PercentComplete, CurrentFps, AverageFps, TimeRemaining);
\r
1742 // This is the END of the road ****************************************
\r