From 11fea069b79880253a450a74a53b31356598d57a Mon Sep 17 00:00:00 2001 From: Lars Op den Kamp Date: Tue, 28 Feb 2012 02:43:05 +0100 Subject: [PATCH] LibCecSharp: recreate the delegates properly when (re)connecting to LibCecSharp --- src/CecSharpTester/CecSharpClient.cs | 40 +------------ src/LibCecSharp/CecSharpTypes.h | 87 ++++++++++++++++------------ src/LibCecSharp/LibCecSharp.cpp | 7 ++- 3 files changed, 56 insertions(+), 78 deletions(-) diff --git a/src/CecSharpTester/CecSharpClient.cs b/src/CecSharpTester/CecSharpClient.cs index 2f49776..442c282 100644 --- a/src/CecSharpTester/CecSharpClient.cs +++ b/src/CecSharpTester/CecSharpClient.cs @@ -93,45 +93,7 @@ namespace CecSharpClient return 1; } - void FlushLog() - { - CecLogMessage message = Lib.GetNextLogMessage(); - bool bGotMessage = !message.Empty; - while (bGotMessage) - { - 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); - Console.WriteLine(strLog); - } - - message = Lib.GetNextLogMessage(); - bGotMessage = !message.Empty; - } - } - - public bool Connect(int timeout) + public bool Connect(int timeout) { CecAdapter[] adapters = Lib.FindAdapters(string.Empty); if (adapters.Length > 0) diff --git a/src/LibCecSharp/CecSharpTypes.h b/src/LibCecSharp/CecSharpTypes.h index 5d61794..7107afc 100644 --- a/src/LibCecSharp/CecSharpTypes.h +++ b/src/LibCecSharp/CecSharpTypes.h @@ -663,37 +663,11 @@ namespace CecSharp public ref class CecCallbackMethods { public: - CecCallbackMethods(void) - { - m_bHasCallbacks = false; - msclr::interop::marshal_context ^ context = gcnew msclr::interop::marshal_context(); - - // create the delegate method for the log message callback - m_logMessageDelegate = gcnew CecLogMessageManagedDelegate(this, &CecCallbackMethods::CecLogMessageManaged); - m_logMessageGCHandle = System::Runtime::InteropServices::GCHandle::Alloc(m_logMessageDelegate); - g_logCB = static_cast(System::Runtime::InteropServices::Marshal::GetFunctionPointerForDelegate(m_logMessageDelegate).ToPointer()); - g_cecCallbacks.CBCecLogMessage = CecLogMessageCB; - - // create the delegate method for the keypress callback - m_keypressDelegate = gcnew CecKeyPressManagedDelegate(this, &CecCallbackMethods::CecKeyPressManaged); - m_keypressGCHandle = System::Runtime::InteropServices::GCHandle::Alloc(m_keypressDelegate); - g_keyCB = static_cast(System::Runtime::InteropServices::Marshal::GetFunctionPointerForDelegate(m_keypressDelegate).ToPointer()); - g_cecCallbacks.CBCecKeyPress = CecKeyPressCB; - - // create the delegate method for the command callback - m_commandDelegate = gcnew CecCommandManagedDelegate(this, &CecCallbackMethods::CecCommandManaged); - m_commandGCHandle = System::Runtime::InteropServices::GCHandle::Alloc(m_commandDelegate); - g_commandCB = static_cast(System::Runtime::InteropServices::Marshal::GetFunctionPointerForDelegate(m_commandDelegate).ToPointer()); - g_cecCallbacks.CBCecCommand = CecCommandCB; - - // create the delegate method for the configuration change callback - m_configDelegate = gcnew CecConfigManagedDelegate(this, &CecCallbackMethods::CecConfigManaged); - m_configGCHandle = System::Runtime::InteropServices::GCHandle::Alloc(m_configDelegate); - g_configCB = static_cast(System::Runtime::InteropServices::Marshal::GetFunctionPointerForDelegate(m_configDelegate).ToPointer()); - g_cecCallbacks.CBCecConfigurationChanged = CecConfigCB; - - delete context; - } + CecCallbackMethods(void) + { + m_bHasCallbacks = false; + m_bDelegatesCreated = false; + } ~CecCallbackMethods(void) { @@ -709,13 +683,12 @@ namespace CecSharp public: virtual void DisableCallbacks(void) { - if (m_bHasCallbacks) - delete m_callbacks; - m_bHasCallbacks = false; + DestroyDelegates(); } + virtual bool EnableCallbacks(CecCallbackMethods ^ callbacks) { - DisableCallbacks(); + CreateDelegates(); if (!m_bHasCallbacks) { m_bHasCallbacks = true; @@ -790,16 +763,53 @@ namespace CecSharp void DestroyDelegates() { - if (m_bHasCallbacks) + m_bHasCallbacks = false; + if (m_bDelegatesCreated) { - m_bHasCallbacks = false; - delete m_callbacks; + m_bDelegatesCreated = false; m_logMessageGCHandle.Free(); m_keypressGCHandle.Free(); m_commandGCHandle.Free(); } } + void CreateDelegates() + { + DestroyDelegates(); + + if (!m_bDelegatesCreated) + { + msclr::interop::marshal_context ^ context = gcnew msclr::interop::marshal_context(); + + // create the delegate method for the log message callback + m_logMessageDelegate = gcnew CecLogMessageManagedDelegate(this, &CecCallbackMethods::CecLogMessageManaged); + m_logMessageGCHandle = System::Runtime::InteropServices::GCHandle::Alloc(m_logMessageDelegate); + g_logCB = static_cast(System::Runtime::InteropServices::Marshal::GetFunctionPointerForDelegate(m_logMessageDelegate).ToPointer()); + g_cecCallbacks.CBCecLogMessage = CecLogMessageCB; + + // create the delegate method for the keypress callback + m_keypressDelegate = gcnew CecKeyPressManagedDelegate(this, &CecCallbackMethods::CecKeyPressManaged); + m_keypressGCHandle = System::Runtime::InteropServices::GCHandle::Alloc(m_keypressDelegate); + g_keyCB = static_cast(System::Runtime::InteropServices::Marshal::GetFunctionPointerForDelegate(m_keypressDelegate).ToPointer()); + g_cecCallbacks.CBCecKeyPress = CecKeyPressCB; + + // create the delegate method for the command callback + m_commandDelegate = gcnew CecCommandManagedDelegate(this, &CecCallbackMethods::CecCommandManaged); + m_commandGCHandle = System::Runtime::InteropServices::GCHandle::Alloc(m_commandDelegate); + g_commandCB = static_cast(System::Runtime::InteropServices::Marshal::GetFunctionPointerForDelegate(m_commandDelegate).ToPointer()); + g_cecCallbacks.CBCecCommand = CecCommandCB; + + // create the delegate method for the configuration change callback + m_configDelegate = gcnew CecConfigManagedDelegate(this, &CecCallbackMethods::CecConfigManaged); + m_configGCHandle = System::Runtime::InteropServices::GCHandle::Alloc(m_configDelegate); + g_configCB = static_cast(System::Runtime::InteropServices::Marshal::GetFunctionPointerForDelegate(m_configDelegate).ToPointer()); + g_cecCallbacks.CBCecConfigurationChanged = CecConfigCB; + + delete context; + m_bDelegatesCreated = true; + } + } + CecLogMessageManagedDelegate ^ m_logMessageDelegate; static System::Runtime::InteropServices::GCHandle m_logMessageGCHandle; LOGCB m_logMessageCallback; @@ -818,5 +828,6 @@ namespace CecSharp CecCallbackMethods ^ m_callbacks; bool m_bHasCallbacks; + bool m_bDelegatesCreated; }; } diff --git a/src/LibCecSharp/LibCecSharp.cpp b/src/LibCecSharp/LibCecSharp.cpp index d6154c3..caf6054 100644 --- a/src/LibCecSharp/LibCecSharp.cpp +++ b/src/LibCecSharp/LibCecSharp.cpp @@ -45,13 +45,15 @@ namespace CecSharp public: LibCecSharp(LibCECConfiguration ^config) { - CecCallbackMethods::EnableCallbacks(config->Callbacks); + m_callbacks = config->Callbacks; + CecCallbackMethods::EnableCallbacks(m_callbacks); if (!InitialiseLibCec(config)) throw gcnew Exception("Could not initialise LibCecSharp"); } LibCecSharp(String ^ strDeviceName, CecDeviceTypeList ^ deviceTypes) { + m_callbacks = gcnew CecCallbackMethods(); LibCECConfiguration ^config = gcnew LibCECConfiguration(); config->SetCallbacks(this); config->DeviceName = strDeviceName; @@ -139,6 +141,8 @@ namespace CecSharp bool Open(String ^ strPort, int iTimeoutMs) { + CecCallbackMethods::EnableCallbacks(m_callbacks); + EnableCallbacks(m_callbacks); marshal_context ^ context = gcnew marshal_context(); const char* strPortC = context->marshal_as(strPort); bool bReturn = m_libCec->Open(strPortC, iTimeoutMs); @@ -550,5 +554,6 @@ namespace CecSharp private: ICECAdapter * m_libCec; + CecCallbackMethods ^ m_callbacks; }; } -- 2.34.1