3 This file is part of the HandBrake source code.
\r
4 Homepage: <http://handbrake.fr/>.
\r
5 It may be used under the terms of the GNU General Public License. */
\r
8 using System.Collections.Generic;
\r
9 using System.Drawing;
\r
10 using System.Globalization;
\r
11 using System.Windows.Forms;
\r
13 using System.Diagnostics;
\r
14 using System.Threading;
\r
15 using Handbrake.EncodeQueue;
\r
16 using Handbrake.Functions;
\r
17 using Handbrake.Presets;
\r
18 using Handbrake.Parsing;
\r
22 public partial class frmMain : Form
\r
24 // Objects which may be used by one or more other objects *************
\r
25 EncodeAndQueueHandler encodeQueue = new EncodeAndQueueHandler();
\r
26 PresetsHandler presetHandler = new PresetsHandler();
\r
27 QueryGenerator queryGen = new QueryGenerator();
\r
29 // Globals: Mainly used for tracking. *********************************
\r
30 public Title selectedTitle;
\r
31 private 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
41 // Delegates **********************************************************
\r
42 private delegate void UpdateWindowHandler();
\r
44 // Applicaiton Startup ************************************************
\r
46 #region Application Startup
\r
49 // Load and setup the splash screen in this thread
\r
50 splash = new frmSplashScreen();
\r
52 Label lblStatus = new Label { Size = new Size(150, 20), Location = new Point(182, 102) };
\r
53 splash.Controls.Add(lblStatus);
\r
55 InitializeComponent();
\r
57 // Update the users config file with the CLI version data.
\r
58 lblStatus.Text = "Setting Version Data ...";
\r
59 Application.DoEvents();
\r
60 Main.setCliVersionData();
\r
62 // Show the form, but leave disabled until preloading is complete then show the main form
\r
63 this.Enabled = false;
\r
65 Application.DoEvents(); // Forces frmMain to draw
\r
67 // Check for new versions, if update checking is enabled
\r
68 if (Properties.Settings.Default.updateStatus)
\r
70 DateTime now = DateTime.Now;
\r
71 DateTime lastCheck = Properties.Settings.Default.lastUpdateCheckDate;
\r
72 TimeSpan elapsed = now.Subtract(lastCheck);
\r
73 if (elapsed.TotalDays > Properties.Settings.Default.daysBetweenUpdateCheck)
\r
75 lblStatus.Text = "Checking for updates ...";
\r
76 Application.DoEvents();
\r
78 Main.BeginCheckForUpdates(new AsyncCallback(UpdateCheckDone), false);
\r
82 // Setup the GUI components
\r
83 lblStatus.Text = "Setting up the GUI ...";
\r
84 Application.DoEvents();
\r
85 loadPresetPanel(); // Load the Preset Panel
\r
86 treeView_presets.ExpandAll();
\r
87 lbl_encode.Text = "";
\r
88 queueWindow = new frmQueue(encodeQueue); // Prepare the Queue
\r
89 if (!Properties.Settings.Default.QueryEditorTab)
\r
90 tabs_panel.TabPages.RemoveAt(7); // Remove the query editor tab if the user does not want it enabled.
\r
92 // Load the user's default settings or Normal Preset
\r
93 if (Properties.Settings.Default.defaultPreset != "")
\r
95 if (presetHandler.GetPreset(Properties.Settings.Default.defaultPreset) != null)
\r
97 string query = presetHandler.GetPreset(Properties.Settings.Default.defaultPreset).Query;
\r
98 Boolean loadPictureSettings = presetHandler.GetPreset(Properties.Settings.Default.defaultPreset).PictureSettings;
\r
102 //Ok, Reset all the H264 widgets before changing the preset
\r
103 x264Panel.reset2Defaults();
\r
105 // Send the query from the file to the Query Parser class, then load the preset
\r
106 QueryParser presetQuery = QueryParser.Parse(query);
\r
107 PresetLoader.presetLoader(this, presetQuery, Properties.Settings.Default.defaultPreset, loadPictureSettings);
\r
109 // The x264 widgets will need updated, so do this now:
\r
110 x264Panel.X264_StandardizeOptString();
\r
111 x264Panel.X264_SetCurrentSettingsInPanel();
\r
115 loadNormalPreset();
\r
118 loadNormalPreset();
\r
120 // Enabled GUI tooltip's if Required
\r
121 if (Properties.Settings.Default.tooltipEnable)
\r
122 ToolTip.Active = true;
\r
124 // Register with Growl (if not using Growl for the encoding completion action, this wont hurt anything)
\r
125 GrowlCommunicator.Register();
\r
128 lblStatus.Text = "Loading Complete!";
\r
129 Application.DoEvents();
\r
132 this.Enabled = true;
\r
134 // Event Handlers and Queue Recovery
\r
139 private void UpdateCheckDone(IAsyncResult result)
\r
141 if (InvokeRequired)
\r
143 Invoke(new MethodInvoker(() => UpdateCheckDone(result)));
\r
147 UpdateCheckInformation info;
\r
151 info = Main.EndCheckForUpdates(result);
\r
153 if (info.NewVersionAvailable)
\r
155 frmUpdater updateWindow = new frmUpdater(info.BuildInformation);
\r
156 updateWindow.ShowDialog();
\r
159 catch (Exception ex)
\r
161 if ((bool)result.AsyncState)
\r
162 MessageBox.Show("Unable to check for updates, Please try again later.\n\nDetailed Error Information:\n" + ex, "Error", MessageBoxButtons.OK, MessageBoxIcon.Error);
\r
166 // Startup Functions
\r
167 private void queueRecovery()
\r
169 if (Main.checkQueueRecovery())
\r
171 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
173 if (result == DialogResult.Yes)
\r
174 encodeQueue.LoadQueueFromFile("hb_queue_recovery.xml"); // Start Recovery
\r
177 // Remove the Queue recovery file if the user doesn't want to recovery the last queue.
\r
178 string queuePath = Path.Combine(Path.GetTempPath(), "hb_queue_recovery.xml");
\r
179 if (File.Exists(queuePath))
\r
180 File.Delete(queuePath);
\r
187 public string SourceName
\r
191 if (this.selectedSourceType == SourceType.DvdDrive)
\r
193 return this.dvdDriveLabel;
\r
196 if(Path.GetFileNameWithoutExtension(this.sourcePath) != "VIDEO_TS")
\r
197 return Path.GetFileNameWithoutExtension(this.sourcePath);
\r
199 return Path.GetFileNameWithoutExtension(Path.GetDirectoryName(this.sourcePath));
\r
205 // Encoding Events for setting up the GUI
\r
206 private void events()
\r
208 // Handle Widget changes when preset is selected.
\r
209 RegisterPresetEventHandler();
\r
211 // Handle Window Resize
\r
212 if (Properties.Settings.Default.MainWindowMinimize)
\r
213 this.Resize += new EventHandler(frmMain_Resize);
\r
215 // Handle Encode Start / Finish / Pause
\r
216 encodeQueue.CurrentJobCompleted += new EventHandler(encodeEnded);
\r
217 encodeQueue.QueuePauseRequested += new EventHandler(encodePaused);
\r
218 encodeQueue.NewJobStarted += new EventHandler(encodeStarted);
\r
220 // Handle a file being draged onto the GUI.
\r
221 this.DragEnter += new DragEventHandler(frmMain_DragEnter);
\r
222 this.DragDrop += new DragEventHandler(frmMain_DragDrop);
\r
225 // 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
226 private void RegisterPresetEventHandler()
\r
229 drop_format.SelectedIndexChanged += new EventHandler(changePresetLabel);
\r
230 check_largeFile.CheckedChanged += new EventHandler(changePresetLabel);
\r
231 check_iPodAtom.CheckedChanged += new EventHandler(changePresetLabel);
\r
232 check_optimiseMP4.CheckedChanged += new EventHandler(changePresetLabel);
\r
234 // Picture Settings
\r
235 //PictureSettings.PictureSettingsChanged += new EventHandler(changePresetLabel);
\r
238 Filters.FilterSettingsChanged += new EventHandler(changePresetLabel);
\r
241 drp_videoEncoder.SelectedIndexChanged += new EventHandler(changePresetLabel);
\r
242 check_2PassEncode.CheckedChanged += new EventHandler(changePresetLabel);
\r
243 check_turbo.CheckedChanged += new EventHandler(changePresetLabel);
\r
244 text_filesize.TextChanged += new EventHandler(changePresetLabel);
\r
245 text_bitrate.TextChanged += new EventHandler(changePresetLabel);
\r
246 slider_videoQuality.ValueChanged += new EventHandler(changePresetLabel);
\r
249 AudioSettings.AudioListChanged += new EventHandler(changePresetLabel);
\r
252 x264Panel.rtf_x264Query.TextChanged += new EventHandler(changePresetLabel);
\r
254 private void UnRegisterPresetEventHandler()
\r
256 // Output Settings
\r
257 drop_format.SelectedIndexChanged -= new EventHandler(changePresetLabel);
\r
258 check_largeFile.CheckedChanged -= new EventHandler(changePresetLabel);
\r
259 check_iPodAtom.CheckedChanged -= new EventHandler(changePresetLabel);
\r
260 check_optimiseMP4.CheckedChanged -= new EventHandler(changePresetLabel);
\r
262 // Picture Settings
\r
263 //PictureSettings.PictureSettingsChanged -= new EventHandler(changePresetLabel);
\r
266 Filters.FilterSettingsChanged -= new EventHandler(changePresetLabel);
\r
269 drp_videoEncoder.SelectedIndexChanged -= new EventHandler(changePresetLabel);
\r
270 check_2PassEncode.CheckedChanged -= new EventHandler(changePresetLabel);
\r
271 check_turbo.CheckedChanged -= new EventHandler(changePresetLabel);
\r
272 text_filesize.TextChanged -= new EventHandler(changePresetLabel);
\r
273 text_bitrate.TextChanged -= new EventHandler(changePresetLabel);
\r
274 slider_videoQuality.ValueChanged -= new EventHandler(changePresetLabel);
\r
277 AudioSettings.AudioListChanged -= new EventHandler(changePresetLabel);
\r
280 x264Panel.rtf_x264Query.TextChanged -= new EventHandler(changePresetLabel);
\r
282 private void changePresetLabel(object sender, EventArgs e)
\r
284 labelPreset.Text = "Output Settings (Preset: Custom)";
\r
287 private static void frmMain_DragEnter(object sender, DragEventArgs e)
\r
289 if (e.Data.GetDataPresent(DataFormats.FileDrop, false))
\r
290 e.Effect = DragDropEffects.All;
\r
292 private void frmMain_DragDrop(object sender, DragEventArgs e)
\r
294 string[] fileList = e.Data.GetData(DataFormats.FileDrop) as string[];
\r
295 sourcePath = string.Empty;
\r
297 if (fileList != null)
\r
299 if (fileList[0] != "")
\r
300 StartScan(fileList[0]);
\r
302 UpdateSourceLabel();
\r
305 UpdateSourceLabel();
\r
307 private void encodeStarted(object sender, EventArgs e)
\r
309 lastAction = "encode";
\r
310 setEncodeStarted();
\r
312 // Experimental HBProc Process Monitoring.
\r
313 if (Properties.Settings.Default.enocdeStatusInGui)
\r
315 Thread encodeMon = new Thread(encodeMonitorThread);
\r
319 private void encodeEnded(object sender, EventArgs e)
\r
321 setEncodeFinished();
\r
323 private void encodePaused(object sender, EventArgs e)
\r
325 setEncodeFinished();
\r
329 // User Interface Menus / Tool Strips *********************************
\r
332 private void mnu_killCLI_Click(object sender, EventArgs e)
\r
336 private void mnu_exit_Click(object sender, EventArgs e)
\r
338 Application.Exit();
\r
343 private void mnu_encode_Click(object sender, EventArgs e)
\r
345 queueWindow.Show();
\r
347 private void mnu_encodeLog_Click(object sender, EventArgs e)
\r
349 frmActivityWindow dvdInfoWindow = new frmActivityWindow(lastAction);
\r
350 dvdInfoWindow.Show();
\r
352 private void mnu_options_Click(object sender, EventArgs e)
\r
354 Form options = new frmOptions(this);
\r
355 options.ShowDialog();
\r
359 #region Presets Menu
\r
360 private void mnu_presetReset_Click(object sender, EventArgs e)
\r
362 presetHandler.UpdateBuiltInPresets();
\r
364 if (treeView_presets.Nodes.Count == 0)
\r
365 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
367 MessageBox.Show("Presets have been updated!", "Alert", MessageBoxButtons.OK, MessageBoxIcon.Information);
\r
369 treeView_presets.ExpandAll();
\r
371 private void mnu_delete_preset_Click(object sender, EventArgs e)
\r
373 presetHandler.RemoveBuiltInPresets();
\r
374 loadPresetPanel(); // Reload the preset panel
\r
376 private void mnu_SelectDefault_Click(object sender, EventArgs e)
\r
378 loadNormalPreset();
\r
380 private void mnu_importMacPreset_Click(object sender, EventArgs e)
\r
384 private void btn_new_preset_Click(object sender, EventArgs e)
\r
386 Form preset = new frmAddPreset(this, queryGen.GenerateCLIQuery(this, 0, null), presetHandler);
\r
387 preset.ShowDialog();
\r
392 private void mnu_user_guide_Click(object sender, EventArgs e)
\r
394 Process.Start("http://trac.handbrake.fr/wiki/HandBrakeGuide");
\r
396 private void mnu_handbrake_home_Click(object sender, EventArgs e)
\r
398 Process.Start("http://handbrake.fr");
\r
400 private void mnu_UpdateCheck_Click(object sender, EventArgs e)
\r
402 lbl_updateCheck.Visible = true;
\r
403 Main.BeginCheckForUpdates(new AsyncCallback(updateCheckDoneMenu), false);
\r
405 private void updateCheckDoneMenu(IAsyncResult result)
\r
407 // Make sure it's running on the calling thread
\r
408 if (InvokeRequired)
\r
410 Invoke(new MethodInvoker(() => updateCheckDoneMenu(result)));
\r
413 UpdateCheckInformation info;
\r
416 // Get the information about the new build, if any, and close the window
\r
417 info = Main.EndCheckForUpdates(result);
\r
419 if (info.NewVersionAvailable && info.BuildInformation != null)
\r
421 frmUpdater updateWindow = new frmUpdater(info.BuildInformation);
\r
422 updateWindow.ShowDialog();
\r
425 MessageBox.Show("There are no new updates at this time.", "Update Check", MessageBoxButtons.OK, MessageBoxIcon.Information);
\r
426 lbl_updateCheck.Visible = false;
\r
429 catch (Exception ex)
\r
431 if ((bool)result.AsyncState)
\r
432 MessageBox.Show("Unable to check for updates, Please try again later.\n\nDetailed Error Information:\n" + ex, "Error", MessageBoxButtons.OK, MessageBoxIcon.Error);
\r
435 private void mnu_about_Click(object sender, EventArgs e)
\r
437 using (frmAbout About = new frmAbout())
\r
439 About.ShowDialog();
\r
445 // Right Click Menu Code
\r
446 private void pmnu_expandAll_Click(object sender, EventArgs e)
\r
448 treeView_presets.ExpandAll();
\r
450 private void pmnu_collapse_Click(object sender, EventArgs e)
\r
452 treeView_presets.CollapseAll();
\r
454 private void pmnu_import_Click(object sender, EventArgs e)
\r
458 private void pmnu_saveChanges_Click(object sender, EventArgs e)
\r
460 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
461 if (result == DialogResult.Yes)
\r
462 presetHandler.Update(treeView_presets.SelectedNode.Text, QueryGenerator.GenerateTabbedComponentsQuery(this), true);
\r
463 else if (result == DialogResult.No)
\r
464 presetHandler.Update(treeView_presets.SelectedNode.Text, QueryGenerator.GenerateTabbedComponentsQuery(this), false);
\r
466 private void pmnu_delete_click(object sender, EventArgs e)
\r
468 if (treeView_presets.SelectedNode != null)
\r
470 presetHandler.Remove(treeView_presets.SelectedNode.Text);
\r
471 treeView_presets.Nodes.Remove(treeView_presets.SelectedNode);
\r
473 treeView_presets.Select();
\r
475 private void presets_menu_Opening(object sender, System.ComponentModel.CancelEventArgs e)
\r
477 // Make sure that the save menu is always disabled by default
\r
478 pmnu_saveChanges.Enabled = false;
\r
480 // Now enable the save menu if the selected preset is a user preset
\r
481 if (treeView_presets.SelectedNode != null)
\r
482 if (presetHandler.CheckIfUserPresetExists(treeView_presets.SelectedNode.Text))
\r
483 pmnu_saveChanges.Enabled = true;
\r
485 treeView_presets.Select();
\r
488 // Presets Management
\r
489 private void btn_addPreset_Click(object sender, EventArgs e)
\r
491 Form preset = new frmAddPreset(this, QueryGenerator.GenerateTabbedComponentsQuery(this), presetHandler);
\r
492 preset.ShowDialog();
\r
494 private void btn_removePreset_Click(object sender, EventArgs e)
\r
496 DialogResult result = MessageBox.Show("Are you sure you wish to delete the selected preset?", "Preset", MessageBoxButtons.YesNo, MessageBoxIcon.Question);
\r
497 if (result == DialogResult.Yes)
\r
499 if (treeView_presets.SelectedNode != null)
\r
501 presetHandler.Remove(treeView_presets.SelectedNode.Text);
\r
502 treeView_presets.Nodes.Remove(treeView_presets.SelectedNode);
\r
505 treeView_presets.Select();
\r
507 private void btn_setDefault_Click(object sender, EventArgs e)
\r
509 if (treeView_presets.SelectedNode != null)
\r
511 DialogResult result = MessageBox.Show("Are you sure you wish to set this preset as the default?", "Preset", MessageBoxButtons.YesNo, MessageBoxIcon.Question);
\r
512 if (result == DialogResult.Yes)
\r
514 Properties.Settings.Default.defaultPreset = treeView_presets.SelectedNode.Text;
\r
515 Properties.Settings.Default.Save();
\r
516 MessageBox.Show("New default preset set.", "Alert", MessageBoxButtons.OK, MessageBoxIcon.Information);
\r
520 MessageBox.Show("Please select a preset first.", "Warning", MessageBoxButtons.OK, MessageBoxIcon.Warning);
\r
522 private void treeview_presets_mouseUp(object sender, MouseEventArgs e)
\r
524 if (e.Button == MouseButtons.Right)
\r
525 treeView_presets.SelectedNode = treeView_presets.GetNodeAt(e.Location);
\r
526 else if (e.Button == MouseButtons.Left)
\r
528 if (treeView_presets.GetNodeAt(e.Location) != null)
\r
530 if (labelPreset.Text.Contains(treeView_presets.GetNodeAt(e.Location).Text))
\r
535 treeView_presets.Select();
\r
537 private void treeView_presets_AfterSelect(object sender, TreeViewEventArgs e)
\r
541 private void treeView_presets_deleteKey(object sender, KeyEventArgs e)
\r
543 if (e.KeyCode == Keys.Delete)
\r
545 DialogResult result = MessageBox.Show("Are you sure you wish to delete the selected preset?", "Preset", MessageBoxButtons.YesNo, MessageBoxIcon.Question);
\r
546 if (result == DialogResult.Yes)
\r
548 if (treeView_presets.SelectedNode != null)
\r
549 presetHandler.Remove(treeView_presets.SelectedNode.Text);
\r
551 // Remember each nodes expanded status so we can reload it
\r
552 List<Boolean> nodeStatus = new List<Boolean>();
\r
553 foreach (TreeNode node in treeView_presets.Nodes)
\r
554 nodeStatus.Add(node.IsExpanded);
\r
556 // Now reload the preset panel
\r
559 // And finally, re-expand any of the nodes if required
\r
561 foreach (TreeNode node in treeView_presets.Nodes)
\r
571 private void selectPreset()
\r
573 if (treeView_presets.SelectedNode != null)
\r
575 // Ok, so, we've selected a preset. Now we want to load it.
\r
576 string presetName = treeView_presets.SelectedNode.Text;
\r
577 if (presetHandler.GetPreset(presetName) != null)
\r
579 string query = presetHandler.GetPreset(presetName).Query;
\r
580 Boolean loadPictureSettings = presetHandler.GetPreset(presetName).PictureSettings;
\r
584 //Ok, Reset all the H264 widgets before changing the preset
\r
585 x264Panel.reset2Defaults();
\r
587 // Send the query from the file to the Query Parser class
\r
588 QueryParser presetQuery = QueryParser.Parse(query);
\r
590 // Now load the preset
\r
591 PresetLoader.presetLoader(this, presetQuery, presetName, loadPictureSettings);
\r
593 // The x264 widgets will need updated, so do this now:
\r
594 x264Panel.X264_StandardizeOptString();
\r
595 x264Panel.X264_SetCurrentSettingsInPanel();
\r
600 private void loadNormalPreset()
\r
602 foreach (TreeNode treenode in treeView_presets.Nodes)
\r
604 foreach (TreeNode node in treenode.Nodes)
\r
606 if (node.Text.Equals("Normal"))
\r
607 treeView_presets.SelectedNode = treeView_presets.Nodes[treenode.Index].Nodes[0];
\r
611 private void importPreset()
\r
613 Import imp = new Import();
\r
614 if (openPreset.ShowDialog() == DialogResult.OK)
\r
616 QueryParser parsed = imp.importMacPreset(openPreset.FileName);
\r
617 if (presetHandler.CheckIfUserPresetExists(parsed.PresetName + " (Imported)"))
\r
619 DialogResult result = MessageBox.Show("This preset appears to already exist. Would you like to overwrite it?", "Overwrite preset?",
\r
620 MessageBoxButtons.YesNo, MessageBoxIcon.Warning);
\r
621 if (result == DialogResult.Yes)
\r
623 PresetLoader.presetLoader(this, parsed, parsed.PresetName, parsed.UsesPictureSettings);
\r
624 presetHandler.Update(parsed.PresetName + " (Imported)", queryGen.GenerateCLIQuery(this, 0, null),
\r
625 parsed.UsesPictureSettings);
\r
630 PresetLoader.presetLoader(this, parsed, parsed.PresetName, parsed.UsesPictureSettings);
\r
631 presetHandler.Add(parsed.PresetName, queryGen.GenerateCLIQuery(this, 0, null), parsed.UsesPictureSettings);
\r
633 if (presetHandler.Add(parsed.PresetName + " (Imported)", queryGen.GenerateCLIQuery(this, 0, null), parsed.UsesPictureSettings))
\r
635 TreeNode preset_treeview = new TreeNode(parsed.PresetName + " (Imported)") { ForeColor = Color.Black };
\r
636 treeView_presets.Nodes.Add(preset_treeview);
\r
644 private void btn_source_Click(object sender, EventArgs e)
\r
646 mnu_dvd_drive.Visible = true;
\r
647 Thread driveInfoThread = new Thread(getDriveInfoThread);
\r
648 driveInfoThread.Start();
\r
650 private void btn_start_Click(object sender, EventArgs e)
\r
652 if (btn_start.Text == "Stop")
\r
654 DialogResult result = MessageBox.Show("Are you sure you wish to cancel the encode?", "Cancel Encode?", MessageBoxButtons.YesNo, MessageBoxIcon.Question);
\r
656 if (result == DialogResult.Yes)
\r
659 encodeQueue.RequestPause();
\r
661 // Allow the CLI to exit cleanly
\r
662 Win32.SetForegroundWindow((int)encodeQueue.processHandle);
\r
663 SendKeys.Send("^C");
\r
666 setEncodeFinished();
\r
671 if (encodeQueue.Count != 0 || (!string.IsNullOrEmpty(sourcePath) && !string.IsNullOrEmpty(text_destination.Text)))
\r
673 string generatedQuery = queryGen.GenerateCLIQuery(this, 0, null);
\r
674 string specifiedQuery = rtf_query.Text != "" ? rtf_query.Text : queryGen.GenerateCLIQuery(this, 0, null);
\r
675 string query = string.Empty;
\r
677 // Check to make sure the generated query matches the GUI settings
\r
678 if (Properties.Settings.Default.PromptOnUnmatchingQueries && !string.IsNullOrEmpty(specifiedQuery) && generatedQuery != specifiedQuery)
\r
680 DialogResult result = MessageBox.Show("The query under the \"Query Editor\" tab " +
\r
681 "does not match the current GUI settings.\n\nBecause the manual query takes " +
\r
682 "priority over the GUI, your recently updated settings will not be taken " +
\r
683 "into account when encoding this job." + Environment.NewLine + Environment.NewLine +
\r
684 "Do you want to replace the manual query with the updated GUI-generated query?",
\r
685 "Manual Query does not Match GUI",
\r
686 MessageBoxButtons.YesNoCancel, MessageBoxIcon.Asterisk,
\r
687 MessageBoxDefaultButton.Button3);
\r
691 case DialogResult.Yes:
\r
692 // Replace the manual query with the generated one
\r
693 query = generatedQuery;
\r
694 rtf_query.Text = generatedQuery;
\r
696 case DialogResult.No:
\r
697 // Use the manual query
\r
698 query = specifiedQuery;
\r
700 case DialogResult.Cancel:
\r
701 // Don't start the encode
\r
707 query = specifiedQuery;
\r
710 DialogResult overwrite = DialogResult.Yes;
\r
711 if (text_destination.Text != "")
\r
712 if (File.Exists(text_destination.Text))
\r
713 overwrite = MessageBox.Show("The destination file already exists. Are you sure you want to overwrite it?", "Overwrite File?", MessageBoxButtons.YesNo, MessageBoxIcon.Question);
\r
715 if (overwrite == DialogResult.Yes)
\r
717 if (encodeQueue.Count == 0)
\r
718 encodeQueue.AddJob(query, sourcePath, text_destination.Text, (rtf_query.Text != ""));
\r
720 queueWindow.setQueue();
\r
721 if (encodeQueue.Count > 1)
\r
722 queueWindow.Show(false);
\r
724 setEncodeStarted(); // Encode is running, so setup the GUI appropriately
\r
725 encodeQueue.StartEncodeQueue(); // Start The Queue Encoding Process
\r
726 lastAction = "encode"; // Set the last action to encode - Used for activity window.
\r
728 if (ActivityWindow != null)
\r
729 ActivityWindow.SetEncodeMode();
\r
733 else if (string.IsNullOrEmpty(sourcePath) || string.IsNullOrEmpty(text_destination.Text))
\r
734 MessageBox.Show("No source or destination selected.", "Warning", MessageBoxButtons.OK, MessageBoxIcon.Warning);
\r
737 private void btn_add2Queue_Click(object sender, EventArgs e)
\r
739 if (string.IsNullOrEmpty(sourcePath) || string.IsNullOrEmpty(text_destination.Text))
\r
740 MessageBox.Show("No source or destination selected.", "Warning", MessageBoxButtons.OK, MessageBoxIcon.Warning);
\r
743 String query = queryGen.GenerateCLIQuery(this, 0, null);
\r
744 if (rtf_query.Text != "")
\r
745 query = rtf_query.Text;
\r
747 if (encodeQueue.CheckForDestinationDuplicate(text_destination.Text))
\r
749 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
750 "Warning", MessageBoxButtons.YesNo, MessageBoxIcon.Warning);
\r
751 if (result == DialogResult.Yes)
\r
752 encodeQueue.AddJob(query, sourcePath, text_destination.Text, (rtf_query.Text != ""));
\r
756 encodeQueue.AddJob(query, sourcePath, text_destination.Text, (rtf_query.Text != ""));
\r
758 lbl_encode.Text = encodeQueue.Count + " encode(s) pending in the queue";
\r
760 queueWindow.Show();
\r
763 private void btn_showQueue_Click(object sender, EventArgs e)
\r
765 queueWindow.Show();
\r
766 queueWindow.Activate();
\r
768 private void tb_preview_Click(object sender, EventArgs e)
\r
770 if (string.IsNullOrEmpty(sourcePath) || string.IsNullOrEmpty(text_destination.Text))
\r
771 MessageBox.Show("No source or destination selected.", "Warning", MessageBoxButtons.OK, MessageBoxIcon.Warning);
\r
774 if (qtpreview == null)
\r
776 qtpreview = new frmPreview(this);
\r
779 else if (qtpreview.IsDisposed)
\r
781 qtpreview = new frmPreview(this);
\r
785 MessageBox.Show(qtpreview, "The preview window is already open!", "Warning", MessageBoxButtons.OK, MessageBoxIcon.Warning);
\r
788 private void btn_ActivityWindow_Click(object sender, EventArgs e)
\r
790 if (ActivityWindow == null || !ActivityWindow.IsHandleCreated)
\r
791 ActivityWindow = new frmActivityWindow(lastAction);
\r
793 switch (lastAction)
\r
796 ActivityWindow.SetScanMode();
\r
799 ActivityWindow.SetEncodeMode();
\r
802 ActivityWindow.SetEncodeMode();
\r
806 ActivityWindow.Show();
\r
807 ActivityWindow.Activate();
\r
811 #region System Tray Icon
\r
812 private void frmMain_Resize(object sender, EventArgs e)
\r
814 if (FormWindowState.Minimized == this.WindowState)
\r
816 notifyIcon.Visible = true;
\r
819 else if (FormWindowState.Normal == this.WindowState)
\r
820 notifyIcon.Visible = false;
\r
822 private void notifyIcon_MouseDoubleClick(object sender, MouseEventArgs e)
\r
824 this.Visible = true;
\r
826 this.WindowState = FormWindowState.Normal;
\r
827 notifyIcon.Visible = false;
\r
829 private void btn_restore_Click(object sender, EventArgs e)
\r
831 this.Visible = true;
\r
833 this.WindowState = FormWindowState.Normal;
\r
834 notifyIcon.Visible = false;
\r
838 #region Tab Control
\r
841 private void btn_dvd_source_Click(object sender, EventArgs e)
\r
843 if (DVD_Open.ShowDialog() == DialogResult.OK)
\r
845 this.selectedSourceType = SourceType.Folder;
\r
846 selectSource(DVD_Open.SelectedPath);
\r
849 UpdateSourceLabel();
\r
851 private void btn_file_source_Click(object sender, EventArgs e)
\r
853 if (ISO_Open.ShowDialog() == DialogResult.OK)
\r
855 this.selectedSourceType = SourceType.VideoFile;
\r
856 selectSource(ISO_Open.FileName);
\r
859 UpdateSourceLabel();
\r
861 private void mnu_dvd_drive_Click(object sender, EventArgs e)
\r
863 if (this.dvdDrivePath == null) return;
\r
864 this.selectedSourceType = SourceType.DvdDrive;
\r
865 selectSource(this.dvdDrivePath);
\r
867 private void selectSource(string file)
\r
869 Check_ChapterMarkers.Enabled = true;
\r
870 lastAction = "scan";
\r
871 sourcePath = string.Empty;
\r
873 if (file == string.Empty) // Must have a file or path
\r
875 UpdateSourceLabel();
\r
879 sourcePath = Path.GetFileName(file);
\r
882 private void drp_dvdtitle_Click(object sender, EventArgs e)
\r
884 if ((drp_dvdtitle.Items.Count == 1) && (drp_dvdtitle.Items[0].ToString() == "Automatic"))
\r
885 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
887 private void drp_dvdtitle_SelectedIndexChanged(object sender, EventArgs e)
\r
889 UnRegisterPresetEventHandler();
\r
891 PictureSettings.lbl_Aspect.Text = "Select a Title"; // Reset some values on the form
\r
892 drop_chapterStart.Items.Clear();
\r
893 drop_chapterFinish.Items.Clear();
\r
895 // If the dropdown is set to automatic nothing else needs to be done.
\r
896 // Otheriwse if its not, title data has to be loased from parsing.
\r
897 if (drp_dvdtitle.Text != "Automatic")
\r
899 selectedTitle = drp_dvdtitle.SelectedItem as Title;
\r
900 lbl_duration.Text = selectedTitle.Duration.ToString();
\r
901 PictureSettings.Source = selectedTitle; // Setup Picture Settings Tab Control
\r
903 // Populate the Angles dropdown
\r
904 drop_angle.Items.Clear();
\r
905 if (!Properties.Settings.Default.noDvdNav)
\r
907 drop_angle.Visible = true;
\r
908 lbl_angle.Visible = true;
\r
909 drop_angle.Items.AddRange(selectedTitle.Angles.ToArray());
\r
910 if (drop_angle.Items.Count != 0)
\r
911 drop_angle.SelectedIndex = 0;
\r
915 drop_angle.Visible = false;
\r
916 lbl_angle.Visible = false;
\r
919 // Populate the Start chapter Dropdown
\r
920 drop_chapterStart.Items.Clear();
\r
921 drop_chapterStart.Items.AddRange(selectedTitle.Chapters.ToArray());
\r
922 if (drop_chapterStart.Items.Count > 0)
\r
923 drop_chapterStart.Text = drop_chapterStart.Items[0].ToString();
\r
925 // Populate the Final Chapter Dropdown
\r
926 drop_chapterFinish.Items.Clear();
\r
927 drop_chapterFinish.Items.AddRange(selectedTitle.Chapters.ToArray());
\r
928 if (drop_chapterFinish.Items.Count > 0)
\r
929 drop_chapterFinish.Text = drop_chapterFinish.Items[drop_chapterFinish.Items.Count - 1].ToString();
\r
931 // Populate the Audio Channels Dropdown
\r
932 AudioSettings.SetTrackList(selectedTitle);
\r
934 // Populate the Subtitles dropdown
\r
935 Subtitles.drp_subtitleTracks.Items.Clear();
\r
936 Subtitles.drp_subtitleTracks.Items.Add("Foreign Audio Search (Bitmap)");
\r
937 Subtitles.drp_subtitleTracks.Items.AddRange(selectedTitle.Subtitles.ToArray());
\r
938 Subtitles.drp_subtitleTracks.SelectedIndex = 0;
\r
940 Subtitles.SetSubtitleTrackAuto();
\r
942 // Update the source label if we have multiple streams
\r
943 if (selectedTitle != null)
\r
944 if (!string.IsNullOrEmpty(selectedTitle.SourceName))
\r
945 labelSource.Text = labelSource.Text = Path.GetFileName(selectedTitle.SourceName);
\r
947 // Run the autoName & chapterNaming functions
\r
948 if (Properties.Settings.Default.autoNaming)
\r
950 string autoPath = Main.autoName(this);
\r
951 if (autoPath != null)
\r
952 text_destination.Text = autoPath;
\r
954 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
957 data_chpt.Rows.Clear();
\r
958 if (selectedTitle.Chapters.Count != 1)
\r
960 DataGridView chapterGridView = Main.chapterNaming(data_chpt, drop_chapterFinish.Text);
\r
961 if (chapterGridView != null)
\r
962 data_chpt = chapterGridView;
\r
966 Check_ChapterMarkers.Checked = false;
\r
967 Check_ChapterMarkers.Enabled = false;
\r
970 // Hack to force the redraw of the scrollbars which don't resize properly when the control is disabled.
\r
971 data_chpt.Columns[0].Width = 166;
\r
972 data_chpt.Columns[0].Width = 165;
\r
974 RegisterPresetEventHandler();
\r
976 private void chapersChanged(object sender, EventArgs e)
\r
978 Control ctl = (Control)sender;
\r
979 int chapterStart, chapterEnd;
\r
980 int.TryParse(drop_chapterStart.Text, out chapterStart);
\r
981 int.TryParse(drop_chapterFinish.Text, out chapterEnd);
\r
985 case "drop_chapterStart":
\r
986 if (drop_chapterFinish.SelectedIndex == -1 && drop_chapterFinish.Items.Count != 0)
\r
987 drop_chapterFinish.SelectedIndex = drop_chapterFinish.Items.Count - 1;
\r
989 if (chapterEnd != 0)
\r
990 if (chapterStart > chapterEnd)
\r
991 drop_chapterFinish.Text = chapterStart.ToString();
\r
993 case "drop_chapterFinish":
\r
994 if (drop_chapterStart.Items.Count >= 1 && drop_chapterStart.SelectedIndex == -1)
\r
995 drop_chapterStart.SelectedIndex = 0;
\r
997 if (chapterStart != 0)
\r
998 if (chapterEnd < chapterStart)
\r
999 drop_chapterFinish.Text = chapterStart.ToString();
\r
1001 // Add more rows to the Chapter menu if needed.
\r
1002 if (Check_ChapterMarkers.Checked)
\r
1004 int i = data_chpt.Rows.Count, finish = 0;
\r
1005 int.TryParse(drop_chapterFinish.Text, out finish);
\r
1007 while (i < finish)
\r
1009 int n = data_chpt.Rows.Add();
\r
1010 data_chpt.Rows[n].Cells[0].Value = (i + 1);
\r
1011 data_chpt.Rows[n].Cells[1].Value = "Chapter " + (i + 1);
\r
1012 data_chpt.Rows[n].Cells[0].ValueType = typeof(int);
\r
1013 data_chpt.Rows[n].Cells[1].ValueType = typeof(string);
\r
1020 // Update the Duration
\r
1021 lbl_duration.Text = Main.calculateDuration(drop_chapterStart.SelectedIndex, drop_chapterFinish.SelectedIndex, selectedTitle).ToString();
\r
1023 // Run the Autonaming function
\r
1024 if (Properties.Settings.Default.autoNaming)
\r
1025 text_destination.Text = Main.autoName(this);
\r
1027 // Disable chapter markers if only 1 chapter is selected.
\r
1028 if (chapterStart == chapterEnd)
\r
1030 Check_ChapterMarkers.Enabled = false;
\r
1031 btn_importChapters.Enabled = false;
\r
1032 data_chpt.Enabled = false;
\r
1036 Check_ChapterMarkers.Enabled = true;
\r
1037 if (Check_ChapterMarkers.Checked)
\r
1039 btn_importChapters.Enabled = true;
\r
1040 data_chpt.Enabled = true;
\r
1046 private void btn_destBrowse_Click(object sender, EventArgs e)
\r
1048 // This removes the file extension from the filename box on the save file dialog.
\r
1049 // It's daft but some users don't realise that typing an extension overrides the dropdown extension selected.
\r
1050 DVD_Save.FileName = Path.GetFileNameWithoutExtension(text_destination.Text);
\r
1052 if (Path.IsPathRooted(text_destination.Text))
\r
1053 DVD_Save.InitialDirectory = Path.GetDirectoryName(text_destination.Text);
\r
1055 // Show the dialog and set the main form file path
\r
1056 if (drop_format.SelectedIndex.Equals(0))
\r
1057 DVD_Save.FilterIndex = 1;
\r
1058 else if (drop_format.SelectedIndex.Equals(1))
\r
1059 DVD_Save.FilterIndex = 2;
\r
1061 if (DVD_Save.ShowDialog() == DialogResult.OK)
\r
1063 // Add a file extension manually, as FileDialog.AddExtension has issues with dots in filenames
\r
1064 switch (DVD_Save.FilterIndex)
\r
1067 if (!Path.GetExtension(DVD_Save.FileName).Equals(".mp4", StringComparison.InvariantCultureIgnoreCase))
\r
1068 if (Properties.Settings.Default.useM4v)
\r
1069 DVD_Save.FileName = DVD_Save.FileName.Replace(".mp4", ".m4v").Replace(".mkv", ".m4v");
\r
1071 DVD_Save.FileName = DVD_Save.FileName.Replace(".m4v", ".mp4").Replace(".mkv", ".mp4");
\r
1074 if (!Path.GetExtension(DVD_Save.FileName).Equals(".mkv", StringComparison.InvariantCultureIgnoreCase))
\r
1075 DVD_Save.FileName = DVD_Save.FileName.Replace(".mp4", ".mkv").Replace(".m4v", ".mkv");
\r
1081 text_destination.Text = DVD_Save.FileName;
\r
1083 // Quicktime requires .m4v file for chapter markers to work. If checked, change the extension to .m4v (mp4 and m4v are the same thing)
\r
1084 if (Check_ChapterMarkers.Checked && DVD_Save.FilterIndex != 2)
\r
1085 SetExtension(".m4v");
\r
1088 private void text_destination_TextChanged(object sender, EventArgs e)
\r
1090 string path = text_destination.Text;
\r
1091 if (path.EndsWith(".mp4") || path.EndsWith(".m4v"))
\r
1092 drop_format.SelectedIndex = 0;
\r
1093 else if (path.EndsWith(".mkv"))
\r
1094 drop_format.SelectedIndex = 1;
\r
1097 // Output Settings
\r
1098 private void drop_format_SelectedIndexChanged(object sender, EventArgs e)
\r
1100 switch (drop_format.SelectedIndex)
\r
1103 if (Properties.Settings.Default.useM4v || Check_ChapterMarkers.Checked || AudioSettings.RequiresM4V() || Subtitles.RequiresM4V())
\r
1104 SetExtension(".m4v");
\r
1106 SetExtension(".mp4");
\r
1109 SetExtension(".mkv");
\r
1113 AudioSettings.SetContainer(drop_format.Text);
\r
1114 Subtitles.SetContainer(drop_format.SelectedIndex);
\r
1116 if (drop_format.Text.Contains("MP4"))
\r
1118 if (drp_videoEncoder.Items.Contains("VP3 (Theora)"))
\r
1120 drp_videoEncoder.Items.Remove("VP3 (Theora)");
\r
1121 drp_videoEncoder.SelectedIndex = 1;
\r
1124 else if (drop_format.Text.Contains("MKV"))
\r
1125 drp_videoEncoder.Items.Add("VP3 (Theora)");
\r
1127 public void SetExtension(string newExtension)
\r
1129 if (newExtension == ".mp4" || newExtension == ".m4v")
\r
1130 if (Properties.Settings.Default.useM4v || Check_ChapterMarkers.Checked || AudioSettings.RequiresM4V() || Subtitles.RequiresM4V())
\r
1131 newExtension = ".m4v";
\r
1133 newExtension = ".mp4";
\r
1135 if (Path.HasExtension(newExtension))
\r
1136 text_destination.Text = Path.ChangeExtension(text_destination.Text, newExtension);
\r
1140 private void drp_videoEncoder_SelectedIndexChanged(object sender, EventArgs e)
\r
1142 setContainerOpts();
\r
1144 //Turn off some options which are H.264 only when the user selects a non h.264 encoder
\r
1145 if (drp_videoEncoder.Text.Contains("H.264"))
\r
1147 if (check_2PassEncode.CheckState == CheckState.Checked)
\r
1148 check_turbo.Enabled = true;
\r
1150 tab_advanced.Enabled = true;
\r
1151 if ((drop_format.Text.Contains("MP4")) || (drop_format.Text.Contains("M4V")))
\r
1152 check_iPodAtom.Enabled = true;
\r
1154 check_iPodAtom.Enabled = false;
\r
1158 check_turbo.CheckState = CheckState.Unchecked;
\r
1159 check_turbo.Enabled = false;
\r
1160 tab_advanced.Enabled = false;
\r
1161 x264Panel.x264Query = "";
\r
1162 check_iPodAtom.Enabled = false;
\r
1163 check_iPodAtom.Checked = false;
\r
1166 // Setup the CQ Slider
\r
1167 switch (drp_videoEncoder.Text)
\r
1169 case "MPEG-4 (FFmpeg)":
\r
1170 if (slider_videoQuality.Value > 31)
\r
1171 slider_videoQuality.Value = 20; // Just reset to 70% QP 10 on encode change.
\r
1172 slider_videoQuality.Minimum = 1;
\r
1173 slider_videoQuality.Maximum = 31;
\r
1175 case "H.264 (x264)":
\r
1176 slider_videoQuality.Minimum = 0;
\r
1177 slider_videoQuality.TickFrequency = 1;
\r
1179 CultureInfo culture = CultureInfo.CreateSpecificCulture("en-US");
\r
1180 double cqStep = Properties.Settings.Default.x264cqstep;
\r
1181 double multiplier = 1.0 / cqStep;
\r
1182 double value = slider_videoQuality.Value * multiplier;
\r
1184 switch (Properties.Settings.Default.x264cqstep.ToString(culture))
\r
1187 slider_videoQuality.Maximum = 255;
\r
1190 slider_videoQuality.Maximum = 204;
\r
1193 slider_videoQuality.Maximum = 102;
\r
1196 slider_videoQuality.Maximum = 51;
\r
1199 slider_videoQuality.Maximum = 51;
\r
1202 if (value < slider_videoQuality.Maximum)
\r
1203 slider_videoQuality.Value = slider_videoQuality.Maximum - (int)value;
\r
1206 case "VP3 (Theora)":
\r
1207 if (slider_videoQuality.Value > 63)
\r
1208 slider_videoQuality.Value = 45; // Just reset to 70% QP 45 on encode change.
\r
1209 slider_videoQuality.Minimum = 0;
\r
1210 slider_videoQuality.Maximum = 63;
\r
1215 /// Set the container format options
\r
1217 public void setContainerOpts()
\r
1219 if ((drop_format.Text.Contains("MP4")) || (drop_format.Text.Contains("M4V")))
\r
1221 check_largeFile.Enabled = true;
\r
1222 check_optimiseMP4.Enabled = true;
\r
1223 check_iPodAtom.Enabled = true;
\r
1227 check_largeFile.Enabled = false;
\r
1228 check_optimiseMP4.Enabled = false;
\r
1229 check_iPodAtom.Enabled = false;
\r
1230 check_largeFile.Checked = false;
\r
1231 check_optimiseMP4.Checked = false;
\r
1232 check_iPodAtom.Checked = false;
\r
1235 private double _cachedCqStep = Properties.Settings.Default.x264cqstep;
\r
1237 /// Update the CQ slider for x264 for a new CQ step. This is set from option
\r
1239 public void setQualityFromSlider()
\r
1241 // Work out the current RF value.
\r
1242 double cqStep = _cachedCqStep;
\r
1243 double rfValue = 51.0 - slider_videoQuality.Value * cqStep;
\r
1245 // Change the maximum value for the slider
\r
1246 switch (Properties.Settings.Default.x264cqstep.ToString(new CultureInfo("en-US")))
\r
1249 slider_videoQuality.Maximum = 255;
\r
1252 slider_videoQuality.Maximum = 204;
\r
1255 slider_videoQuality.Maximum = 102;
\r
1258 slider_videoQuality.Maximum = 51;
\r
1261 slider_videoQuality.Maximum = 51;
\r
1265 // Reset the CQ slider to RF0
\r
1266 slider_videoQuality.Value = slider_videoQuality.Maximum;
\r
1268 // Reset the CQ slider back to the previous value as close as possible
\r
1269 double cqStepNew = Properties.Settings.Default.x264cqstep;
\r
1270 double rfValueCurrent = 51.0 - slider_videoQuality.Value * cqStepNew;
\r
1271 while (rfValueCurrent < rfValue)
\r
1273 slider_videoQuality.Value--;
\r
1274 rfValueCurrent = 51.0 - slider_videoQuality.Value * cqStepNew;
\r
1277 // Cache the CQ step for the next calculation
\r
1278 _cachedCqStep = Properties.Settings.Default.x264cqstep;
\r
1280 private void slider_videoQuality_Scroll(object sender, EventArgs e)
\r
1282 double cqStep = Properties.Settings.Default.x264cqstep;
\r
1283 switch (drp_videoEncoder.Text)
\r
1285 case "MPEG-4 (FFmpeg)":
\r
1286 double rfValue = 31 - (slider_videoQuality.Value - 1);
\r
1287 double max = slider_videoQuality.Maximum;
\r
1288 double min = slider_videoQuality.Minimum;
\r
1289 double val = ((max - min) - (rfValue - min)) / (max - min);
\r
1290 lbl_SliderValue.Text = "QP:" + (32 - slider_videoQuality.Value);
\r
1291 lbl_qualityValue.Text = Math.Round((val * 100), 2).ToString(new CultureInfo("en-US")) + "%";
\r
1293 case "H.264 (x264)":
\r
1294 rfValue = 51.0 - slider_videoQuality.Value * cqStep;
\r
1295 max = slider_videoQuality.Maximum * cqStep;
\r
1296 min = slider_videoQuality.Minimum;
\r
1297 val = ((max - min) - (rfValue - min)) / (max - min);
\r
1298 rfValue = Math.Round(rfValue, 2);
\r
1299 lbl_SliderValue.Text = "RF:" + rfValue.ToString(new CultureInfo("en-US"));
\r
1300 lbl_qualityValue.Text = Math.Round((val * 100), 2).ToString(new CultureInfo("en-US")) + "%";
\r
1302 case "VP3 (Theora)":
\r
1303 rfValue = slider_videoQuality.Value;
\r
1304 double value = rfValue / 63;
\r
1305 lbl_SliderValue.Text = "QP:" + slider_videoQuality.Value;
\r
1306 lbl_qualityValue.Text = Math.Round((value * 100), 2).ToString(new CultureInfo("en-US")) + "%";
\r
1310 private void radio_targetFilesize_CheckedChanged(object sender, EventArgs e)
\r
1312 text_bitrate.Enabled = false;
\r
1313 text_filesize.Enabled = true;
\r
1314 slider_videoQuality.Enabled = false;
\r
1316 check_2PassEncode.Enabled = true;
\r
1318 private void radio_avgBitrate_CheckedChanged(object sender, EventArgs e)
\r
1320 text_bitrate.Enabled = true;
\r
1321 text_filesize.Enabled = false;
\r
1322 slider_videoQuality.Enabled = false;
\r
1324 check_2PassEncode.Enabled = true;
\r
1326 private void radio_cq_CheckedChanged(object sender, EventArgs e)
\r
1328 text_bitrate.Enabled = false;
\r
1329 text_filesize.Enabled = false;
\r
1330 slider_videoQuality.Enabled = true;
\r
1332 check_2PassEncode.Enabled = false;
\r
1333 check_2PassEncode.CheckState = CheckState.Unchecked;
\r
1335 private void check_2PassEncode_CheckedChanged(object sender, EventArgs e)
\r
1337 if (check_2PassEncode.CheckState.ToString() == "Checked")
\r
1339 if (drp_videoEncoder.Text.Contains("H.264"))
\r
1340 check_turbo.Enabled = true;
\r
1344 check_turbo.Enabled = false;
\r
1345 check_turbo.CheckState = CheckState.Unchecked;
\r
1349 // Chapter Marker Tab
\r
1350 private void Check_ChapterMarkers_CheckedChanged(object sender, EventArgs e)
\r
1352 if (Check_ChapterMarkers.Checked)
\r
1354 if (drop_format.SelectedIndex != 1)
\r
1355 SetExtension(".m4v");
\r
1356 data_chpt.Enabled = true;
\r
1357 btn_importChapters.Enabled = true;
\r
1361 if (drop_format.SelectedIndex != 1 && !Properties.Settings.Default.useM4v)
\r
1362 SetExtension(".mp4");
\r
1363 data_chpt.Enabled = false;
\r
1364 btn_importChapters.Enabled = false;
\r
1367 private void btn_importChapters_Click(object sender, EventArgs e)
\r
1369 if (File_ChapterImport.ShowDialog() == DialogResult.OK)
\r
1371 String filename = File_ChapterImport.FileName;
\r
1372 DataGridView imported = Main.importChapterNames(data_chpt, filename);
\r
1373 if (imported != null)
\r
1374 data_chpt = imported;
\r
1377 private void mnu_resetChapters_Click(object sender, EventArgs e)
\r
1379 data_chpt.Rows.Clear();
\r
1380 DataGridView chapterGridView = Main.chapterNaming(data_chpt, drop_chapterFinish.Text);
\r
1381 if (chapterGridView != null)
\r
1383 data_chpt = chapterGridView;
\r
1387 // Query Editor Tab
\r
1388 private void btn_generate_Query_Click(object sender, EventArgs e)
\r
1390 rtf_query.Text = queryGen.GenerateCLIQuery(this, 0, null);
\r
1392 private void btn_clear_Click(object sender, EventArgs e)
\r
1394 rtf_query.Clear();
\r
1398 // MainWindow Components, Actions and Functions ***********************
\r
1400 #region Source Scan
\r
1401 public Boolean isScanning { get; set; }
\r
1402 private Scan SourceScan;
\r
1404 private void StartScan(String filename)
\r
1406 // Setup the GUI components for the scan.
\r
1407 sourcePath = filename;
\r
1408 foreach (Control ctrl in Controls)
\r
1409 if (!(ctrl is StatusStrip || ctrl is MenuStrip || ctrl is ToolStrip))
\r
1410 ctrl.Enabled = false;
\r
1412 lbl_encode.Visible = true;
\r
1413 lbl_encode.Text = "Scanning ...";
\r
1414 btn_source.Enabled = false;
\r
1415 btn_start.Enabled = false;
\r
1416 btn_showQueue.Enabled = false;
\r
1417 btn_add2Queue.Enabled = false;
\r
1418 tb_preview.Enabled = false;
\r
1419 mnu_killCLI.Visible = true;
\r
1421 if (ActivityWindow != null)
\r
1422 ActivityWindow.SetScanMode();
\r
1427 // if (ActivityWindow != null)
\r
1428 // ActivityWindow.SetupLogViewer(true);
\r
1429 isScanning = true;
\r
1430 SourceScan = new Scan();
\r
1431 SourceScan.ScanSource(sourcePath);
\r
1432 SourceScan.ScanStatusChanged += new EventHandler(SourceScan_ScanStatusChanged);
\r
1433 SourceScan.ScanCompleted += new EventHandler(SourceScan_ScanCompleted);
\r
1435 catch (Exception exc)
\r
1437 MessageBox.Show("frmMain.cs - StartScan " + exc, "Error", MessageBoxButtons.OK, MessageBoxIcon.Error);
\r
1441 void SourceScan_ScanStatusChanged(object sender, EventArgs e)
\r
1443 UpdateScanStatusLabel();
\r
1445 void SourceScan_ScanCompleted(object sender, EventArgs e)
\r
1447 UpdateGuiAfterScan();
\r
1450 private void UpdateScanStatusLabel()
\r
1452 if (InvokeRequired)
\r
1454 BeginInvoke(new UpdateWindowHandler(UpdateScanStatusLabel));
\r
1457 lbl_encode.Text = SourceScan.ScanStatus();
\r
1459 private void UpdateGuiAfterScan()
\r
1461 if (InvokeRequired)
\r
1463 BeginInvoke(new UpdateWindowHandler(UpdateGuiAfterScan));
\r
1469 DVD thisDVD = SourceScan.SouceData();
\r
1471 // Setup some GUI components
\r
1472 drp_dvdtitle.Items.Clear();
\r
1473 if (thisDVD.Titles.Count != 0)
\r
1474 drp_dvdtitle.Items.AddRange(thisDVD.Titles.ToArray());
\r
1476 // Now select the longest title
\r
1477 if (thisDVD.Titles.Count != 0)
\r
1478 drp_dvdtitle.SelectedItem = Main.selectLongestTitle(thisDVD);
\r
1480 // Enable the creation of chapter markers if the file is an image of a dvd.
\r
1481 if (sourcePath.ToLower().Contains(".iso") || sourcePath.Contains("VIDEO_TS"))
\r
1482 Check_ChapterMarkers.Enabled = true;
\r
1485 Check_ChapterMarkers.Enabled = false;
\r
1486 Check_ChapterMarkers.Checked = false;
\r
1487 data_chpt.Rows.Clear();
\r
1490 // If no titles were found, Display an error message
\r
1491 if (drp_dvdtitle.Items.Count == 0)
\r
1494 "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
1495 "Error", MessageBoxButtons.OK, MessageBoxIcon.Hand);
\r
1496 sourcePath = string.Empty;
\r
1498 UpdateSourceLabel();
\r
1500 // Enable the GUI components and enable any disabled components
\r
1503 catch (Exception exc)
\r
1505 MessageBox.Show("frmMain.cs - updateUIafterScan " + exc, "Error", MessageBoxButtons.OK, MessageBoxIcon.Error);
\r
1510 private void EnableGUI()
\r
1514 if (InvokeRequired)
\r
1515 BeginInvoke(new UpdateWindowHandler(EnableGUI));
\r
1516 lbl_encode.Text = "Scan Completed";
\r
1517 foreach (Control ctrl in Controls)
\r
1518 ctrl.Enabled = true;
\r
1519 btn_start.Enabled = true;
\r
1520 btn_showQueue.Enabled = true;
\r
1521 btn_add2Queue.Enabled = true;
\r
1522 tb_preview.Enabled = true;
\r
1523 btn_source.Enabled = true;
\r
1524 mnu_killCLI.Visible = false;
\r
1526 catch (Exception exc)
\r
1528 MessageBox.Show("frmMain.cs - EnableGUI() " + exc, "Error", MessageBoxButtons.OK, MessageBoxIcon.Error);
\r
1531 private void KillScan()
\r
1535 SourceScan.ScanCompleted -= new EventHandler(SourceScan_ScanCompleted);
\r
1539 if (SourceScan.ScanProcess() != null)
\r
1540 SourceScan.ScanProcess().Kill();
\r
1542 lbl_encode.Text = "Scan Cancelled!";
\r
1544 catch (Exception ex)
\r
1546 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
1549 private void ResetGUI()
\r
1551 drp_dvdtitle.Items.Clear();
\r
1552 drop_chapterStart.Items.Clear();
\r
1553 drop_chapterFinish.Items.Clear();
\r
1554 lbl_duration.Text = "Select a Title";
\r
1555 PictureSettings.lbl_src_res.Text = "Select a Title";
\r
1556 PictureSettings.lbl_Aspect.Text = "Select a Title";
\r
1557 sourcePath = String.Empty;
\r
1558 text_destination.Text = String.Empty;
\r
1559 selectedTitle = null;
\r
1560 isScanning = false;
\r
1562 private void UpdateSourceLabel()
\r
1564 labelSource.Text = string.IsNullOrEmpty(sourcePath) ? "Select \"Source\" to continue." : this.SourceName;
\r
1566 if (selectedTitle != null)
\r
1567 if (!string.IsNullOrEmpty(selectedTitle.SourceName)) // If it's one of multiple source files, make sure we don't use the folder name
\r
1568 labelSource.Text = Path.GetFileName(selectedTitle.SourceName);
\r
1574 /// Set the GUI to it's finished encoding state.
\r
1576 private void setEncodeFinished()
\r
1580 if (InvokeRequired)
\r
1582 BeginInvoke(new UpdateWindowHandler(setEncodeFinished));
\r
1586 lbl_encode.Text = "Encoding Finished";
\r
1587 btn_start.Text = "Start";
\r
1588 btn_start.ToolTipText = "Start the encoding process";
\r
1589 btn_start.Image = Properties.Resources.Play;
\r
1591 // If the window is minimized, display the notification in a popup.
\r
1592 if (Properties.Settings.Default.trayIconAlerts)
\r
1593 if (FormWindowState.Minimized == this.WindowState)
\r
1595 notifyIcon.BalloonTipText = lbl_encode.Text;
\r
1596 notifyIcon.ShowBalloonTip(500);
\r
1599 catch (Exception exc)
\r
1601 MessageBox.Show(exc.ToString());
\r
1606 /// Set the GUI to it's started encoding state.
\r
1608 private void setEncodeStarted()
\r
1612 if (InvokeRequired)
\r
1614 BeginInvoke(new UpdateWindowHandler(setEncodeStarted));
\r
1618 lbl_encode.Visible = true;
\r
1619 lbl_encode.Text = "Encoding with " + encodeQueue.Count + " encode(s) pending";
\r
1620 btn_start.Text = "Stop";
\r
1621 btn_start.ToolTipText = "Stop the encoding process.";
\r
1622 btn_start.Image = Properties.Resources.stop;
\r
1624 catch (Exception exc)
\r
1626 MessageBox.Show(exc.ToString());
\r
1631 #region DVD Drive Detection
\r
1632 private void getDriveInfoThread()
\r
1636 if (InvokeRequired)
\r
1638 BeginInvoke(new UpdateWindowHandler(getDriveInfoThread));
\r
1642 Boolean foundDrive = false;
\r
1643 DriveInfo[] theCollectionOfDrives = DriveInfo.GetDrives();
\r
1644 foreach (DriveInfo curDrive in theCollectionOfDrives)
\r
1646 if (curDrive.DriveType == DriveType.CDRom && curDrive.IsReady)
\r
1648 if (File.Exists(curDrive.RootDirectory + "VIDEO_TS\\VIDEO_TS.IFO"))
\r
1650 this.dvdDrivePath = curDrive.RootDirectory + "VIDEO_TS";
\r
1651 this.dvdDriveLabel = curDrive.VolumeLabel;
\r
1652 mnu_dvd_drive.Text = this.dvdDrivePath + " (" + this.dvdDriveLabel + ")";
\r
1653 foundDrive = true;
\r
1659 if (foundDrive == false)
\r
1660 mnu_dvd_drive.Text = "[No DVD Drive Ready]";
\r
1664 mnu_dvd_drive.Text = "[No DVD Drive Ready / Found]";
\r
1669 #region Public Methods
\r
1671 /// Access the preset Handler and setup the preset panel.
\r
1673 public void loadPresetPanel()
\r
1675 if (presetHandler.CheckIfPresetsAreOutOfDate())
\r
1676 if (!Properties.Settings.Default.presetNotification)
\r
1677 MessageBox.Show(splash,
\r
1678 "HandBrake has determined your built-in presets are out of date... These presets will now be updated.",
\r
1679 "Preset Update", MessageBoxButtons.OK, MessageBoxIcon.Information);
\r
1681 presetHandler.GetPresetPanel(ref treeView_presets);
\r
1682 treeView_presets.Update();
\r
1688 /// If the queue is being processed, prompt the user to confirm application close.
\r
1690 /// <param name="e"></param>
\r
1691 protected override void OnFormClosing(FormClosingEventArgs e)
\r
1693 // If currently encoding, the queue isn't paused, and there are queue items to process, prompt to confirm close.
\r
1694 if ((encodeQueue.isEncoding) && (!encodeQueue.PauseRequested) && (encodeQueue.Count > 0))
\r
1696 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
1697 "Close HandBrake?", MessageBoxButtons.YesNo, MessageBoxIcon.Question);
\r
1698 if (result == DialogResult.No)
\r
1701 base.OnFormClosing(e);
\r
1705 #region In-GUI Encode Status (Experimental)
\r
1706 private void encodeMonitorThread()
\r
1710 Parser encode = new Parser(encodeQueue.hbProcess.StandardOutput.BaseStream);
\r
1711 encode.OnEncodeProgress += encodeOnEncodeProgress;
\r
1712 while (!encode.EndOfStream)
\r
1713 encode.readEncodeStatus();
\r
1715 catch (Exception exc)
\r
1717 MessageBox.Show(exc.ToString(), "Error", MessageBoxButtons.OK, MessageBoxIcon.Error);
\r
1720 private void encodeOnEncodeProgress(object Sender, int CurrentTask, int TaskCount, float PercentComplete, float CurrentFps, float AverageFps, TimeSpan TimeRemaining)
\r
1722 if (this.InvokeRequired)
\r
1724 this.BeginInvoke(new EncodeProgressEventHandler(encodeOnEncodeProgress),
\r
1725 new object[] { Sender, CurrentTask, TaskCount, PercentComplete, CurrentFps, AverageFps, TimeRemaining });
\r
1728 lbl_encode.Text = string.Format("Encode Progress: {0}%, FPS: {1}, Avg FPS: {2}, Time Remaining: {3} ", PercentComplete, CurrentFps, AverageFps, TimeRemaining);
\r
1733 private enum SourceType
\r
1742 // This is the END of the road ****************************************
\r