cec: added a .net CEC configuration tool
authorLars Op den Kamp <lars@opdenkamp.eu>
Fri, 10 Feb 2012 18:52:25 +0000 (19:52 +0100)
committerLars Op den Kamp <lars@opdenkamp.eu>
Fri, 10 Feb 2012 18:52:25 +0000 (19:52 +0100)
20 files changed:
.gitignore
project/LibCecSharp.sln
src/CecSharpTester/CecSharpClient.cs
src/LibCecSharp/CecSharpTypes.h
src/LibCecSharp/LibCecSharp.cpp
src/cec-config-gui/CecConfigGUI.Designer.cs [new file with mode: 0644]
src/cec-config-gui/CecConfigGUI.cs [new file with mode: 0644]
src/cec-config-gui/CecConfigGUI.resx [new file with mode: 0644]
src/cec-config-gui/Program.cs [new file with mode: 0644]
src/cec-config-gui/Properties/AssemblyInfo.cs [new file with mode: 0644]
src/cec-config-gui/Properties/Resources.Designer.cs [new file with mode: 0644]
src/cec-config-gui/Properties/Resources.resx [new file with mode: 0644]
src/cec-config-gui/Properties/Settings.Designer.cs [new file with mode: 0644]
src/cec-config-gui/Properties/Settings.settings [new file with mode: 0644]
src/cec-config-gui/actions/ConnectToDevice.cs [new file with mode: 0644]
src/cec-config-gui/actions/UpdateConnectedDevice.cs [new file with mode: 0644]
src/cec-config-gui/actions/UpdateEvent.cs [new file with mode: 0644]
src/cec-config-gui/actions/UpdatePhysicalAddress.cs [new file with mode: 0644]
src/cec-config-gui/cec-config-gui.csproj [new file with mode: 0644]
src/lib/adapter/USBCECAdapterCommunication.cpp

