more horizontal refactoring
[swftools.git] / lib / python / SWF.c
index 8700e81..050b36a 100644 (file)
 #include "../rfxswf.h"
 #include "../log.h"
 #include "./pyutils.h"
-#include "./tag.h"
+#include "./tags.h"
 #include "./taglist.h"
+#include "./primitives.h"
+#include "./action.h"
 
 /*
 TODO:
@@ -47,7 +49,7 @@ staticforward PyTypeObject SWFClass;
 
 typedef struct {
     PyObject_HEAD
-    SWF swf; //swf.firstTag ist not used
+    SWF swf; //swf.firstTag is not used
     PyObject*taglist;
     char*filename;
 } SWFObject;
@@ -63,16 +65,24 @@ static PyObject* f_create(PyObject* self, PyObject* args, PyObject* kwargs)
     PyObject * obbox = 0;
     SRECT bbox = {0,0,0,0};
     char* filename = 0;
+    
+    swf = PyObject_New(SWFObject, &SWFClass);
+    mylog("+%08x(%d) create\n", (int)swf, swf->ob_refcnt);
 
     if (!PyArg_ParseTupleAndKeywords(args, kwargs, "|idOs", 
                kwlist, &version, &framerate, 
-               &obbox, filename))
+               &obbox, &filename))
        return NULL;
 
-    if (!PyArg_Parse(obbox, "(iiii)", &bbox.xmin, &bbox.ymin, &bbox.xmax, &bbox.ymax))
-       return NULL;
+    if(obbox) {
+       if (!PY_CHECK_TYPE(obbox, &BBoxClass)) {
+           obbox = f_BBox(0, obbox, 0);
+           if(!obbox)
+               return NULL;
+       }
+       bbox = bbox_getSRECT(obbox);
+    }
 
-    swf = PyObject_New(SWFObject, &SWFClass);
     memset(&swf->swf, 0, sizeof(SWF));
     if(filename)
        swf->filename = strdup(filename);
@@ -87,43 +97,68 @@ static PyObject* f_create(PyObject* self, PyObject* args, PyObject* kwargs)
     if(swf->swf.fileVersion>=6)
        swf->swf.compressed = 1;
 
-    mylog("create %08x -> %08x\n", (int)self, (int)swf);
+    mylog(" %08x(%d) create: done\n", (int)swf, swf->ob_refcnt);
     return (PyObject*)swf;
 }
 //----------------------------------------------------------------------------
-static PyObject* f_load(PyObject* self, PyObject* args)
+static PyObject* f_load(PyObject* self, PyObject* args, PyObject* kwargs)
 {
-    char* filename;
+    static char *kwlist1[] = {"filename", NULL};
+    static char *kwlist2[] = {"data", NULL};
+    char* filename = 0;
+    char* data = 0;
+    int len = 0;
     SWFObject* swf;
     int fi;
 
-    if (!PyArg_ParseTuple(args,"s:load", &filename)) 
-       return NULL;
+    if (!PyArg_ParseTupleAndKeywords(args, kwargs, "s", kwlist1, &filename)) {
+       PyErr_Clear();
+       if (!PyArg_ParseTupleAndKeywords(args, kwargs, "s#", kwlist2, &data, &len)) {
+           PyErr_Clear();
+           PyArg_ParseTupleAndKeywords(args, kwargs, "s:load", kwlist1, &filename);
+           return 0;
+       }
+    }
 
     swf = PyObject_New(SWFObject, &SWFClass);
+    mylog("+%08x(%d) f_load\n", (int)swf, swf->ob_refcnt);
+
     memset(&swf->swf, 0, sizeof(SWF));
-    swf->filename = strdup(filename);
 
-    if(!filename) {
-       PyErr_SetString(PyExc_Exception, setError("Couldn't open file %s", filename));
-        return 0;
-    }
-    fi = open(filename,O_RDONLY|O_BINARY);
-    if (fi<0) { 
-        PyErr_SetString(PyExc_Exception, setError("Couldn't open file %s", filename));
-       return 0;
-    }
-    if(swf_ReadSWF(fi,&swf->swf)<0) { 
-        close(fi);
-        PyErr_SetString(PyExc_Exception, setError("%s is not a valid SWF file or contains errors",filename));
-       return 0;
+    if(filename) {
+       if(!filename) {
+           PyErr_SetString(PyExc_Exception, setError("Couldn't open file %s", filename));
+           return 0;
+       }
+       swf->filename = strdup(filename);
+       fi = open(filename,O_RDONLY|O_BINARY);
+       if (fi<0) { 
+           return PY_ERROR("Couldn't open file %s", filename);
+       }
+       if(swf_ReadSWF(fi,&swf->swf)<0) { 
+           close(fi);
+           return PY_ERROR("%s is not a valid SWF file or contains errors",filename);
+       }
+       close(fi);
+    } else {
+       reader_t r;
+       reader_init_memreader(&r, data, len);
+       swf->filename = 0;
+       if(swf_ReadSWF2(&r, &swf->swf)<0) {
+           return PY_ERROR("<data> is not a valid SWF file or contains errors");
+       }
+       r.dealloc(&r);
     }
-    close(fi);
-    swf->swf.firstTag = 0;
+    swf_FoldAll(&swf->swf);
 
     swf->taglist = taglist_new2(swf->swf.firstTag);
+    if(swf->taglist == NULL) {
+       return NULL;
+    }
+    
+    swf_FreeTags(&swf->swf);
+    swf->swf.firstTag = 0;
     
-    mylog("load %08x -> %08x\n", (int)self, (int)swf);
     return (PyObject*)swf;
 }
 //----------------------------------------------------------------------------
@@ -135,7 +170,7 @@ static PyObject * swf_save(PyObject* self, PyObject* args, PyObject* kwargs)
     int fi;
     char*filename = 0;
     int compress = 0;
-
+    
     if(!self)
        return NULL;
 
@@ -146,6 +181,8 @@ static PyObject * swf_save(PyObject* self, PyObject* args, PyObject* kwargs)
 
     if (!PyArg_ParseTupleAndKeywords(args, kwargs, "|si", kwlist, &filename, &compress))
        return NULL;
+    
+    mylog(" %08x(%d) f_save filename=%s compress=%d\n", (int)self, self->ob_refcnt, filename, compress);
 
     // keyword arg compress (=1) forces compression
     if(compress)
@@ -153,13 +190,17 @@ static PyObject * swf_save(PyObject* self, PyObject* args, PyObject* kwargs)
     
     swf->firstTag = taglist_getTAGs(swfo->taglist);
 
+    /*if(!swf->firstTag)
+       return NULL;*/
+
     // fix the file, in case it is empty or not terminated properly
     {
        TAG*tag = swf->firstTag;
        if(!tag)
            tag = swf->firstTag = swf_InsertTag(0,ST_END);
-       while(tag && tag->next)
+       while(tag && tag->next) {
            tag = tag->next;
+       }
        if(tag->id != ST_END) {
            tag = swf_InsertTag(tag,ST_END);
        }
@@ -170,23 +211,33 @@ static PyObject * swf_save(PyObject* self, PyObject* args, PyObject* kwargs)
        PyErr_SetString(PyExc_Exception, setError("couldn't create output file %s", filename));
        return 0;
     }
