also use pid when initializing rand48
[swftools.git] / lib / python / SWF.c
blobbfa1a8c15c58731e5d3dc21a2fc0ca699b300215
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 #include <sys/types.h>
25 #include <unistd.h>
26 #undef HAVE_STAT
27 #include "../rfxswf.h"
28 #include "../log.h"
29 #include "./pyutils.h"
30 #include "./tags.h"
31 #include "./taglist.h"
32 #include "./primitives.h"
33 #include "./action.h"
36 TODO:
37 1) taglist is rfxswflib's linked list. It should maybe implemented as Python
38 list, which would, however, mean that we would have to convert the list
39 back and forth for the following functions:
40 load, save, writeCGI, unfoldAll, foldAll, optimizeOrder
41 2) taglist should have an ID handler. Every time a tag is inserted, it's ID
42 is stored in a lookup list.
43 3)
46 //-------------------------- Types -------------------------------------------
48 staticforward PyTypeObject SWFClass;
50 /* Tags, Objects */
52 typedef struct {
53 PyObject_HEAD
54 SWF swf; //swf.firstTag is not used
55 PyObject*taglist;
56 char*filename;
57 } SWFObject;
60 //----------------------------------------------------------------------------
61 static PyObject* f_create(PyObject* self, PyObject* args, PyObject* kwargs)
63 static char *kwlist[] = {"version", "fps", "bbox", "name", NULL};
64 SWFObject* swf;
65 int version = 6;
66 double framerate = 25;
67 PyObject * obbox = 0;
68 SRECT bbox = {0,0,0,0};
69 char* filename = 0;
71 swf = PyObject_New(SWFObject, &SWFClass);
72 mylog("+%08x(%d) create\n", (int)swf, swf->ob_refcnt);
74 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "|idOs",
75 kwlist, &version, &framerate,
76 &obbox, &filename))
77 return NULL;
79 if(obbox) {
80 if (!PY_CHECK_TYPE(obbox, &BBoxClass)) {
81 obbox = f_BBox(0, obbox, 0);
82 if(!obbox)
83 return NULL;
85 bbox = bbox_getSRECT(obbox);
88 memset(&swf->swf, 0, sizeof(SWF));
89 if(filename)
90 swf->filename = strdup(filename);
91 else
92 swf->filename = 0;
94 swf->swf.fileVersion = version;
95 swf->swf.frameRate = (int)(framerate*0x100);
96 swf->swf.movieSize = bbox;
97 swf->taglist = taglist_new();
99 if(swf->swf.fileVersion>=6)
100 swf->swf.compressed = 1;
102 mylog(" %08x(%d) create: done\n", (int)swf, swf->ob_refcnt);
103 return (PyObject*)swf;
105 //----------------------------------------------------------------------------
106 static PyObject* f_load(PyObject* self, PyObject* args, PyObject* kwargs)
108 static char *kwlist1[] = {"filename", NULL};
109 static char *kwlist2[] = {"data", NULL};
110 char* filename = 0;
111 char* data = 0;
112 int len = 0;
113 SWFObject* swf;
114 int fi;
116 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "s", kwlist1, &filename)) {
117 PyErr_Clear();
118 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "s#", kwlist2, &data, &len)) {
119 PyErr_Clear();
120 PyArg_ParseTupleAndKeywords(args, kwargs, "s:load", kwlist1, &filename);
121 return 0;
125 swf = PyObject_New(SWFObject, &SWFClass);
126 mylog("+%08x(%d) f_load\n", (int)swf, swf->ob_refcnt);
128 memset(&swf->swf, 0, sizeof(SWF));
130 if(filename) {
131 if(!filename) {
132 PyErr_SetString(PyExc_Exception, setError("Couldn't open file %s", filename));
133 return 0;
135 swf->filename = strdup(filename);
136 fi = open(filename,O_RDONLY|O_BINARY);
137 if (fi<0) {
138 return PY_ERROR("Couldn't open file %s", filename);
140 if(swf_ReadSWF(fi,&swf->swf)<0) {
141 close(fi);
142 return PY_ERROR("%s is not a valid SWF file or contains errors",filename);
144 close(fi);
145 } else {
146 reader_t r;
147 reader_init_memreader(&r, data, len);
148 swf->filename = 0;
149 if(swf_ReadSWF2(&r, &swf->swf)<0) {
150 return PY_ERROR("<data> is not a valid SWF file or contains errors");
152 r.dealloc(&r);
154 swf_FoldAll(&swf->swf);
156 swf->taglist = taglist_new2(swf->swf.firstTag);
157 if(swf->taglist == NULL) {
158 return NULL;
161 swf_FreeTags(&swf->swf);
162 swf->swf.firstTag = 0;
164 return (PyObject*)swf;
166 //----------------------------------------------------------------------------
167 static PyObject * swf_save(PyObject* self, PyObject* args, PyObject* kwargs)
169 static char *kwlist[] = {"name", "compress", NULL};
170 SWFObject*swfo;
171 SWF*swf;
172 int fi;
173 char*filename = 0;
174 int compress = 0;
176 if(!self)
177 return NULL;
179 swfo = (SWFObject*)self;
180 swf = &swfo->swf;
182 filename = swfo->filename;
184 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "|si", kwlist, &filename, &compress))
185 return NULL;
187 mylog(" %08x(%d) f_save filename=%s compress=%d\n", (int)self, self->ob_refcnt, filename, compress);
189 // keyword arg compress (=1) forces compression
190 if(compress)
191 swf->compressed = 1;
193 swf->firstTag = taglist_getTAGs(swfo->taglist);
195 /*if(!swf->firstTag)
196 return NULL;*/
198 // fix the file, in case it is empty or not terminated properly
200 TAG*tag = swf->firstTag;
201 if(!tag)
202 tag = swf->firstTag = swf_InsertTag(0,ST_END);
203 while(tag && tag->next) {
204 tag = tag->next;
206 if(tag->id != ST_END) {
207 tag = swf_InsertTag(tag,ST_END);
211 fi = open(filename, O_WRONLY|O_CREAT|O_TRUNC|O_BINARY, 0644);
212 if(fi<0) {
213 PyErr_SetString(PyExc_Exception, setError("couldn't create output file %s", filename));
214 return 0;
216 if(swf_WriteSWF(fi, swf)<0) {
217 close(fi);
218 PyErr_SetString(PyExc_Exception, setError("WriteSWC() failed."));
219 return 0;
221 close(fi);
223 swf_FreeTags(swf);
224 /*{ TAG * t = swf->firstTag;
225 while (t)
227 mylog("tag: %08x\n",t);
228 mylog(" id: %d (%s)\n", t->id, swf_TagGetName(t));
229 mylog(" data: %08x (%d bytes)\n", t->data, t->len);
230 mylog(" next: %08x\n", t->next);
231 TAG * tnew = t->next;
232 mylog("->free data\n");
233 if (t->data) free(t->data);
234 mylog("->free tag\n");
235 free(t);
236 t = tnew;
239 swf->firstTag = 0;
241 mylog(" %08x(%d) f_save filename=%s done\n", (int)self, self->ob_refcnt, filename);
243 return PY_NONE;
245 //----------------------------------------------------------------------------
246 static PyObject * swf_writeCGI(PyObject* self, PyObject* args)
248 SWFObject*swf = (SWFObject*)self;
249 if(!self || !PyArg_ParseTuple(args,""))
250 return NULL;
251 swf->swf.firstTag = taglist_getTAGs(swf->taglist);
252 if(!swf->swf.firstTag)
253 return NULL;
254 swf_WriteCGI(&swf->swf);
255 swf_FreeTags(&swf->swf);
256 swf->swf.firstTag = 0;
257 return PY_NONE;
259 //----------------------------------------------------------------------------
261 //TODO: void swf_Relocate(SWF*swf, char*bitmap); // bitmap is 65536 bytes, bitmap[a]==0 means id a is free
263 static PyMethodDef swf_functions[] =
264 {{"save", (PyCFunction)swf_save, METH_KEYWORDS, "Save SWF to disk"},
265 {"writeCGI", (PyCFunction)swf_writeCGI, METH_VARARGS, "print SWF as CGI to stdout"},
266 {NULL, NULL, 0, NULL}
269 //----------------------------------------------------------------------------
270 static void swf_dealloc(PyObject* self)
272 mylog("-%08x(%d) swf_dealloc\n", (int)self, self->ob_refcnt);
273 SWFObject*swfo;
274 SWF*swf;
275 swfo = (SWFObject*)self;
276 swf = &swfo->swf;
277 if(swfo->filename) {
278 free(swfo->filename);
279 swfo->filename = 0;
281 Py_DECREF(swfo->taglist);
282 swfo->taglist = 0;
283 PyObject_Del(self);
285 //----------------------------------------------------------------------------
286 static int swf_print(PyObject * self, FILE *fi, int flags) //flags&Py_PRINT_RAW
288 mylog(" %08x(%d) print \n", (int)self, self->ob_refcnt);
289 SWFObject*swf = (SWFObject*)self;
290 swf_DumpHeader(fi, &swf->swf);
291 //void swf_DumpSWF(FILE * f,SWF*swf);
292 return 0;
294 //----------------------------------------------------------------------------
295 static PyObject* swf_getattr(PyObject * self, char* a)
297 SWFObject*swf = (SWFObject*)self;
298 PyObject* ret = 0;
300 if(!strcmp(a, "fps")) {
301 double fps = swf->swf.frameRate/256.0;
302 mylog(" %08x(%d) swf_getattr %s = %f\n", (int)self, self->ob_refcnt, a, fps);
303 return Py_BuildValue("d", fps);
304 } else if(!strcmp(a, "version")) {
305 int version = swf->swf.fileVersion;;
306 mylog(" %08x(%d) swf_getattr %s = %d\n", (int)self, self->ob_refcnt, a, version);
307 return Py_BuildValue("i", version);
308 } else if(!strcmp(a, "name")) {
309 char*filename = swf->filename;
310 mylog(" %08x(%d) swf_getattr %s = %s\n", (int)self, self->ob_refcnt, a, filename);
311 return Py_BuildValue("s", filename);
312 } else if(!strcmp(a, "bbox")) {
313 return f_BBox2(swf->swf.movieSize);
314 } else if(!strcmp(a, "tags")) {
315 PyObject*ret = (PyObject*)(swf->taglist);
316 Py_INCREF(ret);
317 mylog(" %08x(%d) swf_getattr %s = %08x(%d)\n", (int)self, self->ob_refcnt, a, ret, ret->ob_refcnt);
318 return ret;
319 } else if(!strcmp(a, "filesize")) {
320 int s = swf->swf.fileSize;
321 return Py_BuildValue("i", s);
322 } else if(!strcmp(a, "width")) {
323 int w = (swf->swf.movieSize.xmax - swf->swf.movieSize.xmin) / 20;
324 return Py_BuildValue("i", w);
325 } else if(!strcmp(a, "height")) {
326 int h = (swf->swf.movieSize.ymax - swf->swf.movieSize.ymin) / 20;
327 return Py_BuildValue("i", h);
328 } else if(!strcmp(a, "framecount")) {
329 int f = swf->swf.frameCount;
330 return Py_BuildValue("i", f);
333 ret = Py_FindMethod(swf_functions, self, a);
334 mylog(" %08x(%d) swf_getattr %s: %08x\n", (int)self, self->ob_refcnt, a, ret);
335 return ret;
337 //----------------------------------------------------------------------------
338 static int swf_setattr(PyObject * self, char* a, PyObject * o)
340 SWFObject*swf = (SWFObject*)self;
341 if(!strcmp(a, "fps")) {
342 double fps;
343 if (!PyArg_Parse(o, "d", &fps))
344 goto err;
345 swf->swf.frameRate = (int)(fps*0x100);
346 mylog(" %08x(%d) swf_setattr %s = %f\n", (int)self, self->ob_refcnt, a, fps);
347 return 0;
348 } else if(!strcmp(a, "version")) {
349 int version;
350 if (!PyArg_Parse(o, "i", &version))
351 goto err;
352 swf->swf.fileVersion = version;
353 mylog(" %08x(%d) swf_setattr %s = %d\n", (int)self, self->ob_refcnt, a, version);
354 return 0;
355 } else if(!strcmp(a, "name")) {
356 char*filename;
357 if (!PyArg_Parse(o, "s", &filename))
358 goto err;
359 if(swf->filename) {
360 free(swf->filename);swf->filename=0;
362 swf->filename = strdup(filename);
363 mylog(" %08x(%d) swf_setattr %s = %s\n", (int)self, self->ob_refcnt, a, filename);
364 return 0;
365 } else if(!strcmp(a, "bbox")) {
366 PyObject *obbox = o;
367 if (!PY_CHECK_TYPE(obbox, &BBoxClass)) {
368 obbox = f_BBox(0, o, 0);
369 if(!obbox)
370 return 1;
372 SRECT bbox = bbox_getSRECT(obbox);
374 swf->swf.movieSize = bbox;
375 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);
376 return 0;
377 } else if(!strcmp(a, "tags")) {
378 PyObject* taglist;
379 taglist = o;
380 PY_ASSERT_TYPE(taglist,&TagListClass);
381 Py_DECREF(swf->taglist);
382 swf->taglist = taglist;
383 Py_INCREF(swf->taglist);
384 mylog(" %08x(%d) swf_setattr %s = %08x\n", (int)self, self->ob_refcnt, a, swf->taglist);
385 return 0;
387 err:
388 mylog(" %08x(%d) swf_setattr %s = ? (%08x)\n", (int)self, self->ob_refcnt, a, o);
389 return 1;
392 //----------------------------------------------------------------------------
393 static PyTypeObject SWFClass =
395 PyObject_HEAD_INIT(NULL)
397 tp_name: "SWF",
398 tp_basicsize: sizeof(SWFObject),
399 tp_itemsize: 0,
400 tp_dealloc: swf_dealloc,
401 tp_print: swf_print,
402 tp_getattr: swf_getattr,
403 tp_setattr: swf_setattr,
405 //----------------------------------------------------------------------------
407 static PyMethodDef SWFMethods[] =
409 /* SWF creation*/
410 {"load", (PyCFunction)f_load, METH_KEYWORDS, "Load a SWF from disc."},
411 {"create", (PyCFunction)f_create, METH_KEYWORDS, "Create a new SWF from scratch."},
412 {0,0,0,0}
413 // save is a member function
415 PyMethodDef* swf_getMethods()
417 SWFClass.ob_type = &PyType_Type;
418 return SWFMethods;
421 // =============================================================================
423 #include "primitives.h"
424 #include "action.h"
425 #include "tag.h"
426 #include "taglist.h"
428 static PyObject* module_verbose(PyObject* self, PyObject* args, PyObject* kwargs)
430 int _verbose = 0;
431 static char *kwlist[] = {"verbosity", NULL};
432 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "i", kwlist, &_verbose))
433 return NULL;
434 setVerbosity(_verbose);
436 return Py_BuildValue("s", 0);
439 static PyMethodDef LoggingMethods[] =
441 /* Module functions */
442 {"verbose", (PyCFunction)module_verbose, METH_KEYWORDS, "Set the module verbosity"},
443 {0,0,0,0}
446 void initSWF(void)
448 srand48(time(0)*getpid());
450 PyObject*module;
451 PyMethodDef* primitive_methods = primitive_getMethods();
452 PyMethodDef* tag_methods = tags_getMethods();
453 PyMethodDef* action_methods = action_getMethods();
454 PyMethodDef* swf_methods = swf_getMethods();
456 PyMethodDef* all_methods = 0;
457 all_methods = addMethods(all_methods, primitive_methods);
458 all_methods = addMethods(all_methods, tag_methods);
459 all_methods = addMethods(all_methods, action_methods);
460 all_methods = addMethods(all_methods, swf_methods);
462 all_methods = addMethods(all_methods, LoggingMethods);
464 module = Py_InitModule("SWF", all_methods);
466 /* Python doesn't copy the PyMethodDef struct, so we need
467 to keep it around */
468 // free(all_methods)