index 30608704e16ab0aadf48b5562187f1ae00e9ea27..2fe1e2fb79e23e626271394d2670ee2d96869675 100644 (file)
@@ -69,6 +69,8 @@ src/testclient/*.o
 src/CecSharpTester/bin
 src/CecSharpTester/obj
 
+src/cec-config-gui/obj
+
 src/libcec-wmc/bin
 src/libcec-wmc/obj
 
index 93d654ac66284ddec03bd1481d75e59ab6e305b6..81b35c839eb441dcb5bbcb1816cd09a1acd7a728 100644 (file)
@@ -5,6 +5,8 @@ Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "CecSharpTester", "..\src\Ce
 EndProject
 Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "LibCecSharp", "LibCecSharp.vcproj", "{E54D4581-CD59-4687-BB10-694B8192EABA}"
 EndProject
+Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "cec-config-gui", "..\src\cec-config-gui\cec-config-gui.csproj", "{58C106FE-C159-46D3-97E1-73AB83232670}"
+EndProject
 Global
        GlobalSection(SolutionConfigurationPlatforms) = preSolution
                Debug|x64 = Debug|x64
@@ -29,6 +31,14 @@ Global
                {E54D4581-CD59-4687-BB10-694B8192EABA}.Release|x64.Build.0 = Release|x64
                {E54D4581-CD59-4687-BB10-694B8192EABA}.Release|x86.ActiveCfg = Release|Win32
                {E54D4581-CD59-4687-BB10-694B8192EABA}.Release|x86.Build.0 = Release|Win32
+               {58C106FE-C159-46D3-97E1-73AB83232670}.Debug|x64.ActiveCfg = Debug|x64
+               {58C106FE-C159-46D3-97E1-73AB83232670}.Debug|x64.Build.0 = Debug|x64
+               {58C106FE-C159-46D3-97E1-73AB83232670}.Debug|x86.ActiveCfg = Debug|x86
+               {58C106FE-C159-46D3-97E1-73AB83232670}.Debug|x86.Build.0 = Debug|x86
+               {58C106FE-C159-46D3-97E1-73AB83232670}.Release|x64.ActiveCfg = Release|x64
+               {58C106FE-C159-46D3-97E1-73AB83232670}.Release|x64.Build.0 = Release|x64
+               {58C106FE-C159-46D3-97E1-73AB83232670}.Release|x86.ActiveCfg = Release|x86
+               {58C106FE-C159-46D3-97E1-73AB83232670}.Release|x86.Build.0 = Release|x86
        EndGlobalSection
        GlobalSection(SolutionProperties) = preSolution
                HideSolutionNode = FALSE
index f989eb03cdc347fe82fd654ab651e7320f1d558a..061a992047877beebe9b9ec6fd1d7bbc22c19579 100644 (file)
@@ -258,7 +258,7 @@ namespace CecSharpClient
         else if (splitCommand[0] == "pa")
         {
           if (splitCommand.Length > 1)
-            Lib.SetPhysicalAddress(short.Parse(splitCommand[1], System.Globalization.NumberStyles.HexNumber));
+            Lib.SetPhysicalAddress(ushort.Parse(splitCommand[1], System.Globalization.NumberStyles.HexNumber));
         }
         else if (splitCommand[0] == "osd")
         {
index 64172bb4c5cb83ae2f845108bf0c9bcaa5964130..e88166746116a63e47d46609757dd828479ffaee 100644 (file)
@@ -641,11 +641,14 @@ namespace CecSharp
 
                void DestroyDelegates()
                {
-                       m_bHasCallbacks = false;
-                       delete m_callbacks;
-                       m_logMessageGCHandle.Free();
-                       m_keypressGCHandle.Free();
-                       m_commandGCHandle.Free();
+                       if (m_bHasCallbacks)
+                       {
+                               m_bHasCallbacks = false;
+                               delete m_callbacks;
+                               m_logMessageGCHandle.Free();
+                               m_keypressGCHandle.Free();
+                               m_commandGCHandle.Free();
+                       }
                }
 
                CecLogMessageManagedDelegate ^                    m_logMessageDelegate;
@@ -677,11 +680,11 @@ namespace CecSharp
                        ClientVersion       = CecClientVersion::VersionPre1_5;
 
                        GetSettingsFromROM  = false;
-                       UseTVMenuLanguage   = CEC_DEFAULT_SETTING_USE_TV_MENU_LANGUAGE ? true : false;
-                       PowerOnStartup      = CEC_DEFAULT_SETTING_POWER_ON_STARTUP ? true : false;
-                       PowerOffShutdown    = CEC_DEFAULT_SETTING_POWER_OFF_SHUTDOWN ? true : false;
-                       PowerOffScreensaver = CEC_DEFAULT_SETTING_POWER_OFF_SCREENSAVER ? true : false;
-                       PowerOffOnStandby   = CEC_DEFAULT_SETTING_POWER_OFF_ON_STANDBY ? true : false;
+                       UseTVMenuLanguage   = CEC_DEFAULT_SETTING_USE_TV_MENU_LANGUAGE == 1;
+                       PowerOnStartup      = CEC_DEFAULT_SETTING_POWER_ON_STARTUP == 1;
+                       PowerOffShutdown    = CEC_DEFAULT_SETTING_POWER_OFF_SHUTDOWN == 1;
+                       PowerOffScreensaver = CEC_DEFAULT_SETTING_POWER_OFF_SCREENSAVER == 1;
+                       PowerOffOnStandby   = CEC_DEFAULT_SETTING_POWER_OFF_ON_STANDBY == 1;
                }
 
                void SetCallbacks(CecCallbackMethods ^callbacks)
index 698c81753e2c3a4354bb4feab3a7f60cdfed0e54..c6f52a1a17b2bda673177728538602c81421b669 100644 (file)
@@ -226,7 +226,7 @@ namespace CecSharp
                        return m_libCec->SetLogicalAddress((cec_logical_address) logicalAddress);
                }
 
-               bool SetPhysicalAddress(int16_t physicalAddress)
+               bool SetPhysicalAddress(uint16_t physicalAddress)
                {
                        return m_libCec->SetPhysicalAddress(physicalAddress);
                }
@@ -411,6 +411,8 @@ namespace CecSharp
                bool GetCurrentConfiguration(LibCECConfiguration ^configuration)
                {
                        libcec_configuration config;
+                       config.Clear();
+
                        if (m_libCec->GetCurrentConfiguration(&config))
                        {
                                configuration->BaseDevice = (CecLogicalAddress)config.baseDevice;
diff --git a/src/cec-config-gui/CecConfigGUI.Designer.cs b/src/cec-config-gui/CecConfigGUI.Designer.cs
new file mode 100644 (file)
index 0000000..d233121
--- /dev/null
@@ -0,0 +1,376 @@
+namespace CecConfigGui
+{
+  partial class CecConfigGUI
+  {
+    /// <summary>
+    /// Required designer variable.
+    /// </summary>
+    private System.ComponentModel.IContainer components = null;
+
+    /// <summary>
+    /// Clean up any resources being used.
+    /// </summary>
+    /// <param name="disposing">true if managed resources should be disposed; otherwise, false.</param>
+    protected override void Dispose(bool disposing)
+    {
+      if (disposing && (components != null))
+      {
+        components.Dispose();
+      }
+      base.Dispose(disposing);
+    }
+
+    #region Windows Form Designer generated code
+
+    /// <summary>
+    /// Required method for Designer support - do not modify
+    /// the contents of this method with the code editor.
+    /// </summary>
+    private void InitializeComponent()
+    {
+      this.tabControl1 = new System.Windows.Forms.TabControl();
+      this.Configuration = new System.Windows.Forms.TabPage();
+      this.cbPowerOffOnStandby = new System.Windows.Forms.CheckBox();
+      this.cbPowerOffScreensaver = new System.Windows.Forms.CheckBox();
+      this.cbPowerOffShutdown = new System.Windows.Forms.CheckBox();
+      this.cbPowerOnStartup = new System.Windows.Forms.CheckBox();
+      this.cbUseTVMenuLanguage = new System.Windows.Forms.CheckBox();
+      this.lPlayerConfig = new System.Windows.Forms.Label();
+      this.lAdapterConfig = new System.Windows.Forms.Label();
+      this.cbDeviceType = new System.Windows.Forms.ComboBox();
+      this.bClose = new System.Windows.Forms.Button();
+      this.bSave = new System.Windows.Forms.Button();
+      this.cbPortNumber = new System.Windows.Forms.ComboBox();
+      this.lConnectedPhysicalAddress = new System.Windows.Forms.Label();
+      this.tbPhysicalAddress = new System.Windows.Forms.TextBox();
+      this.cbConnectedDevice = new System.Windows.Forms.ComboBox();
+      this.lDeviceType = new System.Windows.Forms.Label();
+      this.lPhysicalAddress = new System.Windows.Forms.Label();
+      this.lConnectedDevice = new System.Windows.Forms.Label();
+      this.lPortNumber = new System.Windows.Forms.Label();
+      this.LogOutput = new System.Windows.Forms.TabPage();
+      this.tbLog = new System.Windows.Forms.TextBox();
+      this.pProgress = new System.Windows.Forms.ProgressBar();
+      this.lStatus = new System.Windows.Forms.Label();
+      this.tabControl1.SuspendLayout();
+      this.Configuration.SuspendLayout();
+      this.LogOutput.SuspendLayout();
+      this.SuspendLayout();
+      // 
+      // tabControl1
+      // 
+      this.tabControl1.Controls.Add(this.Configuration);
+      this.tabControl1.Controls.Add(this.LogOutput);
+      this.tabControl1.Location = new System.Drawing.Point(12, 12);
+      this.tabControl1.Name = "tabControl1";
+      this.tabControl1.SelectedIndex = 0;
+      this.tabControl1.Size = new System.Drawing.Size(600, 385);
+      this.tabControl1.TabIndex = 0;
+      // 
+      // Configuration
+      // 
+      this.Configuration.Controls.Add(this.cbPowerOffOnStandby);
+      this.Configuration.Controls.Add(this.cbPowerOffScreensaver);
+      this.Configuration.Controls.Add(this.cbPowerOffShutdown);
+      this.Configuration.Controls.Add(this.cbPowerOnStartup);
+      this.Configuration.Controls.Add(this.cbUseTVMenuLanguage);
+      this.Configuration.Controls.Add(this.lPlayerConfig);
+      this.Configuration.Controls.Add(this.lAdapterConfig);
+      this.Configuration.Controls.Add(this.cbDeviceType);
+      this.Configuration.Controls.Add(this.bClose);
+      this.Configuration.Controls.Add(this.bSave);
+      this.Configuration.Controls.Add(this.cbPortNumber);
+      this.Configuration.Controls.Add(this.lConnectedPhysicalAddress);
+      this.Configuration.Controls.Add(this.tbPhysicalAddress);
+      this.Configuration.Controls.Add(this.cbConnectedDevice);
+      this.Configuration.Controls.Add(this.lDeviceType);
+      this.Configuration.Controls.Add(this.lPhysicalAddress);
+      this.Configuration.Controls.Add(this.lConnectedDevice);
+      this.Configuration.Controls.Add(this.lPortNumber);
+      this.Configuration.Location = new System.Drawing.Point(4, 22);
+      this.Configuration.Name = "Configuration";
+      this.Configuration.Padding = new System.Windows.Forms.Padding(3);
+      this.Configuration.Size = new System.Drawing.Size(592, 359);
+      this.Configuration.TabIndex = 0;
+      this.Configuration.Text = "Configuration";
+      this.Configuration.UseVisualStyleBackColor = true;
+      // 
+      // cbPowerOffOnStandby
+      // 
+      this.cbPowerOffOnStandby.AutoSize = true;
+      this.cbPowerOffOnStandby.Enabled = false;
+      this.cbPowerOffOnStandby.Location = new System.Drawing.Point(10, 297);
+      this.cbPowerOffOnStandby.Name = "cbPowerOffOnStandby";
+      this.cbPowerOffOnStandby.Size = new System.Drawing.Size(292, 17);
+      this.cbPowerOffOnStandby.TabIndex = 22;
+      this.cbPowerOffOnStandby.Text = "Put this PC in standby mode when the TV is switched off";
+      this.cbPowerOffOnStandby.UseVisualStyleBackColor = true;
+      // 
+      // cbPowerOffScreensaver
+      // 
+      this.cbPowerOffScreensaver.AutoSize = true;
+      this.cbPowerOffScreensaver.Enabled = false;
+      this.cbPowerOffScreensaver.Location = new System.Drawing.Point(10, 273);
+      this.cbPowerOffScreensaver.Name = "cbPowerOffScreensaver";
+      this.cbPowerOffScreensaver.Size = new System.Drawing.Size(301, 17);
+      this.cbPowerOffScreensaver.TabIndex = 21;
+      this.cbPowerOffScreensaver.Text = "Put devices in standby mode when activating screensaver";
+      this.cbPowerOffScreensaver.UseVisualStyleBackColor = true;
+      // 
+      // cbPowerOffShutdown
+      // 
+      this.cbPowerOffShutdown.AutoSize = true;
+      this.cbPowerOffShutdown.Enabled = false;
+      this.cbPowerOffShutdown.Location = new System.Drawing.Point(10, 249);
+      this.cbPowerOffShutdown.Name = "cbPowerOffShutdown";
+      this.cbPowerOffShutdown.Size = new System.Drawing.Size(317, 17);
+      this.cbPowerOffShutdown.TabIndex = 20;
+      this.cbPowerOffShutdown.Text = "Power off devices when stopping the media player application";
+      this.cbPowerOffShutdown.UseVisualStyleBackColor = true;
+      // 
+      // cbPowerOnStartup
+      // 
+      this.cbPowerOnStartup.AutoSize = true;
+      this.cbPowerOnStartup.Enabled = false;
+      this.cbPowerOnStartup.Location = new System.Drawing.Point(10, 225);
+      this.cbPowerOnStartup.Name = "cbPowerOnStartup";
+      this.cbPowerOnStartup.Size = new System.Drawing.Size(306, 17);
+      this.cbPowerOnStartup.TabIndex = 19;
+      this.cbPowerOnStartup.Text = "Power on the TV when starting the media player application";
+      this.cbPowerOnStartup.UseVisualStyleBackColor = true;
+      // 
+      // cbUseTVMenuLanguage
+      // 
+      this.cbUseTVMenuLanguage.AutoSize = true;
+      this.cbUseTVMenuLanguage.Enabled = false;
+      this.cbUseTVMenuLanguage.Location = new System.Drawing.Point(10, 201);
+      this.cbUseTVMenuLanguage.Name = "cbUseTVMenuLanguage";
+      this.cbUseTVMenuLanguage.Size = new System.Drawing.Size(168, 17);
+      this.cbUseTVMenuLanguage.TabIndex = 18;
+      this.cbUseTVMenuLanguage.Text = "Use the TV\'s language setting";
+      this.cbUseTVMenuLanguage.UseVisualStyleBackColor = true;
+      // 
+      // lPlayerConfig
+      // 
+      this.lPlayerConfig.AutoSize = true;
+      this.lPlayerConfig.Font = new System.Drawing.Font("Microsoft Sans Serif", 14.25F, System.Drawing.FontStyle.Bold, System.Drawing.GraphicsUnit.Point, ((byte)(0)));
+      this.lPlayerConfig.Location = new System.Drawing.Point(6, 165);
+      this.lPlayerConfig.Name = "lPlayerConfig";
+      this.lPlayerConfig.Size = new System.Drawing.Size(198, 24);
+      this.lPlayerConfig.TabIndex = 16;
+      this.lPlayerConfig.Text = "Player Configuration";
+      // 
+      // lAdapterConfig
+      // 
+      this.lAdapterConfig.AutoSize = true;
+      this.lAdapterConfig.Font = new System.Drawing.Font("Microsoft Sans Serif", 14.25F, System.Drawing.FontStyle.Bold, System.Drawing.GraphicsUnit.Point, ((byte)(0)));
+      this.lAdapterConfig.Location = new System.Drawing.Point(6, 3);
+      this.lAdapterConfig.Name = "lAdapterConfig";
+      this.lAdapterConfig.Size = new System.Drawing.Size(213, 24);
+      this.lAdapterConfig.TabIndex = 15;
+      this.lAdapterConfig.Text = "Adapter Configuration";
+      // 
+      // cbDeviceType
+      // 
+      this.cbDeviceType.Enabled = false;
+      this.cbDeviceType.FormattingEnabled = true;
+      this.cbDeviceType.Items.AddRange(new object[] {
+            "Recorder",
+            "Player",
+            "Tuner"});
+      this.cbDeviceType.Location = new System.Drawing.Point(174, 123);
+      this.cbDeviceType.Name = "cbDeviceType";
+      this.cbDeviceType.Size = new System.Drawing.Size(121, 21);
+      this.cbDeviceType.TabIndex = 14;
+      this.cbDeviceType.Text = "Recorder";
+      // 
+      // bClose
+      // 
+      this.bClose.Enabled = false;
+      this.bClose.Location = new System.Drawing.Point(189, 330);
+      this.bClose.Name = "bClose";
+      this.bClose.Size = new System.Drawing.Size(75, 23);
+      this.bClose.TabIndex = 13;
+      this.bClose.Text = "Close";
+      this.bClose.UseVisualStyleBackColor = true;
+      this.bClose.Click += new System.EventHandler(this.bCancel_Click);
+      // 
+      // bSave
+      // 
+      this.bSave.Enabled = false;
+      this.bSave.Location = new System.Drawing.Point(298, 330);
+      this.bSave.Name = "bSave";
+      this.bSave.Size = new System.Drawing.Size(125, 23);
+      this.bSave.TabIndex = 12;
+      this.bSave.Text = "Save configuration";
+      this.bSave.UseVisualStyleBackColor = true;
+      this.bSave.Click += new System.EventHandler(this.bSave_Click);
+      // 
+      // cbPortNumber
+      // 
+      this.cbPortNumber.AutoCompleteMode = System.Windows.Forms.AutoCompleteMode.Append;
+      this.cbPortNumber.Enabled = false;
+      this.cbPortNumber.FormattingEnabled = true;
+      this.cbPortNumber.Items.AddRange(new object[] {
+            "1",
+            "2",
+            "3",
+            "4"});
+      this.cbPortNumber.Location = new System.Drawing.Point(174, 40);
+      this.cbPortNumber.Name = "cbPortNumber";
+      this.cbPortNumber.Size = new System.Drawing.Size(38, 21);
+      this.cbPortNumber.TabIndex = 11;
+      this.cbPortNumber.Text = "1";
+      this.cbPortNumber.SelectedIndexChanged += new System.EventHandler(this.connectedDevice_SelectedIndexChanged);
+      // 
+      // lConnectedPhysicalAddress
+      // 
+      this.lConnectedPhysicalAddress.AutoSize = true;
+      this.lConnectedPhysicalAddress.Location = new System.Drawing.Point(310, 70);
+      this.lConnectedPhysicalAddress.Name = "lConnectedPhysicalAddress";
+      this.lConnectedPhysicalAddress.Size = new System.Drawing.Size(75, 13);
+      this.lConnectedPhysicalAddress.TabIndex = 10;
+      this.lConnectedPhysicalAddress.Text = "Address: 0000";
+      // 
+      // tbPhysicalAddress
+      // 
+      this.tbPhysicalAddress.Enabled = false;
+      this.tbPhysicalAddress.Location = new System.Drawing.Point(174, 95);
+      this.tbPhysicalAddress.MaxLength = 4;
+      this.tbPhysicalAddress.Name = "tbPhysicalAddress";
+      this.tbPhysicalAddress.Size = new System.Drawing.Size(38, 20);
+      this.tbPhysicalAddress.TabIndex = 6;
+      this.tbPhysicalAddress.Text = "1000";
+      this.tbPhysicalAddress.TextChanged += new System.EventHandler(this.tbPhysicalAddress_TextChanged);
+      // 
+      // cbConnectedDevice
+      // 
+      this.cbConnectedDevice.AutoCompleteMode = System.Windows.Forms.AutoCompleteMode.Append;
+      this.cbConnectedDevice.Enabled = false;
+      this.cbConnectedDevice.FormattingEnabled = true;
+      this.cbConnectedDevice.Location = new System.Drawing.Point(174, 67);
+      this.cbConnectedDevice.Name = "cbConnectedDevice";
+      this.cbConnectedDevice.Size = new System.Drawing.Size(121, 21);
+      this.cbConnectedDevice.TabIndex = 5;
+      this.cbConnectedDevice.SelectedIndexChanged += new System.EventHandler(this.connectedDevice_SelectedIndexChanged);
+      // 
+      // lDeviceType
+      // 
+      this.lDeviceType.AutoSize = true;
+      this.lDeviceType.Location = new System.Drawing.Point(6, 126);
+      this.lDeviceType.Name = "lDeviceType";
+      this.lDeviceType.Size = new System.Drawing.Size(64, 13);
+      this.lDeviceType.TabIndex = 3;
+      this.lDeviceType.Text = "Device type";
+      // 
+      // lPhysicalAddress
+      // 
+      this.lPhysicalAddress.AutoSize = true;
+      this.lPhysicalAddress.Location = new System.Drawing.Point(6, 98);
+      this.lPhysicalAddress.Name = "lPhysicalAddress";
+      this.lPhysicalAddress.Size = new System.Drawing.Size(86, 13);
+      this.lPhysicalAddress.TabIndex = 2;
+      this.lPhysicalAddress.Text = "Physical address";
+      // 
+      // lConnectedDevice
+      // 
+      this.lConnectedDevice.AutoSize = true;
+      this.lConnectedDevice.Location = new System.Drawing.Point(6, 70);
+      this.lConnectedDevice.Name = "lConnectedDevice";
+      this.lConnectedDevice.Size = new System.Drawing.Size(137, 13);
+      this.lConnectedDevice.TabIndex = 1;
+      this.lConnectedDevice.Text = "Connected to HDMI device";
+      // 
+      // lPortNumber
+      // 
+      this.lPortNumber.AutoSize = true;
+      this.lPortNumber.Location = new System.Drawing.Point(6, 43);
+      this.lPortNumber.Name = "lPortNumber";
+      this.lPortNumber.Size = new System.Drawing.Size(95, 13);
+      this.lPortNumber.TabIndex = 0;
+      this.lPortNumber.Text = "HDMI Port number";
+      // 
+      // LogOutput
+      // 
+      this.LogOutput.Controls.Add(this.tbLog);
+      this.LogOutput.Location = new System.Drawing.Point(4, 22);
+      this.LogOutput.Name = "LogOutput";
+      this.LogOutput.Padding = new System.Windows.Forms.Padding(3);
+      this.LogOutput.Size = new System.Drawing.Size(592, 359);
+      this.LogOutput.TabIndex = 1;
+      this.LogOutput.Text = "Log Output";
+      this.LogOutput.UseVisualStyleBackColor = true;
+      // 
+      // tbLog
+      // 
+      this.tbLog.Location = new System.Drawing.Point(6, 6);
+      this.tbLog.Multiline = true;
+      this.tbLog.Name = "tbLog";
+      this.tbLog.ScrollBars = System.Windows.Forms.ScrollBars.Vertical;
+      this.tbLog.Size = new System.Drawing.Size(580, 347);
+      this.tbLog.TabIndex = 0;
+      // 
+      // pProgress
+      // 
+      this.pProgress.Location = new System.Drawing.Point(314, 407);
+      this.pProgress.Name = "pProgress";
+      this.pProgress.Size = new System.Drawing.Size(298, 23);
+      this.pProgress.TabIndex = 1;
+      // 
+      // lStatus
+      // 
+      this.lStatus.AutoSize = true;
+      this.lStatus.Location = new System.Drawing.Point(12, 416);
+      this.lStatus.Name = "lStatus";
+      this.lStatus.Size = new System.Drawing.Size(61, 13);
+      this.lStatus.TabIndex = 2;
+      this.lStatus.Text = "Initialising...";
+      // 
+      // CecConfigGUI
+      // 
+      this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F);
+      this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font;
+      this.ClientSize = new System.Drawing.Size(624, 442);
+      this.Controls.Add(this.lStatus);
+      this.Controls.Add(this.pProgress);
+      this.Controls.Add(this.tabControl1);
+      this.Name = "CecConfigGUI";
+      this.Text = "Pulse-Eight USB-CEC Adapter";
+      this.tabControl1.ResumeLayout(false);
+      this.Configuration.ResumeLayout(false);
+      this.Configuration.PerformLayout();
+      this.LogOutput.ResumeLayout(false);
+      this.LogOutput.PerformLayout();
+      this.ResumeLayout(false);
+      this.PerformLayout();
+
+    }
+
+    #endregion
+
+    private System.Windows.Forms.TabControl tabControl1;
+    private System.Windows.Forms.TabPage Configuration;
+    private System.Windows.Forms.TabPage LogOutput;
+    private System.Windows.Forms.Label lPortNumber;
+    private System.Windows.Forms.Label lDeviceType;
+    private System.Windows.Forms.Label lPhysicalAddress;
+    private System.Windows.Forms.Label lConnectedDevice;
+    private System.Windows.Forms.ComboBox cbConnectedDevice;
+    private System.Windows.Forms.TextBox tbPhysicalAddress;
+    private System.Windows.Forms.ProgressBar pProgress;
+    private System.Windows.Forms.Label lStatus;
+    private System.Windows.Forms.Label lConnectedPhysicalAddress;
+    private System.Windows.Forms.TextBox tbLog;
+    private System.Windows.Forms.ComboBox cbPortNumber;
+    private System.Windows.Forms.Button bClose;
+    private System.Windows.Forms.Button bSave;
+    private System.Windows.Forms.ComboBox cbDeviceType;
+    private System.Windows.Forms.Label lAdapterConfig;
+    private System.Windows.Forms.CheckBox cbPowerOffOnStandby;
+    private System.Windows.Forms.CheckBox cbPowerOffScreensaver;
+    private System.Windows.Forms.CheckBox cbPowerOffShutdown;
+    private System.Windows.Forms.CheckBox cbPowerOnStartup;
+    private System.Windows.Forms.CheckBox cbUseTVMenuLanguage;
+    private System.Windows.Forms.Label lPlayerConfig;
+  }
+}
\ No newline at end of file
diff --git a/src/cec-config-gui/CecConfigGUI.cs b/src/cec-config-gui/CecConfigGUI.cs
new file mode 100644 (file)
index 0000000..15d3f0d
--- /dev/null
@@ -0,0 +1,432 @@
+using System;
+using System.Collections.Generic;
+using System.ComponentModel;
+using System.Data;
+using System.Drawing;
+using System.Text;
+using System.Windows.Forms;
+using System.Threading;
+using CecSharp;
+using CecConfigGui.actions;
+using System.Globalization;
+using System.IO;
+
+namespace CecConfigGui
+{
+  public partial class CecConfigGUI : Form
+  {
+    public CecConfigGUI()
+    {
+      Config = new LibCECConfiguration();
+      Config.DeviceTypes.Types[0] = CecDeviceType.RecordingDevice;
+      Config.DeviceName = "CEC Config";
+      Config.GetSettingsFromROM = true;
+      Config.ClientVersion = CecClientVersion.Version1_5_0;
+      Callbacks = new CecCallbackWrapper(this);
+      Config.SetCallbacks(Callbacks);
+
+      InitializeComponent();
+      Lib = new LibCecSharp(Config);
+
+      ActiveProcess = new ConnectToDevice(ref Lib);
+      ActiveProcess.EventHandler += new EventHandler<UpdateEvent>(ProcessEventHandler);
+      (new Thread(new ThreadStart(ActiveProcess.Run))).Start();
+    }
+
+    public int ReceiveCommand(CecCommand command)
+    {
+      return 1;
+    }
+
+    public int ReceiveKeypress(CecKeypress key)
+    {
+      return 1;
+    }
+
+    delegate void AddLogMessageCallback(CecLogMessage message);
+    private void AddLogMessage(CecLogMessage message)
+    {
+      if (tbLog.InvokeRequired)
+      {
+        AddLogMessageCallback d = new AddLogMessageCallback(AddLogMessage);
+        try
+        {
+          this.Invoke(d, new object[] { message });
+        }
+        catch (Exception) { }
+      }
+      else
+      {
+        if (((int)message.Level & LogLevel) == (int)message.Level)
+        {
+          string strLevel = "";
+          switch (message.Level)
+          {
+            case CecLogLevel.Error:
+              strLevel = "ERROR:   ";
+              break;
+            case CecLogLevel.Warning:
+              strLevel = "WARNING: ";
+              break;
+            case CecLogLevel.Notice:
+              strLevel = "NOTICE:  ";
+              break;
+            case CecLogLevel.Traffic:
+              strLevel = "TRAFFIC: ";
+              break;
+            case CecLogLevel.Debug:
+              strLevel = "DEBUG:   ";
+              break;
+            default:
+              break;
+          }
+          string strLog = string.Format("{0} {1,16} {2}", strLevel, message.Time, message.Message) + System.Environment.NewLine;
+          tbLog.Text += strLog;
+        }
+      }
+    }
+
+    public int ReceiveLogMessage(CecLogMessage message)
+    {
+      AddLogMessage(message);
+      return 1;
+    }
+
+    delegate void SetControlEnabledCallback(Control control, bool val);
+    private void SetControlEnabled(Control control, bool val)
+    {
+      if (control.InvokeRequired)
+      {
+        SetControlEnabledCallback d = new SetControlEnabledCallback(SetControlEnabled);
+        try
+        {
+          this.Invoke(d, new object[] { control, val });
+        }
+        catch (Exception) { }
+      }
+      else
+      {
+        control.Enabled = val;
+      }
+    }
+
+    private void SetControlsEnabled(bool val)
+    {
+      SetControlEnabled(cbPortNumber, val);
+      SetControlEnabled(cbConnectedDevice, val);
+      SetControlEnabled(tbPhysicalAddress, val);
+      SetControlEnabled(cbDeviceType, val);
+      SetControlEnabled(cbUseTVMenuLanguage, val);
+      SetControlEnabled(cbPowerOnStartup, val);
+      SetControlEnabled(cbPowerOffShutdown, val);
+      SetControlEnabled(cbPowerOffScreensaver, val);
+      SetControlEnabled(cbPowerOffOnStandby, val);
+      SetControlEnabled(bClose, val);
+      SetControlEnabled(bSave, val);
+    }
+
+    delegate void SetControlTextCallback(Control control, string val);
+    private void SetControlText(Control control, string val)
+    {
+      if (control.InvokeRequired)
+      {
+        SetControlTextCallback d = new SetControlTextCallback(SetControlText);
+        try
+        {
+          this.Invoke(d, new object[] { control, val });
+        }
+        catch (Exception) { }
+      }
+      else
+      {
+        control.Text = val;
+      }
+    }
+
+    delegate void SetCheckboxCheckedCallback(CheckBox control, bool val);
+    private void SetCheckboxChecked(CheckBox control, bool val)
+    {
+      if (control.InvokeRequired)
+      {
+        SetCheckboxCheckedCallback d = new SetCheckboxCheckedCallback(SetCheckboxChecked);
+        try
+        {
+          this.Invoke(d, new object[] { control, val });
+        }
+        catch (Exception) { }
+      }
+      else
+      {
+        control.Checked = val;
+      }
+    }
+
+    delegate void SetProgressValueCallback(ProgressBar control, int val);
+    private void SetProgressValue(ProgressBar control, int val)
+    {
+      if (control.InvokeRequired)
+      {
+        SetProgressValueCallback d = new SetProgressValueCallback(SetProgressValue);
+        try
+        {
+          this.Invoke(d, new object[] { control, val });
+        }
+        catch (Exception) { }
+      }
+      else
+      {
+        control.Value = val;
+      }
+    }
+
+    delegate void SetComboBoxItemsCallback(ComboBox control, string selectedText, object[] val);
+    private void SetComboBoxItems(ComboBox control, string selectedText, object[] val)
+    {
+      if (control.InvokeRequired)
+      {
+        SetComboBoxItemsCallback d = new SetComboBoxItemsCallback(SetComboBoxItems);
+        try
+        {
+          this.Invoke(d, new object[] { control, selectedText, val });
+        }
+        catch (Exception) { }
+      }
+      else
+      {
+        control.Items.Clear();
+        control.Items.AddRange(val);
+        control.Text = selectedText;
+      }
+    }
+
+    private void ProcessEventHandler(object src, UpdateEvent updateEvent)
+    {
+      switch (updateEvent.Type)
+      {
+        case UpdateEventType.StatusText:
+          SetControlText(lStatus, updateEvent.StringValue);
+          break;
+        case UpdateEventType.PhysicalAddress:
+          Config.PhysicalAddress = (ushort)updateEvent.IntValue;
+          SetControlText(tbPhysicalAddress, string.Format("{0,4:X}", updateEvent.IntValue));
+          break;
+        case UpdateEventType.ProgressBar:
+          SetProgressValue(pProgress, updateEvent.IntValue);
+          break;
+        case UpdateEventType.TVVendorId:
+          TVVendor = (CecVendorId)updateEvent.IntValue;
+          UpdateSelectedDevice();
+          break;
+        case UpdateEventType.BaseDevicePhysicalAddress:
+          SetControlText(lConnectedPhysicalAddress, string.Format("Address: {0,4:X}", updateEvent.IntValue));
+          break;
+        case UpdateEventType.BaseDevice:
+          Config.BaseDevice = (CecLogicalAddress)updateEvent.IntValue;
+          break;
+        case UpdateEventType.HDMIPort:
+          Config.HDMIPort = (byte)updateEvent.IntValue;
+          break;
+        case UpdateEventType.HasAVRDevice:
+          if (HasAVRDevice != updateEvent.BoolValue)
+          {
+            HasAVRDevice = updateEvent.BoolValue;
+            UpdateSelectedDevice();
+          }
+          break;
+        case UpdateEventType.AVRVendorId:
+          AVRVendor = (CecVendorId)updateEvent.IntValue;
+          UpdateSelectedDevice();
+          break;
+        case UpdateEventType.Configuration:
+          Config = updateEvent.ConfigValue;
+          SetControlText(tbPhysicalAddress, string.Format("{0,4:X}", Config.PhysicalAddress));
+          SetControlText(cbConnectedDevice, Config.BaseDevice == CecLogicalAddress.AudioSystem ? AVRVendorString : TVVendorString);
+          SetControlText(cbPortNumber, Config.HDMIPort.ToString());
+          SetCheckboxChecked(cbUseTVMenuLanguage, Config.UseTVMenuLanguage);
+          SetCheckboxChecked(cbPowerOnStartup, Config.PowerOnStartup);
+          SetCheckboxChecked(cbPowerOffShutdown, Config.PowerOffShutdown);
+          SetCheckboxChecked(cbPowerOffScreensaver, Config.PowerOffScreensaver);
+          SetCheckboxChecked(cbPowerOffOnStandby, Config.PowerOffOnStandby);
+          UpdateSelectedDevice();
+          break;
+        case UpdateEventType.ProcessCompleted:
+          ActiveProcess = null;
+          SetControlsEnabled(true);
+          break;
+      }
+    }
+
+    private void UpdateSelectedDevice()
+    {
+      if (HasAVRDevice)
+        SetComboBoxItems(this.cbConnectedDevice, Config.BaseDevice == CecLogicalAddress.AudioSystem ? AVRVendorString : TVVendorString, new object[] { TVVendorString, AVRVendorString });
+      else
+        SetComboBoxItems(this.cbConnectedDevice, TVVendorString, new object[] { TVVendorString });
+    }
+
+    public string TVVendorString
+    {
+      get
+      {
+        return TVVendor != CecVendorId.Unknown ?
+          "Television (" + Lib.ToString(TVVendor) + ")" :
+          "Television";
+      }
+    }
+
+    public string AVRVendorString
+    {
+      get
+      {
+        return AVRVendor != CecVendorId.Unknown ?
+          "AVR (" + Lib.ToString(AVRVendor) + ")" :
+          "AVR";
+      }
+    }
+
+    protected bool HasAVRDevice;
+    protected CecVendorId TVVendor = CecVendorId.Unknown;
+    protected CecVendorId AVRVendor = CecVendorId.Unknown;
+    protected CecLogicalAddress SelectedConnectedDevice = CecLogicalAddress.Unknown;
+    protected int LogLevel = (int)CecLogLevel.All;
+
+    protected LibCECConfiguration Config;
+    protected LibCecSharp Lib;
+    private CecCallbackWrapper Callbacks;
+    private UpdateProcess ActiveProcess = null;
+
+    private void connectedDevice_SelectedIndexChanged(object sender, EventArgs e)
+    {
+      if (ActiveProcess == null)
+      {
+        SetControlsEnabled(false);
+        SelectedConnectedDevice = (this.cbConnectedDevice.Text.Equals(AVRVendorString)) ? CecLogicalAddress.AudioSystem : CecLogicalAddress.Tv;
+        int iPortNumber = 0;
+        if (!int.TryParse(cbPortNumber.Text, out iPortNumber))
+          iPortNumber = 1;
+        ActiveProcess = new UpdateConnectedDevice(ref Lib, cbConnectedDevice.Text.Equals(AVRVendorString) ? CecLogicalAddress.AudioSystem : CecLogicalAddress.Tv, iPortNumber);
+        ActiveProcess.EventHandler += new EventHandler<UpdateEvent>(ProcessEventHandler);
+        (new Thread(new ThreadStart(ActiveProcess.Run))).Start();
+      }
+    }
+
+    private void bCancel_Click(object sender, EventArgs e)
+    {
+      this.Dispose();
+    }
+
+    private void bSave_Click(object sender, EventArgs e)
+    {
+      SetControlsEnabled(false);
+
+      Config.UseTVMenuLanguage = cbUseTVMenuLanguage.Checked;
+      Config.PowerOnStartup = cbPowerOnStartup.Checked;
+      Config.PowerOffShutdown = cbPowerOffShutdown.Checked;
+      Config.PowerOffScreensaver = cbPowerOffScreensaver.Checked;
+      Config.PowerOffOnStandby = cbPowerOffOnStandby.Checked;
+
+      if (!Lib.CanPersistConfiguration())
+      {
+        if (ActiveProcess == null)
+        {
+          SetControlsEnabled(false);
+          string xbmcDir = Environment.GetFolderPath(Environment.SpecialFolder.ApplicationData) + @"\XBMC\userdata\peripheral_data";
+          string defaultDir = Environment.GetFolderPath(Environment.SpecialFolder.MyDocuments);
+
+          SaveFileDialog dialog = new SaveFileDialog()
+          {
+            Title = "Where do you want to store the settings?",
+            InitialDirectory = Directory.Exists(xbmcDir) ? xbmcDir : defaultDir,
+            FileName = "usb_2548_1001.xml",
+            Filter = "xml files (*.xml)|*.xml|All files (*.*)|*.*",
+            FilterIndex = 1
+          };
+
+          if (dialog.ShowDialog() == DialogResult.OK)
+          {
+            FileStream fs = (FileStream)dialog.OpenFile();
+            if (fs == null)
+            {
+              MessageBox.Show("Cannot open '" + dialog.FileName + "' for writing", "Pulse-Eight USB-CEC Adapter", MessageBoxButtons.OK, MessageBoxIcon.Error);
+            }
+            else
+            {
+              StreamWriter writer = new StreamWriter(fs);
+              StringBuilder output = new StringBuilder();
+              output.AppendLine("<settings>");
+              output.AppendLine("<setting id=\"cec_hdmi_port\" value=\"" + Config.HDMIPort + "\" />");
+              output.AppendLine("<setting id=\"connected_device\" value=\"" + (Config.BaseDevice == CecLogicalAddress.AudioSystem ? 5 : 1) + "\" />");
+              output.AppendLine("<setting id=\"physical_address\" value=\"" + string.Format("{0,4:X}", Config.PhysicalAddress) + "\" />");
+              output.AppendLine("<setting id=\"device_type\" value=\"" + (int)Config.DeviceTypes.Types[0] + "\" />");
+              output.AppendLine("<setting id=\"cec_power_on_startup\" value=\"" + (Config.PowerOnStartup ? 1 : 0) + "\" />");
+              output.AppendLine("<setting id=\"cec_power_off_shutdown\" value=\"" + (Config.PowerOffShutdown ? 1 : 0) + "\" />");
+              output.AppendLine("<setting id=\"cec_standby_screensaver\" value=\"" + (Config.PowerOffScreensaver ? 1 : 0) + "\" />");
+              output.AppendLine("<setting id=\"standby_pc_on_tv_standby\" value=\"" + (Config.PowerOffOnStandby ? 1 : 0) + "\" />");
+              output.AppendLine("<setting id=\"use_tv_menu_language\" value=\"" + (Config.UseTVMenuLanguage ? 1 : 0) + "\" />");
+              output.AppendLine("<setting id=\"enabled\" value=\"1\" />");
+              output.AppendLine("<setting id=\"port\" value=\"\" />");
+              output.AppendLine("</settings>");
+              writer.Write(output.ToString());
+              writer.Close();
+              fs.Close();
+              fs.Dispose();
+              MessageBox.Show("Settings are stored.", "Pulse-Eight USB-CEC Adapter", MessageBoxButtons.OK, MessageBoxIcon.Information);
+            }
+          }
+          SetControlsEnabled(true);
+        }
+      }
+      else
+      {
+        if (!Lib.PersistConfiguration(Config))
+          MessageBox.Show("Could not persist the new settings.", "Pulse-Eight USB-CEC Adapter", MessageBoxButtons.OK, MessageBoxIcon.Error);
+        else
+          MessageBox.Show("Settings are stored.", "Pulse-Eight USB-CEC Adapter", MessageBoxButtons.OK, MessageBoxIcon.Information);
+      }
+      SetControlsEnabled(true);
+    }
+
+    private void tbPhysicalAddress_TextChanged(object sender, EventArgs e)
+    {
+      if (ActiveProcess == null)
+      {
+        if (tbPhysicalAddress.Text.Length != 4)
+          return;
+        ushort physicalAddress = 0;
+        if (!ushort.TryParse(tbPhysicalAddress.Text, NumberStyles.AllowHexSpecifier, null, out physicalAddress))
+          return;
+        SetControlsEnabled(false);
+        SetControlText(cbPortNumber, string.Empty);
+        SetControlText(cbConnectedDevice, string.Empty);
+        ActiveProcess = new UpdatePhysicalAddress(ref Lib, physicalAddress);
+        ActiveProcess.EventHandler += new EventHandler<UpdateEvent>(ProcessEventHandler);
+        (new Thread(new ThreadStart(ActiveProcess.Run))).Start();
+      }
+    }
+  }
+
+  internal class CecCallbackWrapper : CecCallbackMethods
+  {
+    public CecCallbackWrapper(CecConfigGUI gui)
+    {
+      Gui = gui;
+    }
+
+    public override int ReceiveCommand(CecCommand command)
+    {
+      return Gui.ReceiveCommand(command);
+    }
+
+    public override int ReceiveKeypress(CecKeypress key)
+    {
+      return Gui.ReceiveKeypress(key);
+    }
+
+    public override int ReceiveLogMessage(CecLogMessage message)
+    {
+      return Gui.ReceiveLogMessage(message);
+    }
+
+    private CecConfigGUI Gui;
+  }
+}
diff --git a/src/cec-config-gui/CecConfigGUI.resx b/src/cec-config-gui/CecConfigGUI.resx
new file mode 100644 (file)
index 0000000..19dc0dd
--- /dev/null
@@ -0,0 +1,120 @@
+<?xml version="1.0" encoding="utf-8"?>
+<root>
+  <!-- 
+    Microsoft ResX Schema 
+    
+    Version 2.0
+    
+    The primary goals of this format is to allow a simple XML format 
+    that is mostly human readable. The generation and parsing of the 
+    various data types are done through the TypeConverter classes 
+    associated with the data types.
+    
+    Example:
+    
+    ... ado.net/XML headers & schema ...
+    <resheader name="resmimetype">text/microsoft-resx</resheader>
+    <resheader name="version">2.0</resheader>
+    <resheader name="reader">System.Resources.ResXResourceReader, System.Windows.Forms, ...</resheader>
+    <resheader name="writer">System.Resources.ResXResourceWriter, System.Windows.Forms, ...</resheader>
+    <data name="Name1"><value>this is my long string</value><comment>this is a comment</comment></data>
+    <data name="Color1" type="System.Drawing.Color, System.Drawing">Blue</data>
+    <data name="Bitmap1" mimetype="application/x-microsoft.net.object.binary.base64">
+        <value>[base64 mime encoded serialized .NET Framework object]</value>
+    </data>
+    <data name="Icon1" type="System.Drawing.Icon, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
+        <value>[base64 mime encoded string representing a byte array form of the .NET Framework object]</value>
+        <comment>This is a comment</comment>
+    </data>
+                
+    There are any number of "resheader" rows that contain simple 
+    name/value pairs.
+    
+    Each data row contains a name, and value. The row also contains a 
+    type or mimetype. Type corresponds to a .NET class that support 
+    text/value conversion through the TypeConverter architecture. 
+    Classes that don't support this are serialized and stored with the 
+    mimetype set.
+    
+    The mimetype is used for serialized objects, and tells the 
+    ResXResourceReader how to depersist the object. This is currently not 
+    extensible. For a given mimetype the value must be set accordingly:
+    
+    Note - application/x-microsoft.net.object.binary.base64 is the format 
+    that the ResXResourceWriter will generate, however the reader can 
+    read any of the formats listed below.
+    
+    mimetype: application/x-microsoft.net.object.binary.base64
+    value   : The object must be serialized with 
+            : System.Runtime.Serialization.Formatters.Binary.BinaryFormatter
+            : and then encoded with base64 encoding.
+    
+    mimetype: application/x-microsoft.net.object.soap.base64
+    value   : The object must be serialized with 
+            : System.Runtime.Serialization.Formatters.Soap.SoapFormatter
+            : and then encoded with base64 encoding.
+
+    mimetype: application/x-microsoft.net.object.bytearray.base64
+    value   : The object must be serialized into a byte array 
+            : using a System.ComponentModel.TypeConverter
+            : and then encoded with base64 encoding.
+    -->
+  <xsd:schema id="root" xmlns="" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:msdata="urn:schemas-microsoft-com:xml-msdata">
+    <xsd:import namespace="http://www.w3.org/XML/1998/namespace" />
+    <xsd:element name="root" msdata:IsDataSet="true">
+      <xsd:complexType>
+        <xsd:choice maxOccurs="unbounded">
+          <xsd:element name="metadata">
+            <xsd:complexType>
+              <xsd:sequence>
+                <xsd:element name="value" type="xsd:string" minOccurs="0" />
+              </xsd:sequence>
+              <xsd:attribute name="name" use="required" type="xsd:string" />
+              <xsd:attribute name="type" type="xsd:string" />
+              <xsd:attribute name="mimetype" type="xsd:string" />
+              <xsd:attribute ref="xml:space" />
+            </xsd:complexType>
+          </xsd:element>
+          <xsd:element name="assembly">
+            <xsd:complexType>
+              <xsd:attribute name="alias" type="xsd:string" />
+              <xsd:attribute name="name" type="xsd:string" />
+            </xsd:complexType>
+          </xsd:element>
+          <xsd:element name="data">
+            <xsd:complexType>
+              <xsd:sequence>
+                <xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
+                <xsd:element name="comment" type="xsd:string" minOccurs="0" msdata:Ordinal="2" />
+              </xsd:sequence>
+              <xsd:attribute name="name" type="xsd:string" use="required" msdata:Ordinal="1" />
+              <xsd:attribute name="type" type="xsd:string" msdata:Ordinal="3" />
+              <xsd:attribute name="mimetype" type="xsd:string" msdata:Ordinal="4" />
+              <xsd:attribute ref="xml:space" />
+            </xsd:complexType>
+          </xsd:element>
+          <xsd:element name="resheader">
+            <xsd:complexType>
+              <xsd:sequence>
+                <xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
+              </xsd:sequence>
+              <xsd:attribute name="name" type="xsd:string" use="required" />
+            </xsd:complexType>
+          </xsd:element>
+        </xsd:choice>
+      </xsd:complexType>
+    </xsd:element>
+  </xsd:schema>
+  <resheader name="resmimetype">
+    <value>text/microsoft-resx</value>
+  </resheader>
+  <resheader name="version">
+    <value>2.0</value>
+  </resheader>
+  <resheader name="reader">
+    <value>System.Resources.ResXResourceReader, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
+  </resheader>
+  <resheader name="writer">
+    <value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
+  </resheader>
+</root>
\ No newline at end of file
diff --git a/src/cec-config-gui/Program.cs b/src/cec-config-gui/Program.cs
new file mode 100644 (file)
index 0000000..0bc424c
--- /dev/null
@@ -0,0 +1,20 @@
+using System;
+using System.Collections.Generic;
+using System.Windows.Forms;
+
+namespace CecConfigGui
+{
+  static class Program
+  {
+    /// <summary>
+    /// The main entry point for the application.
+    /// </summary>
+    [STAThread]
+    static void Main()
+    {
+      Application.EnableVisualStyles();
+      Application.SetCompatibleTextRenderingDefault(false);
+      Application.Run(new CecConfigGUI());
+    }
+  }
+}
diff --git a/src/cec-config-gui/Properties/AssemblyInfo.cs b/src/cec-config-gui/Properties/AssemblyInfo.cs
new file mode 100644 (file)
index 0000000..ead3cf8
--- /dev/null
@@ -0,0 +1,36 @@
+using System.Reflection;
+using System.Runtime.CompilerServices;
+using System.Runtime.InteropServices;
+
+// General Information about an assembly is controlled through the following 
+// set of attributes. Change these attribute values to modify the information
+// associated with an assembly.
+[assembly: AssemblyTitle("cec-config-gui")]
+[assembly: AssemblyDescription("")]
+[assembly: AssemblyConfiguration("")]
+[assembly: AssemblyCompany("Microsoft")]
+[assembly: AssemblyProduct("cec-config-gui")]
+[assembly: AssemblyCopyright("Copyright © Microsoft 2012")]
+[assembly: AssemblyTrademark("")]
+[assembly: AssemblyCulture("")]
+
+// Setting ComVisible to false makes the types in this assembly not visible 
+// to COM components.  If you need to access a type in this assembly from 
+// COM, set the ComVisible attribute to true on that type.
+[assembly: ComVisible(false)]
+
+// The following GUID is for the ID of the typelib if this project is exposed to COM
+[assembly: Guid("acfc1f63-3e6c-45ca-9296-9fbf8541b4ae")]
+
+// Version information for an assembly consists of the following four values:
+//
+//      Major Version
+//      Minor Version 
+//      Build Number
+//      Revision
+//
+// You can specify all the values or you can default the Build and Revision Numbers 
+// by using the '*' as shown below:
+// [assembly: AssemblyVersion("1.0.*")]
+[assembly: AssemblyVersion("1.0.0.0")]
+[assembly: AssemblyFileVersion("1.0.0.0")]
diff --git a/src/cec-config-gui/Properties/Resources.Designer.cs b/src/cec-config-gui/Properties/Resources.Designer.cs
new file mode 100644 (file)
index 0000000..3ca0535
--- /dev/null
@@ -0,0 +1,63 @@
+//------------------------------------------------------------------------------
+// <auto-generated>
+//     This code was generated by a tool.
+//     Runtime Version:2.0.50727.5448
+//
+//     Changes to this file may cause incorrect behavior and will be lost if
+//     the code is regenerated.
+// </auto-generated>
+//------------------------------------------------------------------------------
+
+namespace CecConfigGui.Properties {
+    using System;
+    
+    
+    /// <summary>
+    ///   A strongly-typed resource class, for looking up localized strings, etc.
+    /// </summary>
+    // This class was auto-generated by the StronglyTypedResourceBuilder
+    // class via a tool like ResGen or Visual Studio.
+    // To add or remove a member, edit your .ResX file then rerun ResGen
+    // with the /str option, or rebuild your VS project.
+    [global::System.CodeDom.Compiler.GeneratedCodeAttribute("System.Resources.Tools.StronglyTypedResourceBuilder", "2.0.0.0")]
+    [global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
+    [global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()]
+    internal class Resources {
+        
+        private static global::System.Resources.ResourceManager resourceMan;
+        
+        private static global::System.Globalization.CultureInfo resourceCulture;
+        
+        [global::System.Diagnostics.CodeAnalysis.SuppressMessageAttribute("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode")]
+        internal Resources() {
+        }
+        
+        /// <summary>
+        ///   Returns the cached ResourceManager instance used by this class.
+        /// </summary>
+        [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)]
+        internal static global::System.Resources.ResourceManager ResourceManager {
+            get {
+                if (object.ReferenceEquals(resourceMan, null)) {
+                    global::System.Resources.ResourceManager temp = new global::System.Resources.ResourceManager("CecConfigGui.Properties.Resources", typeof(Resources).Assembly);
+                    resourceMan = temp;
+                }
+                return resourceMan;
+            }
+        }
+        
+        /// <summary>
+        ///   Overrides the current thread's CurrentUICulture property for all
+        ///   resource lookups using this strongly typed resource class.
+        /// </summary>
+        [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)]
+        internal static global::System.Globalization.CultureInfo Culture {
+            get {
+                return resourceCulture;
+            }
+            set {
+                resourceCulture = value;
+            }
+        }
+    }
+}
diff --git a/src/cec-config-gui/Properties/Resources.resx b/src/cec-config-gui/Properties/Resources.resx
new file mode 100644 (file)
index 0000000..af7dbeb
--- /dev/null
@@ -0,0 +1,117 @@
+<?xml version="1.0" encoding="utf-8"?>
+<root>
+  <!-- 
+    Microsoft ResX Schema 
+    
+    Version 2.0
+    
+    The primary goals of this format is to allow a simple XML format 
+    that is mostly human readable. The generation and parsing of the 
+    various data types are done through the TypeConverter classes 
+    associated with the data types.
+    
+    Example:
+    
+    ... ado.net/XML headers & schema ...
+    <resheader name="resmimetype">text/microsoft-resx</resheader>
+    <resheader name="version">2.0</resheader>
+    <resheader name="reader">System.Resources.ResXResourceReader, System.Windows.Forms, ...</resheader>
+    <resheader name="writer">System.Resources.ResXResourceWriter, System.Windows.Forms, ...</resheader>
+    <data name="Name1"><value>this is my long string</value><comment>this is a comment</comment></data>
+    <data name="Color1" type="System.Drawing.Color, System.Drawing">Blue</data>
+    <data name="Bitmap1" mimetype="application/x-microsoft.net.object.binary.base64">
+        <value>[base64 mime encoded serialized .NET Framework object]</value>
+    </data>
+    <data name="Icon1" type="System.Drawing.Icon, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
+        <value>[base64 mime encoded string representing a byte array form of the .NET Framework object]</value>
+        <comment>This is a comment</comment>
+    </data>
+                
+    There are any number of "resheader" rows that contain simple 
+    name/value pairs.
+    
+    Each data row contains a name, and value. The row also contains a 
+    type or mimetype. Type corresponds to a .NET class that support 
+    text/value conversion through the TypeConverter architecture. 
+    Classes that don't support this are serialized and stored with the 
+    mimetype set.
+    
+    The mimetype is used for serialized objects, and tells the 
+    ResXResourceReader how to depersist the object. This is currently not 
+    extensible. For a given mimetype the value must be set accordingly:
+    
+    Note - application/x-microsoft.net.object.binary.base64 is the format 
+    that the ResXResourceWriter will generate, however the reader can 
+    read any of the formats listed below.
+    
+    mimetype: application/x-microsoft.net.object.binary.base64
+    value   : The object must be serialized with 
+            : System.Serialization.Formatters.Binary.BinaryFormatter
+            : and then encoded with base64 encoding.
+    
+    mimetype: application/x-microsoft.net.object.soap.base64
+    value   : The object must be serialized with 
+            : System.Runtime.Serialization.Formatters.Soap.SoapFormatter
+            : and then encoded with base64 encoding.
+
+    mimetype: application/x-microsoft.net.object.bytearray.base64
+    value   : The object must be serialized into a byte array 
+            : using a System.ComponentModel.TypeConverter
+            : and then encoded with base64 encoding.
+    -->
+  <xsd:schema id="root" xmlns="" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:msdata="urn:schemas-microsoft-com:xml-msdata">
+    <xsd:element name="root" msdata:IsDataSet="true">
+      <xsd:complexType>
+        <xsd:choice maxOccurs="unbounded">
+          <xsd:element name="metadata">
+            <xsd:complexType>
+              <xsd:sequence>
+                <xsd:element name="value" type="xsd:string" minOccurs="0" />
+              </xsd:sequence>
+              <xsd:attribute name="name" type="xsd:string" />
+              <xsd:attribute name="type" type="xsd:string" />
+              <xsd:attribute name="mimetype" type="xsd:string" />
+            </xsd:complexType>
+          </xsd:element>
+          <xsd:element name="assembly">
+            <xsd:complexType>
+              <xsd:attribute name="alias" type="xsd:string" />
+              <xsd:attribute name="name" type="xsd:string" />
+            </xsd:complexType>
+          </xsd:element>
+          <xsd:element name="data">
+            <xsd:complexType>
+              <xsd:sequence>
+                <xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
+                <xsd:element name="comment" type="xsd:string" minOccurs="0" msdata:Ordinal="2" />
+              </xsd:sequence>
+              <xsd:attribute name="name" type="xsd:string" msdata:Ordinal="1" />
+              <xsd:attribute name="type" type="xsd:string" msdata:Ordinal="3" />
+              <xsd:attribute name="mimetype" type="xsd:string" msdata:Ordinal="4" />
+            </xsd:complexType>
+          </xsd:element>
+          <xsd:element name="resheader">
+            <xsd:complexType>
+              <xsd:sequence>
+                <xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
+              </xsd:sequence>
+              <xsd:attribute name="name" type="xsd:string" use="required" />
+            </xsd:complexType>
+          </xsd:element>
+        </xsd:choice>
+      </xsd:complexType>
+    </xsd:element>
+  </xsd:schema>
+  <resheader name="resmimetype">
+    <value>text/microsoft-resx</value>
+  </resheader>
+  <resheader name="version">
+    <value>2.0</value>
+  </resheader>
+  <resheader name="reader">
+    <value>System.Resources.ResXResourceReader, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
+  </resheader>
+  <resheader name="writer">
+    <value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
+  </resheader>
+</root>
\ No newline at end of file
diff --git a/src/cec-config-gui/Properties/Settings.Designer.cs b/src/cec-config-gui/Properties/Settings.Designer.cs
new file mode 100644 (file)
index 0000000..c1a7961
--- /dev/null
@@ -0,0 +1,26 @@
+//------------------------------------------------------------------------------
+// <auto-generated>
+//     This code was generated by a tool.
+//     Runtime Version:2.0.50727.5448
+//
+//     Changes to this file may cause incorrect behavior and will be lost if
+//     the code is regenerated.
+// </auto-generated>
+//------------------------------------------------------------------------------
+
+namespace CecConfigGui.Properties {
+    
+    
+    [global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()]
+    [global::System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.VisualStudio.Editors.SettingsDesigner.SettingsSingleFileGenerator", "9.0.0.0")]
+    internal sealed partial class Settings : global::System.Configuration.ApplicationSettingsBase {
+        
+        private static Settings defaultInstance = ((Settings)(global::System.Configuration.ApplicationSettingsBase.Synchronized(new Settings())));
+        
+        public static Settings Default {
+            get {
+                return defaultInstance;
+            }
+        }
+    }
+}
diff --git a/src/cec-config-gui/Properties/Settings.settings b/src/cec-config-gui/Properties/Settings.settings
new file mode 100644 (file)
index 0000000..3964565
--- /dev/null
@@ -0,0 +1,7 @@
+<?xml version='1.0' encoding='utf-8'?>
+<SettingsFile xmlns="http://schemas.microsoft.com/VisualStudio/2004/01/settings" CurrentProfile="(Default)">
+  <Profiles>
+    <Profile Name="(Default)" />
+  </Profiles>
+  <Settings />
+</SettingsFile>
diff --git a/src/cec-config-gui/actions/ConnectToDevice.cs b/src/cec-config-gui/actions/ConnectToDevice.cs
new file mode 100644 (file)
index 0000000..febc517
--- /dev/null
@@ -0,0 +1,166 @@
+using System;
+using System.Collections.Generic;
+using System.Text;
+using CecSharp;
+using System.Windows.Forms;
+using System.IO;
+using System.Xml;
+using System.Globalization;
+
+namespace CecConfigGui.actions
+{
+  class ConnectToDevice : UpdateProcess
+  {
+    public ConnectToDevice(ref LibCecSharp lib)
+    {
+      Lib = lib;
+    }
+
+    public override void Process()
+    {
+      SendEvent(UpdateEventType.StatusText, "Connecting to the CEC adapter...");
+      SendEvent(UpdateEventType.ProgressBar, 0);
+
+      CecAdapter[] adapters = Lib.FindAdapters(string.Empty);
+      if (adapters.Length == 0 || !Lib.Open(adapters[0].ComPort, 10000))
+      {
+        MessageBox.Show("Could not connect to any CEC adapter. Please check your configuration.", "Pulse-Eight USB-CEC Adapter", MessageBoxButtons.OK);
+        Application.Exit();
+      }
+
+      SendEvent(UpdateEventType.StatusText, "Detecting TV vendor...");
+      SendEvent(UpdateEventType.ProgressBar, 25);
+      SendEvent(UpdateEventType.TVVendorId, (int)Lib.GetDeviceVendorId(CecLogicalAddress.Tv));
+
+      SendEvent(UpdateEventType.ProgressBar, 50);
+      SendEvent(UpdateEventType.StatusText, "Detecting AVR devices...");
+
+      bool hasAVRDevice = Lib.IsActiveDevice(CecLogicalAddress.AudioSystem);
+      SendEvent(UpdateEventType.HasAVRDevice, hasAVRDevice);
+
+      if (hasAVRDevice)
+      {
+        SendEvent(UpdateEventType.ProgressBar, 75);
+        SendEvent(UpdateEventType.StatusText, "Detecting AVR vendor...");
+        SendEvent(UpdateEventType.AVRVendorId, (int)Lib.GetDeviceVendorId(CecLogicalAddress.AudioSystem));
+      }
+
+      if (!Lib.GetDevicePowerStatus(CecLogicalAddress.Tv).Equals(CecPowerStatus.On))
+      {
+        SendEvent(UpdateEventType.ProgressBar, 80);
+        SendEvent(UpdateEventType.StatusText, "Sending power on command...");
+        Lib.PowerOnDevices(CecLogicalAddress.Tv);
+      }
+
+      SendEvent(UpdateEventType.ProgressBar, 90);
+      SendEvent(UpdateEventType.StatusText, "Reading device configuration...");
+
+      LibCECConfiguration config = new LibCECConfiguration();
+
+      if (!Lib.CanPersistConfiguration())
+      {
+        bool gotConfig = false;
+        string xbmcDir = Environment.GetFolderPath(Environment.SpecialFolder.ApplicationData) + @"\XBMC\userdata\peripheral_data";
+        string defaultDir = Environment.GetFolderPath(Environment.SpecialFolder.MyDocuments);
+        string file = defaultDir + @"\usb_2548_1001.xml";
+        if (File.Exists(xbmcDir + @"\usb_2548_1001.xml"))
+          file = xbmcDir + @"\usb_2548_1001.xml";
+
+        if (File.Exists(file))
+        {
+          XmlTextReader reader = new XmlTextReader(file);
+          while (reader.Read())
+          {
+            gotConfig = true;
+            switch (reader.NodeType)
+            {
+              case XmlNodeType.Element:
+                if (reader.Name.ToLower() == "setting")
+                {
+                  string name = string.Empty;
+                  string value = string.Empty;
+
+                  while (reader.MoveToNextAttribute())
+                  {
+                    if (reader.Name.ToLower().Equals("id"))
+                      name = reader.Value.ToLower();
+                    if (reader.Name.ToLower().Equals("value"))
+                      value = reader.Value;
+                  }
+
+                  switch (name)
+                  {
+                    case "cec_hdmi_port":
+                      {
+                        byte iPort;
+                        if (byte.TryParse(value, out iPort))
+                          config.HDMIPort = iPort;
+                      }
+                      break;
+                    case "connected_device":
+                      {
+                        ushort iDevice;
+                        if (ushort.TryParse(value, out iDevice))
+                          config.BaseDevice = (CecLogicalAddress)iDevice;
+                      }
+                      break;
+                    case "physical_address":
+                      {
+                        ushort physicalAddress = 0;
+                        if (ushort.TryParse(value, NumberStyles.AllowHexSpecifier, null, out physicalAddress))
+                          config.PhysicalAddress = physicalAddress;
+                      }
+                      break;
+                    case "device_type":
+                      {
+                        ushort iType;
+                        if (ushort.TryParse(value, out iType))
+                          config.DeviceTypes.Types[0] = (CecDeviceType)iType;
+                      }
+                      break;
+                    case "cec_power_on_startup":
+                      config.PowerOnStartup = value.Equals("1") || value.ToLower().Equals("true") || value.ToLower().Equals("yes");
+                      break;
+                    case "cec_power_off_shutdown":
+                      config.PowerOffShutdown = value.Equals("1") || value.ToLower().Equals("true") || value.ToLower().Equals("yes");
+                      break;
+                    case "cec_standby_screensaver":
+                      config.PowerOffScreensaver = value.Equals("1") || value.ToLower().Equals("true") || value.ToLower().Equals("yes");
+                      break;
+                    case "standby_pc_on_tv_standby":
+                      config.PowerOffOnStandby = value.Equals("1") || value.ToLower().Equals("true") || value.ToLower().Equals("yes");
+                      break;
+                    case "use_tv_menu_language":
+                      config.UseTVMenuLanguage = value.Equals("1") || value.ToLower().Equals("true") || value.ToLower().Equals("yes");
+                      break;
+                    case "enabled":
+                      break;
+                    case "port":
+                      break;
+                    default:
+                      break;
+                  }
+                }
+                break;
+              default:
+                break;
+            }
+          }
+        }
+
+        if (!gotConfig)
+          Lib.GetCurrentConfiguration(config);
+      }
+      else
+      {
+        Lib.GetCurrentConfiguration(config);
+      }
+      SendEvent(config);
+
+      SendEvent(UpdateEventType.ProgressBar, 100);
+      SendEvent(UpdateEventType.StatusText, "Ready.");
+    }
+
+    private LibCecSharp Lib;
+  }
+}
diff --git a/src/cec-config-gui/actions/UpdateConnectedDevice.cs b/src/cec-config-gui/actions/UpdateConnectedDevice.cs
new file mode 100644 (file)
index 0000000..46e9f0c
--- /dev/null
@@ -0,0 +1,57 @@
+using System;
+using System.Collections.Generic;
+using System.Text;
+using CecSharp;
+
+namespace CecConfigGui.actions
+{
+  class UpdateConnectedDevice : UpdateProcess
+  {
+    public UpdateConnectedDevice(ref LibCecSharp lib, CecLogicalAddress address, int portNumber)
+    {
+      Lib = lib;
+      Address = address;
+      PortNumber = portNumber;
+    }
+
+    public override void Process()
+    {
+      SendEvent(UpdateEventType.StatusText, "Requesting physical address...");
+      SendEvent(UpdateEventType.ProgressBar, 0);
+
+      ushort iPhysicalAddress = Lib.GetDevicePhysicalAddress(Address);
+      SendEvent(UpdateEventType.BaseDevicePhysicalAddress, iPhysicalAddress);
+
+      SendEvent(UpdateEventType.StatusText, "Setting new configuration...");
+      SendEvent(UpdateEventType.ProgressBar, 25);
+
+      if (!Lib.SetHDMIPort(Address, (byte)PortNumber))
+      {
+        SendEvent(UpdateEventType.StatusText, "Could not activate the new source");
+      }
+      else
+      {
+        LibCECConfiguration config = new LibCECConfiguration();
+        Lib.GetCurrentConfiguration(config);
+
+        SendEvent(UpdateEventType.StatusText, "Activating source...");
+        SendEvent(UpdateEventType.ProgressBar, 50);
+        Lib.SetActiveSource(config.DeviceTypes.Types[0]);
+
+        SendEvent(UpdateEventType.StatusText, "Reading configuration...");
+        SendEvent(UpdateEventType.ProgressBar, 75);
+        Lib.GetCurrentConfiguration(config);
+
+        SendEvent(UpdateEventType.PhysicalAddress, config.PhysicalAddress);
+        SendEvent(UpdateEventType.BaseDevice, (int)config.BaseDevice);
+        SendEvent(UpdateEventType.HDMIPort, config.HDMIPort);
+        SendEvent(UpdateEventType.StatusText, "Ready.");
+      }
+      SendEvent(UpdateEventType.ProgressBar, 100);
+    }
+
+    private LibCecSharp       Lib;
+    private CecLogicalAddress Address;
+    private int               PortNumber;
+  }
+}
diff --git a/src/cec-config-gui/actions/UpdateEvent.cs b/src/cec-config-gui/actions/UpdateEvent.cs
new file mode 100644 (file)
index 0000000..b559764
--- /dev/null
@@ -0,0 +1,99 @@
+using System;
+using System.Collections.Generic;
+using System.Text;
+using CecSharp;
+
+namespace CecConfigGui
+{
+  public enum UpdateEventType
+  {
+    ProcessCompleted,
+    StatusText,
+    ProgressBar,
+    TVVendorId,
+    BaseDevicePhysicalAddress,
+    BaseDevice,
+    HDMIPort,
+    PhysicalAddress,
+    HasAVRDevice,
+    AVRVendorId,
+    Configuration
+  }
+
+  public class UpdateEvent : EventArgs
+  {
+    public UpdateEvent(UpdateEventType type, bool value)
+    {
+      Type = type;
+      BoolValue = value;
+    }
+
+    public UpdateEvent(UpdateEventType type, int value)
+    {
+      Type = type;
+      IntValue = value;
+    }
+
+    public UpdateEvent(UpdateEventType type, string value)
+    {
+      Type = type;
+      StringValue = value;
+    }
+
+    public UpdateEvent(LibCECConfiguration config)
+    {
+      Type = UpdateEventType.Configuration;
+      ConfigValue = config;
+    }
+
+    public UpdateEventType     Type;
+    public bool                BoolValue   = false;
+    public int                 IntValue    = -1;
+    public string              StringValue = String.Empty;
+    public LibCECConfiguration ConfigValue = null;
+  }
+
+  public abstract class UpdateProcess
+  {
+    public UpdateProcess()
+    {
+    }
+
+    public void SendEvent(UpdateEventType type, bool value)
+    {
+      EventHandler<UpdateEvent> temp = EventHandler;
+      if (temp != null)
+        temp(this, new UpdateEvent(type, value));
+    }
+
+    public void SendEvent(UpdateEventType type, int value)
+    {
+      EventHandler<UpdateEvent> temp = EventHandler;
+      if (temp != null)
+        temp(this, new UpdateEvent(type, value));
+    }
+
+    public void SendEvent(UpdateEventType type, string value)
+    {
+      EventHandler<UpdateEvent> temp = EventHandler;
+      if (temp != null)
+        temp(this, new UpdateEvent(type, value));
+    }
+
+    public void SendEvent(LibCECConfiguration config)
+    {
+      EventHandler<UpdateEvent> temp = EventHandler;
+      if (temp != null)
+        temp(this, new UpdateEvent(config));
+    }
+
+    public void Run()
+    {
+      Process();
+      SendEvent(UpdateEventType.ProcessCompleted, true);
+    }
+
+    public abstract void Process();
+    public event EventHandler<UpdateEvent> EventHandler;
+  }
+}
diff --git a/src/cec-config-gui/actions/UpdatePhysicalAddress.cs b/src/cec-config-gui/actions/UpdatePhysicalAddress.cs
new file mode 100644 (file)
index 0000000..1ed32ce
--- /dev/null
@@ -0,0 +1,48 @@
+using System;
+using System.Collections.Generic;
+using System.Text;
+using CecSharp;
+
+namespace CecConfigGui.actions
+{
+  class UpdatePhysicalAddress : UpdateProcess
+  {
+    public UpdatePhysicalAddress(ref LibCecSharp lib, ushort physicalAddress)
+    {
+      Lib = lib;
+      PhysicalAddress = physicalAddress;
+    }
+
+    public override void Process()
+    {
+      SendEvent(UpdateEventType.BaseDevicePhysicalAddress, 0);
+      SendEvent(UpdateEventType.StatusText, "Setting new configuration...");
+      SendEvent(UpdateEventType.ProgressBar, 25);
+
+      if (!Lib.SetPhysicalAddress(PhysicalAddress))
+      {
+        SendEvent(UpdateEventType.StatusText, "Could not activate the new source");
+      }
+      else
+      {
+        LibCECConfiguration config = new LibCECConfiguration();
+        Lib.GetCurrentConfiguration(config);
+
+        SendEvent(UpdateEventType.StatusText, "Activating source...");
+        SendEvent(UpdateEventType.ProgressBar, 50);
+        Lib.SetActiveSource(config.DeviceTypes.Types[0]);
+
+        SendEvent(UpdateEventType.StatusText, "Reading configuration...");
+        SendEvent(UpdateEventType.ProgressBar, 75);
+        Lib.GetCurrentConfiguration(config);
+
+        SendEvent(config);
+        SendEvent(UpdateEventType.StatusText, "Ready.");
+      }
+      SendEvent(UpdateEventType.ProgressBar, 100);
+    }
+
+    protected LibCecSharp Lib;
+    protected ushort PhysicalAddress;
+  }
+}
diff --git a/src/cec-config-gui/cec-config-gui.csproj b/src/cec-config-gui/cec-config-gui.csproj
new file mode 100644 (file)
index 0000000..84f4131
--- /dev/null
@@ -0,0 +1,107 @@
+<?xml version="1.0" encoding="utf-8"?>
+<Project ToolsVersion="3.5" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
+  <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|x64' ">
+    <DebugSymbols>true</DebugSymbols>
+    <OutputPath>..\..\build\</OutputPath>
+    <DefineConstants>DEBUG;TRACE</DefineConstants>
+    <DebugType>full</DebugType>
+    <PlatformTarget>x64</PlatformTarget>
+    <ErrorReport>prompt</ErrorReport>
+  </PropertyGroup>
+  <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|x64' ">
+    <OutputPath>bin\x64\Release\</OutputPath>
+    <DefineConstants>TRACE</DefineConstants>
+    <Optimize>true</Optimize>
+    <DebugType>pdbonly</DebugType>
+    <PlatformTarget>x64</PlatformTarget>
+    <ErrorReport>prompt</ErrorReport>
+  </PropertyGroup>
+  <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|x86' ">
+    <DebugSymbols>true</DebugSymbols>
+    <OutputPath>..\..\build\</OutputPath>
+    <DefineConstants>DEBUG;TRACE</DefineConstants>
+    <DebugType>full</DebugType>
+    <PlatformTarget>x86</PlatformTarget>
+    <ErrorReport>prompt</ErrorReport>
+  </PropertyGroup>
+  <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|x86' ">
+    <OutputPath>bin\x86\Release\</OutputPath>
+    <DefineConstants>TRACE</DefineConstants>
+    <Optimize>true</Optimize>
+    <DebugType>pdbonly</DebugType>
+    <PlatformTarget>x86</PlatformTarget>
+    <ErrorReport>prompt</ErrorReport>
+  </PropertyGroup>
+  <PropertyGroup>
+    <Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
+    <Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform>
+    <ProductVersion>9.0.21022</ProductVersion>
+    <SchemaVersion>2.0</SchemaVersion>
+    <ProjectGuid>{58C106FE-C159-46D3-97E1-73AB83232670}</ProjectGuid>
+    <OutputType>WinExe</OutputType>
+    <AppDesignerFolder>Properties</AppDesignerFolder>
+    <RootNamespace>CecConfigGui</RootNamespace>
+    <AssemblyName>cec-config-gui</AssemblyName>
+    <TargetFrameworkVersion>v2.0</TargetFrameworkVersion>
+    <FileAlignment>512</FileAlignment>
+  </PropertyGroup>
+  <ItemGroup>
+    <Reference Include="System" />
+    <Reference Include="System.Data" />
+    <Reference Include="System.Deployment" />
+    <Reference Include="System.Drawing" />
+    <Reference Include="System.Windows.Forms" />
+    <Reference Include="System.Xml" />
+  </ItemGroup>
+  <ItemGroup>
+    <Compile Include="actions\ConnectToDevice.cs" />
+    <Compile Include="actions\UpdateConnectedDevice.cs" />
+    <Compile Include="actions\UpdatePhysicalAddress.cs" />
+    <Compile Include="CecConfigGUI.cs">
+      <SubType>Form</SubType>
+    </Compile>
+    <Compile Include="CecConfigGUI.Designer.cs">
+      <DependentUpon>CecConfigGUI.cs</DependentUpon>
+    </Compile>
+    <Compile Include="Program.cs" />
+    <Compile Include="Properties\AssemblyInfo.cs" />
+    <EmbeddedResource Include="CecConfigGUI.resx">
+      <DependentUpon>CecConfigGUI.cs</DependentUpon>
+      <SubType>Designer</SubType>
+    </EmbeddedResource>
+    <EmbeddedResource Include="Properties\Resources.resx">
+      <Generator>ResXFileCodeGenerator</Generator>
+      <LastGenOutput>Resources.Designer.cs</LastGenOutput>
+      <SubType>Designer</SubType>
+    </EmbeddedResource>
+    <Compile Include="Properties\Resources.Designer.cs">
+      <AutoGen>True</AutoGen>
+      <DependentUpon>Resources.resx</DependentUpon>
+      <DesignTime>True</DesignTime>
+    </Compile>
+    <None Include="Properties\Settings.settings">
+      <Generator>SettingsSingleFileGenerator</Generator>
+      <LastGenOutput>Settings.Designer.cs</LastGenOutput>
+    </None>
+    <Compile Include="Properties\Settings.Designer.cs">
+      <AutoGen>True</AutoGen>
+      <DependentUpon>Settings.settings</DependentUpon>
+      <DesignTimeSharedInput>True</DesignTimeSharedInput>
+    </Compile>
+    <Compile Include="actions\UpdateEvent.cs" />
+  </ItemGroup>
+  <ItemGroup>
+    <ProjectReference Include="..\..\project\LibCecSharp.vcproj">
+      <Project>{E54D4581-CD59-4687-BB10-694B8192EABA}</Project>
+      <Name>LibCecSharp</Name>
+    </ProjectReference>
+  </ItemGroup>
+  <Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
+  <!-- To modify your build process, add your task inside one of the targets below and uncomment it. 
+       Other similar extension points exist, see Microsoft.Common.targets.
+  <Target Name="BeforeBuild">
+  </Target>
+  <Target Name="AfterBuild">
+  </Target>
+  -->
+</Project>
\ No newline at end of file
index 62c988b93a93126b1d6d14628101c9d6d3b8a948..32158de76513e32c7cce41c9b58a6488566318d5 100644 (file)
@@ -408,13 +408,13 @@ bool CUSBCECAdapterCommunication::ParseMessage(const CCECAdapterMessage &msg)
 
 uint16_t CUSBCECAdapterCommunication::GetFirmwareVersion(void)
 {
-  CLockObject lock(m_mutex);
   uint16_t iReturn(m_iFirmwareVersion);
   if (!IsRunning())
     return iReturn;
 
   if (iReturn == CEC_FW_VERSION_UNKNOWN)
   {
+    CLockObject lock(m_mutex);
     CLibCEC::AddLog(CEC_LOG_DEBUG, "requesting the firmware version");
     CCECAdapterMessage *output = new CCECAdapterMessage;