-    if(swf->compressed) {
-           if(swf_WriteSWC(fi, swf)<0) {
-               close(fi);
-               PyErr_SetString(PyExc_Exception, setError("WriteSWC() failed."));
-               return 0;
-           }
-    } else {
-           if(swf_WriteSWF(fi, swf)<0) {
-               close(fi);
-               PyErr_SetString(PyExc_Exception, setError("WriteSWC() failed."));
-               return 0;
-           }
+    if(swf_WriteSWF(fi, swf)<0) {
+        close(fi);
+        PyErr_SetString(PyExc_Exception, setError("WriteSWC() failed."));
+        return 0;
     }
     close(fi);
-    
+
+    swf_FreeTags(swf);
+    /*{ TAG * t = swf->firstTag;
+      while (t)
+      { 
+       mylog("tag: %08x\n",t);
+       mylog("  id: %d (%s)\n", t->id, swf_TagGetName(t));
+       mylog("  data: %08x (%d bytes)\n", t->data, t->len);
+       mylog("  next: %08x\n", t->next);
+       TAG * tnew = t->next;
+       mylog("->free data\n");
+       if (t->data) free(t->data);
+       mylog("->free tag\n");
+       free(t);
+       t = tnew;
+      }
+    }*/
     swf->firstTag = 0;
     
+    mylog(" %08x(%d) f_save filename=%s done\n", (int)self, self->ob_refcnt, filename);
+    
     return PY_NONE;
 }
 //----------------------------------------------------------------------------
