| /*********************************************************** |
| Copyright 1991, 1992 by Stichting Mathematisch Centrum, Amsterdam, The |
| Netherlands. |
| |
| All Rights Reserved |
| |
| Permission to use, copy, modify, and distribute this software and its |
| documentation for any purpose and without fee is hereby granted, |
| provided that the above copyright notice appear in all copies and that |
| both that copyright notice and this permission notice appear in |
| supporting documentation, and that the names of Stichting Mathematisch |
| Centrum or CWI not be used in advertising or publicity pertaining to |
| distribution of the software without specific, written prior permission. |
| |
| STICHTING MATHEMATISCH CENTRUM DISCLAIMS ALL WARRANTIES WITH REGARD TO |
| THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND |
| FITNESS, IN NO EVENT SHALL STICHTING MATHEMATISCH CENTRUM BE LIABLE |
| FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES |
| WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN |
| ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT |
| OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. |
| |
| ******************************************************************/ |
| |
| |
| /* Cl objects */ |
| |
| #include <stdarg.h> |
| #include <cl.h> |
| #include "allobjects.h" |
| #include "modsupport.h" /* For getargs() etc. */ |
| #include "ceval.h" /* For call_object() */ |
| |
| typedef struct { |
| OB_HEAD |
| int ob_isCompressor; /* Compressor or Decompressor */ |
| CL_CompressorHdl ob_compressorHdl; |
| long ob_dataMaxSize; |
| object *ob_callbackFunc; |
| object *ob_callbackID; |
| object *ob_data; |
| } clobject; |
| |
| #define CheckCompressor(self) if ((self)->ob_compressorHdl == NULL) { \ |
| err_setstr(RuntimeError, "(de)compressor not active"); \ |
| return NULL; \ |
| } |
| |
| extern typeobject Cltype; /* Really static, forward */ |
| |
| #define is_clobject(v) ((v)->ob_type == &Cltype) |
| |
| static object *ClError; /* exception cl.error */ |
| |
| static int error_handler_called = 0; |
| |
| static void |
| cl_ErrorHandler(long errnum, const char *fmt, ...) |
| { |
| va_list ap; |
| char errbuf[BUFSIZ]; /* hopefully big enough */ |
| |
| error_handler_called = 1; |
| va_start(ap, fmt); |
| vsprintf(errbuf, fmt, ap); |
| va_end(ap); |
| err_setstr(ClError, errbuf); |
| } |
| |
| static object * |
| cl_CloseCompressor(self, args) |
| clobject *self; |
| object *args; |
| { |
| CheckCompressor(self); |
| |
| if (!getnoarg(args)) |
| return NULL; |
| |
| if (clCloseCompressor(self->ob_compressorHdl) == FAILURE) { |
| if (!error_handler_called) |
| err_setstr(ClError, "CloseCompressor failed"); |
| return NULL; |
| } |
| |
| self->ob_compressorHdl = NULL; |
| |
| INCREF(None); |
| return None; |
| } |
| |
| static object * |
| cl_CloseDecompressor(self, args) |
| clobject *self; |
| object *args; |
| { |
| CheckCompressor(self); |
| |
| if (!getnoarg(args)) |
| return NULL; |
| |
| if (clCloseDecompressor(self->ob_compressorHdl) == FAILURE) { |
| if (!error_handler_called) |
| err_setstr(ClError, "CloseDecompressor failed"); |
| return NULL; |
| } |
| |
| self->ob_compressorHdl = NULL; |
| |
| INCREF(None); |
| return None; |
| } |
| |
| static object * |
| cl_Compress(self, args) |
| clobject *self; |
| object *args; |
| { |
| object *data; |
| long frameIndex, numberOfFrames, dataSize; |
| |
| CheckCompressor(self); |
| |
| if (!getargs(args, "(ii)", &frameIndex, &numberOfFrames)) |
| return NULL; |
| |
| data = newsizedstringobject(NULL, |
| numberOfFrames * self->ob_dataMaxSize); |
| if (data == NULL) |
| return NULL; |
| |
| dataSize = numberOfFrames * self->ob_dataMaxSize; |
| |
| error_handler_called = 0; |
| if (clCompress(self->ob_compressorHdl, frameIndex, numberOfFrames, |
| &dataSize, (void *) getstringvalue(data)) == FAILURE) { |
| DECREF(data); |
| if (!error_handler_called) |
| err_setstr(ClError, "compress failed"); |
| return NULL; |
| } |
| |
| if (dataSize < numberOfFrames * self->ob_dataMaxSize) |
| if (resizestring(&data, dataSize)) |
| return NULL; |
| |
| return data; |
| } |
| |
| static object * |
| cl_Decompress(self, args) |
| clobject *self; |
| object *args; |
| { |
| object *data; |
| long frameIndex, numberOfFrames; |
| |
| CheckCompressor(self); |
| |
| if (!getargs(args, "(ii)", &frameIndex, &numberOfFrames)) |
| return NULL; |
| |
| data = newsizedstringobject(NULL, |
| numberOfFrames * self->ob_dataMaxSize); |
| if (data == NULL) |
| return NULL; |
| |
| error_handler_called = 0; |
| if (clDecompress(self->ob_compressorHdl, frameIndex, numberOfFrames, |
| (void *) getstringvalue(data)) == FAILURE) { |
| DECREF(data); |
| if (!error_handler_called) |
| err_setstr(ClError, "decompress failed"); |
| return NULL; |
| } |
| |
| return data; |
| } |
| |
| static object * |
| cl_GetCompressorInfo(self, args) |
| clobject *self; |
| object *args; |
| { |
| long result, infoSize; |
| void *info; |
| object *infoObject, *res; |
| |
| CheckCompressor(self); |
| |
| if (!getnoarg(args)) |
| return NULL; |
| |
| error_handler_called = 0; |
| if (clGetCompressorInfo(self->ob_compressorHdl, &infoSize, &info) == FAILURE) { |
| if (!error_handler_called) |
| err_setstr(ClError, "getcompressorinfo failed"); |
| return NULL; |
| } |
| |
| return newsizedstringobject((char *) info, infoSize); |
| } |
| |
| static object * |
| cl_GetDefault(self, args) |
| clobject *self; |
| object *args; |
| { |
| long initial, result; |
| |
| CheckCompressor(self); |
| |
| if (!getargs(args, "i", &initial)) |
| return NULL; |
| |
| error_handler_called = 0; |
| result = clGetDefault(self->ob_compressorHdl, initial); |
| if (error_handler_called) |
| return NULL; |
| |
| return newintobject(result); |
| } |
| |
| static object * |
| cl_GetMinMax(self, args) |
| clobject *self; |
| object *args; |
| { |
| long param, min, max; |
| |
| CheckCompressor(self); |
| |
| if (!getargs(args, "i", ¶m)) |
| return NULL; |
| |
| error_handler_called = 0; |
| clGetMinMax(self->ob_compressorHdl, param, &min, &max); |
| if (error_handler_called) |
| return NULL; |
| |
| return mkvalue("(ii)", min, max); |
| } |
| |
| static object * |
| cl_GetName(self, args) |
| clobject *self; |
| object *args; |
| { |
| long descriptor; |
| char *name; |
| |
| CheckCompressor(self); |
| |
| if (!getargs(args, "i", &descriptor)) |
| return NULL; |
| |
| error_handler_called = 0; |
| name = clGetName(self->ob_compressorHdl, descriptor); |
| if (error_handler_called) |
| return NULL; |
| if (name == NULL) { |
| err_setstr(ClError, "getname failed"); |
| return NULL; |
| } |
| |
| return newstringobject(name); |
| } |
| |
| static object * |
| doParams(self, args, func, modified) |
| clobject *self; |
| object *args; |
| void (*func)(CL_CompressorHdl, long *, long); |
| int modified; |
| { |
| object *list, *v; |
| long *PVbuffer; |
| long length; |
| int i; |
| |
| CheckCompressor(self); |
| |
| if (!getargs(args, "O", &list)) |
| return NULL; |
| if (!is_listobject(list)) { |
| err_badarg(); |
| return NULL; |
| } |
| length = getlistsize(list); |
| PVbuffer = NEW(long, length); |
| if (PVbuffer == NULL) |
| return err_nomem(); |
| for (i = 0; i < length; i++) { |
| v = getlistitem(list, i); |
| if (!is_intobject(v)) { |
| DEL(PVbuffer); |
| err_badarg(); |
| return NULL; |
| } |
| PVbuffer[i] = getintvalue(v); |
| } |
| |
| error_handler_called = 0; |
| (*func)(self->ob_compressorHdl, PVbuffer, length); |
| if (error_handler_called) |
| return NULL; |
| |
| if (modified) { |
| for (i = 0; i < length; i++) |
| setlistitem(list, i, newintobject(PVbuffer[i])); |
| } |
| |
| DEL(PVbuffer); |
| |
| INCREF(None); |
| return None; |
| } |
| |
| static object * |
| cl_GetParams(self, args) |
| object *self, *args; |
| { |
| return doParams(self, args, clGetParams, 1); |
| } |
| |
| static object * |
| cl_SetParams(self, args) |
| object *self, *args; |
| { |
| return doParams(self, args, clSetParams, 0); |
| } |
| |
| static object * |
| cl_QueryParams(self, args) |
| clobject *self; |
| object *args; |
| { |
| long bufferlength; |
| long *PVbuffer; |
| object *list; |
| int i; |
| |
| CheckCompressor(self); |
| |
| if (!getnoarg(args)) |
| return NULL; |
| |
| error_handler_called = 0; |
| bufferlength = clQueryParams(self->ob_compressorHdl, 0, 0); |
| if (error_handler_called) |
| return NULL; |
| |
| PVbuffer = NEW(long, bufferlength); |
| if (PVbuffer == NULL) |
| return err_nomem(); |
| |
| bufferlength = clQueryParams(self->ob_compressorHdl, PVbuffer, |
| bufferlength); |
| if (error_handler_called) { |
| DEL(PVbuffer); |
| return NULL; |
| } |
| |
| list = newlistobject(bufferlength); |
| if (list == NULL) { |
| DEL(PVbuffer); |
| return NULL; |
| } |
| |
| for (i = 0; i < bufferlength; i++) { |
| if (i & 1) |
| setlistitem(list, i, newintobject(PVbuffer[i])); |
| else |
| setlistitem(list, i, newstringobject((char *) PVbuffer[i])); |
| } |
| |
| DEL(PVbuffer); |
| |
| return list; |
| } |
| |
| static struct methodlist compressor_methods[] = { |
| {"CloseCompressor", cl_CloseCompressor}, |
| {"Compress", cl_Compress}, |
| {"GetCompressorInfo", cl_GetCompressorInfo}, |
| {"GetDefault", cl_GetDefault}, |
| {"GetMinMax", cl_GetMinMax}, |
| {"GetName", cl_GetName}, |
| {"GetParams", cl_GetParams}, |
| {"QueryParams", cl_QueryParams}, |
| {"SetParams", cl_SetParams}, |
| {NULL, NULL} /* sentinel */ |
| }; |
| |
| static struct methodlist decompressor_methods[] = { |
| {"CloseDecompressor", cl_CloseDecompressor}, |
| {"Decompress", cl_Decompress}, |
| {"GetDefault", cl_GetDefault}, |
| {"GetMinMax", cl_GetMinMax}, |
| {"GetName", cl_GetName}, |
| {"GetParams", cl_GetParams}, |
| {"QueryParams", cl_QueryParams}, |
| {"SetParams", cl_SetParams}, |
| {NULL, NULL} /* sentinel */ |
| }; |
| |
| static void |
| cl_dealloc(self) |
| clobject *self; |
| { |
| if (self->ob_compressorHdl) { |
| if (self->ob_isCompressor) |
| clCloseCompressor(self->ob_compressorHdl); |
| else |
| clCloseDecompressor(self->ob_compressorHdl); |
| } |
| XDECREF(self->ob_callbackFunc); |
| XDECREF(self->ob_callbackID); |
| XDECREF(self->ob_data); |
| DEL(self); |
| } |
| |
| static object * |
| cl_getattr(self, name) |
| clobject *self; |
| char *name; |
| { |
| if (self->ob_isCompressor) |
| return findmethod(compressor_methods, (object *)self, name); |
| else |
| return findmethod(decompressor_methods, (object *) self, name); |
| } |
| |
| static typeobject Cltype = { |
| OB_HEAD_INIT(&Typetype) |
| 0, /*ob_size*/ |
| "cl", /*tp_name*/ |
| sizeof(clobject), /*tp_size*/ |
| 0, /*tp_itemsize*/ |
| /* methods */ |
| cl_dealloc, /*tp_dealloc*/ |
| 0, /*tp_print*/ |
| cl_getattr, /*tp_getattr*/ |
| 0, /*tp_setattr*/ |
| 0, /*tp_compare*/ |
| 0, /*tp_repr*/ |
| 0, /*tp_as_number*/ |
| 0, /*tp_as_sequence*/ |
| 0, /*tp_as_mapping*/ |
| }; |
| |
| static long |
| GetFrame(callbackID, frameIndex, numberOfFrames, data) |
| void *callbackID; |
| long frameIndex; |
| long numberOfFrames; |
| void **data; |
| { |
| object *args; |
| clobject *self = (clobject *) callbackID; |
| object *result; |
| |
| args = newtupleobject(3); |
| if (args == NULL) |
| return FAILURE; |
| |
| XINCREF(self->ob_callbackID); |
| settupleitem(args, 0, self->ob_callbackID); |
| settupleitem(args, 1, newintobject(frameIndex)); |
| settupleitem(args, 2, newintobject(numberOfFrames)); |
| |
| if (err_occurred()) { |
| XDECREF(self->ob_callbackID); |
| return FAILURE; |
| } |
| |
| result = call_object(self->ob_callbackFunc, args); |
| DECREF(args); |
| if (result == NULL) |
| return FAILURE; |
| |
| if (!is_stringobject(result)) { |
| DECREF(result); |
| return FAILURE; |
| } |
| |
| XDECREF(self->ob_data); |
| self->ob_data = result; |
| |
| *data = (void *) getstringvalue(result); |
| |
| return SUCCESS; |
| } |
| |
| static long |
| GetData(callbackID, frameIndex, numberOfFrames, dataSize, data) |
| void *callbackID; |
| long frameIndex; |
| long numberOfFrames; |
| long *dataSize; |
| void **data; |
| { |
| object *args, *result; |
| clobject *self = (clobject *) callbackID; |
| |
| args = newtupleobject(3); |
| if (args == NULL) |
| return FAILURE; |
| |
| XINCREF(self->ob_callbackID); |
| settupleitem(args, 0, self->ob_callbackID); |
| settupleitem(args, 1, newintobject(frameIndex)); |
| settupleitem(args, 2, newintobject(numberOfFrames)); |
| |
| if (err_occurred()) { |
| XDECREF(self->ob_callbackID); |
| return FAILURE; |
| } |
| |
| result = call_object(self->ob_callbackFunc, args); |
| DECREF(args); |
| if (result == NULL) |
| return FAILURE; |
| |
| if (!is_stringobject(result)) { |
| DECREF(result); |
| return FAILURE; |
| } |
| |
| XDECREF(self->ob_data); |
| self->ob_data = result; |
| |
| *dataSize = getstringsize(result); |
| *data = (void *) getstringvalue(result); |
| |
| return SUCCESS; |
| } |
| |
| static object * |
| cl_OpenCompressor(self, args) |
| object *self, *args; |
| { |
| CL_CompressionFormat compressionFormat; |
| long qualityFactor; |
| object *GetFrameCBPtr; |
| object *callbackID; |
| clobject *new; |
| |
| if (!getargs(args, "((iiiiiiiiii)iOO)", |
| &compressionFormat.width, |
| &compressionFormat.height, |
| &compressionFormat.frameSize, |
| &compressionFormat.dataMaxSize, |
| &compressionFormat.originalFormat, |
| &compressionFormat.components, |
| &compressionFormat.bitsPerComponent, |
| &compressionFormat.frameRate, |
| &compressionFormat.numberOfFrames, |
| &compressionFormat.compressionScheme, |
| &qualityFactor, &GetFrameCBPtr, &callbackID)) |
| return NULL; |
| |
| new = NEWOBJ(clobject, &Cltype); |
| if (new == 0) |
| return NULL; |
| |
| new->ob_compressorHdl = NULL; |
| new->ob_callbackFunc = NULL; |
| new->ob_callbackID = NULL; |
| new->ob_data = NULL; |
| |
| error_handler_called = 0; |
| if (clOpenCompressor(&compressionFormat, qualityFactor, GetFrame, |
| (void *) new, &new->ob_compressorHdl) == FAILURE) { |
| DECREF(new); |
| if (!error_handler_called) |
| err_setstr(ClError, "opencompressor failed"); |
| return NULL; |
| } |
| |
| new->ob_isCompressor = 1; |
| new->ob_callbackFunc = GetFrameCBPtr; |
| XINCREF(new->ob_callbackFunc); |
| if (callbackID == NULL) |
| callbackID = None; |
| new->ob_callbackID = callbackID; |
| INCREF(new->ob_callbackID); |
| new->ob_data = NULL; |
| new->ob_dataMaxSize = compressionFormat.dataMaxSize; |
| |
| return new; |
| } |
| |
| static object * |
| cl_OpenDecompressor(self, args) |
| object *self, *args; |
| { |
| CL_CompressionFormat compressionFormat; |
| long infoSize; |
| void *info; |
| object *GetDataCBPtr; |
| object *callbackID; |
| clobject *new; |
| object *res; |
| |
| if (!getargs(args, "((iiiiiiiiii)s#OO)", |
| &compressionFormat.width, |
| &compressionFormat.height, |
| &compressionFormat.frameSize, |
| &compressionFormat.dataMaxSize, |
| &compressionFormat.originalFormat, |
| &compressionFormat.components, |
| &compressionFormat.bitsPerComponent, |
| &compressionFormat.frameRate, |
| &compressionFormat.numberOfFrames, |
| &compressionFormat.compressionScheme, |
| &info, &infoSize, &GetDataCBPtr, &callbackID)) |
| return NULL; |
| |
| new = NEWOBJ(clobject, &Cltype); |
| if (new == 0) |
| return NULL; |
| |
| new->ob_compressorHdl = NULL; |
| new->ob_callbackFunc = NULL; |
| new->ob_callbackID = NULL; |
| new->ob_data = NULL; |
| |
| error_handler_called = 0; |
| if (clOpenDecompressor(&compressionFormat, infoSize, info, GetData, |
| (void *) new, &new->ob_compressorHdl) == FAILURE) { |
| new->ob_compressorHdl = NULL; /* just in case... */ |
| DECREF(new); |
| if (!error_handler_called) |
| err_setstr(ClError, "opendecompressor failed"); |
| return NULL; |
| } |
| |
| new->ob_isCompressor = 0; |
| new->ob_callbackFunc = GetDataCBPtr; |
| XINCREF(new->ob_callbackFunc); |
| if (callbackID == NULL) |
| callbackID = None; |
| new->ob_callbackID = callbackID; |
| XINCREF(new->ob_callbackID); |
| new->ob_data = NULL; |
| new->ob_dataMaxSize = compressionFormat.dataMaxSize; |
| |
| return new; |
| } |
| |
| static object * |
| cl_AddParam(self, args) |
| object *self, *args; |
| { |
| char *name; |
| long type, min, max, initial, paramID; |
| |
| if (!getargs(args, "(siiii)", &name, &type, &min, &max, &initial)) |
| return NULL; |
| |
| error_handler_called = 0; |
| if (clAddParam(name, type, min, max, initial, ¶mID) == FAILURE) { |
| if (!error_handler_called) |
| err_setstr(ClError, "addparam failed"); |
| return NULL; |
| } |
| |
| return newintobject(paramID); |
| } |
| |
| static struct methodlist cl_methods[] = { |
| {"AddParam", cl_AddParam}, |
| {"OpenCompressor", cl_OpenCompressor}, |
| {"OpenDecompressor", cl_OpenDecompressor}, |
| {NULL, NULL} /* Sentinel */ |
| }; |
| |
| void |
| initcl() |
| { |
| object *m, *d; |
| |
| m = initmodule("cl", cl_methods); |
| d = getmoduledict(m); |
| |
| ClError = newstringobject("cl.error"); |
| if (ClError == NULL || dictinsert(d, "error", ClError) != 0) |
| fatal("can't define cl.error"); |
| |
| (void) clSetErrorHandler(cl_ErrorHandler); |
| } |