bugfixes in swfc
[swftools.git] / lib / python / SWF.c
blob050b36a43d09f35dab3e96833eff502627a8e56b
1 /* SWF.c
3 Python wrapper for librfxswf- module core.
5 Part of the swftools package.
7 Copyright (c) 2003 Matthias Kramm <kramm@quiss.org>
9 This program is free software; you can redistribute it and/or modify
10 it under the terms of the GNU General Public License as published by
11 the Free Software Foundation; either version 2 of the License, or
12 (at your option) any later version.
14 This program is distributed in the hope that it will be useful,
15 but WITHOUT ANY WARRANTY; without even the implied warranty of
16 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 GNU General Public License for more details.
19 You should have received a copy of the GNU General Public License
20 along with this program; if not, write to the Free Software
21 Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */
23 #include <Python.h>
24 #undef HAVE_STAT
25 #include "../rfxswf.h"
26 #include "../log.h"
27 #include "./pyutils.h"
28 #include "./tags.h"
29 #include "./taglist.h"
30 #include "./primitives.h"
31 #include "./action.h"
34 TODO:
35 1) taglist is rfxswflib's linked list. It should maybe implemented as Python
36 list, which would, however, mean that we would have to convert the list
37 back and forth for the following functions:
38 load, save, writeCGI, unfoldAll, foldAll, optimizeOrder
39 2) taglist should have an ID handler. Every time a tag is inserted, it's ID
40 is stored in a lookup list.
41 3)
44 //-------------------------- Types -------------------------------------------
46 staticforward PyTypeObject SWFClass;
48 /* Tags, Objects */
50 typedef struct {
51 PyObject_HEAD
52 SWF swf; //swf.firstTag is not used
53 PyObject*taglist;
54 char*filename;
55 } SWFObject;
58 //----------------------------------------------------------------------------
59 static PyObject* f_create(PyObject* self, PyObject* args, PyObject* kwargs)
61 static char *kwlist[] = {"version", "fps", "bbox", "name", NULL};
62 SWFObject* swf;
63 int version = 6;
64 double framerate = 25;
65 PyObject * obbox = 0;
66 SRECT bbox = {0,0,0,0};
67 char* filename = 0;
69 swf = PyObject_New(SWFObject, &SWFClass);
70 mylog("+%08x(%d) create\n", (int)swf, swf->ob_refcnt);
72 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "|idOs",
73 kwlist, &version, &framerate,
74 &obbox, &filename))
75 return NULL;
77 if(obbox) {
78 if (!PY_CHECK_TYPE(obbox, &BBoxClass)) {
79 obbox = f_BBox(0, obbox, 0);
80 if(!obbox)
81 return NULL;
83 bbox = bbox_getSRECT(obbox);
86 memset(&swf->swf, 0, sizeof(SWF));
87 if(filename)
88 swf->filename = strdup(filename);
89 else
90 swf->filename = 0;
92 swf->swf.fileVersion = version;
93 swf->swf.frameRate = (int)(framerate*0x100);
94 swf->swf.movieSize = bbox;
95 swf->taglist = taglist_new();
97 if(swf->swf.fileVersion>=6)
98 swf->swf.compressed = 1;
100 mylog(" %08x(%d) create: done\n", (int)swf, swf->ob_refcnt);
101 return (PyObject*)swf;
103 //----------------------------------------------------------------------------
104 static PyObject* f_load(PyObject* self, PyObject* args, PyObject* kwargs)
106 static char *kwlist1[] = {"filename", NULL};
107 static char *kwlist2[] = {"data", NULL};
108 char* filename = 0;
109 char* data = 0;
110 int len = 0;
111 SWFObject* swf;
112 int fi;
114 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "s", kwlist1, &filename)) {
115 PyErr_Clear();
116 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "s#", kwlist2, &data, &len)) {
117 PyErr_Clear();
118 PyArg_ParseTupleAndKeywords(args, kwargs, "s:load", kwlist1, &filename);
119 return 0;
123 swf = PyObject_New(SWFObject, &SWFClass);
124 mylog("+%08x(%d) f_load\n", (int)swf, swf->ob_refcnt);
126 memset(&swf->swf, 0, sizeof(SWF));
128 if(filename) {
129 if(!filename) {
130 PyErr_SetString(PyExc_Exception, setError("Couldn't open file %s", filename));
131 return 0;
133 swf->filename = strdup(filename);
134 fi = open(filename,O_RDONLY|O_BINARY);
135 if (fi<0) {
136 return PY_ERROR("Couldn't open file %s", filename);
138 if(swf_ReadSWF(fi,&swf->swf)<0) {
139 close(fi);
140 return PY_ERROR("%s is not a valid SWF file or contains errors",filename);
142 close(fi);
143 } else {
144 reader_t r;
145 reader_init_memreader(&r, data, len);
146 swf->filename = 0;
147 if(swf_ReadSWF2(&r, &swf->swf)<0) {
148 return PY_ERROR("<data> is not a valid SWF file or contains errors");
150 r.dealloc(&r);
152 swf_FoldAll(&swf->swf);
154 swf->taglist = taglist_new2(swf->swf.firstTag);
155 if(swf->taglist == NULL) {
156 return NULL;
159 swf_FreeTags(&swf->swf);
160 swf->swf.firstTag = 0;
162 return (PyObject*)swf;
164 //----------------------------------------------------------------------------
165 static PyObject * swf_save(PyObject* self, PyObject* args, PyObject* kwargs)
167 static char *kwlist[] = {"name", "compress", NULL};
168 SWFObject*swfo;
169 SWF*swf;
170 int fi;
171 char*filename = 0;
172 int compress = 0;
174 if(!self)
175 return NULL;
177 swfo = (SWFObject*)self;
178 swf = &swfo->swf;
180 filename = swfo->filename;
182 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "|si", kwlist, &filename, &compress))
183 return NULL;
185 mylog(" %08x(%d) f_save filename=%s compress=%d\n", (int)self, self->ob_refcnt, filename, compress);
187 // keyword arg compress (=1) forces compression
188 if(compress)
189 swf->compressed = 1;
191 swf->firstTag = taglist_getTAGs(swfo->taglist);
193 /*if(!swf->firstTag)
194 return NULL;*/
196 // fix the file, in case it is empty or not terminated properly
198 TAG*tag = swf->firstTag;
199 if(!tag)
200 tag = swf->firstTag = swf_InsertTag(0,ST_END);
201 while(tag && tag->next) {
202 tag = tag->next;
204 if(tag->id != ST_END) {
205 tag = swf_InsertTag(tag,ST_END);
209 fi = open(filename, O_WRONLY|O_CREAT|O_TRUNC|O_BINARY, 0644);
210 if(fi<0) {
211 PyErr_SetString(PyExc_Exception, setError("couldn't create output file %s", filename));
212 return 0;
214 if(swf_WriteSWF(fi, swf)<0) {
215 close(fi);
216 PyErr_SetString(PyExc_Exception, setError("WriteSWC() failed."));
217 return 0;
219 close(fi);
221 swf_FreeTags(swf);
222 /*{ TAG * t = swf->firstTag;
223 while (t)
225 mylog("tag: %08x\n",t);
226 mylog(" id: %d (%s)\n", t->id, swf_TagGetName(t));
227 mylog(" data: %08x (%d bytes)\n", t->data, t->len);
228 mylog(" next: %08x\n", t->next);
229 TAG * tnew = t->next;
230 mylog("->free data\n");
231 if (t->data) free(t->data);
232 mylog("->free tag\n");
233 free(t);
234 t = tnew;
237 swf->firstTag = 0;
239 mylog(" %08x(%d) f_save filename=%s done\n", (int)self, self->ob_refcnt, filename);
241 return PY_NONE;
243 //----------------------------------------------------------------------------
244 static PyObject * swf_writeCGI(PyObject* self, PyObject* args)
246 SWFObject*swf = (SWFObject*)self;
247 if(!self || !PyArg_ParseTuple(args,""))
248 return NULL;
249 swf->swf.firstTag = taglist_getTAGs(swf->taglist);
250 if(!swf->swf.firstTag)
251 return NULL;
252 swf_WriteCGI(&swf->swf);
253 swf_FreeTags(&swf->swf);
254 swf->swf.firstTag = 0;
255 return PY_NONE;
257 //----------------------------------------------------------------------------
259 //TODO: void swf_Relocate(SWF*swf, char*bitmap); // bitmap is 65536 bytes, bitmap[a]==0 means id a is free
261 static PyMethodDef swf_functions[] =
262 {{"save", (PyCFunction)swf_save, METH_KEYWORDS, "Save SWF to disk"},
263 {"writeCGI", (PyCFunction)swf_writeCGI, METH_VARARGS, "print SWF as CGI to stdout"},
264 {NULL, NULL, 0, NULL}
267 //----------------------------------------------------------------------------
268 static void swf_dealloc(PyObject* self)
270 mylog("-%08x(%d) swf_dealloc\n", (int)self, self->ob_refcnt);
271 SWFObject*swfo;
272 SWF*swf;
273 swfo = (SWFObject*)self;
274 swf = &swfo->swf;
275 if(swfo->filename) {
276 free(swfo->filename);
277 swfo->filename = 0;
279 Py_DECREF(swfo->taglist);
280 swfo->taglist = 0;
281 PyObject_Del(self);
283 //----------------------------------------------------------------------------
284 static int swf_print(PyObject * self, FILE *fi, int flags) //flags&Py_PRINT_RAW
286 mylog(" %08x(%d) print \n", (int)self, self->ob_refcnt);
287 SWFObject*swf = (SWFObject*)self;
288 swf_DumpHeader(fi, &swf->swf);
289 //void swf_DumpSWF(FILE * f,SWF*swf);
290 return 0;
292 //----------------------------------------------------------------------------
293 static PyObject* swf_getattr(PyObject * self, char* a)
295 SWFObject*swf = (SWFObject*)self;
296 PyObject* ret = 0;
298 if(!strcmp(a, "fps")) {
299 double fps = swf->swf.frameRate/256.0;
300 mylog(" %08x(%d) swf_getattr %s = %f\n", (int)self, self->ob_refcnt, a, fps);
301 return Py_BuildValue("d", fps);
302 } else if(!strcmp(a, "version")) {
303 int version = swf->swf.fileVersion;;
304 mylog(" %08x(%d) swf_getattr %s = %d\n", (int)self, self->ob_refcnt, a, version);
305 return Py_BuildValue("i", version);
306 } else if(!strcmp(a, "name")) {
307 char*filename = swf->filename;
308 mylog(" %08x(%d) swf_getattr %s = %s\n", (int)self, self->ob_refcnt, a, filename);
309 return Py_BuildValue("s", filename);
310 } else if(!strcmp(a, "bbox")) {
311 return f_BBox2(swf->swf.movieSize);
312 } else if(!strcmp(a, "tags")) {
313 PyObject*ret = (PyObject*)(swf->taglist);
314 Py_INCREF(ret);
315 mylog(" %08x(%d) swf_getattr %s = %08x(%d)\n", (int)self, self->ob_refcnt, a, ret, ret->ob_refcnt);
316 return ret;
317 } else if(!strcmp(a, "filesize")) {
318 int s = swf->swf.fileSize;
319 return Py_BuildValue("i", s);
320 } else if(!strcmp(a, "width")) {
321 int w = (swf->swf.movieSize.xmax - swf->swf.movieSize.xmin) / 20;
322 return Py_BuildValue("i", w);
323 } else if(!strcmp(a, "height")) {
324 int h = (swf->swf.movieSize.ymax - swf->swf.movieSize.ymin) / 20;
325 return Py_BuildValue("i", h);
326 } else if(!strcmp(a, "framecount")) {
327 int f = swf->swf.frameCount;
328 return Py_BuildValue("i", f);
331 ret = Py_FindMethod(swf_functions, self, a);
332 mylog(" %08x(%d) swf_getattr %s: %08x\n", (int)self, self->ob_refcnt, a, ret);
333 return ret;
335 //----------------------------------------------------------------------------
336 static int swf_setattr(PyObject * self, char* a, PyObject * o)
338 SWFObject*swf = (SWFObject*)self;
339 if(!strcmp(a, "fps")) {
340 double fps;
341 if (!PyArg_Parse(o, "d", &fps))
342 goto err;
343 swf->swf.frameRate = (int)(fps*0x100);
344 mylog(" %08x(%d) swf_setattr %s = %f\n", (int)self, self->ob_refcnt, a, fps);
345 return 0;
346 } else if(!strcmp(a, "version")) {
347 int version;
348 if (!PyArg_Parse(o, "i", &version))
349 goto err;
350 swf->swf.fileVersion = version;
351 mylog(" %08x(%d) swf_setattr %s = %d\n", (int)self, self->ob_refcnt, a, version);
352 return 0;
353 } else if(!strcmp(a, "name")) {
354 char*filename;
355 if (!PyArg_Parse(o, "s", &filename))
356 goto err;
357 if(swf->filename) {
358 free(swf->filename);swf->filename=0;
360 swf->filename = strdup(filename);
361 mylog(" %08x(%d) swf_setattr %s = %s\n", (int)self, self->ob_refcnt, a, filename);
362 return 0;
363 } else if(!strcmp(a, "bbox")) {
364 PyObject *obbox = o;
365 if (!PY_CHECK_TYPE(obbox, &BBoxClass)) {
366 obbox = f_BBox(0, o, 0);
367 if(!obbox)
368 return 1;
370 SRECT bbox = bbox_getSRECT(obbox);
372 swf->swf.movieSize = bbox;
373 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);
374 return 0;
375 } else if(!strcmp(a, "tags")) {
376 PyObject* taglist;
377 taglist = o;
378 PY_ASSERT_TYPE(taglist,&TagListClass);
379 Py_DECREF(swf->taglist);
380 swf->taglist = taglist;
381 Py_INCREF(swf->taglist);
382 mylog(" %08x(%d) swf_setattr %s = %08x\n", (int)self, self->ob_refcnt, a, swf->taglist);
383 return 0;
385 err:
386 mylog(" %08x(%d) swf_setattr %s = ? (%08x)\n", (int)self, self->ob_refcnt, a, o);
387 return 1;
390 //----------------------------------------------------------------------------
391 static PyTypeObject SWFClass =
393 PyObject_HEAD_INIT(NULL)
395 tp_name: "SWF",
396 tp_basicsize: sizeof(SWFObject),
397 tp_itemsize: 0,
398 tp_dealloc: swf_dealloc,
399 tp_print: swf_print,
400 tp_getattr: swf_getattr,
401 tp_setattr: swf_setattr,
403 //----------------------------------------------------------------------------
405 static PyMethodDef SWFMethods[] =
407 /* SWF creation*/
408 {"load", (PyCFunction)f_load, METH_KEYWORDS, "Load a SWF from disc."},
409 {"create", (PyCFunction)f_create, METH_KEYWORDS, "Create a new SWF from scratch."},
410 {0,0,0,0}
411 // save is a member function
413 PyMethodDef* swf_getMethods()
415 SWFClass.ob_type = &PyType_Type;
416 return SWFMethods;
419 // =============================================================================
421 #include "primitives.h"
422 #include "action.h"
423 #include "tag.h"
424 #include "taglist.h"
426 static PyObject* module_verbose(PyObject* self, PyObject* args, PyObject* kwargs)
428 int _verbose = 0;
429 static char *kwlist[] = {"verbosity", NULL};
430 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "i", kwlist, &_verbose))
431 return NULL;
432 setVerbosity(_verbose);
434 return Py_BuildValue("s", 0);
437 static PyMethodDef LoggingMethods[] =
439 /* Module functions */
440 {"verbose", (PyCFunction)module_verbose, METH_KEYWORDS, "Set the module verbosity"},
441 {0,0,0,0}
444 void initSWF(void)
446 PyObject*module;
447 PyMethodDef* primitive_methods = primitive_getMethods();
448 PyMethodDef* tag_methods = tags_getMethods();
449 PyMethodDef* action_methods = action_getMethods();
450 PyMethodDef* swf_methods = swf_getMethods();
452 PyMethodDef* all_methods = 0;
453 all_methods = addMethods(all_methods, primitive_methods);
454 all_methods = addMethods(all_methods, tag_methods);
455 all_methods = addMethods(all_methods, action_methods);
456 all_methods = addMethods(all_methods, swf_methods);
458 all_methods = addMethods(all_methods, LoggingMethods);
460 module = Py_InitModule("SWF", all_methods);
462 /* Python doesn't copy the PyMethodDef struct, so we need
463 to keep it around */
464 // free(all_methods)