@@ -196,7 +247,10 @@ static PyObject * swf_writeCGI(PyObject* self, PyObject* args)
     if(!self || !PyArg_ParseTuple(args,"")) 
        return NULL;
     swf->swf.firstTag = taglist_getTAGs(swf->taglist);
+    if(!swf->swf.firstTag)
+       return NULL;
     swf_WriteCGI(&swf->swf);
+    swf_FreeTags(&swf->swf);
     swf->swf.firstTag = 0;
     return PY_NONE;
 }
@@ -213,11 +267,11 @@ static PyMethodDef swf_functions[] =
 //----------------------------------------------------------------------------
 static void swf_dealloc(PyObject* self)
 {
+    mylog("-%08x(%d) swf_dealloc\n", (int)self, self->ob_refcnt);
     SWFObject*swfo;
     SWF*swf;
     swfo = (SWFObject*)self;
     swf = &swfo->swf;
-    mylog("swf_dealloc %08x(%d)\n", (int)self, self->ob_refcnt);
     if(swfo->filename) {
        free(swfo->filename);
        swfo->filename = 0;
@@ -229,47 +283,53 @@ static void swf_dealloc(PyObject* self)
 //----------------------------------------------------------------------------
 static int swf_print(PyObject * self, FILE *fi, int flags) //flags&Py_PRINT_RAW
 {
+    mylog(" %08x(%d) print \n", (int)self, self->ob_refcnt);
     SWFObject*swf = (SWFObject*)self;
     swf_DumpHeader(fi, &swf->swf);
     //void swf_DumpSWF(FILE * f,SWF*swf);
-    mylog("print %08x(%d)\n", (int)self, self->ob_refcnt);
     return 0;
 }
 //----------------------------------------------------------------------------
 static PyObject* swf_getattr(PyObject * self, char* a)
 {
     SWFObject*swf = (SWFObject*)self;
-    PyObject* ret;
+    PyObject* ret = 0;
 
     if(!strcmp(a, "fps")) {
        double fps = swf->swf.frameRate/256.0;
-       mylog("swf_getattr %08x(%d) %s = %f\n", (int)self, self->ob_refcnt, a, fps);
+       mylog(" %08x(%d) swf_getattr %s = %f\n", (int)self, self->ob_refcnt, a, fps);
        return Py_BuildValue("d", fps);
     } else if(!strcmp(a, "version")) {
        int version = swf->swf.fileVersion;;
-       mylog("swf_getattr %08x(%d) %s = %d\n", (int)self, self->ob_refcnt, a, version);
+       mylog(" %08x(%d) swf_getattr %s = %d\n", (int)self, self->ob_refcnt, a, version);
        return Py_BuildValue("i", version);
     } else if(!strcmp(a, "name")) {
        char*filename = swf->filename;
-       mylog("swf_getattr %08x(%d) %s = %s\n", (int)self, self->ob_refcnt, a, filename);
+       mylog(" %08x(%d) swf_getattr %s = %s\n", (int)self, self->ob_refcnt, a, filename);
        return Py_BuildValue("s", filename);
     } else if(!strcmp(a, "bbox")) {
-       int xmin,ymin,xmax,ymax;
-       xmin = swf->swf.movieSize.xmin;
-       ymin = swf->swf.movieSize.ymin;
-       xmax = swf->swf.movieSize.xmax;
-       ymax = swf->swf.movieSize.ymax;
-       mylog("swf_getattr %08x(%d) %s = (%d,%d,%d,%d)\n", (int)self, self->ob_refcnt, a, xmin,ymin,xmax,ymax);
-       return Py_BuildValue("(iiii)", xmin, ymin, xmax, ymax); 
+       return f_BBox2(swf->swf.movieSize);
     } else if(!strcmp(a, "tags")) {
        PyObject*ret =  (PyObject*)(swf->taglist);
        Py_INCREF(ret);
-       mylog("swf_getattr %08x(%d) %s = %08x(%d)\n", (int)self, self->ob_refcnt, a, ret, ret->ob_refcnt);
+       mylog(" %08x(%d) swf_getattr %s = %08x(%d)\n", (int)self, self->ob_refcnt, a, ret, ret->ob_refcnt);
        return ret;
+    } else if(!strcmp(a, "filesize")) {
+       int s = swf->swf.fileSize;
+       return Py_BuildValue("i", s);
+    } else if(!strcmp(a, "width")) {
+       int w = (swf->swf.movieSize.xmax - swf->swf.movieSize.xmin) / 20;
+       return Py_BuildValue("i", w);
+    } else if(!strcmp(a, "height")) {
+       int h =  (swf->swf.movieSize.ymax - swf->swf.movieSize.ymin) / 20;
+       return Py_BuildValue("i", h);
+    } else if(!strcmp(a, "framecount")) {
+       int f = swf->swf.frameCount;
+       return Py_BuildValue("i", f);
     }
 
     ret = Py_FindMethod(swf_functions, self, a);
-    mylog("swf_getattr %08x(%d) %s: %08x\n", (int)self, self->ob_refcnt, a, ret);
+    mylog(" %08x(%d) swf_getattr %s: %08x\n", (int)self, self->ob_refcnt, a, ret);
     return ret;
 }
 //----------------------------------------------------------------------------
@@ -281,14 +341,14 @@ static int swf_setattr(PyObject * self, char* a, PyObject * o)
        if (!PyArg_Parse(o, "d", &fps)) 
            goto err;
        swf->swf.frameRate = (int)(fps*0x100);
-       mylog("swf_setattr %08x(%d) %s = %f\n", (int)self, self->ob_refcnt, a, fps);
+       mylog(" %08x(%d) swf_setattr %s = %f\n", (int)self, self->ob_refcnt, a, fps);
        return 0;
     } else if(!strcmp(a, "version")) {
        int version;
        if (!PyArg_Parse(o, "i", &version)) 
            goto err;
        swf->swf.fileVersion = version;
-       mylog("swf_setattr %08x(%d) %s = %d\n", (int)self, self->ob_refcnt, a, version);
+       mylog(" %08x(%d) swf_setattr %s = %d\n", (int)self, self->ob_refcnt, a, version);
        return 0;
     } else if(!strcmp(a, "name")) {
        char*filename;
@@ -298,33 +358,32 @@ static int swf_setattr(PyObject * self, char* a, PyObject * o)
            free(swf->filename);swf->filename=0;
        }
        swf->filename = strdup(filename);
-       mylog("swf_setattr %08x(%d) %s = %s\n", (int)self, self->ob_refcnt, a, filename);
+       mylog(" %08x(%d) swf_setattr %s = %s\n", (int)self, self->ob_refcnt, a, filename);
        return 0;
     } else if(!strcmp(a, "bbox")) {
-       int xmin=0,ymin=0,xmax=0,ymax=0;
-       if (!PyArg_Parse(o, "(iiii)", &xmin, &ymin, &xmax, &ymax)) 
-           goto err;
+       PyObject *obbox = o;
+       if (!PY_CHECK_TYPE(obbox, &BBoxClass)) {
+           obbox = f_BBox(0, o, 0);
+           if(!obbox)
+               return 1;
+       }
+       SRECT bbox = bbox_getSRECT(obbox);
 
-       swf->swf.movieSize.xmin = xmin;
-       swf->swf.movieSize.ymin = ymin;
-       swf->swf.movieSize.xmax = xmax;
-       swf->swf.movieSize.ymax = ymax;
-       mylog("swf_setattr %08x(%d) %s = (%d,%d,%d,%d)\n", (int)self, self->ob_refcnt, a, xmin,ymin,xmax,ymax);
+       swf->swf.movieSize = bbox;
+       mylog(" %08x(%d) swf_setattr %s = (%d,%d,%d,%d)\n", (int)self, self->ob_refcnt, a, bbox.xmin,bbox.ymin,bbox.xmax,bbox.ymax);
        return 0;
     } else if(!strcmp(a, "tags")) {
        PyObject* taglist;
-       /*if (!PyArg_Parse(o, "O!", &TagListClass, &taglist));
-           goto err;*/
-       // TODO: check if it's really a taglist
        taglist = o;
+       PY_ASSERT_TYPE(taglist,&TagListClass);
        Py_DECREF(swf->taglist);
        swf->taglist = taglist;
        Py_INCREF(swf->taglist);
-       mylog("swf_setattr %08x(%d) %s = %08x\n", (int)self, self->ob_refcnt, a, swf->taglist);
+       mylog(" %08x(%d) swf_setattr %s = %08x\n", (int)self, self->ob_refcnt, a, swf->taglist);
        return 0;
     }
 err:
