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
10 using System.Collections.Generic;
\r
11 using System.ComponentModel;
\r
12 using System.Diagnostics;
\r
13 using System.Drawing;
\r
14 using System.Globalization;
\r
16 using System.Threading;
\r
17 using System.Windows.Forms;
\r
24 public partial class frmMain : Form
\r
26 // Objects which may be used by one or more other objects *************
\r
27 private Queue encodeQueue = new Queue();
\r
28 private PresetsHandler presetHandler = new PresetsHandler();
\r
30 // Globals: Mainly used for tracking. *********************************
\r
31 public Title selectedTitle;
\r
32 private frmQueue queueWindow;
\r
33 private frmPreview qtpreview;
\r
34 private frmActivityWindow ActivityWindow;
\r
35 private Form splash;
\r
36 public string sourcePath;
\r
37 private string lastAction;
\r
38 private SourceType selectedSourceType;
\r
39 private string dvdDrivePath;
\r
40 private string dvdDriveLabel;
\r
41 private Preset CurrentlySelectedPreset;
\r
42 private DVD currentSource;
\r
44 // Delegates **********************************************************
\r
45 private delegate void UpdateWindowHandler();
\r
47 // Applicaiton Startup ************************************************
\r
49 #region Application Startup
\r
53 // Load and setup the splash screen in this thread
\r
54 splash = new frmSplashScreen();
\r
56 Label lblStatus = new Label {Size = new Size(150, 20), Location = new Point(182, 102)};
\r
57 splash.Controls.Add(lblStatus);
\r
59 InitializeComponent();
\r
61 // Update the users config file with the CLI version data.
\r
62 lblStatus.Text = "Setting Version Data ...";
\r
63 Application.DoEvents();
\r
64 Main.SetCliVersionData();
\r
66 // Show the form, but leave disabled until preloading is complete then show the main form
\r
67 this.Enabled = false;
\r
69 Application.DoEvents(); // Forces frmMain to draw
\r
71 // Check for new versions, if update checking is enabled
\r
72 if (Properties.Settings.Default.updateStatus)
\r
74 DateTime now = DateTime.Now;
\r
75 DateTime lastCheck = Properties.Settings.Default.lastUpdateCheckDate;
\r
76 TimeSpan elapsed = now.Subtract(lastCheck);
\r
77 if (elapsed.TotalDays > Properties.Settings.Default.daysBetweenUpdateCheck)
\r
79 lblStatus.Text = "Checking for updates ...";
\r
80 Application.DoEvents();
\r
82 Main.BeginCheckForUpdates(new AsyncCallback(UpdateCheckDone), false);
\r
86 // Clear the log files in the background
\r
87 if (Properties.Settings.Default.clearOldLogs)
\r
89 lblStatus.Text = "Clearing Old Log Files ...";
\r
90 Application.DoEvents();
\r
91 Thread clearLog = new Thread(Main.ClearOldLogs);
\r
95 // Setup the GUI components
\r
96 lblStatus.Text = "Setting up the GUI ...";
\r
97 Application.DoEvents();
\r
98 LoadPresetPanel(); // Load the Preset Panel
\r
99 treeView_presets.ExpandAll();
\r
100 lbl_encode.Text = string.Empty;
\r
101 drop_mode.SelectedIndex = 0;
\r
102 queueWindow = new frmQueue(encodeQueue, this); // Prepare the Queue
\r
103 if (!Properties.Settings.Default.QueryEditorTab)
\r
104 tabs_panel.TabPages.RemoveAt(7); // Remove the query editor tab if the user does not want it enabled.
\r
106 // Load the user's default settings or Normal Preset
\r
107 if (Properties.Settings.Default.defaultPreset != string.Empty)
\r
109 if (presetHandler.GetPreset(Properties.Settings.Default.defaultPreset) != null)
\r
111 string query = presetHandler.GetPreset(Properties.Settings.Default.defaultPreset).Query;
\r
112 bool loadPictureSettings =
\r
113 presetHandler.GetPreset(Properties.Settings.Default.defaultPreset).PictureSettings;
\r
117 x264Panel.Reset2Defaults();
\r
119 QueryParser presetQuery = QueryParser.Parse(query);
\r
120 PresetLoader.LoadPreset(this, presetQuery, Properties.Settings.Default.defaultPreset,
\r
121 loadPictureSettings);
\r
123 x264Panel.X264_StandardizeOptString();
\r
124 x264Panel.X264_SetCurrentSettingsInPanel();
\r
128 loadNormalPreset();
\r
131 loadNormalPreset();
\r
133 // Enabled GUI tooltip's if Required
\r
134 if (Properties.Settings.Default.tooltipEnable)
\r
135 ToolTip.Active = true;
\r
137 // Register with Growl (if not using Growl for the encoding completion action, this wont hurt anything)
\r
138 GrowlCommunicator.Register();
\r
140 // Finished Loading
\r
141 lblStatus.Text = "Loading Complete!";
\r
142 Application.DoEvents();
\r
145 this.Enabled = true;
\r
147 // Event Handlers and Queue Recovery
\r
152 private void UpdateCheckDone(IAsyncResult result)
\r
154 if (InvokeRequired)
\r
156 Invoke(new MethodInvoker(() => UpdateCheckDone(result)));
\r
160 UpdateCheckInformation info;
\r
164 info = Main.EndCheckForUpdates(result);
\r
166 if (info.NewVersionAvailable)
\r
168 frmUpdater updateWindow = new frmUpdater(info.BuildInformation);
\r
169 updateWindow.ShowDialog();
\r
172 catch (Exception ex)
\r
174 if ((bool) result.AsyncState)
\r
176 "Unable to check for updates, Please try again later.\n\nDetailed Error Information:\n" + ex,
\r
177 "Error", MessageBoxButtons.OK, MessageBoxIcon.Error);
\r
181 // Startup Functions
\r
182 private void queueRecovery()
\r
184 if (Main.CheckQueueRecovery())
\r
186 DialogResult result =
\r
188 "HandBrake has detected unfinished items on the queue from the last time the application was launched. Would you like to recover these?",
\r
189 "Queue Recovery Possible", MessageBoxButtons.YesNo, MessageBoxIcon.Question);
\r
191 if (result == DialogResult.Yes)
\r
192 encodeQueue.LoadQueueFromFile("hb_queue_recovery.xml"); // Start Recovery
\r
195 // Remove the Queue recovery file if the user doesn't want to recovery the last queue.
\r
196 string queuePath = Path.Combine(Path.GetTempPath(), "hb_queue_recovery.xml");
\r
197 if (File.Exists(queuePath))
\r
198 File.Delete(queuePath);
\r
207 public string SourceName
\r
211 if (this.selectedSourceType == SourceType.DvdDrive)
\r
213 return this.dvdDriveLabel;
\r
216 if (Path.GetFileNameWithoutExtension(this.sourcePath) != "VIDEO_TS")
\r
217 return Path.GetFileNameWithoutExtension(this.sourcePath);
\r
219 return Path.GetFileNameWithoutExtension(Path.GetDirectoryName(this.sourcePath));
\r
227 // Encoding Events for setting up the GUI
\r
228 private void events()
\r
230 // Handle Widget changes when preset is selected.
\r
231 RegisterPresetEventHandler();
\r
233 // Handle Window Resize
\r
234 if (Properties.Settings.Default.MainWindowMinimize)
\r
235 this.Resize += new EventHandler(frmMain_Resize);
\r
237 // Handle Encode Start / Finish / Pause
\r
239 encodeQueue.QueuePauseRequested += new EventHandler(encodePaused);
\r
240 encodeQueue.EncodeStarted += new EventHandler(encodeStarted);
\r
241 encodeQueue.EncodeEnded += new EventHandler(encodeEnded);
\r
243 // Handle a file being draged onto the GUI.
\r
244 this.DragEnter += new DragEventHandler(frmMain_DragEnter);
\r
245 this.DragDrop += new DragEventHandler(frmMain_DragDrop);
\r
248 // 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
249 private void RegisterPresetEventHandler()
\r
252 drop_format.SelectedIndexChanged += new EventHandler(changePresetLabel);
\r
253 check_largeFile.CheckedChanged += new EventHandler(changePresetLabel);
\r
254 check_iPodAtom.CheckedChanged += new EventHandler(changePresetLabel);
\r
255 check_optimiseMP4.CheckedChanged += new EventHandler(changePresetLabel);
\r
257 // Picture Settings
\r
258 // PictureSettings.PictureSettingsChanged += new EventHandler(changePresetLabel);
\r
261 Filters.FilterSettingsChanged += new EventHandler(changePresetLabel);
\r
264 drp_videoEncoder.SelectedIndexChanged += new EventHandler(changePresetLabel);
\r
265 check_2PassEncode.CheckedChanged += new EventHandler(changePresetLabel);
\r
266 check_turbo.CheckedChanged += new EventHandler(changePresetLabel);
\r
267 text_filesize.TextChanged += new EventHandler(changePresetLabel);
\r
268 text_bitrate.TextChanged += new EventHandler(changePresetLabel);
\r
269 slider_videoQuality.ValueChanged += new EventHandler(changePresetLabel);
\r
272 AudioSettings.AudioListChanged += new EventHandler(changePresetLabel);
\r
275 x264Panel.rtf_x264Query.TextChanged += new EventHandler(changePresetLabel);
\r
278 private void UnRegisterPresetEventHandler()
\r
280 // Output Settings
\r
281 drop_format.SelectedIndexChanged -= new EventHandler(changePresetLabel);
\r
282 check_largeFile.CheckedChanged -= new EventHandler(changePresetLabel);
\r
283 check_iPodAtom.CheckedChanged -= new EventHandler(changePresetLabel);
\r
284 check_optimiseMP4.CheckedChanged -= new EventHandler(changePresetLabel);
\r
286 // Picture Settings
\r
287 // PictureSettings.PictureSettingsChanged -= new EventHandler(changePresetLabel);
\r
290 Filters.FilterSettingsChanged -= new EventHandler(changePresetLabel);
\r
293 drp_videoEncoder.SelectedIndexChanged -= new EventHandler(changePresetLabel);
\r
294 check_2PassEncode.CheckedChanged -= new EventHandler(changePresetLabel);
\r
295 check_turbo.CheckedChanged -= new EventHandler(changePresetLabel);
\r
296 text_filesize.TextChanged -= new EventHandler(changePresetLabel);
\r
297 text_bitrate.TextChanged -= new EventHandler(changePresetLabel);
\r
298 slider_videoQuality.ValueChanged -= new EventHandler(changePresetLabel);
\r
301 AudioSettings.AudioListChanged -= new EventHandler(changePresetLabel);
\r
304 x264Panel.rtf_x264Query.TextChanged -= new EventHandler(changePresetLabel);
\r
307 private void changePresetLabel(object sender, EventArgs e)
\r
309 labelPreset.Text = "Output Settings (Preset: Custom)";
\r
310 CurrentlySelectedPreset = null;
\r
313 private static void frmMain_DragEnter(object sender, DragEventArgs e)
\r
315 if (e.Data.GetDataPresent(DataFormats.FileDrop, false))
\r
316 e.Effect = DragDropEffects.All;
\r
319 private void frmMain_DragDrop(object sender, DragEventArgs e)
\r
321 string[] fileList = e.Data.GetData(DataFormats.FileDrop) as string[];
\r
322 sourcePath = string.Empty;
\r
324 if (fileList != null)
\r
326 if (fileList[0] != string.Empty)
\r
328 this.selectedSourceType = SourceType.VideoFile;
\r
329 StartScan(fileList[0], 0);
\r
332 UpdateSourceLabel();
\r
335 UpdateSourceLabel();
\r
338 private void encodeStarted(object sender, EventArgs e)
\r
340 lastAction = "encode";
\r
341 SetEncodeStarted();
\r
343 // Experimental HBProc Process Monitoring.
\r
344 if (Properties.Settings.Default.enocdeStatusInGui)
\r
346 Thread encodeMon = new Thread(EncodeMonitorThread);
\r
351 private void encodeEnded(object sender, EventArgs e)
\r
353 SetEncodeFinished();
\r
356 private void encodePaused(object sender, EventArgs e)
\r
358 SetEncodeFinished();
\r
363 // User Interface Menus / Tool Strips *********************************
\r
367 private void mnu_killCLI_Click(object sender, EventArgs e)
\r
372 private void mnu_exit_Click(object sender, EventArgs e)
\r
374 Application.Exit();
\r
381 private void mnu_encode_Click(object sender, EventArgs e)
\r
383 queueWindow.Show();
\r
386 private void mnu_encodeLog_Click(object sender, EventArgs e)
\r
388 frmActivityWindow dvdInfoWindow = new frmActivityWindow(lastAction);
\r
389 dvdInfoWindow.Show();
\r
392 private void mnu_options_Click(object sender, EventArgs e)
\r
394 Form options = new frmOptions(this);
\r
395 options.ShowDialog();
\r
400 #region Presets Menu
\r
402 private void mnu_presetReset_Click(object sender, EventArgs e)
\r
404 presetHandler.UpdateBuiltInPresets();
\r
406 if (treeView_presets.Nodes.Count == 0)
\r
408 "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!",
\r
409 "Error", MessageBoxButtons.OK, MessageBoxIcon.Error);
\r
411 MessageBox.Show("Presets have been updated!", "Alert", MessageBoxButtons.OK, MessageBoxIcon.Information);
\r
413 treeView_presets.ExpandAll();
\r
416 private void mnu_delete_preset_Click(object sender, EventArgs e)
\r
418 presetHandler.RemoveBuiltInPresets();
\r
419 LoadPresetPanel(); // Reload the preset panel
\r
422 private void mnu_SelectDefault_Click(object sender, EventArgs e)
\r
424 loadNormalPreset();
\r
427 private void mnu_importMacPreset_Click(object sender, EventArgs e)
\r
432 private void btn_new_preset_Click(object sender, EventArgs e)
\r
434 Form preset = new frmAddPreset(this, QueryGenerator.GenerateCliQuery(this, drop_mode.SelectedIndex, 0, null),
\r
436 preset.ShowDialog();
\r
443 private void mnu_user_guide_Click(object sender, EventArgs e)
\r
445 Process.Start("http://trac.handbrake.fr/wiki/HandBrakeGuide");
\r
448 private void mnu_handbrake_home_Click(object sender, EventArgs e)
\r
450 Process.Start("http://handbrake.fr");
\r
453 private void mnu_UpdateCheck_Click(object sender, EventArgs e)
\r
455 lbl_updateCheck.Visible = true;
\r
456 Main.BeginCheckForUpdates(new AsyncCallback(updateCheckDoneMenu), false);
\r
459 private void updateCheckDoneMenu(IAsyncResult result)
\r
461 // Make sure it's running on the calling thread
\r
462 if (InvokeRequired)
\r
464 Invoke(new MethodInvoker(() => updateCheckDoneMenu(result)));
\r
467 UpdateCheckInformation info;
\r
470 // Get the information about the new build, if any, and close the window
\r
471 info = Main.EndCheckForUpdates(result);
\r
473 if (info.NewVersionAvailable && info.BuildInformation != null)
\r
475 frmUpdater updateWindow = new frmUpdater(info.BuildInformation);
\r
476 updateWindow.ShowDialog();
\r
479 MessageBox.Show("There are no new updates at this time.", "Update Check", MessageBoxButtons.OK,
\r
480 MessageBoxIcon.Information);
\r
481 lbl_updateCheck.Visible = false;
\r
484 catch (Exception ex)
\r
486 if ((bool) result.AsyncState)
\r
488 "Unable to check for updates, Please try again later.\n\nDetailed Error Information:\n" + ex,
\r
489 "Error", MessageBoxButtons.OK, MessageBoxIcon.Error);
\r
493 private void mnu_about_Click(object sender, EventArgs e)
\r
495 using (frmAbout About = new frmAbout())
\r
497 About.ShowDialog();
\r
505 // Right Click Menu Code
\r
506 private void pmnu_expandAll_Click(object sender, EventArgs e)
\r
508 treeView_presets.ExpandAll();
\r
511 private void pmnu_collapse_Click(object sender, EventArgs e)
\r
513 treeView_presets.CollapseAll();
\r
516 private void pmnu_import_Click(object sender, EventArgs e)
\r
521 private void pmnu_saveChanges_Click(object sender, EventArgs e)
\r
523 DialogResult result =
\r
525 "Do you wish to include picture settings when updating the preset: " +
\r
526 treeView_presets.SelectedNode.Text, "Update Preset", MessageBoxButtons.YesNoCancel,
\r
527 MessageBoxIcon.Question);
\r
528 if (result == DialogResult.Yes)
\r
529 presetHandler.Update(treeView_presets.SelectedNode.Text,
\r
530 QueryGenerator.GenerateTabbedComponentsQuery(this), true);
\r
531 else if (result == DialogResult.No)
\r
532 presetHandler.Update(treeView_presets.SelectedNode.Text,
\r
533 QueryGenerator.GenerateTabbedComponentsQuery(this), false);
\r
536 private void pmnu_delete_click(object sender, EventArgs e)
\r
538 if (treeView_presets.SelectedNode != null)
\r
540 presetHandler.Remove(treeView_presets.SelectedNode.Text);
\r
541 treeView_presets.Nodes.Remove(treeView_presets.SelectedNode);
\r
543 treeView_presets.Select();
\r
546 private void presets_menu_Opening(object sender, CancelEventArgs e)
\r
548 // Make sure that the save menu is always disabled by default
\r
549 pmnu_saveChanges.Enabled = false;
\r
551 // Now enable the save menu if the selected preset is a user preset
\r
552 if (treeView_presets.SelectedNode != null)
\r
553 if (presetHandler.CheckIfUserPresetExists(treeView_presets.SelectedNode.Text))
\r
554 pmnu_saveChanges.Enabled = true;
\r
556 treeView_presets.Select();
\r
559 // Presets Management
\r
560 private void btn_addPreset_Click(object sender, EventArgs e)
\r
562 Form preset = new frmAddPreset(this, QueryGenerator.GenerateTabbedComponentsQuery(this), presetHandler);
\r
563 preset.ShowDialog();
\r
566 private void btn_removePreset_Click(object sender, EventArgs e)
\r
568 DialogResult result = MessageBox.Show("Are you sure you wish to delete the selected preset?", "Preset",
\r
569 MessageBoxButtons.YesNo, MessageBoxIcon.Question);
\r
570 if (result == DialogResult.Yes)
\r
572 if (treeView_presets.SelectedNode != null)
\r
574 presetHandler.Remove(treeView_presets.SelectedNode.Text);
\r
575 treeView_presets.Nodes.Remove(treeView_presets.SelectedNode);
\r
578 treeView_presets.Select();
\r
581 private void btn_setDefault_Click(object sender, EventArgs e)
\r
583 if (treeView_presets.SelectedNode != null)
\r
585 DialogResult result = MessageBox.Show("Are you sure you wish to set this preset as the default?",
\r
586 "Preset", MessageBoxButtons.YesNo, MessageBoxIcon.Question);
\r
587 if (result == DialogResult.Yes)
\r
589 Properties.Settings.Default.defaultPreset = treeView_presets.SelectedNode.Text;
\r
590 Properties.Settings.Default.Save();
\r
591 MessageBox.Show("New default preset set.", "Alert", MessageBoxButtons.OK, MessageBoxIcon.Information);
\r
595 MessageBox.Show("Please select a preset first.", "Warning", MessageBoxButtons.OK, MessageBoxIcon.Warning);
\r
598 private void treeview_presets_mouseUp(object sender, MouseEventArgs e)
\r
600 if (e.Button == MouseButtons.Right)
\r
601 treeView_presets.SelectedNode = treeView_presets.GetNodeAt(e.Location);
\r
602 else if (e.Button == MouseButtons.Left)
\r
604 if (treeView_presets.GetNodeAt(e.Location) != null)
\r
606 if (labelPreset.Text.Contains(treeView_presets.GetNodeAt(e.Location).Text))
\r
611 treeView_presets.Select();
\r
614 private void treeView_presets_AfterSelect(object sender, TreeViewEventArgs e)
\r
619 private void treeView_presets_deleteKey(object sender, KeyEventArgs e)
\r
621 if (e.KeyCode == Keys.Delete)
\r
623 DialogResult result = MessageBox.Show("Are you sure you wish to delete the selected preset?", "Preset",
\r
624 MessageBoxButtons.YesNo, MessageBoxIcon.Question);
\r
625 if (result == DialogResult.Yes)
\r
627 if (treeView_presets.SelectedNode != null)
\r
628 presetHandler.Remove(treeView_presets.SelectedNode.Text);
\r
630 // Remember each nodes expanded status so we can reload it
\r
631 List<bool> nodeStatus = new List<bool>();
\r
632 foreach (TreeNode node in treeView_presets.Nodes)
\r
633 nodeStatus.Add(node.IsExpanded);
\r
635 // Now reload the preset panel
\r
638 // And finally, re-expand any of the nodes if required
\r
640 foreach (TreeNode node in treeView_presets.Nodes)
\r
651 private void selectPreset()
\r
653 if (treeView_presets.SelectedNode != null)
\r
655 // Ok, so, we've selected a preset. Now we want to load it.
\r
656 string presetName = treeView_presets.SelectedNode.Text;
\r
657 Preset preset = presetHandler.GetPreset(presetName);
\r
658 if (preset != null)
\r
660 string query = presetHandler.GetPreset(presetName).Query;
\r
661 bool loadPictureSettings = presetHandler.GetPreset(presetName).PictureSettings;
\r
665 // Ok, Reset all the H264 widgets before changing the preset
\r
666 x264Panel.Reset2Defaults();
\r
668 // Send the query from the file to the Query Parser class
\r
669 QueryParser presetQuery = QueryParser.Parse(query);
\r
671 // Now load the preset
\r
672 PresetLoader.LoadPreset(this, presetQuery, presetName, loadPictureSettings);
\r
674 // The x264 widgets will need updated, so do this now:
\r
675 x264Panel.X264_StandardizeOptString();
\r
676 x264Panel.X264_SetCurrentSettingsInPanel();
\r
678 // Finally, let this window have a copy of the preset settings.
\r
679 CurrentlySelectedPreset = preset;
\r
680 PictureSettings.SetPresetCropWarningLabel(preset);
\r
686 private void loadNormalPreset()
\r
688 foreach (TreeNode treenode in treeView_presets.Nodes)
\r
690 foreach (TreeNode node in treenode.Nodes)
\r
692 if (node.Text.Equals("Normal"))
\r
693 treeView_presets.SelectedNode = treeView_presets.Nodes[treenode.Index].Nodes[0];
\r
698 private void importPreset()
\r
700 if (openPreset.ShowDialog() == DialogResult.OK)
\r
702 QueryParser parsed = PlistPresetHandler.Import(openPreset.FileName);
\r
703 if (presetHandler.CheckIfUserPresetExists(parsed.PresetName + " (Imported)"))
\r
705 DialogResult result =
\r
706 MessageBox.Show("This preset appears to already exist. Would you like to overwrite it?",
\r
707 "Overwrite preset?",
\r
708 MessageBoxButtons.YesNo, MessageBoxIcon.Warning);
\r
709 if (result == DialogResult.Yes)
\r
711 PresetLoader.LoadPreset(this, parsed, parsed.PresetName, parsed.UsesPictureSettings);
\r
712 presetHandler.Update(parsed.PresetName + " (Imported)",
\r
713 QueryGenerator.GenerateCliQuery(this, drop_mode.SelectedIndex, 0, null),
\r
714 parsed.UsesPictureSettings);
\r
719 PresetLoader.LoadPreset(this, parsed, parsed.PresetName, parsed.UsesPictureSettings);
\r
720 presetHandler.Add(parsed.PresetName,
\r
721 QueryGenerator.GenerateCliQuery(this, drop_mode.SelectedIndex, 0, null),
\r
722 parsed.UsesPictureSettings);
\r
724 if (presetHandler.Add(parsed.PresetName + " (Imported)",
\r
725 QueryGenerator.GenerateCliQuery(this, drop_mode.SelectedIndex, 0, null),
\r
726 parsed.UsesPictureSettings))
\r
728 TreeNode preset_treeview = new TreeNode(parsed.PresetName + " (Imported)")
\r
730 ForeColor = Color.Black
\r
732 treeView_presets.Nodes.Add(preset_treeview);
\r
742 private void btn_source_Click(object sender, EventArgs e)
\r
744 mnu_dvd_drive.Visible = true;
\r
745 Thread driveInfoThread = new Thread(SetDriveSelectionMenuItem);
\r
746 driveInfoThread.Start();
\r
749 private void btn_start_Click(object sender, EventArgs e)
\r
751 if (btn_start.Text == "Stop")
\r
753 DialogResult result;
\r
754 if (Properties.Settings.Default.enocdeStatusInGui &&
\r
755 !Properties.Settings.Default.showCliForInGuiEncodeStatus)
\r
757 result = MessageBox.Show(
\r
758 "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
759 "Cancel Encode?", MessageBoxButtons.YesNo, MessageBoxIcon.Question);
\r
763 result = MessageBox.Show("Are you sure you wish to cancel the encode?", "Cancel Encode?",
\r
764 MessageBoxButtons.YesNo, MessageBoxIcon.Question);
\r
767 if (result == DialogResult.Yes)
\r
770 encodeQueue.Pause();
\r
772 if (Properties.Settings.Default.enocdeStatusInGui &&
\r
773 !Properties.Settings.Default.showCliForInGuiEncodeStatus)
\r
775 encodeQueue.Stop();
\r
776 if (encodeQueue.HbProcess != null)
\r
777 encodeQueue.HbProcess.WaitForExit();
\r
781 encodeQueue.SafelyClose();
\r
785 SetEncodeFinished();
\r
790 if (encodeQueue.Count != 0 ||
\r
791 (!string.IsNullOrEmpty(sourcePath) && !string.IsNullOrEmpty(text_destination.Text)))
\r
793 string generatedQuery = QueryGenerator.GenerateCliQuery(this, drop_mode.SelectedIndex, 0, null);
\r
794 string specifiedQuery = rtf_query.Text != string.Empty
\r
796 : QueryGenerator.GenerateCliQuery(this, drop_mode.SelectedIndex, 0, null);
\r
797 string query = string.Empty;
\r
799 // Check to make sure the generated query matches the GUI settings
\r
800 if (Properties.Settings.Default.PromptOnUnmatchingQueries && !string.IsNullOrEmpty(specifiedQuery) &&
\r
801 generatedQuery != specifiedQuery)
\r
803 DialogResult result = MessageBox.Show("The query under the \"Query Editor\" tab " +
\r
804 "does not match the current GUI settings.\n\nBecause the manual query takes " +
\r
805 "priority over the GUI, your recently updated settings will not be taken " +
\r
806 "into account when encoding this job." +
\r
807 Environment.NewLine + Environment.NewLine +
\r
808 "Do you want to replace the manual query with the updated GUI-generated query?",
\r
809 "Manual Query does not Match GUI",
\r
810 MessageBoxButtons.YesNoCancel, MessageBoxIcon.Asterisk,
\r
811 MessageBoxDefaultButton.Button3);
\r
815 case DialogResult.Yes:
\r
816 // Replace the manual query with the generated one
\r
817 query = generatedQuery;
\r
818 rtf_query.Text = generatedQuery;
\r
820 case DialogResult.No:
\r
821 // Use the manual query
\r
822 query = specifiedQuery;
\r
824 case DialogResult.Cancel:
\r
825 // Don't start the encode
\r
831 query = specifiedQuery;
\r
834 DialogResult overwrite = DialogResult.Yes;
\r
835 if (text_destination.Text != string.Empty)
\r
836 if (File.Exists(text_destination.Text))
\r
839 "The destination file already exists. Are you sure you want to overwrite it?",
\r
840 "Overwrite File?", MessageBoxButtons.YesNo, MessageBoxIcon.Question);
\r
842 if (overwrite == DialogResult.Yes)
\r
844 if (encodeQueue.Count == 0)
\r
845 encodeQueue.Add(query, sourcePath, text_destination.Text, (rtf_query.Text != string.Empty));
\r
847 queueWindow.SetQueue();
\r
848 if (encodeQueue.Count > 1)
\r
849 queueWindow.Show(false);
\r
851 SetEncodeStarted(); // Encode is running, so setup the GUI appropriately
\r
852 encodeQueue.Start(); // Start The Queue Encoding Process
\r
853 lastAction = "encode"; // Set the last action to encode - Used for activity window.
\r
855 if (ActivityWindow != null)
\r
856 ActivityWindow.SetEncodeMode();
\r
860 else if (string.IsNullOrEmpty(sourcePath) || string.IsNullOrEmpty(text_destination.Text))
\r
861 MessageBox.Show("No source or destination selected.", "Warning", MessageBoxButtons.OK,
\r
862 MessageBoxIcon.Warning);
\r
866 private void btn_add2Queue_Click(object sender, EventArgs e)
\r
868 if (string.IsNullOrEmpty(sourcePath) || string.IsNullOrEmpty(text_destination.Text))
\r
869 MessageBox.Show("No source or destination selected.", "Warning", MessageBoxButtons.OK,
\r
870 MessageBoxIcon.Warning);
\r
873 string query = QueryGenerator.GenerateCliQuery(this, drop_mode.SelectedIndex, 0, null);
\r
874 if (rtf_query.Text != string.Empty)
\r
875 query = rtf_query.Text;
\r
877 if (encodeQueue.CheckForDestinationDuplicate(text_destination.Text))
\r
879 DialogResult result =
\r
881 "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
882 "Warning", MessageBoxButtons.YesNo, MessageBoxIcon.Warning);
\r
883 if (result == DialogResult.Yes)
\r
884 encodeQueue.Add(query, sourcePath, text_destination.Text, (rtf_query.Text != string.Empty));
\r
887 encodeQueue.Add(query, sourcePath, text_destination.Text, (rtf_query.Text != string.Empty));
\r
889 lbl_encode.Text = encodeQueue.Count + " encode(s) pending in the queue";
\r
891 queueWindow.Show();
\r
895 private void btn_showQueue_Click(object sender, EventArgs e)
\r
897 queueWindow.Show();
\r
898 queueWindow.Activate();
\r
901 private void tb_preview_Click(object sender, EventArgs e)
\r
903 if (string.IsNullOrEmpty(sourcePath) || string.IsNullOrEmpty(text_destination.Text))
\r
904 MessageBox.Show("No source or destination selected.", "Warning", MessageBoxButtons.OK,
\r
905 MessageBoxIcon.Warning);
\r
908 if (qtpreview == null)
\r
910 qtpreview = new frmPreview(this);
\r
913 else if (qtpreview.IsDisposed)
\r
915 qtpreview = new frmPreview(this);
\r
919 MessageBox.Show(qtpreview, "The preview window is already open!", "Warning", MessageBoxButtons.OK,
\r
920 MessageBoxIcon.Warning);
\r
924 private void btn_ActivityWindow_Click(object sender, EventArgs e)
\r
926 if (ActivityWindow == null || !ActivityWindow.IsHandleCreated)
\r
927 ActivityWindow = new frmActivityWindow(lastAction);
\r
929 switch (lastAction)
\r
932 ActivityWindow.SetScanMode();
\r
935 ActivityWindow.SetEncodeMode();
\r
938 ActivityWindow.SetEncodeMode();
\r
942 ActivityWindow.Show();
\r
943 ActivityWindow.Activate();
\r
948 #region System Tray Icon
\r
950 private void frmMain_Resize(object sender, EventArgs e)
\r
952 if (FormWindowState.Minimized == this.WindowState)
\r
954 notifyIcon.Visible = true;
\r
957 else if (FormWindowState.Normal == this.WindowState)
\r
958 notifyIcon.Visible = false;
\r
961 private void notifyIcon_MouseDoubleClick(object sender, MouseEventArgs e)
\r
963 this.Visible = true;
\r
965 this.WindowState = FormWindowState.Normal;
\r
966 notifyIcon.Visible = false;
\r
969 private void btn_restore_Click(object sender, EventArgs e)
\r
971 this.Visible = true;
\r
973 this.WindowState = FormWindowState.Normal;
\r
974 notifyIcon.Visible = false;
\r
979 #region Tab Control
\r
982 private void btn_dvd_source_Click(object sender, EventArgs e)
\r
984 if (DVD_Open.ShowDialog() == DialogResult.OK)
\r
986 this.selectedSourceType = SourceType.Folder;
\r
987 SelectSource(DVD_Open.SelectedPath);
\r
990 UpdateSourceLabel();
\r
993 private void btn_file_source_Click(object sender, EventArgs e)
\r
995 if (ISO_Open.ShowDialog() == DialogResult.OK)
\r
997 this.selectedSourceType = SourceType.VideoFile;
\r
998 SelectSource(ISO_Open.FileName);
\r
1001 UpdateSourceLabel();
\r
1004 private void mnu_dvd_drive_Click(object sender, EventArgs e)
\r
1006 if (this.dvdDrivePath == null) return;
\r
1007 this.selectedSourceType = SourceType.DvdDrive;
\r
1008 SelectSource(this.dvdDrivePath);
\r
1011 private void SelectSource(string file)
\r
1013 Check_ChapterMarkers.Enabled = true;
\r
1014 lastAction = "scan";
\r
1015 sourcePath = string.Empty;
\r
1017 if (file == string.Empty) // Must have a file or path
\r
1019 UpdateSourceLabel();
\r
1023 sourcePath = Path.GetFileName(file);
\r
1024 StartScan(file, 0);
\r
1027 private void drp_dvdtitle_Click(object sender, EventArgs e)
\r
1029 if ((drp_dvdtitle.Items.Count == 1) && (drp_dvdtitle.Items[0].ToString() == "Automatic"))
\r
1031 "There are no titles to select. Please load a source file by clicking the 'Source' button above before trying to select a title.",
\r
1032 "Alert", MessageBoxButtons.OK, MessageBoxIcon.Asterisk);
\r
1035 private void drp_dvdtitle_SelectedIndexChanged(object sender, EventArgs e)
\r
1037 UnRegisterPresetEventHandler();
\r
1038 drop_mode.SelectedIndex = 0;
\r
1040 PictureSettings.lbl_Aspect.Text = "Select a Title"; // Reset some values on the form
\r
1041 drop_chapterStart.Items.Clear();
\r
1042 drop_chapterFinish.Items.Clear();
\r
1044 // If the dropdown is set to automatic nothing else needs to be done.
\r
1045 // Otheriwse if its not, title data has to be loased from parsing.
\r
1046 if (drp_dvdtitle.Text != "Automatic")
\r
1048 selectedTitle = drp_dvdtitle.SelectedItem as Title;
\r
1049 lbl_duration.Text = selectedTitle.Duration.ToString();
\r
1050 PictureSettings.CurrentlySelectedPreset = CurrentlySelectedPreset;
\r
1051 PictureSettings.Source = selectedTitle; // Setup Picture Settings Tab Control
\r
1053 // Populate the Angles dropdown
\r
1054 drop_angle.Items.Clear();
\r
1055 if (!Properties.Settings.Default.noDvdNav)
\r
1057 drop_angle.Visible = true;
\r
1058 lbl_angle.Visible = true;
\r
1059 drop_angle.Items.AddRange(selectedTitle.Angles.ToArray());
\r
1060 if (drop_angle.Items.Count != 0)
\r
1061 drop_angle.SelectedIndex = 0;
\r
1065 drop_angle.Visible = false;
\r
1066 lbl_angle.Visible = false;
\r
1069 // Populate the Start chapter Dropdown
\r
1070 drop_chapterStart.Items.Clear();
\r
1071 drop_chapterStart.Items.AddRange(selectedTitle.Chapters.ToArray());
\r
1072 if (drop_chapterStart.Items.Count > 0)
\r
1073 drop_chapterStart.Text = drop_chapterStart.Items[0].ToString();
\r
1075 // Populate the Final Chapter Dropdown
\r
1076 drop_chapterFinish.Items.Clear();
\r
1077 drop_chapterFinish.Items.AddRange(selectedTitle.Chapters.ToArray());
\r
1078 if (drop_chapterFinish.Items.Count > 0)
\r
1079 drop_chapterFinish.Text = drop_chapterFinish.Items[drop_chapterFinish.Items.Count - 1].ToString();
\r
1081 // Populate the Audio Channels Dropdown
\r
1082 AudioSettings.SetTrackList(selectedTitle);
\r
1084 // Populate the Subtitles dropdown
\r
1085 Subtitles.SetSubtitleTrackAuto(selectedTitle.Subtitles.ToArray());
\r
1087 // Update the source label if we have multiple streams
\r
1088 if (selectedTitle != null)
\r
1089 if (!string.IsNullOrEmpty(selectedTitle.SourceName))
\r
1090 labelSource.Text = labelSource.Text = Path.GetFileName(selectedTitle.SourceName);
\r
1092 // Run the AutoName & ChapterNaming functions
\r
1093 if (Properties.Settings.Default.autoNaming)
\r
1095 string autoPath = Main.AutoName(this);
\r
1096 if (autoPath != null)
\r
1097 text_destination.Text = autoPath;
\r
1100 "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')",
\r
1101 "Warning", MessageBoxButtons.OK, MessageBoxIcon.Warning);
\r
1104 data_chpt.Rows.Clear();
\r
1105 if (selectedTitle.Chapters.Count != 1)
\r
1107 DataGridView chapterGridView = Main.ChapterNaming(data_chpt, drop_chapterFinish.Text);
\r
1108 if (chapterGridView != null)
\r
1109 data_chpt = chapterGridView;
\r
1113 Check_ChapterMarkers.Checked = false;
\r
1114 Check_ChapterMarkers.Enabled = false;
\r
1117 // Hack to force the redraw of the scrollbars which don't resize properly when the control is disabled.
\r
1118 data_chpt.Columns[0].Width = 166;
\r
1119 data_chpt.Columns[0].Width = 165;
\r
1121 RegisterPresetEventHandler();
\r
1124 private void chapersChanged(object sender, EventArgs e)
\r
1126 if (drop_mode.SelectedIndex != 0) // Function is not used if we are not in chapters mode.
\r
1129 Control ctl = (Control) sender;
\r
1130 int chapterStart, chapterEnd;
\r
1131 int.TryParse(drop_chapterStart.Text, out chapterStart);
\r
1132 int.TryParse(drop_chapterFinish.Text, out chapterEnd);
\r
1136 case "drop_chapterStart":
\r
1137 if (drop_chapterFinish.SelectedIndex == -1 && drop_chapterFinish.Items.Count != 0)
\r
1138 drop_chapterFinish.SelectedIndex = drop_chapterFinish.Items.Count - 1;
\r
1140 if (chapterEnd != 0)
\r
1141 if (chapterStart > chapterEnd)
\r
1142 drop_chapterFinish.Text = chapterStart.ToString();
\r
1144 case "drop_chapterFinish":
\r
1145 if (drop_chapterStart.Items.Count >= 1 && drop_chapterStart.SelectedIndex == -1)
\r
1146 drop_chapterStart.SelectedIndex = 0;
\r
1148 if (chapterStart != 0)
\r
1149 if (chapterEnd < chapterStart)
\r
1150 drop_chapterFinish.Text = chapterStart.ToString();
\r
1152 // Add more rows to the Chapter menu if needed.
\r
1153 if (Check_ChapterMarkers.Checked)
\r
1155 int i = data_chpt.Rows.Count, finish = 0;
\r
1156 int.TryParse(drop_chapterFinish.Text, out finish);
\r
1158 while (i < finish)
\r
1160 int n = data_chpt.Rows.Add();
\r
1161 data_chpt.Rows[n].Cells[0].Value = (i + 1);
\r
1162 data_chpt.Rows[n].Cells[1].Value = "Chapter " + (i + 1);
\r
1163 data_chpt.Rows[n].Cells[0].ValueType = typeof (int);
\r
1164 data_chpt.Rows[n].Cells[1].ValueType = typeof (string);
\r
1171 // Update the Duration
\r
1172 lbl_duration.Text =
\r
1173 Main.CalculateDuration(drop_chapterStart.SelectedIndex, drop_chapterFinish.SelectedIndex, selectedTitle)
\r
1176 // Run the Autonaming function
\r
1177 if (Properties.Settings.Default.autoNaming)
\r
1178 text_destination.Text = Main.AutoName(this);
\r
1180 // Disable chapter markers if only 1 chapter is selected.
\r
1181 if (chapterStart == chapterEnd)
\r
1183 Check_ChapterMarkers.Enabled = false;
\r
1184 btn_importChapters.Enabled = false;
\r
1185 data_chpt.Enabled = false;
\r
1189 Check_ChapterMarkers.Enabled = true;
\r
1190 if (Check_ChapterMarkers.Checked)
\r
1192 btn_importChapters.Enabled = true;
\r
1193 data_chpt.Enabled = true;
\r
1198 private void SecondsOrFramesChanged(object sender, EventArgs e)
\r
1201 int.TryParse(drop_chapterStart.Text, out start);
\r
1202 int.TryParse(drop_chapterFinish.Text, out end);
\r
1203 double duration = end - start;
\r
1205 switch (drop_mode.SelectedIndex)
\r
1208 lbl_duration.Text = TimeSpan.FromSeconds(duration).ToString();
\r
1211 if (selectedTitle != null)
\r
1213 duration = duration/selectedTitle.Fps;
\r
1214 lbl_duration.Text = TimeSpan.FromSeconds(duration).ToString();
\r
1217 lbl_duration.Text = "--:--:--";
\r
1223 private void drop_mode_SelectedIndexChanged(object sender, EventArgs e)
\r
1226 this.drop_chapterFinish.TextChanged -= new EventHandler(this.SecondsOrFramesChanged);
\r
1227 this.drop_chapterStart.TextChanged -= new EventHandler(this.SecondsOrFramesChanged);
\r
1230 switch (drop_mode.SelectedIndex)
\r
1233 drop_chapterStart.DropDownStyle = ComboBoxStyle.DropDownList;
\r
1234 drop_chapterFinish.DropDownStyle = ComboBoxStyle.DropDownList;
\r
1235 if (drop_chapterStart.Items.Count != 0)
\r
1237 drop_chapterStart.SelectedIndex = 0;
\r
1238 drop_chapterFinish.SelectedIndex = drop_chapterFinish.Items.Count - 1;
\r
1241 lbl_duration.Text = "--:--:--";
\r
1244 this.drop_chapterStart.TextChanged += new EventHandler(this.SecondsOrFramesChanged);
\r
1245 this.drop_chapterFinish.TextChanged += new EventHandler(this.SecondsOrFramesChanged);
\r
1246 drop_chapterStart.DropDownStyle = ComboBoxStyle.Simple;
\r
1247 drop_chapterFinish.DropDownStyle = ComboBoxStyle.Simple;
\r
1248 if (selectedTitle != null)
\r
1250 drop_chapterStart.Text = "0";
\r
1251 drop_chapterFinish.Text = selectedTitle.Duration.TotalSeconds.ToString();
\r
1255 this.drop_chapterStart.TextChanged += new EventHandler(this.SecondsOrFramesChanged);
\r
1256 this.drop_chapterFinish.TextChanged += new EventHandler(this.SecondsOrFramesChanged);
\r
1257 drop_chapterStart.DropDownStyle = ComboBoxStyle.Simple;
\r
1258 drop_chapterFinish.DropDownStyle = ComboBoxStyle.Simple;
\r
1259 if (selectedTitle != null)
\r
1261 drop_chapterStart.Text = "0";
\r
1262 drop_chapterFinish.Text = (selectedTitle.Fps*selectedTitle.Duration.TotalSeconds).ToString();
\r
1269 private void btn_destBrowse_Click(object sender, EventArgs e)
\r
1271 // This removes the file extension from the filename box on the save file dialog.
\r
1272 // It's daft but some users don't realise that typing an extension overrides the dropdown extension selected.
\r
1273 DVD_Save.FileName = Path.GetFileNameWithoutExtension(text_destination.Text);
\r
1275 if (Path.IsPathRooted(text_destination.Text))
\r
1276 DVD_Save.InitialDirectory = Path.GetDirectoryName(text_destination.Text);
\r
1278 // Show the dialog and set the main form file path
\r
1279 if (drop_format.SelectedIndex.Equals(0))
\r
1280 DVD_Save.FilterIndex = 1;
\r
1281 else if (drop_format.SelectedIndex.Equals(1))
\r
1282 DVD_Save.FilterIndex = 2;
\r
1284 if (DVD_Save.ShowDialog() == DialogResult.OK)
\r
1286 // Add a file extension manually, as FileDialog.AddExtension has issues with dots in filenames
\r
1287 switch (DVD_Save.FilterIndex)
\r
1291 !Path.GetExtension(DVD_Save.FileName).Equals(".mp4",
\r
1292 StringComparison.InvariantCultureIgnoreCase))
\r
1293 if (Properties.Settings.Default.useM4v)
\r
1294 DVD_Save.FileName = DVD_Save.FileName.Replace(".mp4", ".m4v").Replace(".mkv", ".m4v");
\r
1296 DVD_Save.FileName = DVD_Save.FileName.Replace(".m4v", ".mp4").Replace(".mkv", ".mp4");
\r
1300 !Path.GetExtension(DVD_Save.FileName).Equals(".mkv",
\r
1301 StringComparison.InvariantCultureIgnoreCase))
\r
1302 DVD_Save.FileName = DVD_Save.FileName.Replace(".mp4", ".mkv").Replace(".m4v", ".mkv");
\r
1308 text_destination.Text = DVD_Save.FileName;
\r
1310 // Quicktime requires .m4v file for chapter markers to work. If checked, change the extension to .m4v (mp4 and m4v are the same thing)
\r
1311 if (Check_ChapterMarkers.Checked && DVD_Save.FilterIndex != 2)
\r
1312 SetExtension(".m4v");
\r
1316 private void text_destination_TextChanged(object sender, EventArgs e)
\r
1318 string path = text_destination.Text;
\r
1319 if (path.EndsWith(".mp4") || path.EndsWith(".m4v"))
\r
1320 drop_format.SelectedIndex = 0;
\r
1321 else if (path.EndsWith(".mkv"))
\r
1322 drop_format.SelectedIndex = 1;
\r
1325 // Output Settings
\r
1326 private void drop_format_SelectedIndexChanged(object sender, EventArgs e)
\r
1328 switch (drop_format.SelectedIndex)
\r
1331 if (Properties.Settings.Default.useM4v || Check_ChapterMarkers.Checked ||
\r
1332 AudioSettings.RequiresM4V() || Subtitles.RequiresM4V())
\r
1333 SetExtension(".m4v");
\r
1335 SetExtension(".mp4");
\r
1338 SetExtension(".mkv");
\r
1342 AudioSettings.SetContainer(drop_format.Text);
\r
1343 Subtitles.SetContainer(drop_format.SelectedIndex);
\r
1345 if (drop_format.Text.Contains("MP4"))
\r
1347 if (drp_videoEncoder.Items.Contains("VP3 (Theora)"))
\r
1349 drp_videoEncoder.Items.Remove("VP3 (Theora)");
\r
1350 drp_videoEncoder.SelectedIndex = 1;
\r
1353 else if (drop_format.Text.Contains("MKV"))
\r
1354 drp_videoEncoder.Items.Add("VP3 (Theora)");
\r
1357 public void SetExtension(string newExtension)
\r
1359 if (newExtension == ".mp4" || newExtension == ".m4v")
\r
1360 if (Properties.Settings.Default.useM4v || Check_ChapterMarkers.Checked || AudioSettings.RequiresM4V() ||
\r
1361 Subtitles.RequiresM4V())
\r
1362 newExtension = ".m4v";
\r
1364 newExtension = ".mp4";
\r
1366 if (Path.HasExtension(newExtension))
\r
1367 text_destination.Text = Path.ChangeExtension(text_destination.Text, newExtension);
\r
1371 private void drp_videoEncoder_SelectedIndexChanged(object sender, EventArgs e)
\r
1373 setContainerOpts();
\r
1375 // Turn off some options which are H.264 only when the user selects a non h.264 encoder
\r
1376 if (drp_videoEncoder.Text.Contains("H.264"))
\r
1378 if (check_2PassEncode.CheckState == CheckState.Checked)
\r
1379 check_turbo.Enabled = true;
\r
1381 tab_advanced.Enabled = true;
\r
1382 if ((drop_format.Text.Contains("MP4")) || (drop_format.Text.Contains("M4V")))
\r
1383 check_iPodAtom.Enabled = true;
\r
1385 check_iPodAtom.Enabled = false;
\r
1389 check_turbo.CheckState = CheckState.Unchecked;
\r
1390 check_turbo.Enabled = false;
\r
1391 tab_advanced.Enabled = false;
\r
1392 x264Panel.X264Query = string.Empty;
\r
1393 check_iPodAtom.Enabled = false;
\r
1394 check_iPodAtom.Checked = false;
\r
1397 // Setup the CQ Slider
\r
1398 switch (drp_videoEncoder.Text)
\r
1400 case "MPEG-4 (FFmpeg)":
\r
1401 if (slider_videoQuality.Value > 31)
\r
1402 slider_videoQuality.Value = 20; // Just reset to 70% QP 10 on encode change.
\r
1403 slider_videoQuality.Minimum = 1;
\r
1404 slider_videoQuality.Maximum = 31;
\r
1406 case "H.264 (x264)":
\r
1407 slider_videoQuality.Minimum = 0;
\r
1408 slider_videoQuality.TickFrequency = 1;
\r
1410 CultureInfo culture = CultureInfo.CreateSpecificCulture("en-US");
\r
1411 double cqStep = Properties.Settings.Default.x264cqstep;
\r
1412 double multiplier = 1.0/cqStep;
\r
1413 double value = slider_videoQuality.Value*multiplier;
\r
1415 switch (Properties.Settings.Default.x264cqstep.ToString(culture))
\r
1418 slider_videoQuality.Maximum = 255;
\r
1421 slider_videoQuality.Maximum = 204;
\r
1424 slider_videoQuality.Maximum = 102;
\r
1427 slider_videoQuality.Maximum = 51;
\r
1430 slider_videoQuality.Maximum = 51;
\r
1433 if (value < slider_videoQuality.Maximum)
\r
1434 slider_videoQuality.Value = slider_videoQuality.Maximum - (int) value;
\r
1437 case "VP3 (Theora)":
\r
1438 if (slider_videoQuality.Value > 63)
\r
1439 slider_videoQuality.Value = 45; // Just reset to 70% QP 45 on encode change.
\r
1440 slider_videoQuality.Minimum = 0;
\r
1441 slider_videoQuality.Maximum = 63;
\r
1447 /// Set the container format options
\r
1449 public void setContainerOpts()
\r
1451 if ((drop_format.Text.Contains("MP4")) || (drop_format.Text.Contains("M4V")))
\r
1453 check_largeFile.Enabled = true;
\r
1454 check_optimiseMP4.Enabled = true;
\r
1455 check_iPodAtom.Enabled = true;
\r
1459 check_largeFile.Enabled = false;
\r
1460 check_optimiseMP4.Enabled = false;
\r
1461 check_iPodAtom.Enabled = false;
\r
1462 check_largeFile.Checked = false;
\r
1463 check_optimiseMP4.Checked = false;
\r
1464 check_iPodAtom.Checked = false;
\r
1468 private double _cachedCqStep = Properties.Settings.Default.x264cqstep;
\r
1471 /// Update the CQ slider for x264 for a new CQ step. This is set from option
\r
1473 public void setQualityFromSlider()
\r
1475 // Work out the current RF value.
\r
1476 double cqStep = _cachedCqStep;
\r
1477 double rfValue = 51.0 - slider_videoQuality.Value*cqStep;
\r
1479 // Change the maximum value for the slider
\r
1480 switch (Properties.Settings.Default.x264cqstep.ToString(new CultureInfo("en-US")))
\r
1483 slider_videoQuality.Maximum = 255;
\r
1486 slider_videoQuality.Maximum = 204;
\r
1489 slider_videoQuality.Maximum = 102;
\r
1492 slider_videoQuality.Maximum = 51;
\r
1495 slider_videoQuality.Maximum = 51;
\r
1499 // Reset the CQ slider to RF0
\r
1500 slider_videoQuality.Value = slider_videoQuality.Maximum;
\r
1502 // Reset the CQ slider back to the previous value as close as possible
\r
1503 double cqStepNew = Properties.Settings.Default.x264cqstep;
\r
1504 double rfValueCurrent = 51.0 - slider_videoQuality.Value*cqStepNew;
\r
1505 while (rfValueCurrent < rfValue)
\r
1507 slider_videoQuality.Value--;
\r
1508 rfValueCurrent = 51.0 - slider_videoQuality.Value*cqStepNew;
\r
1511 // Cache the CQ step for the next calculation
\r
1512 _cachedCqStep = Properties.Settings.Default.x264cqstep;
\r
1515 private void slider_videoQuality_Scroll(object sender, EventArgs e)
\r
1517 double cqStep = Properties.Settings.Default.x264cqstep;
\r
1518 switch (drp_videoEncoder.Text)
\r
1520 case "MPEG-4 (FFmpeg)":
\r
1521 lbl_SliderValue.Text = "QP:" + (32 - slider_videoQuality.Value);
\r
1523 case "H.264 (x264)":
\r
1524 double rfValue = 51.0 - slider_videoQuality.Value*cqStep;
\r
1525 rfValue = Math.Round(rfValue, 2);
\r
1526 lbl_SliderValue.Text = "RF:" + rfValue.ToString(new CultureInfo("en-US"));
\r
1528 case "VP3 (Theora)":
\r
1529 lbl_SliderValue.Text = "QP:" + slider_videoQuality.Value;
\r
1534 private void radio_targetFilesize_CheckedChanged(object sender, EventArgs e)
\r
1536 text_bitrate.Enabled = false;
\r
1537 text_filesize.Enabled = true;
\r
1538 slider_videoQuality.Enabled = false;
\r
1540 check_2PassEncode.Enabled = true;
\r
1543 private void radio_avgBitrate_CheckedChanged(object sender, EventArgs e)
\r
1545 text_bitrate.Enabled = true;
\r
1546 text_filesize.Enabled = false;
\r
1547 slider_videoQuality.Enabled = false;
\r
1549 check_2PassEncode.Enabled = true;
\r
1552 private void radio_cq_CheckedChanged(object sender, EventArgs e)
\r
1554 text_bitrate.Enabled = false;
\r
1555 text_filesize.Enabled = false;
\r
1556 slider_videoQuality.Enabled = true;
\r
1558 check_2PassEncode.Enabled = false;
\r
1559 check_2PassEncode.CheckState = CheckState.Unchecked;
\r
1562 private void check_2PassEncode_CheckedChanged(object sender, EventArgs e)
\r
1564 if (check_2PassEncode.CheckState.ToString() == "Checked")
\r
1566 if (drp_videoEncoder.Text.Contains("H.264"))
\r
1567 check_turbo.Enabled = true;
\r
1571 check_turbo.Enabled = false;
\r
1572 check_turbo.CheckState = CheckState.Unchecked;
\r
1576 // Chapter Marker Tab
\r
1577 private void Check_ChapterMarkers_CheckedChanged(object sender, EventArgs e)
\r
1579 if (Check_ChapterMarkers.Checked)
\r
1581 if (drop_format.SelectedIndex != 1)
\r
1582 SetExtension(".m4v");
\r
1583 data_chpt.Enabled = true;
\r
1584 btn_importChapters.Enabled = true;
\r
1588 if (drop_format.SelectedIndex != 1 && !Properties.Settings.Default.useM4v)
\r
1589 SetExtension(".mp4");
\r
1590 data_chpt.Enabled = false;
\r
1591 btn_importChapters.Enabled = false;
\r
1595 private void btn_importChapters_Click(object sender, EventArgs e)
\r
1597 if (File_ChapterImport.ShowDialog() == DialogResult.OK)
\r
1599 string filename = File_ChapterImport.FileName;
\r
1600 DataGridView imported = Main.ImportChapterNames(data_chpt, filename);
\r
1601 if (imported != null)
\r
1602 data_chpt = imported;
\r
1606 private void mnu_resetChapters_Click(object sender, EventArgs e)
\r
1608 data_chpt.Rows.Clear();
\r
1609 DataGridView chapterGridView = Main.ChapterNaming(data_chpt, drop_chapterFinish.Text);
\r
1610 if (chapterGridView != null)
\r
1612 data_chpt = chapterGridView;
\r
1616 // Query Editor Tab
\r
1617 private void btn_generate_Query_Click(object sender, EventArgs e)
\r
1619 rtf_query.Text = QueryGenerator.GenerateCliQuery(this, drop_mode.SelectedIndex, 0, null);
\r
1622 private void btn_clear_Click(object sender, EventArgs e)
\r
1624 rtf_query.Clear();
\r
1629 // MainWindow Components, Actions and Functions ***********************
\r
1631 #region Source Scan
\r
1633 public bool isScanning { get; set; }
\r
1634 private Scan SourceScan;
\r
1636 private void StartScan(string filename, int title)
\r
1638 // Setup the GUI components for the scan.
\r
1639 sourcePath = filename;
\r
1640 foreach (Control ctrl in Controls)
\r
1641 if (!(ctrl is StatusStrip || ctrl is MenuStrip || ctrl is ToolStrip))
\r
1642 ctrl.Enabled = false;
\r
1644 lbl_encode.Visible = true;
\r
1645 lbl_encode.Text = "Scanning ...";
\r
1646 btn_source.Enabled = false;
\r
1647 btn_start.Enabled = false;
\r
1648 btn_showQueue.Enabled = false;
\r
1649 btn_add2Queue.Enabled = false;
\r
1650 tb_preview.Enabled = false;
\r
1651 mnu_killCLI.Visible = true;
\r
1653 if (ActivityWindow != null)
\r
1654 ActivityWindow.SetScanMode();
\r
1659 isScanning = true;
\r
1660 SourceScan = new Scan();
\r
1661 SourceScan.ScanSource(sourcePath, title);
\r
1662 SourceScan.ScanStatusChanged += new EventHandler(SourceScan_ScanStatusChanged);
\r
1663 SourceScan.ScanCompleted += new EventHandler(SourceScan_ScanCompleted);
\r
1665 catch (Exception exc)
\r
1667 MessageBox.Show("frmMain.cs - StartScan " + exc, "Error", MessageBoxButtons.OK, MessageBoxIcon.Error);
\r
1671 private void SourceScan_ScanStatusChanged(object sender, EventArgs e)
\r
1673 UpdateScanStatusLabel();
\r
1676 private void SourceScan_ScanCompleted(object sender, EventArgs e)
\r
1678 UpdateGuiAfterScan();
\r
1681 private void UpdateScanStatusLabel()
\r
1683 if (InvokeRequired)
\r
1685 BeginInvoke(new UpdateWindowHandler(UpdateScanStatusLabel));
\r
1688 lbl_encode.Text = SourceScan.ScanStatus();
\r
1691 private void UpdateGuiAfterScan()
\r
1693 if (InvokeRequired)
\r
1695 BeginInvoke(new UpdateWindowHandler(UpdateGuiAfterScan));
\r
1701 currentSource = SourceScan.SouceData();
\r
1703 // Setup some GUI components
\r
1704 drp_dvdtitle.Items.Clear();
\r
1705 if (currentSource.Titles.Count != 0)
\r
1706 drp_dvdtitle.Items.AddRange(currentSource.Titles.ToArray());
\r
1708 // Now select the longest title
\r
1709 if (currentSource.Titles.Count != 0)
\r
1710 drp_dvdtitle.SelectedItem = Main.SelectLongestTitle(currentSource);
\r
1712 // Enable the creation of chapter markers if the file is an image of a dvd.
\r
1713 if (sourcePath.ToLower().Contains(".iso") || sourcePath.Contains("VIDEO_TS") ||
\r
1714 Directory.Exists(Path.Combine(sourcePath, "VIDEO_TS")))
\r
1715 Check_ChapterMarkers.Enabled = true;
\r
1718 Check_ChapterMarkers.Enabled = false;
\r
1719 Check_ChapterMarkers.Checked = false;
\r
1720 data_chpt.Rows.Clear();
\r
1723 // If no titles were found, Display an error message
\r
1724 if (drp_dvdtitle.Items.Count == 0)
\r
1727 "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
1728 "Error", MessageBoxButtons.OK, MessageBoxIcon.Hand);
\r
1729 sourcePath = string.Empty;
\r
1731 UpdateSourceLabel();
\r
1733 // Enable the GUI components and enable any disabled components
\r
1736 catch (Exception exc)
\r
1738 MessageBox.Show("frmMain.cs - updateUIafterScan " + exc, "Error", MessageBoxButtons.OK,
\r
1739 MessageBoxIcon.Error);
\r
1744 private void EnableGUI()
\r
1748 if (InvokeRequired)
\r
1749 BeginInvoke(new UpdateWindowHandler(EnableGUI));
\r
1750 lbl_encode.Text = "Scan Completed";
\r
1751 foreach (Control ctrl in Controls)
\r
1752 ctrl.Enabled = true;
\r
1753 btn_start.Enabled = true;
\r
1754 btn_showQueue.Enabled = true;
\r
1755 btn_add2Queue.Enabled = true;
\r
1756 tb_preview.Enabled = true;
\r
1757 btn_source.Enabled = true;
\r
1758 mnu_killCLI.Visible = false;
\r
1760 catch (Exception exc)
\r
1762 MessageBox.Show("frmMain.cs - EnableGUI() " + exc, "Error", MessageBoxButtons.OK, MessageBoxIcon.Error);
\r
1766 private void KillScan()
\r
1770 SourceScan.ScanCompleted -= new EventHandler(SourceScan_ScanCompleted);
\r
1774 if (SourceScan.ScanProcess() != null)
\r
1775 SourceScan.ScanProcess().Kill();
\r
1777 lbl_encode.Text = "Scan Cancelled!";
\r
1779 catch (Exception ex)
\r
1782 "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" +
\r
1783 ex.Message, "Error", MessageBoxButtons.OK, MessageBoxIcon.Error);
\r
1787 private void ResetGUI()
\r
1789 drp_dvdtitle.Items.Clear();
\r
1790 drop_chapterStart.Items.Clear();
\r
1791 drop_chapterFinish.Items.Clear();
\r
1792 lbl_duration.Text = "Select a Title";
\r
1793 PictureSettings.lbl_src_res.Text = "Select a Title";
\r
1794 PictureSettings.lbl_Aspect.Text = "Select a Title";
\r
1795 sourcePath = String.Empty;
\r
1796 text_destination.Text = String.Empty;
\r
1797 selectedTitle = null;
\r
1798 isScanning = false;
\r
1801 private void UpdateSourceLabel()
\r
1803 labelSource.Text = string.IsNullOrEmpty(sourcePath) ? "Select \"Source\" to continue." : this.SourceName;
\r
1805 if (selectedTitle != null)
\r
1806 if (!string.IsNullOrEmpty(selectedTitle.SourceName))
\r
1807 // If it's one of multiple source files, make sure we don't use the folder name
\r
1808 labelSource.Text = Path.GetFileName(selectedTitle.SourceName);
\r
1811 public void RecievingJob(Job job)
\r
1813 string query = job.Query;
\r
1814 StartScan(job.Source, 0);
\r
1817 if (query != null)
\r
1819 // Ok, Reset all the H264 widgets before changing the preset
\r
1820 x264Panel.Reset2Defaults();
\r
1822 // Send the query from the file to the Query Parser class
\r
1823 QueryParser presetQuery = QueryParser.Parse(query);
\r
1825 // Now load the preset
\r
1826 PresetLoader.LoadPreset(this, presetQuery, "Load Back From Queue", true);
\r
1828 // The x264 widgets will need updated, so do this now:
\r
1829 x264Panel.X264_StandardizeOptString();
\r
1830 x264Panel.X264_SetCurrentSettingsInPanel();
\r
1832 // Finally, let this window have a copy of the preset settings.
\r
1833 CurrentlySelectedPreset = null;
\r
1834 PictureSettings.SetPresetCropWarningLabel(null);
\r
1840 #region GUI Functions and Actions
\r
1843 /// Set the GUI to it's finished encoding state.
\r
1845 private void SetEncodeFinished()
\r
1849 if (InvokeRequired)
\r
1851 BeginInvoke(new UpdateWindowHandler(SetEncodeFinished));
\r
1855 lbl_encode.Text = "Encoding Finished";
\r
1856 btn_start.Text = "Start";
\r
1857 btn_start.ToolTipText = "Start the encoding process";
\r
1858 btn_start.Image = Properties.Resources.Play;
\r
1860 // If the window is minimized, display the notification in a popup.
\r
1861 if (Properties.Settings.Default.trayIconAlerts)
\r
1862 if (FormWindowState.Minimized == this.WindowState)
\r
1864 notifyIcon.BalloonTipText = lbl_encode.Text;
\r
1865 notifyIcon.ShowBalloonTip(500);
\r
1868 catch (Exception exc)
\r
1870 MessageBox.Show(exc.ToString());
\r
1875 /// Set the GUI to it's started encoding state.
\r
1877 private void SetEncodeStarted()
\r
1881 if (InvokeRequired)
\r
1883 BeginInvoke(new UpdateWindowHandler(SetEncodeStarted));
\r
1887 lbl_encode.Visible = true;
\r
1888 lbl_encode.Text = "Encoding with " + encodeQueue.Count + " encode(s) pending";
\r
1889 btn_start.Text = "Stop";
\r
1890 btn_start.ToolTipText = "Stop the encoding process.";
\r
1891 btn_start.Image = Properties.Resources.stop;
\r
1893 catch (Exception exc)
\r
1895 MessageBox.Show(exc.ToString());
\r
1900 /// Set the DVD Drive selection in the "Source" Menu
\r
1902 private void SetDriveSelectionMenuItem()
\r
1906 if (InvokeRequired)
\r
1908 BeginInvoke(new UpdateWindowHandler(SetDriveSelectionMenuItem));
\r
1912 List<DriveInformation> drives = Main.GetDrives();
\r
1914 if (drives.Count == 0)
\r
1916 mnu_dvd_drive.Text = "[No DVD Drive Ready]";
\r
1920 this.dvdDrivePath = drives[0].RootDirectory + "VIDEO_TS";
\r
1921 this.dvdDriveLabel = drives[0].VolumeLabel;
\r
1922 mnu_dvd_drive.Text = this.dvdDrivePath + " (" + this.dvdDriveLabel + ")";
\r
1926 mnu_dvd_drive.Text = "[No DVD Drive Ready / Found]";
\r
1931 /// Access the preset Handler and setup the preset panel.
\r
1933 private void LoadPresetPanel()
\r
1935 if (presetHandler.CheckIfPresetsAreOutOfDate())
\r
1936 if (!Properties.Settings.Default.presetNotification)
\r
1937 MessageBox.Show(splash,
\r
1938 "HandBrake has determined your built-in presets are out of date... These presets will now be updated.",
\r
1939 "Preset Update", MessageBoxButtons.OK, MessageBoxIcon.Information);
\r
1941 presetHandler.GetPresetPanel(ref treeView_presets);
\r
1942 treeView_presets.Update();
\r
1950 /// Handle GUI shortcuts
\r
1952 /// <param name="msg"></param>
\r
1953 /// <param name="keyData"></param>
\r
1954 /// <returns></returns>
\r
1955 protected override bool ProcessCmdKey(ref Message msg, Keys keyData)
\r
1957 if (keyData == (Keys.Control | Keys.S))
\r
1959 btn_start_Click(this, new EventArgs());
\r
1963 if (keyData == (Keys.Control | Keys.A))
\r
1965 btn_add2Queue_Click(this, new EventArgs());
\r
1968 return base.ProcessCmdKey(ref msg, keyData);
\r
1972 /// If the queue is being processed, prompt the user to confirm application close.
\r
1974 /// <param name="e"></param>
\r
1975 protected override void OnFormClosing(FormClosingEventArgs e)
\r
1977 // If currently encoding, the queue isn't paused, and there are queue items to process, prompt to confirm close.
\r
1978 if ((encodeQueue.IsEncoding) && (!encodeQueue.PauseRequested) && (encodeQueue.Count > 0))
\r
1980 DialogResult result =
\r
1982 "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
1983 "Close HandBrake?", MessageBoxButtons.YesNo, MessageBoxIcon.Question);
\r
1984 if (result == DialogResult.No)
\r
1987 base.OnFormClosing(e);
\r
1992 #region In-GUI Encode Status (Experimental)
\r
1995 /// Starts a new thread to monitor and process the CLI encode status
\r
1997 private void EncodeMonitorThread()
\r
2001 Parser encode = new Parser(encodeQueue.HbProcess.StandardOutput.BaseStream);
\r
2002 encode.OnEncodeProgress += EncodeOnEncodeProgress;
\r
2003 while (!encode.EndOfStream)
\r
2004 encode.readEncodeStatus();
\r
2006 catch (Exception exc)
\r
2008 MessageBox.Show(exc.ToString(), "Error", MessageBoxButtons.OK, MessageBoxIcon.Error);
\r
2013 /// Displays the Encode status in the GUI
\r
2015 /// <param name="Sender"></param>
\r
2016 /// <param name="CurrentTask"></param>
\r
2017 /// <param name="TaskCount"></param>
\r
2018 /// <param name="PercentComplete"></param>
\r
2019 /// <param name="CurrentFps"></param>
\r
2020 /// <param name="AverageFps"></param>
\r
2021 /// <param name="TimeRemaining"></param>
\r
2022 private void EncodeOnEncodeProgress(object Sender, int CurrentTask, int TaskCount, float PercentComplete,
\r
2023 float CurrentFps, float AverageFps, TimeSpan TimeRemaining)
\r
2025 if (this.InvokeRequired)
\r
2027 this.BeginInvoke(new EncodeProgressEventHandler(EncodeOnEncodeProgress),
\r
2030 Sender, CurrentTask, TaskCount, PercentComplete, CurrentFps, AverageFps,
\r
2036 string.Format("Encode Progress: {0}%, FPS: {1}, Avg FPS: {2}, Time Remaining: {3} ",
\r
2037 PercentComplete, CurrentFps, AverageFps, TimeRemaining);
\r
2042 // This is the END of the road ****************************************
\r