From 4da15bcbbbd800b7af230294224f0d7248e8dd72 Mon Sep 17 00:00:00 2001
From: sr55 <sr55.hb@outlook.com>
Date: Tue, 14 Feb 2012 20:07:18 +0000
Subject: [PATCH] WinGui: Fix AllowSleep/Prevent Sleep to always use the same
 thread.  Fix an exception when using up arrows on the tile dropdown before
 performing a scan.

git-svn-id: svn://svn.handbrake.fr/HandBrake/trunk@4448 b64f7644-9d1e-0410-96f1-a4d463321fa5
---
 .../Functions/Win32.cs                        |  62 ++++++++-
 win/CS/frmMain.cs                             | 124 +++++++++---------
 2 files changed, 123 insertions(+), 63 deletions(-)

diff --git a/win/CS/HandBrake.ApplicationServices/Functions/Win32.cs b/win/CS/HandBrake.ApplicationServices/Functions/Win32.cs
index 8cb464b80..94a34f529 100644
--- a/win/CS/HandBrake.ApplicationServices/Functions/Win32.cs
+++ b/win/CS/HandBrake.ApplicationServices/Functions/Win32.cs
@@ -6,13 +6,22 @@
 namespace HandBrake.ApplicationServices.Functions
 {
     using System;
+    using System.ComponentModel;
+    using System.Diagnostics;
     using System.Runtime.InteropServices;
+    using System.Windows;
+    using System.Windows.Threading;
 
     /// <summary>
     /// Win32 API calls
     /// </summary>
     public class Win32
     {
+        /// <summary>
+        /// Used to force UI Thread.
+        /// </summary>
+        private static Action<Action> executor = action => action();
+
         /// <summary>
         /// Set the Forground Window
         /// </summary>
@@ -52,13 +61,21 @@ namespace HandBrake.ApplicationServices.Functions
         public struct MEMORYSTATUSEX
         {
             public int dwLength;
+
             public int dwMemoryLoad;
+
             public ulong ullTotalPhys;
+
             public ulong ullAvailPhys;
+
             public ulong ullTotalPageFile;
+
             public ulong ullAvailPageFile;
+
             public ulong ullTotalVirtual;
+
             public ulong ullAvailVirtual;
+
             public ulong ullAvailExtendedVirtual;
         }
 
@@ -74,7 +91,6 @@ namespace HandBrake.ApplicationServices.Functions
         [DllImport("kernel32.dll", SetLastError = true)]
         public static extern bool GlobalMemoryStatusEx(ref MEMORYSTATUSEX lpBuffer);
 
-
         /// <summary>
         /// Generate a Console Ctrl Event
         /// </summary>
@@ -112,7 +128,7 @@ namespace HandBrake.ApplicationServices.Functions
         }
 
         [DllImport("kernel32.dll", CharSet = CharSet.Auto, SetLastError = true)]
-        static extern EXECUTION_STATE SetThreadExecutionState(EXECUTION_STATE esFlags);
+        private static extern EXECUTION_STATE SetThreadExecutionState(EXECUTION_STATE esFlags);
 
         /// <summary>
         /// Execution State
@@ -121,16 +137,29 @@ namespace HandBrake.ApplicationServices.Functions
         public enum EXECUTION_STATE : uint
         {
             ES_SYSTEM_REQUIRED = 0x00000001,
+
             ES_CONTINUOUS = 0x80000000,
+
             ES_AWAYMODE_REQUIRED = 0x00000040
         }
 
+        /// <summary>
+        /// Initializes static members of the <see cref="Win32"/> class.
+        /// </summary>
+        static Win32()
+        {
+            InitializeWithDispatcher();
+        }
+
         /// <summary>
         /// Prevent the system from sleeping
         /// </summary>
         public static void PreventSleep()
         {
-            SetThreadExecutionState(EXECUTION_STATE.ES_CONTINUOUS | EXECUTION_STATE.ES_SYSTEM_REQUIRED | EXECUTION_STATE.ES_AWAYMODE_REQUIRED);
+            executor(
+                () => SetThreadExecutionState(
+                    EXECUTION_STATE.ES_CONTINUOUS | EXECUTION_STATE.ES_SYSTEM_REQUIRED
+                    | EXECUTION_STATE.ES_AWAYMODE_REQUIRED));
         }
 
         /// <summary>
@@ -138,7 +167,32 @@ namespace HandBrake.ApplicationServices.Functions
         /// </summary>
         public static void AllowSleep()
         {
-            SetThreadExecutionState(EXECUTION_STATE.ES_CONTINUOUS);
+            executor(
+                () => SetThreadExecutionState(EXECUTION_STATE.ES_CONTINUOUS));
+        }
+
+        /// <summary>
+        ///   Initializes the framework using the current dispatcher.
+        /// </summary>
+        public static void InitializeWithDispatcher()
+        {
+            var dispatcher = Dispatcher.CurrentDispatcher;
+
+            SetUIThreadMarshaller(action =>
+            {
+                if (dispatcher.CheckAccess())
+                    action();
+                else dispatcher.Invoke(action);
+            });
+        }
+
+        /// <summary>
+        /// Sets a custom UI thread marshaller.
+        /// </summary>
+        /// <param name="marshaller">The marshaller.</param>
+        public static void SetUIThreadMarshaller(Action<Action> marshaller)
+        {
+            executor = marshaller;
         }
     }
 }
