Skip to content

Commit

Permalink
fixed: python wrapper compilation and missing callbacks
Browse files Browse the repository at this point in the history
  • Loading branch information
opdenkamp committed Jul 10, 2020
1 parent ce41b50 commit 26febbf
Show file tree
Hide file tree
Showing 2 changed files with 57 additions and 16 deletions.
53 changes: 38 additions & 15 deletions src/libcec/SwigHelper.h
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,7 @@
#define SWIG_PYTHON_USE_GIL
#define LIBCEC_SWIG_EXPORTS

#include "env.h"
#include "cectypes.h"
#include "cec.h"
#include "CECTypeUtils.h"
Expand All @@ -56,6 +57,7 @@ namespace CEC
PYTHON_CB_ALERT,
PYTHON_CB_MENU_STATE,
PYTHON_CB_SOURCE_ACTIVATED,
PYTHON_CB_CONFIGURATION,
NB_PYTHON_CB,
};

Expand All @@ -69,7 +71,8 @@ namespace CEC
CCecPythonCallbacks(libcec_configuration* config) :
m_configuration(config)
{
assert(m_configuration);
assert(!!config);
assert(!!m_configuration);

config->callbacks = new ICECCallbacks;
if (!config->callbacks)
Expand All @@ -78,11 +81,13 @@ namespace CEC
for (size_t ptr = 0; ptr < NB_PYTHON_CB; ++ptr)
m_callbacks[ptr] = NULL;

m_configuration->callbacks->logMessage = CBCecLogMessage;
m_configuration->callbacks->keyPress = CBCecKeyPress;
m_configuration->callbacks->commandReceived = CBCecCommand;
m_configuration->callbacks->menuStateChanged = CBCecMenuStateChanged;
m_configuration->callbacks->sourceActivated = CBCecSourceActivated;
m_configuration->callbacks->logMessage = CBCecLogMessage;
m_configuration->callbacks->keyPress = CBCecKeyPress;
m_configuration->callbacks->commandReceived = CBCecCommand;
m_configuration->callbacks->configurationChanged = CBCecConfigurationChanged;
m_configuration->callbacks->alert = CBCecAlert;
m_configuration->callbacks->menuStateChanged = CBCecMenuStateChanged;
m_configuration->callbacks->sourceActivated = CBCecSourceActivated;
}

/**
Expand Down Expand Up @@ -110,8 +115,8 @@ namespace CEC
if (callback >= NB_PYTHON_CB || !m_callbacks[callback])
return retval;

PyObject* result = NULL;
if (m_callbacks[callback])
PyObject* result = nullptr;
if (!!m_callbacks[callback])
{
/** call the callback */
result = PyEval_CallObject(m_callbacks[callback], arglist);
Expand Down Expand Up @@ -141,7 +146,7 @@ namespace CEC
assert(PyCallable_Check(pyfunc));

/** unref previous callback (if any) */
if (m_callbacks[cb])
if (!!m_callbacks[cb])
Py_XDECREF(m_callbacks[cb]);

/** set the new callback */
Expand All @@ -153,7 +158,7 @@ namespace CEC
static inline int CallPythonCallback(void* param, enum libcecSwigCallback callback, PyObject* arglist)
{
CCecPythonCallbacks* pCallbacks = static_cast<CCecPythonCallbacks*>(param);
return pCallbacks ?
return !!pCallbacks ?
pCallbacks->CallPythonCallback(callback, arglist) :
0;
}
Expand Down Expand Up @@ -199,6 +204,22 @@ namespace CEC
PyGILState_Release(gstate);
}

static void CBCecAlert(void* param, const libcec_alert alert, const libcec_parameter cbparam)
{
PyGILState_STATE gstate = PyGILState_Ensure();
CallPythonCallback(param, PYTHON_CB_ALERT,
Py_BuildValue("(I,I)", alert, cbparam));
PyGILState_Release(gstate);
}

static void CBCecConfigurationChanged(void* param, const libcec_configuration* configuration)
{
PyGILState_STATE gstate = PyGILState_Ensure();
CallPythonCallback(param, PYTHON_CB_CONFIGURATION,
Py_BuildValue("(I)", configuration));
PyGILState_Release(gstate);
}

PyObject* m_callbacks[NB_PYTHON_CB];
libcec_configuration* m_configuration;
};
Expand All @@ -208,25 +229,27 @@ namespace CEC
/** allocate callbacks struct and python callbacks if needed */
if (!self->callbackParam)
self->callbackParam = new CCecPythonCallbacks(self);

if (!self->callbackParam)
throw std::bad_alloc();
return static_cast<CCecPythonCallbacks*>(self->callbackParam);
}
}

static void _SetCallback(CEC::libcec_configuration* self, size_t cb, PyObject* pyfunc)
{
assert(self);
assert(!!self);
CEC::CCecPythonCallbacks* pCallbacks = CEC::_GetCallbacks(self);
if (pCallbacks)
if (!!pCallbacks)
pCallbacks->SetCallback(cb, pyfunc);
else
printf("ERROR: cannot set callback to %p: out of memory\n", pyfunc);
throw std::bad_alloc();
}

void _ClearCallbacks(CEC::libcec_configuration* self)
{
assert(!!self);
CEC::CCecPythonCallbacks* pCallbacks = static_cast<CEC::CCecPythonCallbacks*>(self->callbackParam);
if (pCallbacks)
if (!!pCallbacks)
delete pCallbacks;
self->callbackParam = NULL;
}
Expand Down
20 changes: 19 additions & 1 deletion src/libcec/libcec.i
Original file line number Diff line number Diff line change
Expand Up @@ -93,6 +93,16 @@
_SetCallback(self, CEC::PYTHON_CB_SOURCE_ACTIVATED, pyfunc);
}

void SetAlertCallback(PyObject* pyfunc)
{
_SetCallback(self, CEC::PYTHON_CB_ALERT, pyfunc);
}

void SetConfigurationChangedCallback(PyObject* pyfunc)
{
_SetCallback(self, CEC::PYTHON_CB_CONFIGURATION, pyfunc);
}

void ClearCallbacks(void)
{
_ClearCallbacks(self);
Expand All @@ -117,14 +127,18 @@ namespace std {
if (self->GetCurrentConfiguration(&config))
{
_ClearCallbacks(&config);
%#if CEC_LIB_VERSION_MAJOR >= 5
self->DisableCallbacks();
%#else
self->EnableCallbacks(NULL, NULL);
%#endif
}
}

static CEC::ICECAdapter* Create(CEC::libcec_configuration* configuration)
{
CEC::ICECAdapter* lib = CECInitialise(configuration);
if (lib)
if (!!lib)
{
lib->InitVideoStandalone();
PyEval_InitThreads();
Expand All @@ -144,6 +158,10 @@ namespace std {
}

%ignore CEC::ICECAdapter::~ICECAdapter;
%ignore CEC::ICECAdapter::SetCallbacks;
%ignore CEC::ICECAdapter::EnableCallbacks;
%ignore CEC::ICECAdapter::CanPersistConfiguration;
%ignore CEC::ICECAdapter::PersistConfiguration;
%ignore CEC::ICECCallbacks;
%ignore CEC::DetectAdapters;
%ignore CEC::GetDeviceMenuLanguage;
Expand Down

0 comments on commit 26febbf

Please sign in to comment.