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.Model;
\r
18 using Handbrake.Presets;
\r
19 using Handbrake.Parsing;
\r
23 public partial class frmMain : Form
\r
25 // Objects which may be used by one or more other objects *************
\r
26 Queue encodeQueue = new Queue();
\r
27 PresetsHandler presetHandler = new PresetsHandler();
\r
29 // Globals: Mainly used for tracking. *********************************
\r
30 public Title selectedTitle;
\r
31 private frmQueue queueWindow;
\r
32 private frmPreview qtpreview;
\r
33 private frmActivityWindow ActivityWindow;
\r
34 private Form splash;
\r
35 public string sourcePath;
\r
36 private string lastAction;
\r
37 private SourceType selectedSourceType;
\r
38 private string dvdDrivePath;
\r
39 private string dvdDriveLabel;
\r
40 private Preset CurrentlySelectedPreset;
\r
41 private DVD currentSource;
\r
43 // Delegates **********************************************************
\r
44 private delegate void UpdateWindowHandler();
\r
46 // Applicaiton Startup ************************************************
\r
48 #region Application Startup
\r
51 // Load and setup the splash screen in this thread
\r
52 splash = new frmSplashScreen();
\r
54 Label lblStatus = new Label { Size = new Size(150, 20), Location = new Point(182, 102) };
\r
55 splash.Controls.Add(lblStatus);
\r
57 InitializeComponent();
\r
59 // Update the users config file with the CLI version data.
\r
60 lblStatus.Text = "Setting Version Data ...";
\r
61 Application.DoEvents();
\r
62 Main.SetCliVersionData();
\r
64 // Show the form, but leave disabled until preloading is complete then show the main form
\r
65 this.Enabled = false;
\r
67 Application.DoEvents(); // Forces frmMain to draw
\r
69 // Check for new versions, if update checking is enabled
\r
70 if (Properties.Settings.Default.updateStatus)
\r
72 DateTime now = DateTime.Now;
\r
73 DateTime lastCheck = Properties.Settings.Default.lastUpdateCheckDate;
\r
74 TimeSpan elapsed = now.Subtract(lastCheck);
\r
75 if (elapsed.TotalDays > Properties.Settings.Default.daysBetweenUpdateCheck)
\r
77 lblStatus.Text = "Checking for updates ...";
\r
78 Application.DoEvents();
\r
80 Main.BeginCheckForUpdates(new AsyncCallback(UpdateCheckDone), false);
\r
84 // Clear the log files in the background
\r
85 if (Properties.Settings.Default.clearOldLogs)
\r
87 lblStatus.Text = "Clearing Old Log Files ...";
\r
88 Application.DoEvents();
\r
89 Thread clearLog = new Thread(Main.ClearOldLogs);
\r
93 // Setup the GUI components
\r
94 lblStatus.Text = "Setting up the GUI ...";
\r
95 Application.DoEvents();
\r
96 LoadPresetPanel(); // Load the Preset Panel
\r
97 treeView_presets.ExpandAll();
\r
98 lbl_encode.Text = "";
\r
99 drop_mode.SelectedIndex = 0;
\r
100 queueWindow = new frmQueue(encodeQueue, this); // Prepare the Queue
\r
101 if (!Properties.Settings.Default.QueryEditorTab)
\r
102 tabs_panel.TabPages.RemoveAt(7); // Remove the query editor tab if the user does not want it enabled.
\r
104 // Load the user's default settings or Normal Preset
\r
105 if (Properties.Settings.Default.defaultPreset != "")
\r
107 if (presetHandler.GetPreset(Properties.Settings.Default.defaultPreset) != null)
\r
109 string query = presetHandler.GetPreset(Properties.Settings.Default.defaultPreset).Query;
\r
110 Boolean loadPictureSettings = presetHandler.GetPreset(Properties.Settings.Default.defaultPreset).PictureSettings;
\r
114 x264Panel.reset2Defaults();
\r
116 QueryParser presetQuery = QueryParser.Parse(query);
\r
117 PresetLoader.LoadPreset(this, presetQuery, Properties.Settings.Default.defaultPreset, loadPictureSettings);
\r
119 x264Panel.X264_StandardizeOptString();
\r
120 x264Panel.X264_SetCurrentSettingsInPanel();
\r
124 loadNormalPreset();
\r
127 loadNormalPreset();
\r
129 // Enabled GUI tooltip's if Required
\r
130 if (Properties.Settings.Default.tooltipEnable)
\r
131 ToolTip.Active = true;
\r
133 // Register with Growl (if not using Growl for the encoding completion action, this wont hurt anything)
\r
134 GrowlCommunicator.Register();
\r
137 lblStatus.Text = "Loading Complete!";
\r
138 Application.DoEvents();
\r
141 this.Enabled = true;
\r
143 // Event Handlers and Queue Recovery
\r
148 private void UpdateCheckDone(IAsyncResult result)
\r
150 if (InvokeRequired)
\r
152 Invoke(new MethodInvoker(() => UpdateCheckDone(result)));
\r
156 UpdateCheckInformation info;
\r
160 info = Main.EndCheckForUpdates(result);
\r
162 if (info.NewVersionAvailable)
\r
164 frmUpdater updateWindow = new frmUpdater(info.BuildInformation);
\r
165 updateWindow.ShowDialog();
\r
168 catch (Exception ex)
\r
170 if ((bool)result.AsyncState)
\r
171 MessageBox.Show("Unable to check for updates, Please try again later.\n\nDetailed Error Information:\n" + ex, "Error", MessageBoxButtons.OK, MessageBoxIcon.Error);
\r
175 // Startup Functions
\r
176 private void queueRecovery()
\r
178 if (Main.CheckQueueRecovery())
\r
180 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
182 if (result == DialogResult.Yes)
\r
183 encodeQueue.LoadQueueFromFile("hb_queue_recovery.xml"); // Start Recovery
\r
186 // Remove the Queue recovery file if the user doesn't want to recovery the last queue.
\r
187 string queuePath = Path.Combine(Path.GetTempPath(), "hb_queue_recovery.xml");
\r
188 if (File.Exists(queuePath))
\r
189 File.Delete(queuePath);
\r
196 public string SourceName
\r
200 if (this.selectedSourceType == SourceType.DvdDrive)
\r
202 return this.dvdDriveLabel;
\r
205 if (Path.GetFileNameWithoutExtension(this.sourcePath) != "VIDEO_TS")
\r
206 return Path.GetFileNameWithoutExtension(this.sourcePath);
\r
208 return Path.GetFileNameWithoutExtension(Path.GetDirectoryName(this.sourcePath));
\r
214 // Encoding Events for setting up the GUI
\r
215 private void events()
\r
217 // Handle Widget changes when preset is selected.
\r
218 RegisterPresetEventHandler();
\r
220 // Handle Window Resize
\r
221 if (Properties.Settings.Default.MainWindowMinimize)
\r
222 this.Resize += new EventHandler(frmMain_Resize);
\r
224 // Handle Encode Start / Finish / Pause
\r
226 encodeQueue.QueuePauseRequested += new EventHandler(encodePaused);
\r
227 encodeQueue.EncodeStarted += new EventHandler(encodeStarted);
\r
228 encodeQueue.EncodeEnded += new EventHandler(encodeEnded);
\r
230 // Handle a file being draged onto the GUI.
\r
231 this.DragEnter += new DragEventHandler(frmMain_DragEnter);
\r
232 this.DragDrop += new DragEventHandler(frmMain_DragDrop);
\r
235 // 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
236 private void RegisterPresetEventHandler()
\r
239 drop_format.SelectedIndexChanged += new EventHandler(changePresetLabel);
\r
240 check_largeFile.CheckedChanged += new EventHandler(changePresetLabel);
\r
241 check_iPodAtom.CheckedChanged += new EventHandler(changePresetLabel);
\r
242 check_optimiseMP4.CheckedChanged += new EventHandler(changePresetLabel);
\r
244 // Picture Settings
\r
245 //PictureSettings.PictureSettingsChanged += new EventHandler(changePresetLabel);
\r
248 Filters.FilterSettingsChanged += new EventHandler(changePresetLabel);
\r
251 drp_videoEncoder.SelectedIndexChanged += new EventHandler(changePresetLabel);
\r
252 check_2PassEncode.CheckedChanged += new EventHandler(changePresetLabel);
\r
253 check_turbo.CheckedChanged += new EventHandler(changePresetLabel);
\r
254 text_filesize.TextChanged += new EventHandler(changePresetLabel);
\r
255 text_bitrate.TextChanged += new EventHandler(changePresetLabel);
\r
256 slider_videoQuality.ValueChanged += new EventHandler(changePresetLabel);
\r
259 AudioSettings.AudioListChanged += new EventHandler(changePresetLabel);
\r
262 x264Panel.rtf_x264Query.TextChanged += new EventHandler(changePresetLabel);
\r
264 private void UnRegisterPresetEventHandler()
\r
266 // Output Settings
\r
267 drop_format.SelectedIndexChanged -= new EventHandler(changePresetLabel);
\r
268 check_largeFile.CheckedChanged -= new EventHandler(changePresetLabel);
\r
269 check_iPodAtom.CheckedChanged -= new EventHandler(changePresetLabel);
\r
270 check_optimiseMP4.CheckedChanged -= new EventHandler(changePresetLabel);
\r
272 // Picture Settings
\r
273 //PictureSettings.PictureSettingsChanged -= new EventHandler(changePresetLabel);
\r
276 Filters.FilterSettingsChanged -= new EventHandler(changePresetLabel);
\r
279 drp_videoEncoder.SelectedIndexChanged -= new EventHandler(changePresetLabel);
\r
280 check_2PassEncode.CheckedChanged -= new EventHandler(changePresetLabel);
\r
281 check_turbo.CheckedChanged -= new EventHandler(changePresetLabel);
\r
282 text_filesize.TextChanged -= new EventHandler(changePresetLabel);
\r
283 text_bitrate.TextChanged -= new EventHandler(changePresetLabel);
\r
284 slider_videoQuality.ValueChanged -= new EventHandler(changePresetLabel);
\r
287 AudioSettings.AudioListChanged -= new EventHandler(changePresetLabel);
\r
290 x264Panel.rtf_x264Query.TextChanged -= new EventHandler(changePresetLabel);
\r
292 private void changePresetLabel(object sender, EventArgs e)
\r
294 labelPreset.Text = "Output Settings (Preset: Custom)";
\r
295 CurrentlySelectedPreset = null;
\r
298 private static void frmMain_DragEnter(object sender, DragEventArgs e)
\r
300 if (e.Data.GetDataPresent(DataFormats.FileDrop, false))
\r
301 e.Effect = DragDropEffects.All;
\r
303 private void frmMain_DragDrop(object sender, DragEventArgs e)
\r
305 string[] fileList = e.Data.GetData(DataFormats.FileDrop) as string[];
\r
306 sourcePath = string.Empty;
\r
308 if (fileList != null)
\r
310 if (fileList[0] != "")
\r
312 this.selectedSourceType = SourceType.VideoFile;
\r
313 StartScan(fileList[0], 0);
\r
316 UpdateSourceLabel();
\r
319 UpdateSourceLabel();
\r
321 private void encodeStarted(object sender, EventArgs e)
\r
323 lastAction = "encode";
\r
324 SetEncodeStarted();
\r
326 // Experimental HBProc Process Monitoring.
\r
327 if (Properties.Settings.Default.enocdeStatusInGui)
\r
329 Thread encodeMon = new Thread(EncodeMonitorThread);
\r
333 private void encodeEnded(object sender, EventArgs e)
\r
335 SetEncodeFinished();
\r
337 private void encodePaused(object sender, EventArgs e)
\r
339 SetEncodeFinished();
\r
343 // User Interface Menus / Tool Strips *********************************
\r
346 private void mnu_killCLI_Click(object sender, EventArgs e)
\r
350 private void mnu_exit_Click(object sender, EventArgs e)
\r
352 Application.Exit();
\r
357 private void mnu_encode_Click(object sender, EventArgs e)
\r
359 queueWindow.Show();
\r
361 private void mnu_encodeLog_Click(object sender, EventArgs e)
\r
363 frmActivityWindow dvdInfoWindow = new frmActivityWindow(lastAction);
\r
364 dvdInfoWindow.Show();
\r
366 private void mnu_options_Click(object sender, EventArgs e)
\r
368 Form options = new frmOptions(this);
\r
369 options.ShowDialog();
\r
373 #region Presets Menu
\r
374 private void mnu_presetReset_Click(object sender, EventArgs e)
\r
376 presetHandler.UpdateBuiltInPresets();
\r
378 if (treeView_presets.Nodes.Count == 0)
\r
379 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
381 MessageBox.Show("Presets have been updated!", "Alert", MessageBoxButtons.OK, MessageBoxIcon.Information);
\r
383 treeView_presets.ExpandAll();
\r
385 private void mnu_delete_preset_Click(object sender, EventArgs e)
\r
387 presetHandler.RemoveBuiltInPresets();
\r
388 LoadPresetPanel(); // Reload the preset panel
\r
390 private void mnu_SelectDefault_Click(object sender, EventArgs e)
\r
392 loadNormalPreset();
\r
394 private void mnu_importMacPreset_Click(object sender, EventArgs e)
\r
398 private void btn_new_preset_Click(object sender, EventArgs e)
\r
400 Form preset = new frmAddPreset(this, QueryGenerator.GenerateCLIQuery(this, drop_mode.SelectedIndex, 0, null), presetHandler);
\r
401 preset.ShowDialog();
\r
406 private void mnu_user_guide_Click(object sender, EventArgs e)
\r
408 Process.Start("http://trac.handbrake.fr/wiki/HandBrakeGuide");
\r
410 private void mnu_handbrake_home_Click(object sender, EventArgs e)
\r
412 Process.Start("http://handbrake.fr");
\r
414 private void mnu_UpdateCheck_Click(object sender, EventArgs e)
\r
416 lbl_updateCheck.Visible = true;
\r
417 Main.BeginCheckForUpdates(new AsyncCallback(updateCheckDoneMenu), false);
\r
419 private void updateCheckDoneMenu(IAsyncResult result)
\r
421 // Make sure it's running on the calling thread
\r
422 if (InvokeRequired)
\r
424 Invoke(new MethodInvoker(() => updateCheckDoneMenu(result)));
\r
427 UpdateCheckInformation info;
\r
430 // Get the information about the new build, if any, and close the window
\r
431 info = Main.EndCheckForUpdates(result);
\r
433 if (info.NewVersionAvailable && info.BuildInformation != null)
\r
435 frmUpdater updateWindow = new frmUpdater(info.BuildInformation);
\r
436 updateWindow.ShowDialog();
\r
439 MessageBox.Show("There are no new updates at this time.", "Update Check", MessageBoxButtons.OK, MessageBoxIcon.Information);
\r
440 lbl_updateCheck.Visible = false;
\r
443 catch (Exception ex)
\r
445 if ((bool)result.AsyncState)
\r
446 MessageBox.Show("Unable to check for updates, Please try again later.\n\nDetailed Error Information:\n" + ex, "Error", MessageBoxButtons.OK, MessageBoxIcon.Error);
\r
449 private void mnu_about_Click(object sender, EventArgs e)
\r
451 using (frmAbout About = new frmAbout())
\r
453 About.ShowDialog();
\r
459 // Right Click Menu Code
\r
460 private void pmnu_expandAll_Click(object sender, EventArgs e)
\r
462 treeView_presets.ExpandAll();
\r
464 private void pmnu_collapse_Click(object sender, EventArgs e)
\r
466 treeView_presets.CollapseAll();
\r
468 private void pmnu_import_Click(object sender, EventArgs e)
\r
472 private void pmnu_saveChanges_Click(object sender, EventArgs e)
\r
474 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
475 if (result == DialogResult.Yes)
\r
476 presetHandler.Update(treeView_presets.SelectedNode.Text, QueryGenerator.GenerateTabbedComponentsQuery(this), true);
\r
477 else if (result == DialogResult.No)
\r
478 presetHandler.Update(treeView_presets.SelectedNode.Text, QueryGenerator.GenerateTabbedComponentsQuery(this), false);
\r
480 private void pmnu_delete_click(object sender, EventArgs e)
\r
482 if (treeView_presets.SelectedNode != null)
\r
484 presetHandler.Remove(treeView_presets.SelectedNode.Text);
\r
485 treeView_presets.Nodes.Remove(treeView_presets.SelectedNode);
\r
487 treeView_presets.Select();
\r
489 private void presets_menu_Opening(object sender, System.ComponentModel.CancelEventArgs e)
\r
491 // Make sure that the save menu is always disabled by default
\r
492 pmnu_saveChanges.Enabled = false;
\r
494 // Now enable the save menu if the selected preset is a user preset
\r
495 if (treeView_presets.SelectedNode != null)
\r
496 if (presetHandler.CheckIfUserPresetExists(treeView_presets.SelectedNode.Text))
\r
497 pmnu_saveChanges.Enabled = true;
\r
499 treeView_presets.Select();
\r
502 // Presets Management
\r
503 private void btn_addPreset_Click(object sender, EventArgs e)
\r
505 Form preset = new frmAddPreset(this, QueryGenerator.GenerateTabbedComponentsQuery(this), presetHandler);
\r
506 preset.ShowDialog();
\r
508 private void btn_removePreset_Click(object sender, EventArgs e)
\r
510 DialogResult result = MessageBox.Show("Are you sure you wish to delete the selected preset?", "Preset", MessageBoxButtons.YesNo, MessageBoxIcon.Question);
\r
511 if (result == DialogResult.Yes)
\r
513 if (treeView_presets.SelectedNode != null)
\r
515 presetHandler.Remove(treeView_presets.SelectedNode.Text);
\r
516 treeView_presets.Nodes.Remove(treeView_presets.SelectedNode);
\r
519 treeView_presets.Select();
\r
521 private void btn_setDefault_Click(object sender, EventArgs e)
\r
523 if (treeView_presets.SelectedNode != null)
\r
525 DialogResult result = MessageBox.Show("Are you sure you wish to set this preset as the default?", "Preset", MessageBoxButtons.YesNo, MessageBoxIcon.Question);
\r
526 if (result == DialogResult.Yes)
\r
528 Properties.Settings.Default.defaultPreset = treeView_presets.SelectedNode.Text;
\r
529 Properties.Settings.Default.Save();
\r
530 MessageBox.Show("New default preset set.", "Alert", MessageBoxButtons.OK, MessageBoxIcon.Information);
\r
534 MessageBox.Show("Please select a preset first.", "Warning", MessageBoxButtons.OK, MessageBoxIcon.Warning);
\r
536 private void treeview_presets_mouseUp(object sender, MouseEventArgs e)
\r
538 if (e.Button == MouseButtons.Right)
\r
539 treeView_presets.SelectedNode = treeView_presets.GetNodeAt(e.Location);
\r
540 else if (e.Button == MouseButtons.Left)
\r
542 if (treeView_presets.GetNodeAt(e.Location) != null)
\r
544 if (labelPreset.Text.Contains(treeView_presets.GetNodeAt(e.Location).Text))
\r
549 treeView_presets.Select();
\r
551 private void treeView_presets_AfterSelect(object sender, TreeViewEventArgs e)
\r
555 private void treeView_presets_deleteKey(object sender, KeyEventArgs e)
\r
557 if (e.KeyCode == Keys.Delete)
\r
559 DialogResult result = MessageBox.Show("Are you sure you wish to delete the selected preset?", "Preset", MessageBoxButtons.YesNo, MessageBoxIcon.Question);
\r
560 if (result == DialogResult.Yes)
\r
562 if (treeView_presets.SelectedNode != null)
\r
563 presetHandler.Remove(treeView_presets.SelectedNode.Text);
\r
565 // Remember each nodes expanded status so we can reload it
\r
566 List<Boolean> nodeStatus = new List<Boolean>();
\r
567 foreach (TreeNode node in treeView_presets.Nodes)
\r
568 nodeStatus.Add(node.IsExpanded);
\r
570 // Now reload the preset panel
\r
573 // And finally, re-expand any of the nodes if required
\r
575 foreach (TreeNode node in treeView_presets.Nodes)
\r
585 private void selectPreset()
\r
587 if (treeView_presets.SelectedNode != null)
\r
589 // Ok, so, we've selected a preset. Now we want to load it.
\r
590 string presetName = treeView_presets.SelectedNode.Text;
\r
591 Preset preset = presetHandler.GetPreset(presetName);
\r
592 if (preset != null)
\r
594 string query = presetHandler.GetPreset(presetName).Query;
\r
595 Boolean loadPictureSettings = presetHandler.GetPreset(presetName).PictureSettings;
\r
599 //Ok, Reset all the H264 widgets before changing the preset
\r
600 x264Panel.reset2Defaults();
\r
602 // Send the query from the file to the Query Parser class
\r
603 QueryParser presetQuery = QueryParser.Parse(query);
\r
605 // Now load the preset
\r
606 PresetLoader.LoadPreset(this, presetQuery, presetName, loadPictureSettings);
\r
608 // The x264 widgets will need updated, so do this now:
\r
609 x264Panel.X264_StandardizeOptString();
\r
610 x264Panel.X264_SetCurrentSettingsInPanel();
\r
612 // Finally, let this window have a copy of the preset settings.
\r
613 CurrentlySelectedPreset = preset;
\r
614 PictureSettings.SetPresetCropWarningLabel(preset);
\r
619 private void loadNormalPreset()
\r
621 foreach (TreeNode treenode in treeView_presets.Nodes)
\r
623 foreach (TreeNode node in treenode.Nodes)
\r
625 if (node.Text.Equals("Normal"))
\r
626 treeView_presets.SelectedNode = treeView_presets.Nodes[treenode.Index].Nodes[0];
\r
630 private void importPreset()
\r
632 if (openPreset.ShowDialog() == DialogResult.OK)
\r
634 QueryParser parsed = PlistPresetHandler.Import(openPreset.FileName);
\r
635 if (presetHandler.CheckIfUserPresetExists(parsed.PresetName + " (Imported)"))
\r
637 DialogResult result = MessageBox.Show("This preset appears to already exist. Would you like to overwrite it?", "Overwrite preset?",
\r
638 MessageBoxButtons.YesNo, MessageBoxIcon.Warning);
\r
639 if (result == DialogResult.Yes)
\r
641 PresetLoader.LoadPreset(this, parsed, parsed.PresetName, parsed.UsesPictureSettings);
\r
642 presetHandler.Update(parsed.PresetName + " (Imported)", QueryGenerator.GenerateCLIQuery(this, drop_mode.SelectedIndex, 0, null),
\r
643 parsed.UsesPictureSettings);
\r
648 PresetLoader.LoadPreset(this, parsed, parsed.PresetName, parsed.UsesPictureSettings);
\r
649 presetHandler.Add(parsed.PresetName, QueryGenerator.GenerateCLIQuery(this, drop_mode.SelectedIndex, 0, null), parsed.UsesPictureSettings);
\r
651 if (presetHandler.Add(parsed.PresetName + " (Imported)", QueryGenerator.GenerateCLIQuery(this, drop_mode.SelectedIndex, 0, null), parsed.UsesPictureSettings))
\r
653 TreeNode preset_treeview = new TreeNode(parsed.PresetName + " (Imported)") { ForeColor = Color.Black };
\r
654 treeView_presets.Nodes.Add(preset_treeview);
\r
662 private void btn_source_Click(object sender, EventArgs e)
\r
664 mnu_dvd_drive.Visible = true;
\r
665 Thread driveInfoThread = new Thread(SetDriveSelectionMenuItem);
\r
666 driveInfoThread.Start();
\r
668 private void btn_start_Click(object sender, EventArgs e)
\r
670 if (btn_start.Text == "Stop")
\r
672 DialogResult result;
\r
673 if (Properties.Settings.Default.enocdeStatusInGui && !Properties.Settings.Default.showCliForInGuiEncodeStatus)
\r
675 result = MessageBox.Show(
\r
676 "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
677 "Cancel Encode?", MessageBoxButtons.YesNo, MessageBoxIcon.Question);
\r
681 result = MessageBox.Show("Are you sure you wish to cancel the encode?", "Cancel Encode?",
\r
682 MessageBoxButtons.YesNo, MessageBoxIcon.Question);
\r
685 if (result == DialogResult.Yes)
\r
688 encodeQueue.Pause();
\r
690 if (Properties.Settings.Default.enocdeStatusInGui && !Properties.Settings.Default.showCliForInGuiEncodeStatus)
\r
692 encodeQueue.Stop();
\r
693 if (encodeQueue.HbProcess != null)
\r
694 encodeQueue.HbProcess.WaitForExit();
\r
698 encodeQueue.SafelyClose();
\r
702 SetEncodeFinished();
\r
707 if (encodeQueue.Count != 0 || (!string.IsNullOrEmpty(sourcePath) && !string.IsNullOrEmpty(text_destination.Text)))
\r
709 string generatedQuery = QueryGenerator.GenerateCLIQuery(this, drop_mode.SelectedIndex, 0, null);
\r
710 string specifiedQuery = rtf_query.Text != "" ? rtf_query.Text : QueryGenerator.GenerateCLIQuery(this, drop_mode.SelectedIndex, 0, null);
\r
711 string query = string.Empty;
\r
713 // Check to make sure the generated query matches the GUI settings
\r
714 if (Properties.Settings.Default.PromptOnUnmatchingQueries && !string.IsNullOrEmpty(specifiedQuery) && generatedQuery != specifiedQuery)
\r
716 DialogResult result = MessageBox.Show("The query under the \"Query Editor\" tab " +
\r
717 "does not match the current GUI settings.\n\nBecause the manual query takes " +
\r
718 "priority over the GUI, your recently updated settings will not be taken " +
\r
719 "into account when encoding this job." + Environment.NewLine + Environment.NewLine +
\r
720 "Do you want to replace the manual query with the updated GUI-generated query?",
\r
721 "Manual Query does not Match GUI",
\r
722 MessageBoxButtons.YesNoCancel, MessageBoxIcon.Asterisk,
\r
723 MessageBoxDefaultButton.Button3);
\r
727 case DialogResult.Yes:
\r
728 // Replace the manual query with the generated one
\r
729 query = generatedQuery;
\r
730 rtf_query.Text = generatedQuery;
\r
732 case DialogResult.No:
\r
733 // Use the manual query
\r
734 query = specifiedQuery;
\r
736 case DialogResult.Cancel:
\r
737 // Don't start the encode
\r
743 query = specifiedQuery;
\r
746 DialogResult overwrite = DialogResult.Yes;
\r
747 if (text_destination.Text != "")
\r
748 if (File.Exists(text_destination.Text))
\r
749 overwrite = MessageBox.Show("The destination file already exists. Are you sure you want to overwrite it?", "Overwrite File?", MessageBoxButtons.YesNo, MessageBoxIcon.Question);
\r
751 if (overwrite == DialogResult.Yes)
\r
753 if (encodeQueue.Count == 0)
\r
754 encodeQueue.Add(query, sourcePath, text_destination.Text, (rtf_query.Text != ""));
\r
756 queueWindow.SetQueue();
\r
757 if (encodeQueue.Count > 1)
\r
758 queueWindow.Show(false);
\r
760 SetEncodeStarted(); // Encode is running, so setup the GUI appropriately
\r
761 encodeQueue.Start(); // Start The Queue Encoding Process
\r
762 lastAction = "encode"; // Set the last action to encode - Used for activity window.
\r
764 if (ActivityWindow != null)
\r
765 ActivityWindow.SetEncodeMode();
\r
769 else if (string.IsNullOrEmpty(sourcePath) || string.IsNullOrEmpty(text_destination.Text))
\r
770 MessageBox.Show("No source or destination selected.", "Warning", MessageBoxButtons.OK, MessageBoxIcon.Warning);
\r
773 private void btn_add2Queue_Click(object sender, EventArgs e)
\r
775 if (string.IsNullOrEmpty(sourcePath) || string.IsNullOrEmpty(text_destination.Text))
\r
776 MessageBox.Show("No source or destination selected.", "Warning", MessageBoxButtons.OK, MessageBoxIcon.Warning);
\r
779 String query = QueryGenerator.GenerateCLIQuery(this, drop_mode.SelectedIndex, 0, null);
\r
780 if (rtf_query.Text != "")
\r
781 query = rtf_query.Text;
\r
783 if (encodeQueue.CheckForDestinationDuplicate(text_destination.Text))
\r
785 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
786 "Warning", MessageBoxButtons.YesNo, MessageBoxIcon.Warning);
\r
787 if (result == DialogResult.Yes)
\r
788 encodeQueue.Add(query, sourcePath, text_destination.Text, (rtf_query.Text != ""));
\r
792 encodeQueue.Add(query, sourcePath, text_destination.Text, (rtf_query.Text != ""));
\r
794 lbl_encode.Text = encodeQueue.Count + " encode(s) pending in the queue";
\r
796 queueWindow.Show();
\r
799 private void btn_showQueue_Click(object sender, EventArgs e)
\r
801 queueWindow.Show();
\r
802 queueWindow.Activate();
\r
804 private void tb_preview_Click(object sender, EventArgs e)
\r
806 if (string.IsNullOrEmpty(sourcePath) || string.IsNullOrEmpty(text_destination.Text))
\r
807 MessageBox.Show("No source or destination selected.", "Warning", MessageBoxButtons.OK, MessageBoxIcon.Warning);
\r
810 if (qtpreview == null)
\r
812 qtpreview = new frmPreview(this);
\r
815 else if (qtpreview.IsDisposed)
\r
817 qtpreview = new frmPreview(this);
\r
821 MessageBox.Show(qtpreview, "The preview window is already open!", "Warning", MessageBoxButtons.OK, MessageBoxIcon.Warning);
\r
824 private void btn_ActivityWindow_Click(object sender, EventArgs e)
\r
826 if (ActivityWindow == null || !ActivityWindow.IsHandleCreated)
\r
827 ActivityWindow = new frmActivityWindow(lastAction);
\r
829 switch (lastAction)
\r
832 ActivityWindow.SetScanMode();
\r
835 ActivityWindow.SetEncodeMode();
\r
838 ActivityWindow.SetEncodeMode();
\r
842 ActivityWindow.Show();
\r
843 ActivityWindow.Activate();
\r
847 #region System Tray Icon
\r
848 private void frmMain_Resize(object sender, EventArgs e)
\r
850 if (FormWindowState.Minimized == this.WindowState)
\r
852 notifyIcon.Visible = true;
\r
855 else if (FormWindowState.Normal == this.WindowState)
\r
856 notifyIcon.Visible = false;
\r
858 private void notifyIcon_MouseDoubleClick(object sender, MouseEventArgs e)
\r
860 this.Visible = true;
\r
862 this.WindowState = FormWindowState.Normal;
\r
863 notifyIcon.Visible = false;
\r
865 private void btn_restore_Click(object sender, EventArgs e)
\r
867 this.Visible = true;
\r
869 this.WindowState = FormWindowState.Normal;
\r
870 notifyIcon.Visible = false;
\r
874 #region Tab Control
\r
877 private void btn_dvd_source_Click(object sender, EventArgs e)
\r
879 if (DVD_Open.ShowDialog() == DialogResult.OK)
\r
881 this.selectedSourceType = SourceType.Folder;
\r
882 SelectSource(DVD_Open.SelectedPath);
\r
885 UpdateSourceLabel();
\r
887 private void btn_file_source_Click(object sender, EventArgs e)
\r
889 if (ISO_Open.ShowDialog() == DialogResult.OK)
\r
891 this.selectedSourceType = SourceType.VideoFile;
\r
892 SelectSource(ISO_Open.FileName);
\r
895 UpdateSourceLabel();
\r
897 private void mnu_dvd_drive_Click(object sender, EventArgs e)
\r
899 if (this.dvdDrivePath == null) return;
\r
900 this.selectedSourceType = SourceType.DvdDrive;
\r
901 SelectSource(this.dvdDrivePath);
\r
903 private void SelectSource(string file)
\r
905 Check_ChapterMarkers.Enabled = true;
\r
906 lastAction = "scan";
\r
907 sourcePath = string.Empty;
\r
909 if (file == string.Empty) // Must have a file or path
\r
911 UpdateSourceLabel();
\r
915 sourcePath = Path.GetFileName(file);
\r
916 StartScan(file, 0);
\r
918 private void drp_dvdtitle_Click(object sender, EventArgs e)
\r
920 if ((drp_dvdtitle.Items.Count == 1) && (drp_dvdtitle.Items[0].ToString() == "Automatic"))
\r
921 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
923 private void drp_dvdtitle_SelectedIndexChanged(object sender, EventArgs e)
\r
925 UnRegisterPresetEventHandler();
\r
926 drop_mode.SelectedIndex = 0;
\r
928 PictureSettings.lbl_Aspect.Text = "Select a Title"; // Reset some values on the form
\r
929 drop_chapterStart.Items.Clear();
\r
930 drop_chapterFinish.Items.Clear();
\r
932 // If the dropdown is set to automatic nothing else needs to be done.
\r
933 // Otheriwse if its not, title data has to be loased from parsing.
\r
934 if (drp_dvdtitle.Text != "Automatic")
\r
936 selectedTitle = drp_dvdtitle.SelectedItem as Title;
\r
937 lbl_duration.Text = selectedTitle.Duration.ToString();
\r
938 PictureSettings.CurrentlySelectedPreset = CurrentlySelectedPreset;
\r
939 PictureSettings.Source = selectedTitle; // Setup Picture Settings Tab Control
\r
941 // Populate the Angles dropdown
\r
942 drop_angle.Items.Clear();
\r
943 if (!Properties.Settings.Default.noDvdNav)
\r
945 drop_angle.Visible = true;
\r
946 lbl_angle.Visible = true;
\r
947 drop_angle.Items.AddRange(selectedTitle.Angles.ToArray());
\r
948 if (drop_angle.Items.Count != 0)
\r
949 drop_angle.SelectedIndex = 0;
\r
953 drop_angle.Visible = false;
\r
954 lbl_angle.Visible = false;
\r
957 // Populate the Start chapter Dropdown
\r
958 drop_chapterStart.Items.Clear();
\r
959 drop_chapterStart.Items.AddRange(selectedTitle.Chapters.ToArray());
\r
960 if (drop_chapterStart.Items.Count > 0)
\r
961 drop_chapterStart.Text = drop_chapterStart.Items[0].ToString();
\r
963 // Populate the Final Chapter Dropdown
\r
964 drop_chapterFinish.Items.Clear();
\r
965 drop_chapterFinish.Items.AddRange(selectedTitle.Chapters.ToArray());
\r
966 if (drop_chapterFinish.Items.Count > 0)
\r
967 drop_chapterFinish.Text = drop_chapterFinish.Items[drop_chapterFinish.Items.Count - 1].ToString();
\r
969 // Populate the Audio Channels Dropdown
\r
970 AudioSettings.SetTrackList(selectedTitle);
\r
972 // Populate the Subtitles dropdown
\r
973 Subtitles.SetSubtitleTrackAuto(selectedTitle.Subtitles.ToArray());
\r
975 // Update the source label if we have multiple streams
\r
976 if (selectedTitle != null)
\r
977 if (!string.IsNullOrEmpty(selectedTitle.SourceName))
\r
978 labelSource.Text = labelSource.Text = Path.GetFileName(selectedTitle.SourceName);
\r
980 // Run the AutoName & ChapterNaming functions
\r
981 if (Properties.Settings.Default.autoNaming)
\r
983 string autoPath = Main.AutoName(this);
\r
984 if (autoPath != null)
\r
985 text_destination.Text = autoPath;
\r
987 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
990 data_chpt.Rows.Clear();
\r
991 if (selectedTitle.Chapters.Count != 1)
\r
993 DataGridView chapterGridView = Main.ChapterNaming(data_chpt, drop_chapterFinish.Text);
\r
994 if (chapterGridView != null)
\r
995 data_chpt = chapterGridView;
\r
999 Check_ChapterMarkers.Checked = false;
\r
1000 Check_ChapterMarkers.Enabled = false;
\r
1003 // Hack to force the redraw of the scrollbars which don't resize properly when the control is disabled.
\r
1004 data_chpt.Columns[0].Width = 166;
\r
1005 data_chpt.Columns[0].Width = 165;
\r
1007 RegisterPresetEventHandler();
\r
1009 private void chapersChanged(object sender, EventArgs e)
\r
1011 if (drop_mode.SelectedIndex != 0) // Function is not used if we are not in chapters mode.
\r
1014 Control ctl = (Control)sender;
\r
1015 int chapterStart, chapterEnd;
\r
1016 int.TryParse(drop_chapterStart.Text, out chapterStart);
\r
1017 int.TryParse(drop_chapterFinish.Text, out chapterEnd);
\r
1021 case "drop_chapterStart":
\r
1022 if (drop_chapterFinish.SelectedIndex == -1 && drop_chapterFinish.Items.Count != 0)
\r
1023 drop_chapterFinish.SelectedIndex = drop_chapterFinish.Items.Count - 1;
\r
1025 if (chapterEnd != 0)
\r
1026 if (chapterStart > chapterEnd)
\r
1027 drop_chapterFinish.Text = chapterStart.ToString();
\r
1029 case "drop_chapterFinish":
\r
1030 if (drop_chapterStart.Items.Count >= 1 && drop_chapterStart.SelectedIndex == -1)
\r
1031 drop_chapterStart.SelectedIndex = 0;
\r
1033 if (chapterStart != 0)
\r
1034 if (chapterEnd < chapterStart)
\r
1035 drop_chapterFinish.Text = chapterStart.ToString();
\r
1037 // Add more rows to the Chapter menu if needed.
\r
1038 if (Check_ChapterMarkers.Checked)
\r
1040 int i = data_chpt.Rows.Count, finish = 0;
\r
1041 int.TryParse(drop_chapterFinish.Text, out finish);
\r
1043 while (i < finish)
\r
1045 int n = data_chpt.Rows.Add();
\r
1046 data_chpt.Rows[n].Cells[0].Value = (i + 1);
\r
1047 data_chpt.Rows[n].Cells[1].Value = "Chapter " + (i + 1);
\r
1048 data_chpt.Rows[n].Cells[0].ValueType = typeof(int);
\r
1049 data_chpt.Rows[n].Cells[1].ValueType = typeof(string);
\r
1056 // Update the Duration
\r
1057 lbl_duration.Text = Main.CalculateDuration(drop_chapterStart.SelectedIndex, drop_chapterFinish.SelectedIndex, selectedTitle).ToString();
\r
1059 // Run the Autonaming function
\r
1060 if (Properties.Settings.Default.autoNaming)
\r
1061 text_destination.Text = Main.AutoName(this);
\r
1063 // Disable chapter markers if only 1 chapter is selected.
\r
1064 if (chapterStart == chapterEnd)
\r
1066 Check_ChapterMarkers.Enabled = false;
\r
1067 btn_importChapters.Enabled = false;
\r
1068 data_chpt.Enabled = false;
\r
1072 Check_ChapterMarkers.Enabled = true;
\r
1073 if (Check_ChapterMarkers.Checked)
\r
1075 btn_importChapters.Enabled = true;
\r
1076 data_chpt.Enabled = true;
\r
1080 private void SecondsOrFramesChanged(object sender, EventArgs e)
\r
1083 int.TryParse(drop_chapterStart.Text, out start);
\r
1084 int.TryParse(drop_chapterFinish.Text, out end);
\r
1085 double duration = end - start;
\r
1087 switch (drop_mode.SelectedIndex)
\r
1090 lbl_duration.Text = TimeSpan.FromSeconds(duration).ToString();
\r
1093 if (selectedTitle != null)
\r
1095 duration = duration / selectedTitle.Fps;
\r
1096 lbl_duration.Text = TimeSpan.FromSeconds(duration).ToString();
\r
1099 lbl_duration.Text = "--:--:--";
\r
1104 private void drop_mode_SelectedIndexChanged(object sender, EventArgs e)
\r
1107 this.drop_chapterFinish.TextChanged -= new System.EventHandler(this.SecondsOrFramesChanged);
\r
1108 this.drop_chapterStart.TextChanged -= new System.EventHandler(this.SecondsOrFramesChanged);
\r
1111 switch (drop_mode.SelectedIndex)
\r
1114 drop_chapterStart.DropDownStyle = ComboBoxStyle.DropDownList;
\r
1115 drop_chapterFinish.DropDownStyle = ComboBoxStyle.DropDownList;
\r
1116 if (drop_chapterStart.Items.Count != 0)
\r
1118 drop_chapterStart.SelectedIndex = 0;
\r
1119 drop_chapterFinish.SelectedIndex = drop_chapterFinish.Items.Count - 1;
\r
1122 lbl_duration.Text = "--:--:--";
\r
1125 this.drop_chapterStart.TextChanged += new System.EventHandler(this.SecondsOrFramesChanged);
\r
1126 this.drop_chapterFinish.TextChanged += new System.EventHandler(this.SecondsOrFramesChanged);
\r
1127 drop_chapterStart.DropDownStyle = ComboBoxStyle.Simple;
\r
1128 drop_chapterFinish.DropDownStyle = ComboBoxStyle.Simple;
\r
1129 if (selectedTitle != null)
\r
1131 drop_chapterStart.Text = "0";
\r
1132 drop_chapterFinish.Text = selectedTitle.Duration.TotalSeconds.ToString();
\r
1136 this.drop_chapterStart.TextChanged += new System.EventHandler(this.SecondsOrFramesChanged);
\r
1137 this.drop_chapterFinish.TextChanged += new System.EventHandler(this.SecondsOrFramesChanged);
\r
1138 drop_chapterStart.DropDownStyle = ComboBoxStyle.Simple;
\r
1139 drop_chapterFinish.DropDownStyle = ComboBoxStyle.Simple;
\r
1140 if (selectedTitle != null)
\r
1142 drop_chapterStart.Text = "0";
\r
1143 drop_chapterFinish.Text = (selectedTitle.Fps * selectedTitle.Duration.TotalSeconds).ToString();
\r
1150 private void btn_destBrowse_Click(object sender, EventArgs e)
\r
1152 // This removes the file extension from the filename box on the save file dialog.
\r
1153 // It's daft but some users don't realise that typing an extension overrides the dropdown extension selected.
\r
1154 DVD_Save.FileName = Path.GetFileNameWithoutExtension(text_destination.Text);
\r
1156 if (Path.IsPathRooted(text_destination.Text))
\r
1157 DVD_Save.InitialDirectory = Path.GetDirectoryName(text_destination.Text);
\r
1159 // Show the dialog and set the main form file path
\r
1160 if (drop_format.SelectedIndex.Equals(0))
\r
1161 DVD_Save.FilterIndex = 1;
\r
1162 else if (drop_format.SelectedIndex.Equals(1))
\r
1163 DVD_Save.FilterIndex = 2;
\r
1165 if (DVD_Save.ShowDialog() == DialogResult.OK)
\r
1167 // Add a file extension manually, as FileDialog.AddExtension has issues with dots in filenames
\r
1168 switch (DVD_Save.FilterIndex)
\r
1171 if (!Path.GetExtension(DVD_Save.FileName).Equals(".mp4", StringComparison.InvariantCultureIgnoreCase))
\r
1172 if (Properties.Settings.Default.useM4v)
\r
1173 DVD_Save.FileName = DVD_Save.FileName.Replace(".mp4", ".m4v").Replace(".mkv", ".m4v");
\r
1175 DVD_Save.FileName = DVD_Save.FileName.Replace(".m4v", ".mp4").Replace(".mkv", ".mp4");
\r
1178 if (!Path.GetExtension(DVD_Save.FileName).Equals(".mkv", StringComparison.InvariantCultureIgnoreCase))
\r
1179 DVD_Save.FileName = DVD_Save.FileName.Replace(".mp4", ".mkv").Replace(".m4v", ".mkv");
\r
1185 text_destination.Text = DVD_Save.FileName;
\r
1187 // Quicktime requires .m4v file for chapter markers to work. If checked, change the extension to .m4v (mp4 and m4v are the same thing)
\r
1188 if (Check_ChapterMarkers.Checked && DVD_Save.FilterIndex != 2)
\r
1189 SetExtension(".m4v");
\r
1192 private void text_destination_TextChanged(object sender, EventArgs e)
\r
1194 string path = text_destination.Text;
\r
1195 if (path.EndsWith(".mp4") || path.EndsWith(".m4v"))
\r
1196 drop_format.SelectedIndex = 0;
\r
1197 else if (path.EndsWith(".mkv"))
\r
1198 drop_format.SelectedIndex = 1;
\r
1201 // Output Settings
\r
1202 private void drop_format_SelectedIndexChanged(object sender, EventArgs e)
\r
1204 switch (drop_format.SelectedIndex)
\r
1207 if (Properties.Settings.Default.useM4v || Check_ChapterMarkers.Checked || AudioSettings.RequiresM4V() || Subtitles.RequiresM4V())
\r
1208 SetExtension(".m4v");
\r
1210 SetExtension(".mp4");
\r
1213 SetExtension(".mkv");
\r
1217 AudioSettings.SetContainer(drop_format.Text);
\r
1218 Subtitles.SetContainer(drop_format.SelectedIndex);
\r
1220 if (drop_format.Text.Contains("MP4"))
\r
1222 if (drp_videoEncoder.Items.Contains("VP3 (Theora)"))
\r
1224 drp_videoEncoder.Items.Remove("VP3 (Theora)");
\r
1225 drp_videoEncoder.SelectedIndex = 1;
\r
1228 else if (drop_format.Text.Contains("MKV"))
\r
1229 drp_videoEncoder.Items.Add("VP3 (Theora)");
\r
1231 public void SetExtension(string newExtension)
\r
1233 if (newExtension == ".mp4" || newExtension == ".m4v")
\r
1234 if (Properties.Settings.Default.useM4v || Check_ChapterMarkers.Checked || AudioSettings.RequiresM4V() || Subtitles.RequiresM4V())
\r
1235 newExtension = ".m4v";
\r
1237 newExtension = ".mp4";
\r
1239 if (Path.HasExtension(newExtension))
\r
1240 text_destination.Text = Path.ChangeExtension(text_destination.Text, newExtension);
\r
1244 private void drp_videoEncoder_SelectedIndexChanged(object sender, EventArgs e)
\r
1246 setContainerOpts();
\r
1248 //Turn off some options which are H.264 only when the user selects a non h.264 encoder
\r
1249 if (drp_videoEncoder.Text.Contains("H.264"))
\r
1251 if (check_2PassEncode.CheckState == CheckState.Checked)
\r
1252 check_turbo.Enabled = true;
\r
1254 tab_advanced.Enabled = true;
\r
1255 if ((drop_format.Text.Contains("MP4")) || (drop_format.Text.Contains("M4V")))
\r
1256 check_iPodAtom.Enabled = true;
\r
1258 check_iPodAtom.Enabled = false;
\r
1262 check_turbo.CheckState = CheckState.Unchecked;
\r
1263 check_turbo.Enabled = false;
\r
1264 tab_advanced.Enabled = false;
\r
1265 x264Panel.x264Query = "";
\r
1266 check_iPodAtom.Enabled = false;
\r
1267 check_iPodAtom.Checked = false;
\r
1270 // Setup the CQ Slider
\r
1271 switch (drp_videoEncoder.Text)
\r
1273 case "MPEG-4 (FFmpeg)":
\r
1274 if (slider_videoQuality.Value > 31)
\r
1275 slider_videoQuality.Value = 20; // Just reset to 70% QP 10 on encode change.
\r
1276 slider_videoQuality.Minimum = 1;
\r
1277 slider_videoQuality.Maximum = 31;
\r
1279 case "H.264 (x264)":
\r
1280 slider_videoQuality.Minimum = 0;
\r
1281 slider_videoQuality.TickFrequency = 1;
\r
1283 CultureInfo culture = CultureInfo.CreateSpecificCulture("en-US");
\r
1284 double cqStep = Properties.Settings.Default.x264cqstep;
\r
1285 double multiplier = 1.0 / cqStep;
\r
1286 double value = slider_videoQuality.Value * multiplier;
\r
1288 switch (Properties.Settings.Default.x264cqstep.ToString(culture))
\r
1291 slider_videoQuality.Maximum = 255;
\r
1294 slider_videoQuality.Maximum = 204;
\r
1297 slider_videoQuality.Maximum = 102;
\r
1300 slider_videoQuality.Maximum = 51;
\r
1303 slider_videoQuality.Maximum = 51;
\r
1306 if (value < slider_videoQuality.Maximum)
\r
1307 slider_videoQuality.Value = slider_videoQuality.Maximum - (int)value;
\r
1310 case "VP3 (Theora)":
\r
1311 if (slider_videoQuality.Value > 63)
\r
1312 slider_videoQuality.Value = 45; // Just reset to 70% QP 45 on encode change.
\r
1313 slider_videoQuality.Minimum = 0;
\r
1314 slider_videoQuality.Maximum = 63;
\r
1319 /// Set the container format options
\r
1321 public void setContainerOpts()
\r
1323 if ((drop_format.Text.Contains("MP4")) || (drop_format.Text.Contains("M4V")))
\r
1325 check_largeFile.Enabled = true;
\r
1326 check_optimiseMP4.Enabled = true;
\r
1327 check_iPodAtom.Enabled = true;
\r
1331 check_largeFile.Enabled = false;
\r
1332 check_optimiseMP4.Enabled = false;
\r
1333 check_iPodAtom.Enabled = false;
\r
1334 check_largeFile.Checked = false;
\r
1335 check_optimiseMP4.Checked = false;
\r
1336 check_iPodAtom.Checked = false;
\r
1339 private double _cachedCqStep = Properties.Settings.Default.x264cqstep;
\r
1341 /// Update the CQ slider for x264 for a new CQ step. This is set from option
\r
1343 public void setQualityFromSlider()
\r
1345 // Work out the current RF value.
\r
1346 double cqStep = _cachedCqStep;
\r
1347 double rfValue = 51.0 - slider_videoQuality.Value * cqStep;
\r
1349 // Change the maximum value for the slider
\r
1350 switch (Properties.Settings.Default.x264cqstep.ToString(new CultureInfo("en-US")))
\r
1353 slider_videoQuality.Maximum = 255;
\r
1356 slider_videoQuality.Maximum = 204;
\r
1359 slider_videoQuality.Maximum = 102;
\r
1362 slider_videoQuality.Maximum = 51;
\r
1365 slider_videoQuality.Maximum = 51;
\r
1369 // Reset the CQ slider to RF0
\r
1370 slider_videoQuality.Value = slider_videoQuality.Maximum;
\r
1372 // Reset the CQ slider back to the previous value as close as possible
\r
1373 double cqStepNew = Properties.Settings.Default.x264cqstep;
\r
1374 double rfValueCurrent = 51.0 - slider_videoQuality.Value * cqStepNew;
\r
1375 while (rfValueCurrent < rfValue)
\r
1377 slider_videoQuality.Value--;
\r
1378 rfValueCurrent = 51.0 - slider_videoQuality.Value * cqStepNew;
\r
1381 // Cache the CQ step for the next calculation
\r
1382 _cachedCqStep = Properties.Settings.Default.x264cqstep;
\r
1384 private void slider_videoQuality_Scroll(object sender, EventArgs e)
\r
1386 double cqStep = Properties.Settings.Default.x264cqstep;
\r
1387 switch (drp_videoEncoder.Text)
\r
1389 case "MPEG-4 (FFmpeg)":
\r
1390 double rfValue = 31 - (slider_videoQuality.Value - 1);
\r
1391 double max = slider_videoQuality.Maximum;
\r
1392 double min = slider_videoQuality.Minimum;
\r
1393 double val = ((max - min) - (rfValue - min)) / (max - min);
\r
1394 lbl_SliderValue.Text = "QP:" + (32 - slider_videoQuality.Value);
\r
1395 lbl_qualityValue.Text = Math.Round((val * 100), 2).ToString(new CultureInfo("en-US")) + "%";
\r
1397 case "H.264 (x264)":
\r
1398 rfValue = 51.0 - slider_videoQuality.Value * cqStep;
\r
1399 max = slider_videoQuality.Maximum * cqStep;
\r
1400 min = slider_videoQuality.Minimum;
\r
1401 val = ((max - min) - (rfValue - min)) / (max - min);
\r
1402 rfValue = Math.Round(rfValue, 2);
\r
1403 lbl_SliderValue.Text = "RF:" + rfValue.ToString(new CultureInfo("en-US"));
\r
1404 lbl_qualityValue.Text = Math.Round((val * 100), 2).ToString(new CultureInfo("en-US")) + "%";
\r
1406 case "VP3 (Theora)":
\r
1407 rfValue = slider_videoQuality.Value;
\r
1408 double value = rfValue / 63;
\r
1409 lbl_SliderValue.Text = "QP:" + slider_videoQuality.Value;
\r
1410 lbl_qualityValue.Text = Math.Round((value * 100), 2).ToString(new CultureInfo("en-US")) + "%";
\r
1414 private void radio_targetFilesize_CheckedChanged(object sender, EventArgs e)
\r
1416 text_bitrate.Enabled = false;
\r
1417 text_filesize.Enabled = true;
\r
1418 slider_videoQuality.Enabled = false;
\r
1420 check_2PassEncode.Enabled = true;
\r
1422 private void radio_avgBitrate_CheckedChanged(object sender, EventArgs e)
\r
1424 text_bitrate.Enabled = true;
\r
1425 text_filesize.Enabled = false;
\r
1426 slider_videoQuality.Enabled = false;
\r
1428 check_2PassEncode.Enabled = true;
\r
1430 private void radio_cq_CheckedChanged(object sender, EventArgs e)
\r
1432 text_bitrate.Enabled = false;
\r
1433 text_filesize.Enabled = false;
\r
1434 slider_videoQuality.Enabled = true;
\r
1436 check_2PassEncode.Enabled = false;
\r
1437 check_2PassEncode.CheckState = CheckState.Unchecked;
\r
1439 private void check_2PassEncode_CheckedChanged(object sender, EventArgs e)
\r
1441 if (check_2PassEncode.CheckState.ToString() == "Checked")
\r
1443 if (drp_videoEncoder.Text.Contains("H.264"))
\r
1444 check_turbo.Enabled = true;
\r
1448 check_turbo.Enabled = false;
\r
1449 check_turbo.CheckState = CheckState.Unchecked;
\r
1453 // Chapter Marker Tab
\r
1454 private void Check_ChapterMarkers_CheckedChanged(object sender, EventArgs e)
\r
1456 if (Check_ChapterMarkers.Checked)
\r
1458 if (drop_format.SelectedIndex != 1)
\r
1459 SetExtension(".m4v");
\r
1460 data_chpt.Enabled = true;
\r
1461 btn_importChapters.Enabled = true;
\r
1465 if (drop_format.SelectedIndex != 1 && !Properties.Settings.Default.useM4v)
\r
1466 SetExtension(".mp4");
\r
1467 data_chpt.Enabled = false;
\r
1468 btn_importChapters.Enabled = false;
\r
1471 private void btn_importChapters_Click(object sender, EventArgs e)
\r
1473 if (File_ChapterImport.ShowDialog() == DialogResult.OK)
\r
1475 String filename = File_ChapterImport.FileName;
\r
1476 DataGridView imported = Main.ImportChapterNames(data_chpt, filename);
\r
1477 if (imported != null)
\r
1478 data_chpt = imported;
\r
1481 private void mnu_resetChapters_Click(object sender, EventArgs e)
\r
1483 data_chpt.Rows.Clear();
\r
1484 DataGridView chapterGridView = Main.ChapterNaming(data_chpt, drop_chapterFinish.Text);
\r
1485 if (chapterGridView != null)
\r
1487 data_chpt = chapterGridView;
\r
1491 // Query Editor Tab
\r
1492 private void btn_generate_Query_Click(object sender, EventArgs e)
\r
1494 rtf_query.Text = QueryGenerator.GenerateCLIQuery(this, drop_mode.SelectedIndex, 0, null);
\r
1496 private void btn_clear_Click(object sender, EventArgs e)
\r
1498 rtf_query.Clear();
\r
1502 // MainWindow Components, Actions and Functions ***********************
\r
1504 #region Source Scan
\r
1505 public Boolean isScanning { get; set; }
\r
1506 private Scan SourceScan;
\r
1508 private void StartScan(String filename, int title)
\r
1510 // Setup the GUI components for the scan.
\r
1511 sourcePath = filename;
\r
1512 foreach (Control ctrl in Controls)
\r
1513 if (!(ctrl is StatusStrip || ctrl is MenuStrip || ctrl is ToolStrip))
\r
1514 ctrl.Enabled = false;
\r
1516 lbl_encode.Visible = true;
\r
1517 lbl_encode.Text = "Scanning ...";
\r
1518 btn_source.Enabled = false;
\r
1519 btn_start.Enabled = false;
\r
1520 btn_showQueue.Enabled = false;
\r
1521 btn_add2Queue.Enabled = false;
\r
1522 tb_preview.Enabled = false;
\r
1523 mnu_killCLI.Visible = true;
\r
1525 if (ActivityWindow != null)
\r
1526 ActivityWindow.SetScanMode();
\r
1531 isScanning = true;
\r
1532 SourceScan = new Scan();
\r
1533 SourceScan.ScanSource(sourcePath, title);
\r
1534 SourceScan.ScanStatusChanged += new EventHandler(SourceScan_ScanStatusChanged);
\r
1535 SourceScan.ScanCompleted += new EventHandler(SourceScan_ScanCompleted);
\r
1537 catch (Exception exc)
\r
1539 MessageBox.Show("frmMain.cs - StartScan " + exc, "Error", MessageBoxButtons.OK, MessageBoxIcon.Error);
\r
1543 void SourceScan_ScanStatusChanged(object sender, EventArgs e)
\r
1545 UpdateScanStatusLabel();
\r
1547 void SourceScan_ScanCompleted(object sender, EventArgs e)
\r
1549 UpdateGuiAfterScan();
\r
1552 private void UpdateScanStatusLabel()
\r
1554 if (InvokeRequired)
\r
1556 BeginInvoke(new UpdateWindowHandler(UpdateScanStatusLabel));
\r
1559 lbl_encode.Text = SourceScan.ScanStatus();
\r
1561 private void UpdateGuiAfterScan()
\r
1563 if (InvokeRequired)
\r
1565 BeginInvoke(new UpdateWindowHandler(UpdateGuiAfterScan));
\r
1571 currentSource = SourceScan.SouceData();
\r
1573 // Setup some GUI components
\r
1574 drp_dvdtitle.Items.Clear();
\r
1575 if (currentSource.Titles.Count != 0)
\r
1576 drp_dvdtitle.Items.AddRange(currentSource.Titles.ToArray());
\r
1578 // Now select the longest title
\r
1579 if (currentSource.Titles.Count != 0)
\r
1580 drp_dvdtitle.SelectedItem = Main.SelectLongestTitle(currentSource);
\r
1582 // Enable the creation of chapter markers if the file is an image of a dvd.
\r
1583 if (sourcePath.ToLower().Contains(".iso") || sourcePath.Contains("VIDEO_TS") || Directory.Exists(Path.Combine(sourcePath, "VIDEO_TS")))
\r
1584 Check_ChapterMarkers.Enabled = true;
\r
1587 Check_ChapterMarkers.Enabled = false;
\r
1588 Check_ChapterMarkers.Checked = false;
\r
1589 data_chpt.Rows.Clear();
\r
1592 // If no titles were found, Display an error message
\r
1593 if (drp_dvdtitle.Items.Count == 0)
\r
1596 "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
1597 "Error", MessageBoxButtons.OK, MessageBoxIcon.Hand);
\r
1598 sourcePath = string.Empty;
\r
1600 UpdateSourceLabel();
\r
1602 // Enable the GUI components and enable any disabled components
\r
1605 catch (Exception exc)
\r
1607 MessageBox.Show("frmMain.cs - updateUIafterScan " + exc, "Error", MessageBoxButtons.OK, MessageBoxIcon.Error);
\r
1612 private void EnableGUI()
\r
1616 if (InvokeRequired)
\r
1617 BeginInvoke(new UpdateWindowHandler(EnableGUI));
\r
1618 lbl_encode.Text = "Scan Completed";
\r
1619 foreach (Control ctrl in Controls)
\r
1620 ctrl.Enabled = true;
\r
1621 btn_start.Enabled = true;
\r
1622 btn_showQueue.Enabled = true;
\r
1623 btn_add2Queue.Enabled = true;
\r
1624 tb_preview.Enabled = true;
\r
1625 btn_source.Enabled = true;
\r
1626 mnu_killCLI.Visible = false;
\r
1628 catch (Exception exc)
\r
1630 MessageBox.Show("frmMain.cs - EnableGUI() " + exc, "Error", MessageBoxButtons.OK, MessageBoxIcon.Error);
\r
1633 private void KillScan()
\r
1637 SourceScan.ScanCompleted -= new EventHandler(SourceScan_ScanCompleted);
\r
1641 if (SourceScan.ScanProcess() != null)
\r
1642 SourceScan.ScanProcess().Kill();
\r
1644 lbl_encode.Text = "Scan Cancelled!";
\r
1646 catch (Exception ex)
\r
1648 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
1651 private void ResetGUI()
\r
1653 drp_dvdtitle.Items.Clear();
\r
1654 drop_chapterStart.Items.Clear();
\r
1655 drop_chapterFinish.Items.Clear();
\r
1656 lbl_duration.Text = "Select a Title";
\r
1657 PictureSettings.lbl_src_res.Text = "Select a Title";
\r
1658 PictureSettings.lbl_Aspect.Text = "Select a Title";
\r
1659 sourcePath = String.Empty;
\r
1660 text_destination.Text = String.Empty;
\r
1661 selectedTitle = null;
\r
1662 isScanning = false;
\r
1664 private void UpdateSourceLabel()
\r
1666 labelSource.Text = string.IsNullOrEmpty(sourcePath) ? "Select \"Source\" to continue." : this.SourceName;
\r
1668 if (selectedTitle != null)
\r
1669 if (!string.IsNullOrEmpty(selectedTitle.SourceName)) // If it's one of multiple source files, make sure we don't use the folder name
\r
1670 labelSource.Text = Path.GetFileName(selectedTitle.SourceName);
\r
1673 public void RecievingJob(Job job)
\r
1675 string query = job.Query;
\r
1676 StartScan(job.Source, 0);
\r
1679 if (query != null)
\r
1681 //Ok, Reset all the H264 widgets before changing the preset
\r
1682 x264Panel.reset2Defaults();
\r
1684 // Send the query from the file to the Query Parser class
\r
1685 QueryParser presetQuery = QueryParser.Parse(query);
\r
1687 // Now load the preset
\r
1688 PresetLoader.LoadPreset(this, presetQuery, "Load Back From Queue", true);
\r
1690 // The x264 widgets will need updated, so do this now:
\r
1691 x264Panel.X264_StandardizeOptString();
\r
1692 x264Panel.X264_SetCurrentSettingsInPanel();
\r
1694 // Finally, let this window have a copy of the preset settings.
\r
1695 CurrentlySelectedPreset = null;
\r
1696 PictureSettings.SetPresetCropWarningLabel(null);
\r
1702 #region GUI Functions and Actions
\r
1704 /// Set the GUI to it's finished encoding state.
\r
1706 private void SetEncodeFinished()
\r
1710 if (InvokeRequired)
\r
1712 BeginInvoke(new UpdateWindowHandler(SetEncodeFinished));
\r
1716 lbl_encode.Text = "Encoding Finished";
\r
1717 btn_start.Text = "Start";
\r
1718 btn_start.ToolTipText = "Start the encoding process";
\r
1719 btn_start.Image = Properties.Resources.Play;
\r
1721 // If the window is minimized, display the notification in a popup.
\r
1722 if (Properties.Settings.Default.trayIconAlerts)
\r
1723 if (FormWindowState.Minimized == this.WindowState)
\r
1725 notifyIcon.BalloonTipText = lbl_encode.Text;
\r
1726 notifyIcon.ShowBalloonTip(500);
\r
1729 catch (Exception exc)
\r
1731 MessageBox.Show(exc.ToString());
\r
1736 /// Set the GUI to it's started encoding state.
\r
1738 private void SetEncodeStarted()
\r
1742 if (InvokeRequired)
\r
1744 BeginInvoke(new UpdateWindowHandler(SetEncodeStarted));
\r
1748 lbl_encode.Visible = true;
\r
1749 lbl_encode.Text = "Encoding with " + encodeQueue.Count + " encode(s) pending";
\r
1750 btn_start.Text = "Stop";
\r
1751 btn_start.ToolTipText = "Stop the encoding process.";
\r
1752 btn_start.Image = Properties.Resources.stop;
\r
1754 catch (Exception exc)
\r
1756 MessageBox.Show(exc.ToString());
\r
1761 /// Set the DVD Drive selection in the "Source" Menu
\r
1763 private void SetDriveSelectionMenuItem()
\r
1767 if (InvokeRequired)
\r
1769 BeginInvoke(new UpdateWindowHandler(SetDriveSelectionMenuItem));
\r
1773 List<DriveInformation> drives = Main.GetDrives();
\r
1775 if (drives.Count == 0)
\r
1777 mnu_dvd_drive.Text = "[No DVD Drive Ready]";
\r
1781 this.dvdDrivePath = drives[0].RootDirectory + "VIDEO_TS";
\r
1782 this.dvdDriveLabel = drives[0].VolumeLabel;
\r
1783 mnu_dvd_drive.Text = this.dvdDrivePath + " (" + this.dvdDriveLabel + ")";
\r
1787 mnu_dvd_drive.Text = "[No DVD Drive Ready / Found]";
\r
1792 /// Access the preset Handler and setup the preset panel.
\r
1794 private void LoadPresetPanel()
\r
1796 if (presetHandler.CheckIfPresetsAreOutOfDate())
\r
1797 if (!Properties.Settings.Default.presetNotification)
\r
1798 MessageBox.Show(splash,
\r
1799 "HandBrake has determined your built-in presets are out of date... These presets will now be updated.",
\r
1800 "Preset Update", MessageBoxButtons.OK, MessageBoxIcon.Information);
\r
1802 presetHandler.GetPresetPanel(ref treeView_presets);
\r
1803 treeView_presets.Update();
\r
1810 /// Handle GUI shortcuts
\r
1812 /// <param name="msg"></param>
\r
1813 /// <param name="keyData"></param>
\r
1814 /// <returns></returns>
\r
1815 protected override bool ProcessCmdKey(ref Message msg, Keys keyData)
\r
1817 if (keyData == (Keys.Control | Keys.S))
\r
1819 btn_start_Click(this, new EventArgs());
\r
1823 if (keyData == (Keys.Control | Keys.A))
\r
1825 btn_add2Queue_Click(this, new EventArgs());
\r
1828 return base.ProcessCmdKey(ref msg, keyData);
\r
1832 /// If the queue is being processed, prompt the user to confirm application close.
\r
1834 /// <param name="e"></param>
\r
1835 protected override void OnFormClosing(FormClosingEventArgs e)
\r
1837 // If currently encoding, the queue isn't paused, and there are queue items to process, prompt to confirm close.
\r
1838 if ((encodeQueue.IsEncoding) && (!encodeQueue.PauseRequested) && (encodeQueue.Count > 0))
\r
1840 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
1841 "Close HandBrake?", MessageBoxButtons.YesNo, MessageBoxIcon.Question);
\r
1842 if (result == DialogResult.No)
\r
1845 base.OnFormClosing(e);
\r
1849 #region In-GUI Encode Status (Experimental)
\r
1851 /// Starts a new thread to monitor and process the CLI encode status
\r
1853 private void EncodeMonitorThread()
\r
1857 Parser encode = new Parser(encodeQueue.HbProcess.StandardOutput.BaseStream);
\r
1858 encode.OnEncodeProgress += EncodeOnEncodeProgress;
\r
1859 while (!encode.EndOfStream)
\r
1860 encode.readEncodeStatus();
\r
1862 catch (Exception exc)
\r
1864 MessageBox.Show(exc.ToString(), "Error", MessageBoxButtons.OK, MessageBoxIcon.Error);
\r
1869 /// Displays the Encode status in the GUI
\r
1871 /// <param name="Sender"></param>
\r
1872 /// <param name="CurrentTask"></param>
\r
1873 /// <param name="TaskCount"></param>
\r
1874 /// <param name="PercentComplete"></param>
\r
1875 /// <param name="CurrentFps"></param>
\r
1876 /// <param name="AverageFps"></param>
\r
1877 /// <param name="TimeRemaining"></param>
\r
1878 private void EncodeOnEncodeProgress(object Sender, int CurrentTask, int TaskCount, float PercentComplete, float CurrentFps, float AverageFps, TimeSpan TimeRemaining)
\r
1880 if (this.InvokeRequired)
\r
1882 this.BeginInvoke(new EncodeProgressEventHandler(EncodeOnEncodeProgress),
\r
1883 new object[] { Sender, CurrentTask, TaskCount, PercentComplete, CurrentFps, AverageFps, TimeRemaining });
\r
1886 lbl_encode.Text = string.Format("Encode Progress: {0}%, FPS: {1}, Avg FPS: {2}, Time Remaining: {3} ", PercentComplete, CurrentFps, AverageFps, TimeRemaining);
\r
1890 // This is the END of the road ****************************************
\r