diff --git a/win/CS/frmMain.cs b/win/CS/frmMain.cs
index 5ecc41f87..876c5fa49 100644
--- a/win/CS/frmMain.cs
+++ b/win/CS/frmMain.cs
@@ -151,7 +151,7 @@ namespace Handbrake
             // Check for new versions, if update checking is enabled
             if (userSettingService.GetUserSetting<bool>(UserSettingConstants.UpdateStatus))
             {
-                if (DateTime.Now.Subtract(userSettingService.GetUserSetting<DateTime>(UserSettingConstants.LastUpdateCheckDate)).TotalDays 
+                if (DateTime.Now.Subtract(userSettingService.GetUserSetting<DateTime>(UserSettingConstants.LastUpdateCheckDate)).TotalDays
                     > userSettingService.GetUserSetting<int>(UserSettingConstants.DaysBetweenUpdateCheck))
                 {
                     // Set when the last update was
@@ -222,7 +222,7 @@ namespace Handbrake
 
                 if (info.NewVersionAvailable)
                 {
-                    UpdateInfo updateWindow = new UpdateInfo(info, userSettingService.GetUserSetting<string>(ASUserSettingConstants.HandBrakeVersion), 
+                    UpdateInfo updateWindow = new UpdateInfo(info, userSettingService.GetUserSetting<string>(ASUserSettingConstants.HandBrakeVersion),
                         userSettingService.GetUserSetting<string>(ASUserSettingConstants.HandBrakeBuild));
                     updateWindow.ShowDialog();
                 }
@@ -467,7 +467,7 @@ namespace Handbrake
                                                   ? userSettingService.GetUserSetting<string>(UserSettingConstants.Appcast_x64)
                                                   : userSettingService.GetUserSetting<string>(UserSettingConstants.Appcast_i686);
             UpdateService.BeginCheckForUpdates(new AsyncCallback(UpdateCheckDoneMenu), false,
-                url, userSettingService.GetUserSetting<int>(ASUserSettingConstants.HandBrakeBuild), 
+                url, userSettingService.GetUserSetting<int>(ASUserSettingConstants.HandBrakeBuild),
                 userSettingService.GetUserSetting<int>(UserSettingConstants.Skipversion), userSettingService.GetUserSetting<string>(ASUserSettingConstants.HandBrakeVersion));
         }
 
@@ -561,10 +561,10 @@ namespace Handbrake
             Preset preset = new Preset
                 {
                     Name = this.treeView_presets.SelectedNode.Text,
-                    Query = query,                  
+                    Query = query,
                     CropSettings = (result == DialogResult.Yes),
                     AudioPassthruSettings = this.AudioSettings.PassthruSettings,
-                    Task = QueryParserUtility.Parse(query),                
+                    Task = QueryParserUtility.Parse(query),
                 };
 
             presetHandler.Update(preset);
@@ -646,15 +646,15 @@ namespace Handbrake
                 }
                 else
                 {
-                   Preset preset = treeView_presets.SelectedNode.Tag as Preset;
-                   if (preset != null && preset.IsDefault)
-                   {
-                       MessageBox.Show(
-                           "Your default preset can not be deleted. It is a required preset.",
-                           "Warning",
-                           MessageBoxButtons.OK,
-                           MessageBoxIcon.Information);
-                   }
+                    Preset preset = treeView_presets.SelectedNode.Tag as Preset;
+                    if (preset != null && preset.IsDefault)
+                    {
+                        MessageBox.Show(
+                            "Your default preset can not be deleted. It is a required preset.",
+                            "Warning",
+                            MessageBoxButtons.OK,
+                            MessageBoxIcon.Information);
+                    }
 
                     // Delete the selected item.
                     presetHandler.Remove((Preset)treeView_presets.SelectedNode.Tag);
@@ -687,7 +687,7 @@ namespace Handbrake
         }
 
         private void MnuImportPreset_Click(object sender, EventArgs e)
-        {         
+        {
             this.ImportPreset();
         }
 
@@ -883,7 +883,7 @@ namespace Handbrake
                         Description = string.Empty,
                         AudioPassthruSettings = parsed.AllowedPassthruOptions
                     };
-                    
+
                     if (presetHandler.Add(preset))
                     {
                         TreeNode preset_treeview = new TreeNode(parsed.PresetName)
@@ -1027,7 +1027,7 @@ namespace Handbrake
                         {
                             case DialogResult.Yes:
                                 // Replace the manual query with the generated one
-        
+
                                 rtf_query.Text = task.Query;
                                 break;
                             case DialogResult.No:
@@ -1056,7 +1056,7 @@ namespace Handbrake
 
                     if (overwrite == DialogResult.Yes)
                     {
-                        
+
 
                         if (this.queueProcessor.QueueManager.Count == 0)
                             this.queueProcessor.QueueManager.Add(QueryGenerator.GenerateFullQuery(this));
@@ -1209,7 +1209,7 @@ namespace Handbrake
                     MessageBoxButtons.OK,
                     MessageBoxIcon.Warning);
             }
-            
+
         }
 
         private bool AddItemToQueue(bool showError)
@@ -1501,58 +1501,64 @@ namespace Handbrake
             drop_chapterStart.Items.Clear();
             drop_chapterFinish.Items.Clear();
 
-            // If the dropdown is set to automatic nothing else needs to be done.
-            // Otheriwse if its not, title data has to be loaded from parsing.
-            if (drp_dvdtitle.Text != "Automatic")
+            if (string.IsNullOrEmpty(drp_dvdtitle.Text) || drp_dvdtitle.Text == "Automatic" || this.currentSource == null)
             {
-                selectedTitle = drp_dvdtitle.SelectedItem as Title;
-                lbl_duration.Text = selectedTitle.Duration.ToString();
-                PictureSettings.CurrentlySelectedPreset = this.currentlySelectedPreset;
-                PictureSettings.Source = selectedTitle; // Setup Picture Settings Tab Control
+                return;
+            }
 
-                // Populate the Angles dropdown
-                drop_angle.Items.Clear();
-                if (!userSettingService.GetUserSetting<bool>(ASUserSettingConstants.DisableLibDvdNav))
-                {
-                    drop_angle.Visible = true;
-                    lbl_angle.Visible = true;
+            selectedTitle = drp_dvdtitle.SelectedItem as Title;
+            if (selectedTitle == null)
+            {
+                return;
+            }
 
-                    for (int i = 1; i <= selectedTitle.AngleCount; i++)
-                        drop_angle.Items.Add(i.ToString());
+            lbl_duration.Text = selectedTitle.Duration.ToString();
+            PictureSettings.CurrentlySelectedPreset = this.currentlySelectedPreset;
+            PictureSettings.Source = selectedTitle; // Setup Picture Settings Tab Control
 
-                    if (drop_angle.Items.Count == 0)
-                    {
-                        drop_angle.Visible = false;
-                        lbl_angle.Visible = false;
-                    }
+            // Populate the Angles dropdown
+            drop_angle.Items.Clear();
+            if (!userSettingService.GetUserSetting<bool>(ASUserSettingConstants.DisableLibDvdNav))
+            {
+                drop_angle.Visible = true;
+                lbl_angle.Visible = true;
 
-                    if (drop_angle.Items.Count != 0)
-                        drop_angle.SelectedIndex = 0;
-                }
-                else
+                for (int i = 1; i <= selectedTitle.AngleCount; i++)
+                    drop_angle.Items.Add(i.ToString());
+
+                if (drop_angle.Items.Count == 0)
                 {
                     drop_angle.Visible = false;
                     lbl_angle.Visible = false;
                 }
 
-                // Populate the Start chapter Dropdown
-                drop_chapterStart.Items.Clear();
-                drop_chapterStart.Items.AddRange(selectedTitle.Chapters.ToArray());
-                if (drop_chapterStart.Items.Count > 0)
-                    drop_chapterStart.Text = drop_chapterStart.Items[0].ToString();
+                if (drop_angle.Items.Count != 0)
+                    drop_angle.SelectedIndex = 0;
+            }
+            else
+            {
+                drop_angle.Visible = false;
+                lbl_angle.Visible = false;
+            }
+
+            // Populate the Start chapter Dropdown
+            drop_chapterStart.Items.Clear();
+            drop_chapterStart.Items.AddRange(selectedTitle.Chapters.ToArray());
+            if (drop_chapterStart.Items.Count > 0)
+                drop_chapterStart.Text = drop_chapterStart.Items[0].ToString();
+
+            // Populate the Final Chapter Dropdown
+            drop_chapterFinish.Items.Clear();
+            drop_chapterFinish.Items.AddRange(selectedTitle.Chapters.ToArray());
+            if (drop_chapterFinish.Items.Count > 0)
+                drop_chapterFinish.Text = drop_chapterFinish.Items[drop_chapterFinish.Items.Count - 1].ToString();
 
-                // Populate the Final Chapter Dropdown
-                drop_chapterFinish.Items.Clear();
-                drop_chapterFinish.Items.AddRange(selectedTitle.Chapters.ToArray());
-                if (drop_chapterFinish.Items.Count > 0)
-                    drop_chapterFinish.Text = drop_chapterFinish.Items[drop_chapterFinish.Items.Count - 1].ToString();
+            // Populate the Audio Channels Dropdown
+            AudioSettings.SetTrackListAfterTitleChange(selectedTitle, this.currentlySelectedPreset);
 
-                // Populate the Audio Channels Dropdown
-                AudioSettings.SetTrackListAfterTitleChange(selectedTitle, this.currentlySelectedPreset);
+            // Populate the Subtitles dropdown
+            Subtitles.SetSubtitleTrackAuto(selectedTitle.Subtitles.ToArray());
 
-                // Populate the Subtitles dropdown
-                Subtitles.SetSubtitleTrackAuto(selectedTitle.Subtitles.ToArray());
-            }
             // Update the source label if we have multiple streams
             if (selectedTitle != null)
                 if (!string.IsNullOrEmpty(selectedTitle.SourceName))
@@ -1755,7 +1761,7 @@ namespace Handbrake
                 {
                     case 1:
                         if (!Path.GetExtension(DVD_Save.FileName).Equals(".mp4", StringComparison.InvariantCultureIgnoreCase))
-                            if (this.userSettingService.GetUserSetting<int>(UserSettingConstants.UseM4v) == 2 || 
+                            if (this.userSettingService.GetUserSetting<int>(UserSettingConstants.UseM4v) == 2 ||
                                 this.userSettingService.GetUserSetting<int>(UserSettingConstants.UseM4v) == 0)
                                 DVD_Save.FileName = DVD_Save.FileName.Replace(".mp4", ".m4v").Replace(".mkv", ".m4v");
                             else
-- 
2.40.0