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 drop_chapterStart.Items.Clear();
\r
1041 drop_chapterFinish.Items.Clear();
\r
1043 // If the dropdown is set to automatic nothing else needs to be done.
\r
1044 // Otheriwse if its not, title data has to be loased from parsing.
\r
1045 if (drp_dvdtitle.Text != "Automatic")
\r
1047 selectedTitle = drp_dvdtitle.SelectedItem as Title;
\r
1048 lbl_duration.Text = selectedTitle.Duration.ToString();
\r
1049 PictureSettings.CurrentlySelectedPreset = CurrentlySelectedPreset;
\r
1050 PictureSettings.Source = selectedTitle; // Setup Picture Settings Tab Control
\r
1052 // Populate the Angles dropdown
\r
1053 drop_angle.Items.Clear();
\r
1054 if (!Properties.Settings.Default.noDvdNav)
\r
1056 drop_angle.Visible = true;
\r
1057 lbl_angle.Visible = true;
\r
1058 drop_angle.Items.AddRange(selectedTitle.Angles.ToArray());
\r
1059 if (drop_angle.Items.Count != 0)
\r
1060 drop_angle.SelectedIndex = 0;
\r
1064 drop_angle.Visible = false;
\r
1065 lbl_angle.Visible = false;
\r
1068 // Populate the Start chapter Dropdown
\r
1069 drop_chapterStart.Items.Clear();
\r
1070 drop_chapterStart.Items.AddRange(selectedTitle.Chapters.ToArray());
\r
1071 if (drop_chapterStart.Items.Count > 0)
\r
1072 drop_chapterStart.Text = drop_chapterStart.Items[0].ToString();
\r
1074 // Populate the Final Chapter Dropdown
\r
1075 drop_chapterFinish.Items.Clear();
\r
1076 drop_chapterFinish.Items.AddRange(selectedTitle.Chapters.ToArray());
\r
1077 if (drop_chapterFinish.Items.Count > 0)
\r
1078 drop_chapterFinish.Text = drop_chapterFinish.Items[drop_chapterFinish.Items.Count - 1].ToString();
\r
1080 // Populate the Audio Channels Dropdown
\r
1081 AudioSettings.SetTrackList(selectedTitle);
\r
1083 // Populate the Subtitles dropdown
\r
1084 Subtitles.SetSubtitleTrackAuto(selectedTitle.Subtitles.ToArray());
\r
1086 // Update the source label if we have multiple streams
\r
1087 if (selectedTitle != null)
\r
1088 if (!string.IsNullOrEmpty(selectedTitle.SourceName))
\r
1089 labelSource.Text = labelSource.Text = Path.GetFileName(selectedTitle.SourceName);
\r
1091 // Run the AutoName & ChapterNaming functions
\r
1092 if (Properties.Settings.Default.autoNaming)
\r
1094 string autoPath = Main.AutoName(this);
\r
1095 if (autoPath != null)
\r
1096 text_destination.Text = autoPath;
\r
1099 "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
1100 "Warning", MessageBoxButtons.OK, MessageBoxIcon.Warning);
\r
1103 data_chpt.Rows.Clear();
\r
1104 if (selectedTitle.Chapters.Count != 1)
\r
1106 DataGridView chapterGridView = Main.ChapterNaming(data_chpt, drop_chapterFinish.Text);
\r
1107 if (chapterGridView != null)
\r
1108 data_chpt = chapterGridView;
\r
1112 Check_ChapterMarkers.Checked = false;
\r
1113 Check_ChapterMarkers.Enabled = false;
\r
1116 // Hack to force the redraw of the scrollbars which don't resize properly when the control is disabled.
\r
1117 data_chpt.Columns[0].Width = 166;
\r
1118 data_chpt.Columns[0].Width = 165;
\r
1120 RegisterPresetEventHandler();
\r
1123 private void chapersChanged(object sender, EventArgs e)
\r
1125 if (drop_mode.SelectedIndex != 0) // Function is not used if we are not in chapters mode.
\r
1128 Control ctl = (Control) sender;
\r
1129 int chapterStart, chapterEnd;
\r
1130 int.TryParse(drop_chapterStart.Text, out chapterStart);
\r
1131 int.TryParse(drop_chapterFinish.Text, out chapterEnd);
\r
1135 case "drop_chapterStart":
\r
1136 if (drop_chapterFinish.SelectedIndex == -1 && drop_chapterFinish.Items.Count != 0)
\r
1137 drop_chapterFinish.SelectedIndex = drop_chapterFinish.Items.Count - 1;
\r
1139 if (chapterEnd != 0)
\r
1140 if (chapterStart > chapterEnd)
\r
1141 drop_chapterFinish.Text = chapterStart.ToString();
\r
1143 case "drop_chapterFinish":
\r
1144 if (drop_chapterStart.Items.Count >= 1 && drop_chapterStart.SelectedIndex == -1)
\r
1145 drop_chapterStart.SelectedIndex = 0;
\r
1147 if (chapterStart != 0)
\r
1148 if (chapterEnd < chapterStart)
\r
1149 drop_chapterFinish.Text = chapterStart.ToString();
\r
1151 // Add more rows to the Chapter menu if needed.
\r
1152 if (Check_ChapterMarkers.Checked)
\r
1154 int i = data_chpt.Rows.Count, finish = 0;
\r
1155 int.TryParse(drop_chapterFinish.Text, out finish);
\r
1157 while (i < finish)
\r
1159 int n = data_chpt.Rows.Add();
\r
1160 data_chpt.Rows[n].Cells[0].Value = (i + 1);
\r
1161 data_chpt.Rows[n].Cells[1].Value = "Chapter " + (i + 1);
\r
1162 data_chpt.Rows[n].Cells[0].ValueType = typeof (int);
\r
1163 data_chpt.Rows[n].Cells[1].ValueType = typeof (string);
\r
1170 // Update the Duration
\r
1171 lbl_duration.Text =
\r
1172 Main.CalculateDuration(drop_chapterStart.SelectedIndex, drop_chapterFinish.SelectedIndex, selectedTitle)
\r
1175 // Run the Autonaming function
\r
1176 if (Properties.Settings.Default.autoNaming)
\r
1177 text_destination.Text = Main.AutoName(this);
\r
1179 // Disable chapter markers if only 1 chapter is selected.
\r
1180 if (chapterStart == chapterEnd)
\r
1182 Check_ChapterMarkers.Enabled = false;
\r
1183 btn_importChapters.Enabled = false;
\r
1184 data_chpt.Enabled = false;
\r
1188 Check_ChapterMarkers.Enabled = true;
\r
1189 if (Check_ChapterMarkers.Checked)
\r
1191 btn_importChapters.Enabled = true;
\r
1192 data_chpt.Enabled = true;
\r
1197 private void SecondsOrFramesChanged(object sender, EventArgs e)
\r
1200 int.TryParse(drop_chapterStart.Text, out start);
\r
1201 int.TryParse(drop_chapterFinish.Text, out end);
\r
1202 double duration = end - start;
\r
1204 switch (drop_mode.SelectedIndex)
\r
1207 lbl_duration.Text = TimeSpan.FromSeconds(duration).ToString();
\r
1210 if (selectedTitle != null)
\r
1212 duration = duration/selectedTitle.Fps;
\r
1213 lbl_duration.Text = TimeSpan.FromSeconds(duration).ToString();
\r
1216 lbl_duration.Text = "--:--:--";
\r
1222 private void drop_mode_SelectedIndexChanged(object sender, EventArgs e)
\r
1225 this.drop_chapterFinish.TextChanged -= new EventHandler(this.SecondsOrFramesChanged);
\r
1226 this.drop_chapterStart.TextChanged -= new EventHandler(this.SecondsOrFramesChanged);
\r
1229 switch (drop_mode.SelectedIndex)
\r
1232 drop_chapterStart.DropDownStyle = ComboBoxStyle.DropDownList;
\r
1233 drop_chapterFinish.DropDownStyle = ComboBoxStyle.DropDownList;
\r
1234 if (drop_chapterStart.Items.Count != 0)
\r
1236 drop_chapterStart.SelectedIndex = 0;
\r
1237 drop_chapterFinish.SelectedIndex = drop_chapterFinish.Items.Count - 1;
\r
1240 lbl_duration.Text = "--:--:--";
\r
1243 this.drop_chapterStart.TextChanged += new EventHandler(this.SecondsOrFramesChanged);
\r
1244 this.drop_chapterFinish.TextChanged += new EventHandler(this.SecondsOrFramesChanged);
\r
1245 drop_chapterStart.DropDownStyle = ComboBoxStyle.Simple;
\r
1246 drop_chapterFinish.DropDownStyle = ComboBoxStyle.Simple;
\r
1247 if (selectedTitle != null)
\r
1249 drop_chapterStart.Text = "0";
\r
1250 drop_chapterFinish.Text = selectedTitle.Duration.TotalSeconds.ToString();
\r
1254 this.drop_chapterStart.TextChanged += new EventHandler(this.SecondsOrFramesChanged);
\r
1255 this.drop_chapterFinish.TextChanged += new EventHandler(this.SecondsOrFramesChanged);
\r
1256 drop_chapterStart.DropDownStyle = ComboBoxStyle.Simple;
\r
1257 drop_chapterFinish.DropDownStyle = ComboBoxStyle.Simple;
\r
1258 if (selectedTitle != null)
\r
1260 drop_chapterStart.Text = "0";
\r
1261 drop_chapterFinish.Text = (selectedTitle.Fps*selectedTitle.Duration.TotalSeconds).ToString();
\r
1268 private void btn_destBrowse_Click(object sender, EventArgs e)
\r
1270 // This removes the file extension from the filename box on the save file dialog.
\r
1271 // It's daft but some users don't realise that typing an extension overrides the dropdown extension selected.
\r
1272 DVD_Save.FileName = Path.GetFileNameWithoutExtension(text_destination.Text);
\r
1274 if (Path.IsPathRooted(text_destination.Text))
\r
1275 DVD_Save.InitialDirectory = Path.GetDirectoryName(text_destination.Text);
\r
1277 // Show the dialog and set the main form file path
\r
1278 if (drop_format.SelectedIndex.Equals(0))
\r
1279 DVD_Save.FilterIndex = 1;
\r
1280 else if (drop_format.SelectedIndex.Equals(1))
\r
1281 DVD_Save.FilterIndex = 2;
\r
1283 if (DVD_Save.ShowDialog() == DialogResult.OK)
\r
1285 // Add a file extension manually, as FileDialog.AddExtension has issues with dots in filenames
\r
1286 switch (DVD_Save.FilterIndex)
\r
1290 !Path.GetExtension(DVD_Save.FileName).Equals(".mp4",
\r
1291 StringComparison.InvariantCultureIgnoreCase))
\r
1292 if (Properties.Settings.Default.useM4v)
\r
1293 DVD_Save.FileName = DVD_Save.FileName.Replace(".mp4", ".m4v").Replace(".mkv", ".m4v");
\r
1295 DVD_Save.FileName = DVD_Save.FileName.Replace(".m4v", ".mp4").Replace(".mkv", ".mp4");
\r
1299 !Path.GetExtension(DVD_Save.FileName).Equals(".mkv",
\r
1300 StringComparison.InvariantCultureIgnoreCase))
\r
1301 DVD_Save.FileName = DVD_Save.FileName.Replace(".mp4", ".mkv").Replace(".m4v", ".mkv");
\r
1307 text_destination.Text = DVD_Save.FileName;
\r
1309 // Quicktime requires .m4v file for chapter markers to work. If checked, change the extension to .m4v (mp4 and m4v are the same thing)
\r
1310 if (Check_ChapterMarkers.Checked && DVD_Save.FilterIndex != 2)
\r
1311 SetExtension(".m4v");
\r
1315 private void text_destination_TextChanged(object sender, EventArgs e)
\r
1317 string path = text_destination.Text;
\r
1318 if (path.EndsWith(".mp4") || path.EndsWith(".m4v"))
\r
1319 drop_format.SelectedIndex = 0;
\r
1320 else if (path.EndsWith(".mkv"))
\r
1321 drop_format.SelectedIndex = 1;
\r
1324 // Output Settings
\r
1325 private void drop_format_SelectedIndexChanged(object sender, EventArgs e)
\r
1327 switch (drop_format.SelectedIndex)
\r
1330 if (Properties.Settings.Default.useM4v || Check_ChapterMarkers.Checked ||
\r
1331 AudioSettings.RequiresM4V() || Subtitles.RequiresM4V())
\r
1332 SetExtension(".m4v");
\r
1334 SetExtension(".mp4");
\r
1337 SetExtension(".mkv");
\r
1341 AudioSettings.SetContainer(drop_format.Text);
\r
1342 Subtitles.SetContainer(drop_format.SelectedIndex);
\r
1344 if (drop_format.Text.Contains("MP4"))
\r
1346 if (drp_videoEncoder.Items.Contains("VP3 (Theora)"))
\r
1348 drp_videoEncoder.Items.Remove("VP3 (Theora)");
\r
1349 drp_videoEncoder.SelectedIndex = 1;
\r
1352 else if (drop_format.Text.Contains("MKV"))
\r
1353 drp_videoEncoder.Items.Add("VP3 (Theora)");
\r
1356 public void SetExtension(string newExtension)
\r
1358 if (newExtension == ".mp4" || newExtension == ".m4v")
\r
1359 if (Properties.Settings.Default.useM4v || Check_ChapterMarkers.Checked || AudioSettings.RequiresM4V() ||
\r
1360 Subtitles.RequiresM4V())
\r
1361 newExtension = ".m4v";
\r
1363 newExtension = ".mp4";
\r
1365 if (Path.HasExtension(newExtension))
\r
1366 text_destination.Text = Path.ChangeExtension(text_destination.Text, newExtension);
\r
1370 private void drp_videoEncoder_SelectedIndexChanged(object sender, EventArgs e)
\r
1372 setContainerOpts();
\r
1374 // Turn off some options which are H.264 only when the user selects a non h.264 encoder
\r
1375 if (drp_videoEncoder.Text.Contains("H.264"))
\r
1377 if (check_2PassEncode.CheckState == CheckState.Checked)
\r
1378 check_turbo.Enabled = true;
\r
1380 tab_advanced.Enabled = true;
\r
1381 if ((drop_format.Text.Contains("MP4")) || (drop_format.Text.Contains("M4V")))
\r
1382 check_iPodAtom.Enabled = true;
\r
1384 check_iPodAtom.Enabled = false;
\r
1388 check_turbo.CheckState = CheckState.Unchecked;
\r
1389 check_turbo.Enabled = false;
\r
1390 tab_advanced.Enabled = false;
\r
1391 x264Panel.X264Query = string.Empty;
\r
1392 check_iPodAtom.Enabled = false;
\r
1393 check_iPodAtom.Checked = false;
\r
1396 // Setup the CQ Slider
\r
1397 switch (drp_videoEncoder.Text)
\r
1399 case "MPEG-4 (FFmpeg)":
\r
1400 if (slider_videoQuality.Value > 31)
\r
1401 slider_videoQuality.Value = 20; // Just reset to 70% QP 10 on encode change.
\r
1402 slider_videoQuality.Minimum = 1;
\r
1403 slider_videoQuality.Maximum = 31;
\r
1405 case "H.264 (x264)":
\r
1406 slider_videoQuality.Minimum = 0;
\r
1407 slider_videoQuality.TickFrequency = 1;
\r
1409 CultureInfo culture = CultureInfo.CreateSpecificCulture("en-US");
\r
1410 double cqStep = Properties.Settings.Default.x264cqstep;
\r
1411 double multiplier = 1.0/cqStep;
\r
1412 double value = slider_videoQuality.Value*multiplier;
\r
1414 switch (Properties.Settings.Default.x264cqstep.ToString(culture))
\r
1417 slider_videoQuality.Maximum = 255;
\r
1420 slider_videoQuality.Maximum = 204;
\r
1423 slider_videoQuality.Maximum = 102;
\r
1426 slider_videoQuality.Maximum = 51;
\r
1429 slider_videoQuality.Maximum = 51;
\r
1432 if (value < slider_videoQuality.Maximum)
\r
1433 slider_videoQuality.Value = slider_videoQuality.Maximum - (int) value;
\r
1436 case "VP3 (Theora)":
\r
1437 if (slider_videoQuality.Value > 63)
\r
1438 slider_videoQuality.Value = 45; // Just reset to 70% QP 45 on encode change.
\r
1439 slider_videoQuality.Minimum = 0;
\r
1440 slider_videoQuality.Maximum = 63;
\r
1446 /// Set the container format options
\r
1448 public void setContainerOpts()
\r
1450 if ((drop_format.Text.Contains("MP4")) || (drop_format.Text.Contains("M4V")))
\r
1452 check_largeFile.Enabled = true;
\r
1453 check_optimiseMP4.Enabled = true;
\r
1454 check_iPodAtom.Enabled = true;
\r
1458 check_largeFile.Enabled = false;
\r
1459 check_optimiseMP4.Enabled = false;
\r
1460 check_iPodAtom.Enabled = false;
\r
1461 check_largeFile.Checked = false;
\r
1462 check_optimiseMP4.Checked = false;
\r
1463 check_iPodAtom.Checked = false;
\r
1467 private double _cachedCqStep = Properties.Settings.Default.x264cqstep;
\r
1470 /// Update the CQ slider for x264 for a new CQ step. This is set from option
\r
1472 public void setQualityFromSlider()
\r
1474 // Work out the current RF value.
\r
1475 double cqStep = _cachedCqStep;
\r
1476 double rfValue = 51.0 - slider_videoQuality.Value*cqStep;
\r
1478 // Change the maximum value for the slider
\r
1479 switch (Properties.Settings.Default.x264cqstep.ToString(new CultureInfo("en-US")))
\r
1482 slider_videoQuality.Maximum = 255;
\r
1485 slider_videoQuality.Maximum = 204;
\r
1488 slider_videoQuality.Maximum = 102;
\r
1491 slider_videoQuality.Maximum = 51;
\r
1494 slider_videoQuality.Maximum = 51;
\r
1498 // Reset the CQ slider to RF0
\r
1499 slider_videoQuality.Value = slider_videoQuality.Maximum;
\r
1501 // Reset the CQ slider back to the previous value as close as possible
\r
1502 double cqStepNew = Properties.Settings.Default.x264cqstep;
\r
1503 double rfValueCurrent = 51.0 - slider_videoQuality.Value*cqStepNew;
\r
1504 while (rfValueCurrent < rfValue)
\r
1506 slider_videoQuality.Value--;
\r
1507 rfValueCurrent = 51.0 - slider_videoQuality.Value*cqStepNew;
\r
1510 // Cache the CQ step for the next calculation
\r
1511 _cachedCqStep = Properties.Settings.Default.x264cqstep;
\r
1514 private void slider_videoQuality_Scroll(object sender, EventArgs e)
\r
1516 double cqStep = Properties.Settings.Default.x264cqstep;
\r
1517 switch (drp_videoEncoder.Text)
\r
1519 case "MPEG-4 (FFmpeg)":
\r
1520 lbl_SliderValue.Text = "QP:" + (32 - slider_videoQuality.Value);
\r
1522 case "H.264 (x264)":
\r
1523 double rfValue = 51.0 - slider_videoQuality.Value*cqStep;
\r
1524 rfValue = Math.Round(rfValue, 2);
\r
1525 lbl_SliderValue.Text = "RF:" + rfValue.ToString(new CultureInfo("en-US"));
\r
1527 case "VP3 (Theora)":
\r
1528 lbl_SliderValue.Text = "QP:" + slider_videoQuality.Value;
\r
1533 private void radio_targetFilesize_CheckedChanged(object sender, EventArgs e)
\r
1535 text_bitrate.Enabled = false;
\r
1536 text_filesize.Enabled = true;
\r
1537 slider_videoQuality.Enabled = false;
\r
1539 check_2PassEncode.Enabled = true;
\r
1542 private void radio_avgBitrate_CheckedChanged(object sender, EventArgs e)
\r
1544 text_bitrate.Enabled = true;
\r
1545 text_filesize.Enabled = false;
\r
1546 slider_videoQuality.Enabled = false;
\r
1548 check_2PassEncode.Enabled = true;
\r
1551 private void radio_cq_CheckedChanged(object sender, EventArgs e)
\r
1553 text_bitrate.Enabled = false;
\r
1554 text_filesize.Enabled = false;
\r
1555 slider_videoQuality.Enabled = true;
\r
1557 check_2PassEncode.Enabled = false;
\r
1558 check_2PassEncode.CheckState = CheckState.Unchecked;
\r
1561 private void check_2PassEncode_CheckedChanged(object sender, EventArgs e)
\r
1563 if (check_2PassEncode.CheckState.ToString() == "Checked")
\r
1565 if (drp_videoEncoder.Text.Contains("H.264"))
\r
1566 check_turbo.Enabled = true;
\r
1570 check_turbo.Enabled = false;
\r
1571 check_turbo.CheckState = CheckState.Unchecked;
\r
1575 // Chapter Marker Tab
\r
1576 private void Check_ChapterMarkers_CheckedChanged(object sender, EventArgs e)
\r
1578 if (Check_ChapterMarkers.Checked)
\r
1580 if (drop_format.SelectedIndex != 1)
\r
1581 SetExtension(".m4v");
\r
1582 data_chpt.Enabled = true;
\r
1583 btn_importChapters.Enabled = true;
\r
1587 if (drop_format.SelectedIndex != 1 && !Properties.Settings.Default.useM4v)
\r
1588 SetExtension(".mp4");
\r
1589 data_chpt.Enabled = false;
\r
1590 btn_importChapters.Enabled = false;
\r
1594 private void btn_importChapters_Click(object sender, EventArgs e)
\r
1596 if (File_ChapterImport.ShowDialog() == DialogResult.OK)
\r
1598 string filename = File_ChapterImport.FileName;
\r
1599 DataGridView imported = Main.ImportChapterNames(data_chpt, filename);
\r
1600 if (imported != null)
\r
1601 data_chpt = imported;
\r
1605 private void mnu_resetChapters_Click(object sender, EventArgs e)
\r
1607 data_chpt.Rows.Clear();
\r
1608 DataGridView chapterGridView = Main.ChapterNaming(data_chpt, drop_chapterFinish.Text);
\r
1609 if (chapterGridView != null)
\r
1611 data_chpt = chapterGridView;
\r
1615 // Query Editor Tab
\r
1616 private void btn_generate_Query_Click(object sender, EventArgs e)
\r
1618 rtf_query.Text = QueryGenerator.GenerateCliQuery(this, drop_mode.SelectedIndex, 0, null);
\r
1621 private void btn_clear_Click(object sender, EventArgs e)
\r
1623 rtf_query.Clear();
\r
1628 // MainWindow Components, Actions and Functions ***********************
\r
1630 #region Source Scan
\r
1632 public bool isScanning { get; set; }
\r
1633 private Scan SourceScan;
\r
1635 private void StartScan(string filename, int title)
\r
1637 // Setup the GUI components for the scan.
\r
1638 sourcePath = filename;
\r
1639 foreach (Control ctrl in Controls)
\r
1640 if (!(ctrl is StatusStrip || ctrl is MenuStrip || ctrl is ToolStrip))
\r
1641 ctrl.Enabled = false;
\r
1643 lbl_encode.Visible = true;
\r
1644 lbl_encode.Text = "Scanning ...";
\r
1645 btn_source.Enabled = false;
\r
1646 btn_start.Enabled = false;
\r
1647 btn_showQueue.Enabled = false;
\r
1648 btn_add2Queue.Enabled = false;
\r
1649 tb_preview.Enabled = false;
\r
1650 mnu_killCLI.Visible = true;
\r
1652 if (ActivityWindow != null)
\r
1653 ActivityWindow.SetScanMode();
\r
1658 isScanning = true;
\r
1659 SourceScan = new Scan();
\r
1660 SourceScan.ScanSource(sourcePath, title);
\r
1661 SourceScan.ScanStatusChanged += new EventHandler(SourceScan_ScanStatusChanged);
\r
1662 SourceScan.ScanCompleted += new EventHandler(SourceScan_ScanCompleted);
\r
1664 catch (Exception exc)
\r
1666 MessageBox.Show("frmMain.cs - StartScan " + exc, "Error", MessageBoxButtons.OK, MessageBoxIcon.Error);
\r
1670 private void SourceScan_ScanStatusChanged(object sender, EventArgs e)
\r
1672 UpdateScanStatusLabel();
\r
1675 private void SourceScan_ScanCompleted(object sender, EventArgs e)
\r
1677 UpdateGuiAfterScan();
\r
1680 private void UpdateScanStatusLabel()
\r
1682 if (InvokeRequired)
\r
1684 BeginInvoke(new UpdateWindowHandler(UpdateScanStatusLabel));
\r
1687 lbl_encode.Text = SourceScan.ScanStatus();
\r
1690 private void UpdateGuiAfterScan()
\r
1692 if (InvokeRequired)
\r
1694 BeginInvoke(new UpdateWindowHandler(UpdateGuiAfterScan));
\r
1700 currentSource = SourceScan.SouceData();
\r
1702 // Setup some GUI components
\r
1703 drp_dvdtitle.Items.Clear();
\r
1704 if (currentSource.Titles.Count != 0)
\r
1705 drp_dvdtitle.Items.AddRange(currentSource.Titles.ToArray());
\r
1707 // Now select the longest title
\r
1708 if (currentSource.Titles.Count != 0)
\r
1709 drp_dvdtitle.SelectedItem = Main.SelectLongestTitle(currentSource);
\r
1711 // Enable the creation of chapter markers if the file is an image of a dvd.
\r
1712 if (sourcePath.ToLower().Contains(".iso") || sourcePath.Contains("VIDEO_TS") ||
\r
1713 Directory.Exists(Path.Combine(sourcePath, "VIDEO_TS")))
\r
1714 Check_ChapterMarkers.Enabled = true;
\r
1717 Check_ChapterMarkers.Enabled = false;
\r
1718 Check_ChapterMarkers.Checked = false;
\r
1719 data_chpt.Rows.Clear();
\r
1722 // If no titles were found, Display an error message
\r
1723 if (drp_dvdtitle.Items.Count == 0)
\r
1726 "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
1727 "Error", MessageBoxButtons.OK, MessageBoxIcon.Hand);
\r
1728 sourcePath = string.Empty;
\r
1730 UpdateSourceLabel();
\r
1732 // Enable the GUI components and enable any disabled components
\r
1735 catch (Exception exc)
\r
1737 MessageBox.Show("frmMain.cs - updateUIafterScan " + exc, "Error", MessageBoxButtons.OK,
\r
1738 MessageBoxIcon.Error);
\r
1743 private void EnableGUI()
\r
1747 if (InvokeRequired)
\r
1748 BeginInvoke(new UpdateWindowHandler(EnableGUI));
\r
1749 lbl_encode.Text = "Scan Completed";
\r
1750 foreach (Control ctrl in Controls)
\r
1751 ctrl.Enabled = true;
\r
1752 btn_start.Enabled = true;
\r
1753 btn_showQueue.Enabled = true;
\r
1754 btn_add2Queue.Enabled = true;
\r
1755 tb_preview.Enabled = true;
\r
1756 btn_source.Enabled = true;
\r
1757 mnu_killCLI.Visible = false;
\r
1759 catch (Exception exc)
\r
1761 MessageBox.Show("frmMain.cs - EnableGUI() " + exc, "Error", MessageBoxButtons.OK, MessageBoxIcon.Error);
\r
1765 private void KillScan()
\r
1769 SourceScan.ScanCompleted -= new EventHandler(SourceScan_ScanCompleted);
\r
1773 if (SourceScan.ScanProcess() != null)
\r
1774 SourceScan.ScanProcess().Kill();
\r
1776 lbl_encode.Text = "Scan Cancelled!";
\r
1778 catch (Exception ex)
\r
1781 "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
1782 ex.Message, "Error", MessageBoxButtons.OK, MessageBoxIcon.Error);
\r
1786 private void ResetGUI()
\r
1788 drp_dvdtitle.Items.Clear();
\r
1789 drop_chapterStart.Items.Clear();
\r
1790 drop_chapterFinish.Items.Clear();
\r
1791 lbl_duration.Text = "Select a Title";
\r
1792 PictureSettings.lbl_src_res.Text = "Select a Title";
\r
1793 sourcePath = String.Empty;
\r
1794 text_destination.Text = String.Empty;
\r
1795 selectedTitle = null;
\r
1796 isScanning = false;
\r
1799 private void UpdateSourceLabel()
\r
1801 labelSource.Text = string.IsNullOrEmpty(sourcePath) ? "Select \"Source\" to continue." : this.SourceName;
\r
1803 if (selectedTitle != null)
\r
1804 if (!string.IsNullOrEmpty(selectedTitle.SourceName))
\r
1805 // If it's one of multiple source files, make sure we don't use the folder name
\r
1806 labelSource.Text = Path.GetFileName(selectedTitle.SourceName);
\r
1809 public void RecievingJob(Job job)
\r
1811 string query = job.Query;
\r
1812 StartScan(job.Source, 0);
\r
1815 if (query != null)
\r
1817 // Ok, Reset all the H264 widgets before changing the preset
\r
1818 x264Panel.Reset2Defaults();
\r
1820 // Send the query from the file to the Query Parser class
\r
1821 QueryParser presetQuery = QueryParser.Parse(query);
\r
1823 // Now load the preset
\r
1824 PresetLoader.LoadPreset(this, presetQuery, "Load Back From Queue", true);
\r
1826 // The x264 widgets will need updated, so do this now:
\r
1827 x264Panel.X264_StandardizeOptString();
\r
1828 x264Panel.X264_SetCurrentSettingsInPanel();
\r
1830 // Finally, let this window have a copy of the preset settings.
\r
1831 CurrentlySelectedPreset = null;
\r
1832 PictureSettings.SetPresetCropWarningLabel(null);
\r
1838 #region GUI Functions and Actions
\r
1841 /// Set the GUI to it's finished encoding state.
\r
1843 private void SetEncodeFinished()
\r
1847 if (InvokeRequired)
\r
1849 BeginInvoke(new UpdateWindowHandler(SetEncodeFinished));
\r
1853 lbl_encode.Text = "Encoding Finished";
\r
1854 btn_start.Text = "Start";
\r
1855 btn_start.ToolTipText = "Start the encoding process";
\r
1856 btn_start.Image = Properties.Resources.Play;
\r
1858 // If the window is minimized, display the notification in a popup.
\r
1859 if (Properties.Settings.Default.trayIconAlerts)
\r
1860 if (FormWindowState.Minimized == this.WindowState)
\r
1862 notifyIcon.BalloonTipText = lbl_encode.Text;
\r
1863 notifyIcon.ShowBalloonTip(500);
\r
1866 catch (Exception exc)
\r
1868 MessageBox.Show(exc.ToString());
\r
1873 /// Set the GUI to it's started encoding state.
\r
1875 private void SetEncodeStarted()
\r
1879 if (InvokeRequired)
\r
1881 BeginInvoke(new UpdateWindowHandler(SetEncodeStarted));
\r
1885 lbl_encode.Visible = true;
\r
1886 lbl_encode.Text = "Encoding with " + encodeQueue.Count + " encode(s) pending";
\r
1887 btn_start.Text = "Stop";
\r
1888 btn_start.ToolTipText = "Stop the encoding process.";
\r
1889 btn_start.Image = Properties.Resources.stop;
\r
1891 catch (Exception exc)
\r
1893 MessageBox.Show(exc.ToString());
\r
1898 /// Set the DVD Drive selection in the "Source" Menu
\r
1900 private void SetDriveSelectionMenuItem()
\r
1904 if (InvokeRequired)
\r
1906 BeginInvoke(new UpdateWindowHandler(SetDriveSelectionMenuItem));
\r
1910 List<DriveInformation> drives = Main.GetDrives();
\r
1912 if (drives.Count == 0)
\r
1914 mnu_dvd_drive.Text = "[No DVD Drive Ready]";
\r
1918 this.dvdDrivePath = drives[0].RootDirectory + "VIDEO_TS";
\r
1919 this.dvdDriveLabel = drives[0].VolumeLabel;
\r
1920 mnu_dvd_drive.Text = this.dvdDrivePath + " (" + this.dvdDriveLabel + ")";
\r
1924 mnu_dvd_drive.Text = "[No DVD Drive Ready / Found]";
\r
1929 /// Access the preset Handler and setup the preset panel.
\r
1931 private void LoadPresetPanel()
\r
1933 if (presetHandler.CheckIfPresetsAreOutOfDate())
\r
1934 if (!Properties.Settings.Default.presetNotification)
\r
1935 MessageBox.Show(splash,
\r
1936 "HandBrake has determined your built-in presets are out of date... These presets will now be updated.",
\r
1937 "Preset Update", MessageBoxButtons.OK, MessageBoxIcon.Information);
\r
1939 presetHandler.GetPresetPanel(ref treeView_presets);
\r
1940 treeView_presets.Update();
\r
1948 /// Handle GUI shortcuts
\r
1950 /// <param name="msg"></param>
\r
1951 /// <param name="keyData"></param>
\r
1952 /// <returns></returns>
\r
1953 protected override bool ProcessCmdKey(ref Message msg, Keys keyData)
\r
1955 if (keyData == (Keys.Control | Keys.S))
\r
1957 btn_start_Click(this, new EventArgs());
\r
1961 if (keyData == (Keys.Control | Keys.A))
\r
1963 btn_add2Queue_Click(this, new EventArgs());
\r
1966 return base.ProcessCmdKey(ref msg, keyData);
\r
1970 /// If the queue is being processed, prompt the user to confirm application close.
\r
1972 /// <param name="e"></param>
\r
1973 protected override void OnFormClosing(FormClosingEventArgs e)
\r
1975 // If currently encoding, the queue isn't paused, and there are queue items to process, prompt to confirm close.
\r
1976 if ((encodeQueue.IsEncoding) && (!encodeQueue.PauseRequested) && (encodeQueue.Count > 0))
\r
1978 DialogResult result =
\r
1980 "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
1981 "Close HandBrake?", MessageBoxButtons.YesNo, MessageBoxIcon.Question);
\r
1982 if (result == DialogResult.No)
\r
1985 base.OnFormClosing(e);
\r
1990 #region In-GUI Encode Status (Experimental)
\r
1993 /// Starts a new thread to monitor and process the CLI encode status
\r
1995 private void EncodeMonitorThread()
\r
1999 Parser encode = new Parser(encodeQueue.HbProcess.StandardOutput.BaseStream);
\r
2000 encode.OnEncodeProgress += EncodeOnEncodeProgress;
\r
2001 while (!encode.EndOfStream)
\r
2002 encode.ReadEncodeStatus();
\r
2004 catch (Exception exc)
\r
2006 MessageBox.Show(exc.ToString(), "Error", MessageBoxButtons.OK, MessageBoxIcon.Error);
\r
2011 /// Displays the Encode status in the GUI
\r
2013 /// <param name="Sender"></param>
\r
2014 /// <param name="CurrentTask"></param>
\r
2015 /// <param name="TaskCount"></param>
\r
2016 /// <param name="PercentComplete"></param>
\r
2017 /// <param name="CurrentFps"></param>
\r
2018 /// <param name="AverageFps"></param>
\r
2019 /// <param name="TimeRemaining"></param>
\r
2020 private void EncodeOnEncodeProgress(object Sender, int CurrentTask, int TaskCount, float PercentComplete,
\r
2021 float CurrentFps, float AverageFps, TimeSpan TimeRemaining)
\r
2023 if (this.InvokeRequired)
\r
2025 this.BeginInvoke(new EncodeProgressEventHandler(EncodeOnEncodeProgress),
\r
2028 Sender, CurrentTask, TaskCount, PercentComplete, CurrentFps, AverageFps,
\r
2034 string.Format("Encode Progress: {0}%, FPS: {1}, Avg FPS: {2}, Time Remaining: {3} ",
\r
2035 PercentComplete, CurrentFps, AverageFps, TimeRemaining);
\r
2040 // This is the END of the road ****************************************
\r