-    mylog("swf_setattr %08x(%d) %s = ? (%08x)\n", (int)self, self->ob_refcnt, a, o);
+    mylog(" %08x(%d) swf_setattr %s = ? (%08x)\n", (int)self, self->ob_refcnt, a, o);
     return 1;
 }
 
@@ -346,7 +405,7 @@ static PyTypeObject SWFClass =
 static PyMethodDef SWFMethods[] = 
 {
     /* SWF creation*/
-    {"load", f_load, METH_VARARGS, "Load a SWF from disc."},
+    {"load", (PyCFunction)f_load, METH_KEYWORDS, "Load a SWF from disc."},
     {"create", (PyCFunction)f_create, METH_KEYWORDS, "Create a new SWF from scratch."},
     {0,0,0,0}
     // save is a member function
@@ -364,29 +423,32 @@ PyMethodDef* swf_getMethods()
 #include "tag.h"
 #include "taglist.h"
 
-static PyObject* module_verbose(PyObject* self, PyObject* args)
+static PyObject* module_verbose(PyObject* self, PyObject* args, PyObject* kwargs)
 {
-    if (!PyArg_ParseTuple(args,"i", &verbose)) 
+    int _verbose = 0;
+    static char *kwlist[] = {"verbosity", NULL};
+    if (!PyArg_ParseTupleAndKeywords(args, kwargs, "i", kwlist, &_verbose))
        return NULL;
+    setVerbosity(_verbose);
+
     return Py_BuildValue("s", 0);
 }
 
 static PyMethodDef LoggingMethods[] = 
 {
     /* Module functions */
-    {"verbose", module_verbose, METH_VARARGS, "Set the module verbosity"},
+    {"verbose", (PyCFunction)module_verbose, METH_KEYWORDS, "Set the module verbosity"},
     {0,0,0,0}
 };
-    
+
 void initSWF(void)
 {
+    PyObject*module;
     PyMethodDef* primitive_methods = primitive_getMethods();
-    PyMethodDef* tag_methods = tag_getMethods();
+    PyMethodDef* tag_methods = tags_getMethods();
     PyMethodDef* action_methods = action_getMethods();
     PyMethodDef* swf_methods = swf_getMethods();
 
-    initLog("test.log",8,0,0,0,0);
-
     PyMethodDef* all_methods = 0;
     all_methods = addMethods(all_methods, primitive_methods);
     all_methods = addMethods(all_methods, tag_methods);
@@ -395,5 +457,9 @@ void initSWF(void)
 
     all_methods = addMethods(all_methods, LoggingMethods);
 
-    (void)Py_InitModule("SWF", all_methods);
+    module = Py_InitModule("SWF", all_methods);
+
+    /* Python doesn't copy the PyMethodDef struct, so we need
+       to keep it around */
+    // free(all_methods) 
 }