Beginning of the implementation of linphone_core_new() wrapper + Allow setting log handler from python.

This commit is contained in:
Ghislain MARY 2014-07-29 18:11:14 +02:00
parent a4c2f0ef36
commit 1a2990a8b6
4 changed files with 134 additions and 77 deletions

View file

@ -72,13 +72,12 @@ blacklisted_functions = [
'linphone_core_get_supported_video_sizes',
'linphone_core_get_video_codecs',
'linphone_core_get_video_policy',
'linphone_core_new',
'linphone_core_new_with_config',
'linphone_core_payload_type_enabled',
'linphone_core_payload_type_is_vbr',
'linphone_core_publish',
'linphone_core_set_log_file',
'linphone_core_set_log_handler',
'linphone_core_set_log_handler', # Hand-written but put directly in the linphone module
'linphone_core_set_log_level',
'linphone_core_set_payload_type_bitrate',
'linphone_core_set_preferred_video_size',
@ -107,12 +106,16 @@ blacklisted_functions = [
'lp_config_load_dict_to_section',
'lp_config_section_to_dict'
]
hand_written_functions = [
'linphone_core_new'
]
def generate(apixmlfile):
tree = ET.parse(apixmlfile)
renderer = pystache.Renderer()
m = LinphoneModule(tree, blacklisted_classes, blacklisted_functions)
m = LinphoneModule(tree, blacklisted_classes, blacklisted_functions, hand_written_functions)
f = open("linphone.c", "w")
os.chdir('apixml2python')
f.write(renderer.render(m))

View file

@ -0,0 +1,108 @@
static void pylinphone_log(const char *level, int indent, const char *fmt, va_list args) {
static int current_indent = 1;
PyObject *linphone_module = PyImport_ImportModule("linphone");
if ((linphone_module != NULL) && PyObject_HasAttrString(linphone_module, "__log_handler")) {
PyObject *log_handler = PyObject_GetAttrString(linphone_module, "__log_handler");
if ((log_handler != NULL) && PyFunction_Check(log_handler)) {
char logstr[4096];
int i = 0;
if (indent == -1) current_indent--;
if (current_indent < 1) current_indent = 1;
if ((indent >= -1) && (indent <= 1)) {
for (i = 0; i < current_indent; i++) {
logstr[i] = '\t';
}
}
if (indent == 1) current_indent++;
if (vsnprintf(logstr + i, sizeof(logstr) - i, fmt, args) > 0) {
PyEval_CallFunction(log_handler, "ss", level, logstr);
}
}
}
}
static PYLINPHONE_INLINE void pylinphone_trace(int indent, const char *fmt, ...) {
va_list args;
va_start(args, fmt);
pylinphone_log("debug", indent, fmt, args);
va_end(args);
}
static const char * pylinphone_ortp_log_level_to_string(OrtpLogLevel lev) {
switch (lev) {
default:
case ORTP_DEBUG:
return "debug";
case ORTP_MESSAGE:
return "info";
case ORTP_WARNING:
return "warning";
case ORTP_ERROR:
return "error";
case ORTP_FATAL:
return "critical";
case ORTP_TRACE:
return "debug";
}
}
static void pylinphone_module_log_handler(OrtpLogLevel lev, const char *fmt, va_list args) {
PyObject *linphone_module = PyImport_ImportModule("linphone");
const char *level = pylinphone_ortp_log_level_to_string(lev);
if ((linphone_module != NULL) && PyObject_HasAttrString(linphone_module, "__log_handler")) {
PyObject *log_handler = PyObject_GetAttrString(linphone_module, "__log_handler");
if ((log_handler != NULL) && PyFunction_Check(log_handler)) {
char logstr[4096];
if (vsnprintf(logstr, sizeof(logstr), fmt, args) > 0) {
PyEval_CallFunction(log_handler, "ss", level, logstr);
}
}
}
}
static void pylinphone_init_logging(void) {
linphone_core_set_log_handler(pylinphone_module_log_handler);
linphone_core_set_log_level(ORTP_MESSAGE|ORTP_WARNING|ORTP_ERROR|ORTP_FATAL);
}
static PyObject * pylinphone_module_method_set_log_handler(PyObject *self, PyObject *args) {
PyObject *linphone_module = PyImport_ImportModule("linphone");
PyObject *callback;
if (!PyArg_ParseTuple(args, "O", &callback)) {
return NULL;
}
if (linphone_module != NULL) {
Py_INCREF(callback);
PyObject_SetAttrString(linphone_module, "__log_handler", callback);
}
Py_RETURN_NONE;
}
static PyObject * pylinphone_Core_class_method_new(PyObject *cls, PyObject *args) {
LinphoneCore * cresult;
pylinphone_CoreObject *self;
PyObject * pyret;
LinphoneCoreVTable _vtable = { 0 };
const char * _config_path;
const char * _factory_config_path;
if (!PyArg_ParseTuple(args, "zz", &_config_path, &_factory_config_path)) {
return NULL;
}
self = (pylinphone_CoreObject *)PyObject_New(pylinphone_CoreObject, &pylinphone_CoreType);
if (self == NULL) {
return NULL;
}
pylinphone_trace(1, "[PYLINPHONE] >>> %s(\"%s\", \"%s\")", __FUNCTION__, _config_path, _factory_config_path);
cresult = linphone_core_new(&_vtable, _config_path, _factory_config_path, self);
self->native_ptr = cresult;
pyret = Py_BuildValue("O", self);
pylinphone_trace(-1, "[PYLINPHONE] <<< %s -> %p", __FUNCTION__, pyret);
Py_DECREF(self);
return pyret;
}

View file

@ -537,7 +537,7 @@ class SetterMethodDefinition(MethodDefinition):
class LinphoneModule(object):
def __init__(self, tree, blacklisted_classes, blacklisted_functions):
def __init__(self, tree, blacklisted_classes, blacklisted_functions, hand_written_functions):
self.internal_instance_method_names = ['destroy', 'ref', 'unref']
self.internal_property_names = ['user_data']
self.enums = []
@ -577,6 +577,7 @@ class LinphoneModule(object):
c['class_destroyable'] = (xml_class.get('destroyable') == 'true')
c['class_has_user_data'] = False
c['class_type_methods'] = []
c['class_type_hand_written_methods'] = []
xml_type_methods = xml_class.findall("./classmethods/classmethod")
for xml_type_method in xml_type_methods:
if xml_type_method.get('deprecated') == 'true':
@ -586,8 +587,11 @@ class LinphoneModule(object):
continue
m = {}
m['method_name'] = method_name.replace(c['class_c_function_prefix'], '')
m['method_xml_node'] = xml_type_method
c['class_type_methods'].append(m)
if method_name in hand_written_functions:
c['class_type_hand_written_methods'].append(m)
else:
m['method_xml_node'] = xml_type_method
c['class_type_methods'].append(m)
c['class_instance_methods'] = []
xml_instance_methods = xml_class.findall("./instancemethods/instancemethod")
for xml_instance_method in xml_instance_methods:

View file

@ -30,76 +30,7 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
#endif
static PyObject *logging_module = NULL;
static int current_indent = 1;
static void init_logging(void) {
logging_module = PyImport_ImportModule("logging");
if (logging_module != NULL) {
PyObject *constant;
PyObject *func;
PyObject *kws;
long level = 0;
constant = PyObject_GetAttrString(logging_module, "DEBUG");
if (PyInt_Check(constant)) {
level = PyInt_AsLong(constant);
}
Py_DECREF(constant);
func = PyObject_GetAttrString(logging_module, "basicConfig");
kws = Py_BuildValue("{s:i,s:s}", "level", level, "format", "%(levelname)s: %(message)s");
PyEval_CallObjectWithKeywords(func, NULL, kws);
Py_DECREF(kws);
Py_DECREF(func);
}
}
static void pylinphone_log(const char *level, int indent, const char *fmt, va_list args) {
if (logging_module != NULL) {
char logstr[4096];
int i = 0;
if (indent == -1) current_indent--;
if (current_indent < 1) current_indent = 1;
if ((indent >= -1) && (indent <= 1)) {
for (i = 0; i < current_indent; i++) {
logstr[i] = '\t';
}
}
if (indent == 1) current_indent++;
if (vsnprintf(logstr + i, sizeof(logstr) - i, fmt, args) > 0) {
PyEval_CallMethod(logging_module, level, "(s)", logstr);
}
}
}
static PYLINPHONE_INLINE void pylinphone_debug(const char *fmt, ...) {
va_list args;
va_start(args, fmt);
pylinphone_log("debug", 0xff, fmt, args);
va_end(args);
}
static PYLINPHONE_INLINE void pylinphone_info(const char *fmt, ...) {
va_list args;
va_start(args, fmt);
pylinphone_log("info", 0xff, fmt, args);
va_end(args);
}
static PYLINPHONE_INLINE void pylinphone_warning(const char *fmt, ...) {
va_list args;
va_start(args, fmt);
pylinphone_log("warning", 0xff, fmt, args);
va_end(args);
}
static PYLINPHONE_INLINE void pylinphone_trace(int indent, const char *fmt, ...) {
va_list args;
va_start(args, fmt);
pylinphone_log("debug", indent, fmt, args);
va_end(args);
}
static PYLINPHONE_INLINE void pylinphone_trace(int indent, const char *fmt, ...);
{{#classes}}
@ -118,6 +49,9 @@ typedef struct {
{{#classes}}
static {{class_cname}} * pylinphone_{{class_name}}_get_native_ptr(PyObject *self);
static PyObject * pylinphone_{{class_name}}_new_from_native_ptr(PyTypeObject *type, const {{class_cname}} *native_ptr);
{{#class_type_hand_written_methods}}
static PyObject * pylinphone_{{class_name}}_class_method_{{method_name}}(PyObject *cls, PyObject *args);
{{/class_type_hand_written_methods}}
{{/classes}}
{{#classes}}
@ -157,6 +91,9 @@ static PyObject * pylinphone_{{class_name}}_instance_method_{{method_name}}(PyOb
static PyMethodDef pylinphone_{{class_name}}_instance_methods[] = {
// TODO: Handle doc
/* Class methods */
{{#class_type_hand_written_methods}}
{ "{{method_name}}", pylinphone_{{class_name}}_class_method_{{method_name}}, METH_VARARGS | METH_CLASS, "" },
{{/class_type_hand_written_methods}}
{{#class_type_methods}}
{ "{{method_name}}", pylinphone_{{class_name}}_class_method_{{method_name}}, METH_VARARGS | METH_CLASS, "" },
{{/class_type_methods}}
@ -234,8 +171,13 @@ static PyTypeObject pylinphone_{{class_name}}Type = {
{{/classes}}
{{> handwritten}}
static PyMethodDef pylinphone_ModuleMethods[] = {
/* Sentinel */
{ "set_log_handler", pylinphone_module_method_set_log_handler, METH_VARARGS, "" },
{ NULL, NULL, 0, NULL }
};
@ -248,7 +190,7 @@ PyMODINIT_FUNC initlinphone(void) {
PyObject *m;
PyObject *menum;
init_logging();
pylinphone_init_logging();
{{#classes}}
if (PyType_Ready(&pylinphone_{{class_name}}Type) < 0) return;