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 Queue encodeQueue = new Queue();
\r
26 PresetsHandler presetHandler = new PresetsHandler();
\r
28 // Globals: Mainly used for tracking. *********************************
\r
29 public Title selectedTitle;
\r
30 private frmQueue queueWindow;
\r
31 private frmPreview qtpreview;
\r
32 private frmActivityWindow ActivityWindow;
\r
33 private Form splash;
\r
34 public string sourcePath;
\r
35 private string lastAction;
\r
36 private SourceType selectedSourceType;
\r
37 private string dvdDrivePath;
\r
38 private string dvdDriveLabel;
\r
39 private Preset CurrentlySelectedPreset;
\r
40 private DVD currentSource;
\r
42 // Delegates **********************************************************
\r
43 private delegate void UpdateWindowHandler();
\r
45 // Applicaiton Startup ************************************************
\r
47 #region Application Startup
\r
50 // Load and setup the splash screen in this thread
\r
51 splash = new frmSplashScreen();
\r
53 Label lblStatus = new Label { Size = new Size(150, 20), Location = new Point(182, 102) };
\r
54 splash.Controls.Add(lblStatus);
\r
56 InitializeComponent();
\r
58 // Update the users config file with the CLI version data.
\r
59 lblStatus.Text = "Setting Version Data ...";
\r
60 Application.DoEvents();
\r
61 Main.SetCliVersionData();
\r
63 // Show the form, but leave disabled until preloading is complete then show the main form
\r
64 this.Enabled = false;
\r
66 Application.DoEvents(); // Forces frmMain to draw
\r
68 // Check for new versions, if update checking is enabled
\r
69 if (Properties.Settings.Default.updateStatus)
\r
71 DateTime now = DateTime.Now;
\r
72 DateTime lastCheck = Properties.Settings.Default.lastUpdateCheckDate;
\r
73 TimeSpan elapsed = now.Subtract(lastCheck);
\r
74 if (elapsed.TotalDays > Properties.Settings.Default.daysBetweenUpdateCheck)
\r
76 lblStatus.Text = "Checking for updates ...";
\r
77 Application.DoEvents();
\r
79 Main.BeginCheckForUpdates(new AsyncCallback(UpdateCheckDone), false);
\r
83 // Clear the log files in the background
\r
84 if (Properties.Settings.Default.clearOldLogs)
\r
86 lblStatus.Text = "Clearing Old Log Files ...";
\r
87 Application.DoEvents();
\r
88 Thread clearLog = new Thread(Main.ClearOldLogs);
\r
92 // Setup the GUI components
\r
93 lblStatus.Text = "Setting up the GUI ...";
\r
94 Application.DoEvents();
\r
95 loadPresetPanel(); // Load the Preset Panel
\r
96 treeView_presets.ExpandAll();
\r
97 lbl_encode.Text = "";
\r
98 drop_mode.SelectedIndex = 0;
\r
99 queueWindow = new frmQueue(encodeQueue, this); // Prepare the Queue
\r
100 if (!Properties.Settings.Default.QueryEditorTab)
\r
101 tabs_panel.TabPages.RemoveAt(7); // Remove the query editor tab if the user does not want it enabled.
\r
103 // Load the user's default settings or Normal Preset
\r
104 if (Properties.Settings.Default.defaultPreset != "")
\r
106 if (presetHandler.GetPreset(Properties.Settings.Default.defaultPreset) != null)
\r
108 string query = presetHandler.GetPreset(Properties.Settings.Default.defaultPreset).Query;
\r
109 Boolean loadPictureSettings = presetHandler.GetPreset(Properties.Settings.Default.defaultPreset).PictureSettings;
\r
113 x264Panel.reset2Defaults();
\r
115 QueryParser presetQuery = QueryParser.Parse(query);
\r
116 PresetLoader.LoadPreset(this, presetQuery, Properties.Settings.Default.defaultPreset, loadPictureSettings);
\r
118 x264Panel.X264_StandardizeOptString();
\r
119 x264Panel.X264_SetCurrentSettingsInPanel();
\r
123 loadNormalPreset();
\r
126 loadNormalPreset();
\r
128 // Enabled GUI tooltip's if Required
\r
129 if (Properties.Settings.Default.tooltipEnable)
\r
130 ToolTip.Active = true;
\r
132 // Register with Growl (if not using Growl for the encoding completion action, this wont hurt anything)
\r
133 GrowlCommunicator.Register();
\r
136 lblStatus.Text = "Loading Complete!";
\r
137 Application.DoEvents();
\r
140 this.Enabled = true;
\r
142 // Event Handlers and Queue Recovery
\r
147 private void UpdateCheckDone(IAsyncResult result)
\r
149 if (InvokeRequired)
\r
151 Invoke(new MethodInvoker(() => UpdateCheckDone(result)));
\r
155 UpdateCheckInformation info;
\r
159 info = Main.EndCheckForUpdates(result);
\r
161 if (info.NewVersionAvailable)
\r
163 frmUpdater updateWindow = new frmUpdater(info.BuildInformation);
\r
164 updateWindow.ShowDialog();
\r
167 catch (Exception ex)
\r
169 if ((bool)result.AsyncState)
\r
170 MessageBox.Show("Unable to check for updates, Please try again later.\n\nDetailed Error Information:\n" + ex, "Error", MessageBoxButtons.OK, MessageBoxIcon.Error);
\r
174 // Startup Functions
\r
175 private void queueRecovery()
\r
177 if (Main.CheckQueueRecovery())
\r
179 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
181 if (result == DialogResult.Yes)
\r
182 encodeQueue.LoadQueueFromFile("hb_queue_recovery.xml"); // Start Recovery
\r
185 // Remove the Queue recovery file if the user doesn't want to recovery the last queue.
\r
186 string queuePath = Path.Combine(Path.GetTempPath(), "hb_queue_recovery.xml");
\r
187 if (File.Exists(queuePath))
\r
188 File.Delete(queuePath);
\r
195 public string SourceName
\r
199 if (this.selectedSourceType == SourceType.DvdDrive)
\r
201 return this.dvdDriveLabel;
\r
204 if (Path.GetFileNameWithoutExtension(this.sourcePath) != "VIDEO_TS")
\r
205 return Path.GetFileNameWithoutExtension(this.sourcePath);
\r
207 return Path.GetFileNameWithoutExtension(Path.GetDirectoryName(this.sourcePath));
\r
213 // Encoding Events for setting up the GUI
\r
214 private void events()
\r
216 // Handle Widget changes when preset is selected.
\r
217 RegisterPresetEventHandler();
\r
219 // Handle Window Resize
\r
220 if (Properties.Settings.Default.MainWindowMinimize)
\r
221 this.Resize += new EventHandler(frmMain_Resize);
\r
223 // Handle Encode Start / Finish / Pause
\r
225 encodeQueue.QueuePauseRequested += new EventHandler(encodePaused);
\r
226 encodeQueue.EncodeStarted += new EventHandler(encodeStarted);
\r
227 encodeQueue.EncodeEnded += new EventHandler(encodeEnded);
\r
229 // Handle a file being draged onto the GUI.
\r
230 this.DragEnter += new DragEventHandler(frmMain_DragEnter);
\r
231 this.DragDrop += new DragEventHandler(frmMain_DragDrop);
\r
234 // 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
235 private void RegisterPresetEventHandler()
\r
238 drop_format.SelectedIndexChanged += new EventHandler(changePresetLabel);
\r
239 check_largeFile.CheckedChanged += new EventHandler(changePresetLabel);
\r
240 check_iPodAtom.CheckedChanged += new EventHandler(changePresetLabel);
\r
241 check_optimiseMP4.CheckedChanged += new EventHandler(changePresetLabel);
\r
243 // Picture Settings
\r
244 //PictureSettings.PictureSettingsChanged += new EventHandler(changePresetLabel);
\r
247 Filters.FilterSettingsChanged += new EventHandler(changePresetLabel);
\r
250 drp_videoEncoder.SelectedIndexChanged += new EventHandler(changePresetLabel);
\r
251 check_2PassEncode.CheckedChanged += new EventHandler(changePresetLabel);
\r
252 check_turbo.CheckedChanged += new EventHandler(changePresetLabel);
\r
253 text_filesize.TextChanged += new EventHandler(changePresetLabel);
\r
254 text_bitrate.TextChanged += new EventHandler(changePresetLabel);
\r
255 slider_videoQuality.ValueChanged += new EventHandler(changePresetLabel);
\r
258 AudioSettings.AudioListChanged += new EventHandler(changePresetLabel);
\r
261 x264Panel.rtf_x264Query.TextChanged += new EventHandler(changePresetLabel);
\r
263 private void UnRegisterPresetEventHandler()
\r
265 // Output Settings
\r
266 drop_format.SelectedIndexChanged -= new EventHandler(changePresetLabel);
\r
267 check_largeFile.CheckedChanged -= new EventHandler(changePresetLabel);
\r
268 check_iPodAtom.CheckedChanged -= new EventHandler(changePresetLabel);
\r
269 check_optimiseMP4.CheckedChanged -= new EventHandler(changePresetLabel);
\r
271 // Picture Settings
\r
272 //PictureSettings.PictureSettingsChanged -= new EventHandler(changePresetLabel);
\r
275 Filters.FilterSettingsChanged -= new EventHandler(changePresetLabel);
\r
278 drp_videoEncoder.SelectedIndexChanged -= new EventHandler(changePresetLabel);
\r
279 check_2PassEncode.CheckedChanged -= new EventHandler(changePresetLabel);
\r
280 check_turbo.CheckedChanged -= new EventHandler(changePresetLabel);
\r
281 text_filesize.TextChanged -= new EventHandler(changePresetLabel);
\r
282 text_bitrate.TextChanged -= new EventHandler(changePresetLabel);
\r
283 slider_videoQuality.ValueChanged -= new EventHandler(changePresetLabel);
\r
286 AudioSettings.AudioListChanged -= new EventHandler(changePresetLabel);
\r
289 x264Panel.rtf_x264Query.TextChanged -= new EventHandler(changePresetLabel);
\r
291 private void changePresetLabel(object sender, EventArgs e)
\r
293 labelPreset.Text = "Output Settings (Preset: Custom)";
\r
294 CurrentlySelectedPreset = null;
\r
297 private static void frmMain_DragEnter(object sender, DragEventArgs e)
\r
299 if (e.Data.GetDataPresent(DataFormats.FileDrop, false))
\r
300 e.Effect = DragDropEffects.All;
\r
302 private void frmMain_DragDrop(object sender, DragEventArgs e)
\r
304 string[] fileList = e.Data.GetData(DataFormats.FileDrop) as string[];
\r
305 sourcePath = string.Empty;
\r
307 if (fileList != null)
\r
309 if (fileList[0] != "")
\r
311 this.selectedSourceType = SourceType.VideoFile;
\r
312 StartScan(fileList[0], 0);
\r
315 UpdateSourceLabel();
\r
318 UpdateSourceLabel();
\r
320 private void encodeStarted(object sender, EventArgs e)
\r
322 lastAction = "encode";
\r
323 setEncodeStarted();
\r
325 // Experimental HBProc Process Monitoring.
\r
326 if (Properties.Settings.Default.enocdeStatusInGui)
\r
328 Thread encodeMon = new Thread(encodeMonitorThread);
\r
332 private void encodeEnded(object sender, EventArgs e)
\r
334 setEncodeFinished();
\r
336 private void encodePaused(object sender, EventArgs e)
\r
338 setEncodeFinished();
\r
342 // User Interface Menus / Tool Strips *********************************
\r
345 private void mnu_killCLI_Click(object sender, EventArgs e)
\r
349 private void mnu_exit_Click(object sender, EventArgs e)
\r
351 Application.Exit();
\r
356 private void mnu_encode_Click(object sender, EventArgs e)
\r
358 queueWindow.Show();
\r
360 private void mnu_encodeLog_Click(object sender, EventArgs e)
\r
362 frmActivityWindow dvdInfoWindow = new frmActivityWindow(lastAction);
\r
363 dvdInfoWindow.Show();
\r
365 private void mnu_options_Click(object sender, EventArgs e)
\r
367 Form options = new frmOptions(this);
\r
368 options.ShowDialog();
\r
372 #region Presets Menu
\r
373 private void mnu_presetReset_Click(object sender, EventArgs e)
\r
375 presetHandler.UpdateBuiltInPresets();
\r
377 if (treeView_presets.Nodes.Count == 0)
\r
378 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
380 MessageBox.Show("Presets have been updated!", "Alert", MessageBoxButtons.OK, MessageBoxIcon.Information);
\r
382 treeView_presets.ExpandAll();
\r
384 private void mnu_delete_preset_Click(object sender, EventArgs e)
\r
386 presetHandler.RemoveBuiltInPresets();
\r
387 loadPresetPanel(); // Reload the preset panel
\r
389 private void mnu_SelectDefault_Click(object sender, EventArgs e)
\r
391 loadNormalPreset();
\r
393 private void mnu_importMacPreset_Click(object sender, EventArgs e)
\r
397 private void btn_new_preset_Click(object sender, EventArgs e)
\r
399 Form preset = new frmAddPreset(this, QueryGenerator.GenerateCLIQuery(this, drop_mode.SelectedIndex, 0, null), presetHandler);
\r
400 preset.ShowDialog();
\r
405 private void mnu_user_guide_Click(object sender, EventArgs e)
\r
407 Process.Start("http://trac.handbrake.fr/wiki/HandBrakeGuide");
\r
409 private void mnu_handbrake_home_Click(object sender, EventArgs e)
\r
411 Process.Start("http://handbrake.fr");
\r
413 private void mnu_UpdateCheck_Click(object sender, EventArgs e)
\r
415 lbl_updateCheck.Visible = true;
\r
416 Main.BeginCheckForUpdates(new AsyncCallback(updateCheckDoneMenu), false);
\r
418 private void updateCheckDoneMenu(IAsyncResult result)
\r
420 // Make sure it's running on the calling thread
\r
421 if (InvokeRequired)
\r
423 Invoke(new MethodInvoker(() => updateCheckDoneMenu(result)));
\r
426 UpdateCheckInformation info;
\r
429 // Get the information about the new build, if any, and close the window
\r
430 info = Main.EndCheckForUpdates(result);
\r
432 if (info.NewVersionAvailable && info.BuildInformation != null)
\r
434 frmUpdater updateWindow = new frmUpdater(info.BuildInformation);
\r
435 updateWindow.ShowDialog();
\r
438 MessageBox.Show("There are no new updates at this time.", "Update Check", MessageBoxButtons.OK, MessageBoxIcon.Information);
\r
439 lbl_updateCheck.Visible = false;
\r
442 catch (Exception ex)
\r
444 if ((bool)result.AsyncState)
\r
445 MessageBox.Show("Unable to check for updates, Please try again later.\n\nDetailed Error Information:\n" + ex, "Error", MessageBoxButtons.OK, MessageBoxIcon.Error);
\r
448 private void mnu_about_Click(object sender, EventArgs e)
\r
450 using (frmAbout About = new frmAbout())
\r
452 About.ShowDialog();
\r
458 // Right Click Menu Code
\r
459 private void pmnu_expandAll_Click(object sender, EventArgs e)
\r
461 treeView_presets.ExpandAll();
\r
463 private void pmnu_collapse_Click(object sender, EventArgs e)
\r
465 treeView_presets.CollapseAll();
\r
467 private void pmnu_import_Click(object sender, EventArgs e)
\r
471 private void pmnu_saveChanges_Click(object sender, EventArgs e)
\r
473 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
474 if (result == DialogResult.Yes)
\r
475 presetHandler.Update(treeView_presets.SelectedNode.Text, QueryGenerator.GenerateTabbedComponentsQuery(this), true);
\r
476 else if (result == DialogResult.No)
\r
477 presetHandler.Update(treeView_presets.SelectedNode.Text, QueryGenerator.GenerateTabbedComponentsQuery(this), false);
\r
479 private void pmnu_delete_click(object sender, EventArgs e)
\r
481 if (treeView_presets.SelectedNode != null)
\r
483 presetHandler.Remove(treeView_presets.SelectedNode.Text);
\r
484 treeView_presets.Nodes.Remove(treeView_presets.SelectedNode);
\r
486 treeView_presets.Select();
\r
488 private void presets_menu_Opening(object sender, System.ComponentModel.CancelEventArgs e)
\r
490 // Make sure that the save menu is always disabled by default
\r
491 pmnu_saveChanges.Enabled = false;
\r
493 // Now enable the save menu if the selected preset is a user preset
\r
494 if (treeView_presets.SelectedNode != null)
\r
495 if (presetHandler.CheckIfUserPresetExists(treeView_presets.SelectedNode.Text))
\r
496 pmnu_saveChanges.Enabled = true;
\r
498 treeView_presets.Select();
\r
501 // Presets Management
\r
502 private void btn_addPreset_Click(object sender, EventArgs e)
\r
504 Form preset = new frmAddPreset(this, QueryGenerator.GenerateTabbedComponentsQuery(this), presetHandler);
\r
505 preset.ShowDialog();
\r
507 private void btn_removePreset_Click(object sender, EventArgs e)
\r
509 DialogResult result = MessageBox.Show("Are you sure you wish to delete the selected preset?", "Preset", MessageBoxButtons.YesNo, MessageBoxIcon.Question);
\r
510 if (result == DialogResult.Yes)
\r
512 if (treeView_presets.SelectedNode != null)
\r
514 presetHandler.Remove(treeView_presets.SelectedNode.Text);
\r
515 treeView_presets.Nodes.Remove(treeView_presets.SelectedNode);
\r
518 treeView_presets.Select();
\r
520 private void btn_setDefault_Click(object sender, EventArgs e)
\r
522 if (treeView_presets.SelectedNode != null)
\r
524 DialogResult result = MessageBox.Show("Are you sure you wish to set this preset as the default?", "Preset", MessageBoxButtons.YesNo, MessageBoxIcon.Question);
\r
525 if (result == DialogResult.Yes)
\r
527 Properties.Settings.Default.defaultPreset = treeView_presets.SelectedNode.Text;
\r
528 Properties.Settings.Default.Save();
\r
529 MessageBox.Show("New default preset set.", "Alert", MessageBoxButtons.OK, MessageBoxIcon.Information);
\r
533 MessageBox.Show("Please select a preset first.", "Warning", MessageBoxButtons.OK, MessageBoxIcon.Warning);
\r
535 private void treeview_presets_mouseUp(object sender, MouseEventArgs e)
\r
537 if (e.Button == MouseButtons.Right)
\r
538 treeView_presets.SelectedNode = treeView_presets.GetNodeAt(e.Location);
\r
539 else if (e.Button == MouseButtons.Left)
\r
541 if (treeView_presets.GetNodeAt(e.Location) != null)
\r
543 if (labelPreset.Text.Contains(treeView_presets.GetNodeAt(e.Location).Text))
\r
548 treeView_presets.Select();
\r
550 private void treeView_presets_AfterSelect(object sender, TreeViewEventArgs e)
\r
554 private void treeView_presets_deleteKey(object sender, KeyEventArgs e)
\r
556 if (e.KeyCode == Keys.Delete)
\r
558 DialogResult result = MessageBox.Show("Are you sure you wish to delete the selected preset?", "Preset", MessageBoxButtons.YesNo, MessageBoxIcon.Question);
\r
559 if (result == DialogResult.Yes)
\r
561 if (treeView_presets.SelectedNode != null)
\r
562 presetHandler.Remove(treeView_presets.SelectedNode.Text);
\r
564 // Remember each nodes expanded status so we can reload it
\r
565 List<Boolean> nodeStatus = new List<Boolean>();
\r
566 foreach (TreeNode node in treeView_presets.Nodes)
\r
567 nodeStatus.Add(node.IsExpanded);
\r
569 // Now reload the preset panel
\r
572 // And finally, re-expand any of the nodes if required
\r
574 foreach (TreeNode node in treeView_presets.Nodes)
\r
584 private void selectPreset()
\r
586 if (treeView_presets.SelectedNode != null)
\r
588 // Ok, so, we've selected a preset. Now we want to load it.
\r
589 string presetName = treeView_presets.SelectedNode.Text;
\r
590 Preset preset = presetHandler.GetPreset(presetName);
\r
591 if (preset != null)
\r
593 string query = presetHandler.GetPreset(presetName).Query;
\r
594 Boolean loadPictureSettings = presetHandler.GetPreset(presetName).PictureSettings;
\r
598 //Ok, Reset all the H264 widgets before changing the preset
\r
599 x264Panel.reset2Defaults();
\r
601 // Send the query from the file to the Query Parser class
\r
602 QueryParser presetQuery = QueryParser.Parse(query);
\r
604 // Now load the preset
\r
605 PresetLoader.LoadPreset(this, presetQuery, presetName, loadPictureSettings);
\r
607 // The x264 widgets will need updated, so do this now:
\r
608 x264Panel.X264_StandardizeOptString();
\r
609 x264Panel.X264_SetCurrentSettingsInPanel();
\r
611 // Finally, let this window have a copy of the preset settings.
\r
612 CurrentlySelectedPreset = preset;
\r
613 PictureSettings.SetPresetCropWarningLabel(preset);
\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
629 private void importPreset()
\r
631 if (openPreset.ShowDialog() == DialogResult.OK)
\r
633 QueryParser parsed = PlistPresetHandler.Import(openPreset.FileName);
\r
634 if (presetHandler.CheckIfUserPresetExists(parsed.PresetName + " (Imported)"))
\r
636 DialogResult result = MessageBox.Show("This preset appears to already exist. Would you like to overwrite it?", "Overwrite preset?",
\r
637 MessageBoxButtons.YesNo, MessageBoxIcon.Warning);
\r
638 if (result == DialogResult.Yes)
\r
640 PresetLoader.LoadPreset(this, parsed, parsed.PresetName, parsed.UsesPictureSettings);
\r
641 presetHandler.Update(parsed.PresetName + " (Imported)", QueryGenerator.GenerateCLIQuery(this, drop_mode.SelectedIndex, 0, null),
\r
642 parsed.UsesPictureSettings);
\r
647 PresetLoader.LoadPreset(this, parsed, parsed.PresetName, parsed.UsesPictureSettings);
\r
648 presetHandler.Add(parsed.PresetName, QueryGenerator.GenerateCLIQuery(this, drop_mode.SelectedIndex, 0, null), parsed.UsesPictureSettings);
\r
650 if (presetHandler.Add(parsed.PresetName + " (Imported)", QueryGenerator.GenerateCLIQuery(this, drop_mode.SelectedIndex, 0, null), parsed.UsesPictureSettings))
\r
652 TreeNode preset_treeview = new TreeNode(parsed.PresetName + " (Imported)") { ForeColor = Color.Black };
\r
653 treeView_presets.Nodes.Add(preset_treeview);
\r
661 private void btn_source_Click(object sender, EventArgs e)
\r
663 mnu_dvd_drive.Visible = true;
\r
664 Thread driveInfoThread = new Thread(getDriveInfoThread);
\r
665 driveInfoThread.Start();
\r
667 private void btn_start_Click(object sender, EventArgs e)
\r
669 if (btn_start.Text == "Stop")
\r
671 DialogResult result;
\r
672 if (Properties.Settings.Default.enocdeStatusInGui && !Properties.Settings.Default.showCliForInGuiEncodeStatus)
\r
674 result = MessageBox.Show(
\r
675 "Are you sure you wish to cancel the encode?\n\nPlease note, when 'Enable in-GUI encode status' is enabled, stopping this encode will render the file unplayable. ",
\r
676 "Cancel Encode?", MessageBoxButtons.YesNo, MessageBoxIcon.Question);
\r
680 result = MessageBox.Show("Are you sure you wish to cancel the encode?", "Cancel Encode?",
\r
681 MessageBoxButtons.YesNo, MessageBoxIcon.Question);
\r
684 if (result == DialogResult.Yes)
\r
687 encodeQueue.Pause();
\r
689 if (Properties.Settings.Default.enocdeStatusInGui && !Properties.Settings.Default.showCliForInGuiEncodeStatus)
\r
691 encodeQueue.Stop();
\r
692 if (encodeQueue.HbProcess != null)
\r
693 encodeQueue.HbProcess.WaitForExit();
\r
697 encodeQueue.SafelyClose();
\r
701 setEncodeFinished();
\r
706 if (encodeQueue.Count != 0 || (!string.IsNullOrEmpty(sourcePath) && !string.IsNullOrEmpty(text_destination.Text)))
\r
708 string generatedQuery = QueryGenerator.GenerateCLIQuery(this, drop_mode.SelectedIndex, 0, null);
\r
709 string specifiedQuery = rtf_query.Text != "" ? rtf_query.Text : QueryGenerator.GenerateCLIQuery(this, drop_mode.SelectedIndex, 0, null);
\r
710 string query = string.Empty;
\r
712 // Check to make sure the generated query matches the GUI settings
\r
713 if (Properties.Settings.Default.PromptOnUnmatchingQueries && !string.IsNullOrEmpty(specifiedQuery) && generatedQuery != specifiedQuery)
\r
715 DialogResult result = MessageBox.Show("The query under the \"Query Editor\" tab " +
\r
716 "does not match the current GUI settings.\n\nBecause the manual query takes " +
\r
717 "priority over the GUI, your recently updated settings will not be taken " +
\r
718 "into account when encoding this job." + Environment.NewLine + Environment.NewLine +
\r
719 "Do you want to replace the manual query with the updated GUI-generated query?",
\r
720 "Manual Query does not Match GUI",
\r
721 MessageBoxButtons.YesNoCancel, MessageBoxIcon.Asterisk,
\r
722 MessageBoxDefaultButton.Button3);
\r
726 case DialogResult.Yes:
\r
727 // Replace the manual query with the generated one
\r
728 query = generatedQuery;
\r
729 rtf_query.Text = generatedQuery;
\r
731 case DialogResult.No:
\r
732 // Use the manual query
\r
733 query = specifiedQuery;
\r
735 case DialogResult.Cancel:
\r
736 // Don't start the encode
\r
742 query = specifiedQuery;
\r
745 DialogResult overwrite = DialogResult.Yes;
\r
746 if (text_destination.Text != "")
\r
747 if (File.Exists(text_destination.Text))
\r
748 overwrite = MessageBox.Show("The destination file already exists. Are you sure you want to overwrite it?", "Overwrite File?", MessageBoxButtons.YesNo, MessageBoxIcon.Question);
\r
750 if (overwrite == DialogResult.Yes)
\r
752 if (encodeQueue.Count == 0)
\r
753 encodeQueue.Add(query, sourcePath, text_destination.Text, (rtf_query.Text != ""));
\r
755 queueWindow.SetQueue();
\r
756 if (encodeQueue.Count > 1)
\r
757 queueWindow.Show(false);
\r
759 setEncodeStarted(); // Encode is running, so setup the GUI appropriately
\r
760 encodeQueue.Start(); // Start The Queue Encoding Process
\r
761 lastAction = "encode"; // Set the last action to encode - Used for activity window.
\r
763 if (ActivityWindow != null)
\r
764 ActivityWindow.SetEncodeMode();
\r
768 else if (string.IsNullOrEmpty(sourcePath) || string.IsNullOrEmpty(text_destination.Text))
\r
769 MessageBox.Show("No source or destination selected.", "Warning", MessageBoxButtons.OK, MessageBoxIcon.Warning);
\r
772 private void btn_add2Queue_Click(object sender, EventArgs e)
\r
774 if (string.IsNullOrEmpty(sourcePath) || string.IsNullOrEmpty(text_destination.Text))
\r
775 MessageBox.Show("No source or destination selected.", "Warning", MessageBoxButtons.OK, MessageBoxIcon.Warning);
\r
778 String query = QueryGenerator.GenerateCLIQuery(this, drop_mode.SelectedIndex, 0, null);
\r
779 if (rtf_query.Text != "")
\r
780 query = rtf_query.Text;
\r
782 if (encodeQueue.CheckForDestinationDuplicate(text_destination.Text))
\r
784 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
785 "Warning", MessageBoxButtons.YesNo, MessageBoxIcon.Warning);
\r
786 if (result == DialogResult.Yes)
\r
787 encodeQueue.Add(query, sourcePath, text_destination.Text, (rtf_query.Text != ""));
\r
791 encodeQueue.Add(query, sourcePath, text_destination.Text, (rtf_query.Text != ""));
\r
793 lbl_encode.Text = encodeQueue.Count + " encode(s) pending in the queue";
\r
795 queueWindow.Show();
\r
798 private void btn_showQueue_Click(object sender, EventArgs e)
\r
800 queueWindow.Show();
\r
801 queueWindow.Activate();
\r
803 private void tb_preview_Click(object sender, EventArgs e)
\r
805 if (string.IsNullOrEmpty(sourcePath) || string.IsNullOrEmpty(text_destination.Text))
\r
806 MessageBox.Show("No source or destination selected.", "Warning", MessageBoxButtons.OK, MessageBoxIcon.Warning);
\r
809 if (qtpreview == null)
\r
811 qtpreview = new frmPreview(this);
\r
814 else if (qtpreview.IsDisposed)
\r
816 qtpreview = new frmPreview(this);
\r
820 MessageBox.Show(qtpreview, "The preview window is already open!", "Warning", MessageBoxButtons.OK, MessageBoxIcon.Warning);
\r
823 private void btn_ActivityWindow_Click(object sender, EventArgs e)
\r
825 if (ActivityWindow == null || !ActivityWindow.IsHandleCreated)
\r
826 ActivityWindow = new frmActivityWindow(lastAction);
\r
828 switch (lastAction)
\r
831 ActivityWindow.SetScanMode();
\r
834 ActivityWindow.SetEncodeMode();
\r
837 ActivityWindow.SetEncodeMode();
\r
841 ActivityWindow.Show();
\r
842 ActivityWindow.Activate();
\r
846 #region System Tray Icon
\r
847 private void frmMain_Resize(object sender, EventArgs e)
\r
849 if (FormWindowState.Minimized == this.WindowState)
\r
851 notifyIcon.Visible = true;
\r
854 else if (FormWindowState.Normal == this.WindowState)
\r
855 notifyIcon.Visible = false;
\r
857 private void notifyIcon_MouseDoubleClick(object sender, MouseEventArgs e)
\r
859 this.Visible = true;
\r
861 this.WindowState = FormWindowState.Normal;
\r
862 notifyIcon.Visible = false;
\r
864 private void btn_restore_Click(object sender, EventArgs e)
\r
866 this.Visible = true;
\r
868 this.WindowState = FormWindowState.Normal;
\r
869 notifyIcon.Visible = false;
\r
873 #region Tab Control
\r
876 private void btn_dvd_source_Click(object sender, EventArgs e)
\r
878 if (DVD_Open.ShowDialog() == DialogResult.OK)
\r
880 this.selectedSourceType = SourceType.Folder;
\r
881 SelectSource(DVD_Open.SelectedPath);
\r
884 UpdateSourceLabel();
\r
886 private void btn_file_source_Click(object sender, EventArgs e)
\r
888 if (ISO_Open.ShowDialog() == DialogResult.OK)
\r
890 this.selectedSourceType = SourceType.VideoFile;
\r
891 SelectSource(ISO_Open.FileName);
\r
894 UpdateSourceLabel();
\r
896 private void mnu_dvd_drive_Click(object sender, EventArgs e)
\r
898 if (this.dvdDrivePath == null) return;
\r
899 this.selectedSourceType = SourceType.DvdDrive;
\r
900 SelectSource(this.dvdDrivePath);
\r
902 private void SelectSource(string file)
\r
904 Check_ChapterMarkers.Enabled = true;
\r
905 lastAction = "scan";
\r
906 sourcePath = string.Empty;
\r
908 if (file == string.Empty) // Must have a file or path
\r
910 UpdateSourceLabel();
\r
914 sourcePath = Path.GetFileName(file);
\r
915 StartScan(file, 0);
\r
917 private void drp_dvdtitle_Click(object sender, EventArgs e)
\r
919 if ((drp_dvdtitle.Items.Count == 1) && (drp_dvdtitle.Items[0].ToString() == "Automatic"))
\r
920 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
922 private void drp_dvdtitle_SelectedIndexChanged(object sender, EventArgs e)
\r
924 UnRegisterPresetEventHandler();
\r
925 drop_mode.SelectedIndex = 0;
\r
927 PictureSettings.lbl_Aspect.Text = "Select a Title"; // Reset some values on the form
\r
928 drop_chapterStart.Items.Clear();
\r
929 drop_chapterFinish.Items.Clear();
\r
931 // If the dropdown is set to automatic nothing else needs to be done.
\r
932 // Otheriwse if its not, title data has to be loased from parsing.
\r
933 if (drp_dvdtitle.Text != "Automatic")
\r
935 selectedTitle = drp_dvdtitle.SelectedItem as Title;
\r
936 lbl_duration.Text = selectedTitle.Duration.ToString();
\r
937 PictureSettings.CurrentlySelectedPreset = CurrentlySelectedPreset;
\r
938 PictureSettings.Source = selectedTitle; // Setup Picture Settings Tab Control
\r
940 // Populate the Angles dropdown
\r
941 drop_angle.Items.Clear();
\r
942 if (!Properties.Settings.Default.noDvdNav)
\r
944 drop_angle.Visible = true;
\r
945 lbl_angle.Visible = true;
\r
946 drop_angle.Items.AddRange(selectedTitle.Angles.ToArray());
\r
947 if (drop_angle.Items.Count != 0)
\r
948 drop_angle.SelectedIndex = 0;
\r
952 drop_angle.Visible = false;
\r
953 lbl_angle.Visible = false;
\r
956 // Populate the Start chapter Dropdown
\r
957 drop_chapterStart.Items.Clear();
\r
958 drop_chapterStart.Items.AddRange(selectedTitle.Chapters.ToArray());
\r
959 if (drop_chapterStart.Items.Count > 0)
\r
960 drop_chapterStart.Text = drop_chapterStart.Items[0].ToString();
\r
962 // Populate the Final Chapter Dropdown
\r
963 drop_chapterFinish.Items.Clear();
\r
964 drop_chapterFinish.Items.AddRange(selectedTitle.Chapters.ToArray());
\r
965 if (drop_chapterFinish.Items.Count > 0)
\r
966 drop_chapterFinish.Text = drop_chapterFinish.Items[drop_chapterFinish.Items.Count - 1].ToString();
\r
968 // Populate the Audio Channels Dropdown
\r
969 AudioSettings.SetTrackList(selectedTitle);
\r
971 // Populate the Subtitles dropdown
\r
972 Subtitles.SetSubtitleTrackAuto(selectedTitle.Subtitles.ToArray());
\r
974 // Update the source label if we have multiple streams
\r
975 if (selectedTitle != null)
\r
976 if (!string.IsNullOrEmpty(selectedTitle.SourceName))
\r
977 labelSource.Text = labelSource.Text = Path.GetFileName(selectedTitle.SourceName);
\r
979 // Run the AutoName & ChapterNaming functions
\r
980 if (Properties.Settings.Default.autoNaming)
\r
982 string autoPath = Main.AutoName(this);
\r
983 if (autoPath != null)
\r
984 text_destination.Text = autoPath;
\r
986 MessageBox.Show("You currently have \"Automatically name output files\" enabled for the destination file box, but you do not have a default directory set.\n\nYou should set a \"Default Path\" in HandBrakes preferences. (See 'Tools' menu -> 'Options' -> 'General' Tab -> 'Default Path')", "Warning", MessageBoxButtons.OK, MessageBoxIcon.Warning);
\r
989 data_chpt.Rows.Clear();
\r
990 if (selectedTitle.Chapters.Count != 1)
\r
992 DataGridView chapterGridView = Main.ChapterNaming(data_chpt, drop_chapterFinish.Text);
\r
993 if (chapterGridView != null)
\r
994 data_chpt = chapterGridView;
\r
998 Check_ChapterMarkers.Checked = false;
\r
999 Check_ChapterMarkers.Enabled = false;
\r
1002 // Hack to force the redraw of the scrollbars which don't resize properly when the control is disabled.
\r
1003 data_chpt.Columns[0].Width = 166;
\r
1004 data_chpt.Columns[0].Width = 165;
\r
1006 RegisterPresetEventHandler();
\r
1008 private void chapersChanged(object sender, EventArgs e)
\r
1010 if (drop_mode.SelectedIndex != 0) // Function is not used if we are not in chapters mode.
\r
1013 Control ctl = (Control)sender;
\r
1014 int chapterStart, chapterEnd;
\r
1015 int.TryParse(drop_chapterStart.Text, out chapterStart);
\r
1016 int.TryParse(drop_chapterFinish.Text, out chapterEnd);
\r
1020 case "drop_chapterStart":
\r
1021 if (drop_chapterFinish.SelectedIndex == -1 && drop_chapterFinish.Items.Count != 0)
\r
1022 drop_chapterFinish.SelectedIndex = drop_chapterFinish.Items.Count - 1;
\r
1024 if (chapterEnd != 0)
\r
1025 if (chapterStart > chapterEnd)
\r
1026 drop_chapterFinish.Text = chapterStart.ToString();
\r
1028 case "drop_chapterFinish":
\r
1029 if (drop_chapterStart.Items.Count >= 1 && drop_chapterStart.SelectedIndex == -1)
\r
1030 drop_chapterStart.SelectedIndex = 0;
\r
1032 if (chapterStart != 0)
\r
1033 if (chapterEnd < chapterStart)
\r
1034 drop_chapterFinish.Text = chapterStart.ToString();
\r
1036 // Add more rows to the Chapter menu if needed.
\r
1037 if (Check_ChapterMarkers.Checked)
\r
1039 int i = data_chpt.Rows.Count, finish = 0;
\r
1040 int.TryParse(drop_chapterFinish.Text, out finish);
\r
1042 while (i < finish)
\r
1044 int n = data_chpt.Rows.Add();
\r
1045 data_chpt.Rows[n].Cells[0].Value = (i + 1);
\r
1046 data_chpt.Rows[n].Cells[1].Value = "Chapter " + (i + 1);
\r
1047 data_chpt.Rows[n].Cells[0].ValueType = typeof(int);
\r
1048 data_chpt.Rows[n].Cells[1].ValueType = typeof(string);
\r
1055 // Update the Duration
\r
1056 lbl_duration.Text = Main.CalculateDuration(drop_chapterStart.SelectedIndex, drop_chapterFinish.SelectedIndex, selectedTitle).ToString();
\r
1058 // Run the Autonaming function
\r
1059 if (Properties.Settings.Default.autoNaming)
\r
1060 text_destination.Text = Main.AutoName(this);
\r
1062 // Disable chapter markers if only 1 chapter is selected.
\r
1063 if (chapterStart == chapterEnd)
\r
1065 Check_ChapterMarkers.Enabled = false;
\r
1066 btn_importChapters.Enabled = false;
\r
1067 data_chpt.Enabled = false;
\r
1071 Check_ChapterMarkers.Enabled = true;
\r
1072 if (Check_ChapterMarkers.Checked)
\r
1074 btn_importChapters.Enabled = true;
\r
1075 data_chpt.Enabled = true;
\r
1079 private void SecondsOrFramesChanged(object sender, EventArgs e)
\r
1082 int.TryParse(drop_chapterStart.Text, out start);
\r
1083 int.TryParse(drop_chapterFinish.Text, out end);
\r
1084 double duration = end - start;
\r
1086 switch (drop_mode.SelectedIndex)
\r
1089 lbl_duration.Text = TimeSpan.FromSeconds(duration).ToString();
\r
1092 if (selectedTitle != null)
\r
1094 duration = duration / selectedTitle.Fps;
\r
1095 lbl_duration.Text = TimeSpan.FromSeconds(duration).ToString();
\r
1098 lbl_duration.Text = "--:--:--";
\r
1103 private void drop_mode_SelectedIndexChanged(object sender, EventArgs e)
\r
1106 this.drop_chapterFinish.TextChanged -= new System.EventHandler(this.SecondsOrFramesChanged);
\r
1107 this.drop_chapterStart.TextChanged -= new System.EventHandler(this.SecondsOrFramesChanged);
\r
1110 switch (drop_mode.SelectedIndex)
\r
1113 drop_chapterStart.DropDownStyle = ComboBoxStyle.DropDownList;
\r
1114 drop_chapterFinish.DropDownStyle = ComboBoxStyle.DropDownList;
\r
1115 if (drop_chapterStart.Items.Count != 0)
\r
1117 drop_chapterStart.SelectedIndex = 0;
\r
1118 drop_chapterFinish.SelectedIndex = drop_chapterFinish.Items.Count - 1;
\r
1121 lbl_duration.Text = "--:--:--";
\r
1124 this.drop_chapterStart.TextChanged += new System.EventHandler(this.SecondsOrFramesChanged);
\r
1125 this.drop_chapterFinish.TextChanged += new System.EventHandler(this.SecondsOrFramesChanged);
\r
1126 drop_chapterStart.DropDownStyle = ComboBoxStyle.Simple;
\r
1127 drop_chapterFinish.DropDownStyle = ComboBoxStyle.Simple;
\r
1128 if (selectedTitle != null)
\r
1130 drop_chapterStart.Text = "0";
\r
1131 drop_chapterFinish.Text = selectedTitle.Duration.TotalSeconds.ToString();
\r
1135 this.drop_chapterStart.TextChanged += new System.EventHandler(this.SecondsOrFramesChanged);
\r
1136 this.drop_chapterFinish.TextChanged += new System.EventHandler(this.SecondsOrFramesChanged);
\r
1137 drop_chapterStart.DropDownStyle = ComboBoxStyle.Simple;
\r
1138 drop_chapterFinish.DropDownStyle = ComboBoxStyle.Simple;
\r
1139 if (selectedTitle != null)
\r
1141 drop_chapterStart.Text = "0";
\r
1142 drop_chapterFinish.Text = (selectedTitle.Fps * selectedTitle.Duration.TotalSeconds).ToString();
\r
1149 private void btn_destBrowse_Click(object sender, EventArgs e)
\r
1151 // This removes the file extension from the filename box on the save file dialog.
\r
1152 // It's daft but some users don't realise that typing an extension overrides the dropdown extension selected.
\r
1153 DVD_Save.FileName = Path.GetFileNameWithoutExtension(text_destination.Text);
\r
1155 if (Path.IsPathRooted(text_destination.Text))
\r
1156 DVD_Save.InitialDirectory = Path.GetDirectoryName(text_destination.Text);
\r
1158 // Show the dialog and set the main form file path
\r
1159 if (drop_format.SelectedIndex.Equals(0))
\r
1160 DVD_Save.FilterIndex = 1;
\r
1161 else if (drop_format.SelectedIndex.Equals(1))
\r
1162 DVD_Save.FilterIndex = 2;
\r
1164 if (DVD_Save.ShowDialog() == DialogResult.OK)
\r
1166 // Add a file extension manually, as FileDialog.AddExtension has issues with dots in filenames
\r
1167 switch (DVD_Save.FilterIndex)
\r
1170 if (!Path.GetExtension(DVD_Save.FileName).Equals(".mp4", StringComparison.InvariantCultureIgnoreCase))
\r
1171 if (Properties.Settings.Default.useM4v)
\r
1172 DVD_Save.FileName = DVD_Save.FileName.Replace(".mp4", ".m4v").Replace(".mkv", ".m4v");
\r
1174 DVD_Save.FileName = DVD_Save.FileName.Replace(".m4v", ".mp4").Replace(".mkv", ".mp4");
\r
1177 if (!Path.GetExtension(DVD_Save.FileName).Equals(".mkv", StringComparison.InvariantCultureIgnoreCase))
\r
1178 DVD_Save.FileName = DVD_Save.FileName.Replace(".mp4", ".mkv").Replace(".m4v", ".mkv");
\r
1184 text_destination.Text = DVD_Save.FileName;
\r
1186 // Quicktime requires .m4v file for chapter markers to work. If checked, change the extension to .m4v (mp4 and m4v are the same thing)
\r
1187 if (Check_ChapterMarkers.Checked && DVD_Save.FilterIndex != 2)
\r
1188 SetExtension(".m4v");
\r
1191 private void text_destination_TextChanged(object sender, EventArgs e)
\r
1193 string path = text_destination.Text;
\r
1194 if (path.EndsWith(".mp4") || path.EndsWith(".m4v"))
\r
1195 drop_format.SelectedIndex = 0;
\r
1196 else if (path.EndsWith(".mkv"))
\r
1197 drop_format.SelectedIndex = 1;
\r
1200 // Output Settings
\r
1201 private void drop_format_SelectedIndexChanged(object sender, EventArgs e)
\r
1203 switch (drop_format.SelectedIndex)
\r
1206 if (Properties.Settings.Default.useM4v || Check_ChapterMarkers.Checked || AudioSettings.RequiresM4V() || Subtitles.RequiresM4V())
\r
1207 SetExtension(".m4v");
\r
1209 SetExtension(".mp4");
\r
1212 SetExtension(".mkv");
\r
1216 AudioSettings.SetContainer(drop_format.Text);
\r
1217 Subtitles.SetContainer(drop_format.SelectedIndex);
\r
1219 if (drop_format.Text.Contains("MP4"))
\r
1221 if (drp_videoEncoder.Items.Contains("VP3 (Theora)"))
\r
1223 drp_videoEncoder.Items.Remove("VP3 (Theora)");
\r
1224 drp_videoEncoder.SelectedIndex = 1;
\r
1227 else if (drop_format.Text.Contains("MKV"))
\r
1228 drp_videoEncoder.Items.Add("VP3 (Theora)");
\r
1230 public void SetExtension(string newExtension)
\r
1232 if (newExtension == ".mp4" || newExtension == ".m4v")
\r
1233 if (Properties.Settings.Default.useM4v || Check_ChapterMarkers.Checked || AudioSettings.RequiresM4V() || Subtitles.RequiresM4V())
\r
1234 newExtension = ".m4v";
\r
1236 newExtension = ".mp4";
\r
1238 if (Path.HasExtension(newExtension))
\r
1239 text_destination.Text = Path.ChangeExtension(text_destination.Text, newExtension);
\r
1243 private void drp_videoEncoder_SelectedIndexChanged(object sender, EventArgs e)
\r
1245 setContainerOpts();
\r
1247 //Turn off some options which are H.264 only when the user selects a non h.264 encoder
\r
1248 if (drp_videoEncoder.Text.Contains("H.264"))
\r
1250 if (check_2PassEncode.CheckState == CheckState.Checked)
\r
1251 check_turbo.Enabled = true;
\r
1253 tab_advanced.Enabled = true;
\r
1254 if ((drop_format.Text.Contains("MP4")) || (drop_format.Text.Contains("M4V")))
\r
1255 check_iPodAtom.Enabled = true;
\r
1257 check_iPodAtom.Enabled = false;
\r
1261 check_turbo.CheckState = CheckState.Unchecked;
\r
1262 check_turbo.Enabled = false;
\r
1263 tab_advanced.Enabled = false;
\r
1264 x264Panel.x264Query = "";
\r
1265 check_iPodAtom.Enabled = false;
\r
1266 check_iPodAtom.Checked = false;
\r
1269 // Setup the CQ Slider
\r
1270 switch (drp_videoEncoder.Text)
\r
1272 case "MPEG-4 (FFmpeg)":
\r
1273 if (slider_videoQuality.Value > 31)
\r
1274 slider_videoQuality.Value = 20; // Just reset to 70% QP 10 on encode change.
\r
1275 slider_videoQuality.Minimum = 1;
\r
1276 slider_videoQuality.Maximum = 31;
\r
1278 case "H.264 (x264)":
\r
1279 slider_videoQuality.Minimum = 0;
\r
1280 slider_videoQuality.TickFrequency = 1;
\r
1282 CultureInfo culture = CultureInfo.CreateSpecificCulture("en-US");
\r
1283 double cqStep = Properties.Settings.Default.x264cqstep;
\r
1284 double multiplier = 1.0 / cqStep;
\r
1285 double value = slider_videoQuality.Value * multiplier;
\r
1287 switch (Properties.Settings.Default.x264cqstep.ToString(culture))
\r
1290 slider_videoQuality.Maximum = 255;
\r
1293 slider_videoQuality.Maximum = 204;
\r
1296 slider_videoQuality.Maximum = 102;
\r
1299 slider_videoQuality.Maximum = 51;
\r
1302 slider_videoQuality.Maximum = 51;
\r
1305 if (value < slider_videoQuality.Maximum)
\r
1306 slider_videoQuality.Value = slider_videoQuality.Maximum - (int)value;
\r
1309 case "VP3 (Theora)":
\r
1310 if (slider_videoQuality.Value > 63)
\r
1311 slider_videoQuality.Value = 45; // Just reset to 70% QP 45 on encode change.
\r
1312 slider_videoQuality.Minimum = 0;
\r
1313 slider_videoQuality.Maximum = 63;
\r
1318 /// Set the container format options
\r
1320 public void setContainerOpts()
\r
1322 if ((drop_format.Text.Contains("MP4")) || (drop_format.Text.Contains("M4V")))
\r
1324 check_largeFile.Enabled = true;
\r
1325 check_optimiseMP4.Enabled = true;
\r
1326 check_iPodAtom.Enabled = true;
\r
1330 check_largeFile.Enabled = false;
\r
1331 check_optimiseMP4.Enabled = false;
\r
1332 check_iPodAtom.Enabled = false;
\r
1333 check_largeFile.Checked = false;
\r
1334 check_optimiseMP4.Checked = false;
\r
1335 check_iPodAtom.Checked = false;
\r
1338 private double _cachedCqStep = Properties.Settings.Default.x264cqstep;
\r
1340 /// Update the CQ slider for x264 for a new CQ step. This is set from option
\r
1342 public void setQualityFromSlider()
\r
1344 // Work out the current RF value.
\r
1345 double cqStep = _cachedCqStep;
\r
1346 double rfValue = 51.0 - slider_videoQuality.Value * cqStep;
\r
1348 // Change the maximum value for the slider
\r
1349 switch (Properties.Settings.Default.x264cqstep.ToString(new CultureInfo("en-US")))
\r
1352 slider_videoQuality.Maximum = 255;
\r
1355 slider_videoQuality.Maximum = 204;
\r
1358 slider_videoQuality.Maximum = 102;
\r
1361 slider_videoQuality.Maximum = 51;
\r
1364 slider_videoQuality.Maximum = 51;
\r
1368 // Reset the CQ slider to RF0
\r
1369 slider_videoQuality.Value = slider_videoQuality.Maximum;
\r
1371 // Reset the CQ slider back to the previous value as close as possible
\r
1372 double cqStepNew = Properties.Settings.Default.x264cqstep;
\r
1373 double rfValueCurrent = 51.0 - slider_videoQuality.Value * cqStepNew;
\r
1374 while (rfValueCurrent < rfValue)
\r
1376 slider_videoQuality.Value--;
\r
1377 rfValueCurrent = 51.0 - slider_videoQuality.Value * cqStepNew;
\r
1380 // Cache the CQ step for the next calculation
\r
1381 _cachedCqStep = Properties.Settings.Default.x264cqstep;
\r
1383 private void slider_videoQuality_Scroll(object sender, EventArgs e)
\r
1385 double cqStep = Properties.Settings.Default.x264cqstep;
\r
1386 switch (drp_videoEncoder.Text)
\r
1388 case "MPEG-4 (FFmpeg)":
\r
1389 double rfValue = 31 - (slider_videoQuality.Value - 1);
\r
1390 double max = slider_videoQuality.Maximum;
\r
1391 double min = slider_videoQuality.Minimum;
\r
1392 double val = ((max - min) - (rfValue - min)) / (max - min);
\r
1393 lbl_SliderValue.Text = "QP:" + (32 - slider_videoQuality.Value);
\r
1394 lbl_qualityValue.Text = Math.Round((val * 100), 2).ToString(new CultureInfo("en-US")) + "%";
\r
1396 case "H.264 (x264)":
\r
1397 rfValue = 51.0 - slider_videoQuality.Value * cqStep;
\r
1398 max = slider_videoQuality.Maximum * cqStep;
\r
1399 min = slider_videoQuality.Minimum;
\r
1400 val = ((max - min) - (rfValue - min)) / (max - min);
\r
1401 rfValue = Math.Round(rfValue, 2);
\r
1402 lbl_SliderValue.Text = "RF:" + rfValue.ToString(new CultureInfo("en-US"));
\r
1403 lbl_qualityValue.Text = Math.Round((val * 100), 2).ToString(new CultureInfo("en-US")) + "%";
\r
1405 case "VP3 (Theora)":
\r
1406 rfValue = slider_videoQuality.Value;
\r
1407 double value = rfValue / 63;
\r
1408 lbl_SliderValue.Text = "QP:" + slider_videoQuality.Value;
\r
1409 lbl_qualityValue.Text = Math.Round((value * 100), 2).ToString(new CultureInfo("en-US")) + "%";
\r
1413 private void radio_targetFilesize_CheckedChanged(object sender, EventArgs e)
\r
1415 text_bitrate.Enabled = false;
\r
1416 text_filesize.Enabled = true;
\r
1417 slider_videoQuality.Enabled = false;
\r
1419 check_2PassEncode.Enabled = true;
\r
1421 private void radio_avgBitrate_CheckedChanged(object sender, EventArgs e)
\r
1423 text_bitrate.Enabled = true;
\r
1424 text_filesize.Enabled = false;
\r
1425 slider_videoQuality.Enabled = false;
\r
1427 check_2PassEncode.Enabled = true;
\r
1429 private void radio_cq_CheckedChanged(object sender, EventArgs e)
\r
1431 text_bitrate.Enabled = false;
\r
1432 text_filesize.Enabled = false;
\r
1433 slider_videoQuality.Enabled = true;
\r
1435 check_2PassEncode.Enabled = false;
\r
1436 check_2PassEncode.CheckState = CheckState.Unchecked;
\r
1438 private void check_2PassEncode_CheckedChanged(object sender, EventArgs e)
\r
1440 if (check_2PassEncode.CheckState.ToString() == "Checked")
\r
1442 if (drp_videoEncoder.Text.Contains("H.264"))
\r
1443 check_turbo.Enabled = true;
\r
1447 check_turbo.Enabled = false;
\r
1448 check_turbo.CheckState = CheckState.Unchecked;
\r
1452 // Chapter Marker Tab
\r
1453 private void Check_ChapterMarkers_CheckedChanged(object sender, EventArgs e)
\r
1455 if (Check_ChapterMarkers.Checked)
\r
1457 if (drop_format.SelectedIndex != 1)
\r
1458 SetExtension(".m4v");
\r
1459 data_chpt.Enabled = true;
\r
1460 btn_importChapters.Enabled = true;
\r
1464 if (drop_format.SelectedIndex != 1 && !Properties.Settings.Default.useM4v)
\r
1465 SetExtension(".mp4");
\r
1466 data_chpt.Enabled = false;
\r
1467 btn_importChapters.Enabled = false;
\r
1470 private void btn_importChapters_Click(object sender, EventArgs e)
\r
1472 if (File_ChapterImport.ShowDialog() == DialogResult.OK)
\r
1474 String filename = File_ChapterImport.FileName;
\r
1475 DataGridView imported = Main.ImportChapterNames(data_chpt, filename);
\r
1476 if (imported != null)
\r
1477 data_chpt = imported;
\r
1480 private void mnu_resetChapters_Click(object sender, EventArgs e)
\r
1482 data_chpt.Rows.Clear();
\r
1483 DataGridView chapterGridView = Main.ChapterNaming(data_chpt, drop_chapterFinish.Text);
\r
1484 if (chapterGridView != null)
\r
1486 data_chpt = chapterGridView;
\r
1490 // Query Editor Tab
\r
1491 private void btn_generate_Query_Click(object sender, EventArgs e)
\r
1493 rtf_query.Text = QueryGenerator.GenerateCLIQuery(this, drop_mode.SelectedIndex, 0, null);
\r
1495 private void btn_clear_Click(object sender, EventArgs e)
\r
1497 rtf_query.Clear();
\r
1501 // MainWindow Components, Actions and Functions ***********************
\r
1503 #region Source Scan
\r
1504 public Boolean isScanning { get; set; }
\r
1505 private Scan SourceScan;
\r
1507 private void StartScan(String filename, int title)
\r
1509 // Setup the GUI components for the scan.
\r
1510 sourcePath = filename;
\r
1511 foreach (Control ctrl in Controls)
\r
1512 if (!(ctrl is StatusStrip || ctrl is MenuStrip || ctrl is ToolStrip))
\r
1513 ctrl.Enabled = false;
\r
1515 lbl_encode.Visible = true;
\r
1516 lbl_encode.Text = "Scanning ...";
\r
1517 btn_source.Enabled = false;
\r
1518 btn_start.Enabled = false;
\r
1519 btn_showQueue.Enabled = false;
\r
1520 btn_add2Queue.Enabled = false;
\r
1521 tb_preview.Enabled = false;
\r
1522 mnu_killCLI.Visible = true;
\r
1524 if (ActivityWindow != null)
\r
1525 ActivityWindow.SetScanMode();
\r
1530 isScanning = true;
\r
1531 SourceScan = new Scan();
\r
1532 SourceScan.ScanSource(sourcePath, title);
\r
1533 SourceScan.ScanStatusChanged += new EventHandler(SourceScan_ScanStatusChanged);
\r
1534 SourceScan.ScanCompleted += new EventHandler(SourceScan_ScanCompleted);
\r
1536 catch (Exception exc)
\r
1538 MessageBox.Show("frmMain.cs - StartScan " + exc, "Error", MessageBoxButtons.OK, MessageBoxIcon.Error);
\r
1542 void SourceScan_ScanStatusChanged(object sender, EventArgs e)
\r
1544 UpdateScanStatusLabel();
\r
1546 void SourceScan_ScanCompleted(object sender, EventArgs e)
\r
1548 UpdateGuiAfterScan();
\r
1551 private void UpdateScanStatusLabel()
\r
1553 if (InvokeRequired)
\r
1555 BeginInvoke(new UpdateWindowHandler(UpdateScanStatusLabel));
\r
1558 lbl_encode.Text = SourceScan.ScanStatus();
\r
1560 private void UpdateGuiAfterScan()
\r
1562 if (InvokeRequired)
\r
1564 BeginInvoke(new UpdateWindowHandler(UpdateGuiAfterScan));
\r
1570 currentSource = SourceScan.SouceData();
\r
1572 // Setup some GUI components
\r
1573 drp_dvdtitle.Items.Clear();
\r
1574 if (currentSource.Titles.Count != 0)
\r
1575 drp_dvdtitle.Items.AddRange(currentSource.Titles.ToArray());
\r
1577 // Now select the longest title
\r
1578 if (currentSource.Titles.Count != 0)
\r
1579 drp_dvdtitle.SelectedItem = Main.SelectLongestTitle(currentSource);
\r
1581 // Enable the creation of chapter markers if the file is an image of a dvd.
\r
1582 if (sourcePath.ToLower().Contains(".iso") || sourcePath.Contains("VIDEO_TS") || Directory.Exists(Path.Combine(sourcePath, "VIDEO_TS")))
\r
1583 Check_ChapterMarkers.Enabled = true;
\r
1586 Check_ChapterMarkers.Enabled = false;
\r
1587 Check_ChapterMarkers.Checked = false;
\r
1588 data_chpt.Rows.Clear();
\r
1591 // If no titles were found, Display an error message
\r
1592 if (drp_dvdtitle.Items.Count == 0)
\r
1595 "No Title(s) found. \n\nYour Source may be copy protected, badly mastered or in a format which HandBrake does not support. \nPlease refer to the Documentation and FAQ (see Help Menu).",
\r
1596 "Error", MessageBoxButtons.OK, MessageBoxIcon.Hand);
\r
1597 sourcePath = string.Empty;
\r
1599 UpdateSourceLabel();
\r
1601 // Enable the GUI components and enable any disabled components
\r
1604 catch (Exception exc)
\r
1606 MessageBox.Show("frmMain.cs - updateUIafterScan " + exc, "Error", MessageBoxButtons.OK, MessageBoxIcon.Error);
\r
1611 private void EnableGUI()
\r
1615 if (InvokeRequired)
\r
1616 BeginInvoke(new UpdateWindowHandler(EnableGUI));
\r
1617 lbl_encode.Text = "Scan Completed";
\r
1618 foreach (Control ctrl in Controls)
\r
1619 ctrl.Enabled = true;
\r
1620 btn_start.Enabled = true;
\r
1621 btn_showQueue.Enabled = true;
\r
1622 btn_add2Queue.Enabled = true;
\r
1623 tb_preview.Enabled = true;
\r
1624 btn_source.Enabled = true;
\r
1625 mnu_killCLI.Visible = false;
\r
1627 catch (Exception exc)
\r
1629 MessageBox.Show("frmMain.cs - EnableGUI() " + exc, "Error", MessageBoxButtons.OK, MessageBoxIcon.Error);
\r
1632 private void KillScan()
\r
1636 SourceScan.ScanCompleted -= new EventHandler(SourceScan_ScanCompleted);
\r
1640 if (SourceScan.ScanProcess() != null)
\r
1641 SourceScan.ScanProcess().Kill();
\r
1643 lbl_encode.Text = "Scan Cancelled!";
\r
1645 catch (Exception ex)
\r
1647 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
1650 private void ResetGUI()
\r
1652 drp_dvdtitle.Items.Clear();
\r
1653 drop_chapterStart.Items.Clear();
\r
1654 drop_chapterFinish.Items.Clear();
\r
1655 lbl_duration.Text = "Select a Title";
\r
1656 PictureSettings.lbl_src_res.Text = "Select a Title";
\r
1657 PictureSettings.lbl_Aspect.Text = "Select a Title";
\r
1658 sourcePath = String.Empty;
\r
1659 text_destination.Text = String.Empty;
\r
1660 selectedTitle = null;
\r
1661 isScanning = false;
\r
1663 private void UpdateSourceLabel()
\r
1665 labelSource.Text = string.IsNullOrEmpty(sourcePath) ? "Select \"Source\" to continue." : this.SourceName;
\r
1667 if (selectedTitle != null)
\r
1668 if (!string.IsNullOrEmpty(selectedTitle.SourceName)) // If it's one of multiple source files, make sure we don't use the folder name
\r
1669 labelSource.Text = Path.GetFileName(selectedTitle.SourceName);
\r
1672 public void RecievingJob(Job job)
\r
1674 string query = job.Query;
\r
1675 StartScan(job.Source, 0);
\r
1678 if (query != null)
\r
1680 //Ok, Reset all the H264 widgets before changing the preset
\r
1681 x264Panel.reset2Defaults();
\r
1683 // Send the query from the file to the Query Parser class
\r
1684 QueryParser presetQuery = QueryParser.Parse(query);
\r
1686 // Now load the preset
\r
1687 PresetLoader.LoadPreset(this, presetQuery, "Load Back From Queue", true);
\r
1689 // The x264 widgets will need updated, so do this now:
\r
1690 x264Panel.X264_StandardizeOptString();
\r
1691 x264Panel.X264_SetCurrentSettingsInPanel();
\r
1693 // Finally, let this window have a copy of the preset settings.
\r
1694 CurrentlySelectedPreset = null;
\r
1695 PictureSettings.SetPresetCropWarningLabel(null);
\r
1703 /// Set the GUI to it's finished encoding state.
\r
1705 private void setEncodeFinished()
\r
1709 if (InvokeRequired)
\r
1711 BeginInvoke(new UpdateWindowHandler(setEncodeFinished));
\r
1715 lbl_encode.Text = "Encoding Finished";
\r
1716 btn_start.Text = "Start";
\r
1717 btn_start.ToolTipText = "Start the encoding process";
\r
1718 btn_start.Image = Properties.Resources.Play;
\r
1720 // If the window is minimized, display the notification in a popup.
\r
1721 if (Properties.Settings.Default.trayIconAlerts)
\r
1722 if (FormWindowState.Minimized == this.WindowState)
\r
1724 notifyIcon.BalloonTipText = lbl_encode.Text;
\r
1725 notifyIcon.ShowBalloonTip(500);
\r
1728 catch (Exception exc)
\r
1730 MessageBox.Show(exc.ToString());
\r
1735 /// Set the GUI to it's started encoding state.
\r
1737 private void setEncodeStarted()
\r
1741 if (InvokeRequired)
\r
1743 BeginInvoke(new UpdateWindowHandler(setEncodeStarted));
\r
1747 lbl_encode.Visible = true;
\r
1748 lbl_encode.Text = "Encoding with " + encodeQueue.Count + " encode(s) pending";
\r
1749 btn_start.Text = "Stop";
\r
1750 btn_start.ToolTipText = "Stop the encoding process.";
\r
1751 btn_start.Image = Properties.Resources.stop;
\r
1753 catch (Exception exc)
\r
1755 MessageBox.Show(exc.ToString());
\r
1760 #region DVD Drive Detection
\r
1761 private void getDriveInfoThread()
\r
1765 if (InvokeRequired)
\r
1767 BeginInvoke(new UpdateWindowHandler(getDriveInfoThread));
\r
1771 Boolean foundDrive = false;
\r
1772 DriveInfo[] theCollectionOfDrives = DriveInfo.GetDrives();
\r
1773 foreach (DriveInfo curDrive in theCollectionOfDrives)
\r
1775 if (curDrive.DriveType == DriveType.CDRom && curDrive.IsReady)
\r
1777 if (File.Exists(curDrive.RootDirectory + "VIDEO_TS\\VIDEO_TS.IFO"))
\r
1779 this.dvdDrivePath = curDrive.RootDirectory + "VIDEO_TS";
\r
1780 this.dvdDriveLabel = curDrive.VolumeLabel;
\r
1781 mnu_dvd_drive.Text = this.dvdDrivePath + " (" + this.dvdDriveLabel + ")";
\r
1782 foundDrive = true;
\r
1788 if (foundDrive == false)
\r
1789 mnu_dvd_drive.Text = "[No DVD Drive Ready]";
\r
1793 mnu_dvd_drive.Text = "[No DVD Drive Ready / Found]";
\r
1798 #region Public Methods
\r
1800 /// Access the preset Handler and setup the preset panel.
\r
1802 public void loadPresetPanel()
\r
1804 if (presetHandler.CheckIfPresetsAreOutOfDate())
\r
1805 if (!Properties.Settings.Default.presetNotification)
\r
1806 MessageBox.Show(splash,
\r
1807 "HandBrake has determined your built-in presets are out of date... These presets will now be updated.",
\r
1808 "Preset Update", MessageBoxButtons.OK, MessageBoxIcon.Information);
\r
1810 presetHandler.GetPresetPanel(ref treeView_presets);
\r
1811 treeView_presets.Update();
\r
1818 /// Handle GUI shortcuts
\r
1820 /// <param name="msg"></param>
\r
1821 /// <param name="keyData"></param>
\r
1822 /// <returns></returns>
\r
1823 protected override bool ProcessCmdKey(ref Message msg, Keys keyData)
\r
1825 if (keyData == (Keys.Control | Keys.S))
\r
1827 btn_start_Click(this, new EventArgs());
\r
1831 if (keyData == (Keys.Control | Keys.A))
\r
1833 btn_add2Queue_Click(this, new EventArgs());
\r
1836 return base.ProcessCmdKey(ref msg, keyData);
\r
1840 /// If the queue is being processed, prompt the user to confirm application close.
\r
1842 /// <param name="e"></param>
\r
1843 protected override void OnFormClosing(FormClosingEventArgs e)
\r
1845 // If currently encoding, the queue isn't paused, and there are queue items to process, prompt to confirm close.
\r
1846 if ((encodeQueue.IsEncoding) && (!encodeQueue.PauseRequested) && (encodeQueue.Count > 0))
\r
1848 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
1849 "Close HandBrake?", MessageBoxButtons.YesNo, MessageBoxIcon.Question);
\r
1850 if (result == DialogResult.No)
\r
1853 base.OnFormClosing(e);
\r
1857 #region In-GUI Encode Status (Experimental)
\r
1858 private void encodeMonitorThread()
\r
1862 Parser encode = new Parser(encodeQueue.HbProcess.StandardOutput.BaseStream);
\r
1863 encode.OnEncodeProgress += encodeOnEncodeProgress;
\r
1864 while (!encode.EndOfStream)
\r
1865 encode.readEncodeStatus();
\r
1867 catch (Exception exc)
\r
1869 MessageBox.Show(exc.ToString(), "Error", MessageBoxButtons.OK, MessageBoxIcon.Error);
\r
1872 private void encodeOnEncodeProgress(object Sender, int CurrentTask, int TaskCount, float PercentComplete, float CurrentFps, float AverageFps, TimeSpan TimeRemaining)
\r
1874 if (this.InvokeRequired)
\r
1876 this.BeginInvoke(new EncodeProgressEventHandler(encodeOnEncodeProgress),
\r
1877 new object[] { Sender, CurrentTask, TaskCount, PercentComplete, CurrentFps, AverageFps, TimeRemaining });
\r
1880 lbl_encode.Text = string.Format("Encode Progress: {0}%, FPS: {1}, Avg FPS: {2}, Time Remaining: {3} ", PercentComplete, CurrentFps, AverageFps, TimeRemaining);
\r
1885 private enum SourceType
\r
1894 // This is the END of the road ****************************************
\r