add back playanim from 2.4x (not functional, #if 0'd)
[blender.git] / source / blender / windowmanager / intern / wm_playanim.c
1 #if 0
2 /**
3  * $Id: playanim.c 17755 2008-12-09 04:57:42Z bdiego $
4  *
5  * ***** BEGIN GPL LICENSE BLOCK *****
6  *
7  * This program is free software; you can redistribute it and/or
8  * modify it under the terms of the GNU General Public License
9  * as published by the Free Software Foundation; either version 2
10  * of the License, or (at your option) any later version.
11  *
12  * This program is distributed in the hope that it will be useful,
13  * but WITHOUT ANY WARRANTY; without even the implied warranty of
14  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15  * GNU General Public License for more details.
16  *
17  * You should have received a copy of the GNU General Public License
18  * along with this program; if not, write to the Free Software Foundation,
19  * Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
20  *
21  * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV.
22  * All rights reserved.
23  *
24  * The Original Code is: all of this file.
25  *
26  * Contributor(s): none yet.
27  *
28  * ***** END GPL LICENSE BLOCK *****
29  */
30
31 #include <sys/types.h>
32 #include <fcntl.h>
33 #include <stdlib.h>
34 #include <string.h>
35
36 #ifdef HAVE_CONFIG_H
37 #include <config.h>
38 #endif
39
40 #ifndef WIN32
41 #include <unistd.h>
42 #include <sys/times.h>
43 #include <sys/wait.h>
44 #else
45 #include <io.h>
46 #endif   
47 #include "MEM_guardedalloc.h"
48
49 #include "PIL_time.h"
50
51 #include <math.h>
52
53 #include "BLI_blenlib.h"
54 #include "BLI_arithb.h"
55
56 #include "IMB_imbuf_types.h"
57 #include "IMB_imbuf.h"
58
59 #include "BDR_editcurve.h"
60
61 #include "BKE_blender.h"
62 #include "BKE_global.h"
63 #include "BKE_utildefines.h"
64
65 #include "BIF_gl.h"
66 #include "BIF_glutil.h"
67 #include "BIF_screen.h"
68 #include "BIF_mywindow.h"
69
70 #include "BMF_Api.h"
71
72 #ifdef WITH_QUICKTIME
73 #ifdef _WIN32
74 #include <QTML.h>
75 #include <Movies.h>
76 #elif defined(__APPLE__)
77 #include <QuickTime/Movies.h>
78 #endif /* __APPLE__ */
79 #endif /* WITH_QUICKTIME */
80
81 #include "playanim_ext.h"
82 #include "mydevice.h"
83 #include "blendef.h"
84 #include "winlay.h"
85
86 /* ***************** gl_util.c ****************** */
87
88 static Window *g_window = NULL;
89 static int qualN = 0;
90
91 #define LSHIFT  (1<<0)
92 #define RSHIFT  (1<<1)
93 #define SHIFT   (LSHIFT | RSHIFT)
94 #define LALT    (1<<2)
95 #define RALT    (1<<3)
96 #define ALT     (LALT | RALT)
97 #define LCTRL   (1<<4)
98 #define RCTRL   (1<<5)
99 #define LMOUSE  (1<<16)
100 #define MMOUSE  (1<<17)
101 #define RMOUSE  (1<<18)
102 #define MOUSE   (LMOUSE | MMOUSE | RMOUSE)
103
104 unsigned short screen_qread(short *val, char *ascii);
105
106 /* implementation */
107 static int qreadN(short *val)
108 {
109         char ascii;
110         int event = screen_qread(val, &ascii);
111
112         switch(event){
113         case LEFTMOUSE:
114                 if (*val) qualN |= LMOUSE;
115                 else qualN &= ~LMOUSE;
116                 break;
117         case MIDDLEMOUSE:
118                 if (*val) qualN |= MMOUSE;
119                 else qualN &= ~MMOUSE;
120                 break;
121         case RIGHTMOUSE:
122                 if (*val) qualN |= RMOUSE;
123                 else qualN &= ~RMOUSE;
124                 break;
125         case LEFTSHIFTKEY:
126                 if (*val) qualN |= LSHIFT;
127                 else qualN &= ~LSHIFT;
128                 break;
129         case RIGHTSHIFTKEY:
130                 if (*val) qualN |= RSHIFT;
131                 else qualN &= ~RSHIFT;
132                 break;
133         case LEFTCTRLKEY:
134                 if (*val) qualN |= LCTRL;
135                 else qualN &= ~LCTRL;
136                 break;
137         case RIGHTCTRLKEY:
138                 if (*val) qualN |= RCTRL;
139                 else qualN &= ~RCTRL;
140                 break;
141         case LEFTALTKEY:
142                 if (*val) qualN |= LALT;
143                 else qualN &= ~LALT;
144                 break;
145         case RIGHTALTKEY:
146                 if (*val) qualN |= RALT;
147                 else qualN &= ~RALT;
148                 break;
149         }
150
151         return(event);
152 }
153
154 /* ***************** gl_util.c ****************** */
155
156
157
158
159 typedef struct pict{
160         struct pict *next, *prev;
161         char *mem;
162         int size;
163         char *name;
164         struct ImBuf *ibuf;
165         struct anim *anim;
166         int frame;
167         int IB_flags;
168 }Pict;
169
170 static struct ListBase _picsbase = {0,0};
171 static struct ListBase *picsbase = &_picsbase;
172 static int fromdisk = FALSE;
173 static int fstep = 1; 
174 static float zoomx = 1.0 , zoomy = 1.0;
175 static double ptottime = 0.0, swaptime = 0.04;
176
177 static int pupdate_time(void)
178 {
179         static double ltime;
180         double time;
181
182         time = PIL_check_seconds_timer();
183
184         ptottime += (time - ltime);
185         ltime = time;
186         return (ptottime < 0);
187 }
188
189 static void toscreen(Pict *picture, struct ImBuf *ibuf)
190 {
191         
192         if (ibuf == 0){
193                 printf("no ibuf !\n");
194                 return;
195         }
196         if (ibuf->rect==NULL && ibuf->rect_float) {
197                 IMB_rect_from_float(ibuf);
198                 imb_freerectfloatImBuf(ibuf);
199         }
200         if (ibuf->rect==NULL)
201                 return;
202
203         glRasterPos2f(0.0f, 0.0f);
204
205         glDrawPixels(ibuf->x, ibuf->y, GL_RGBA, GL_UNSIGNED_BYTE, ibuf->rect);
206         
207         pupdate_time();
208
209         if(picture && (qualN & (SHIFT|LMOUSE))) {
210                 char str[512];
211                 cpack(-1);
212                 glRasterPos2f(0.02f,  0.03f);
213                 sprintf(str, "%s | %.2f frames/s\n", picture->name, fstep / swaptime);
214                 BMF_DrawString(G.fonts, str);
215         }
216         
217         window_swap_buffers(g_window);
218 }
219
220 static void build_pict_list(char * first, int totframes, int fstep)
221 {
222         int size,pic,file;
223         char *mem, name[512];
224         short val;
225         struct pict * picture = 0;
226         struct ImBuf *ibuf = 0;
227         int count = 0;
228         char str[512];
229         struct anim * anim;
230         
231         if (IMB_isanim(first)) {
232                 anim = IMB_open_anim(first, IB_rect);
233                 if (anim) {
234                         ibuf = IMB_anim_absolute(anim, 0);
235                         if (ibuf) {
236                                 toscreen(NULL, ibuf);
237                                 IMB_freeImBuf(ibuf);
238                         }
239                         
240                         for (pic = 0; pic < IMB_anim_get_duration(anim); pic ++) {
241                                 picture = (Pict*)MEM_callocN(sizeof(Pict),"Pict");
242                                 picture->anim = anim;
243                                 picture->frame = pic;
244                                 picture->IB_flags = IB_rect;
245                                 sprintf(str, "%s : %d", first, pic + 1);
246                                 picture->name = strdup(str);
247                                 BLI_addtail(picsbase, picture);
248                         }
249                 } 
250                 else printf("couldn't open anim %s\n", first);
251         } 
252         else {
253         
254                 strcpy(name,first);
255         
256                 pupdate_time();
257                 ptottime = 1.0;
258                 
259 /*
260      O_DIRECT
261             If set, all reads and writes on the resulting file descriptor will
262             be performed directly to or from the user program buffer, provided
263             appropriate size and alignment restrictions are met.  Refer to the
264             F_SETFL and F_DIOINFO commands in the fcntl(2) manual entry for
265             information about how to determine the alignment constraints.
266             O_DIRECT is a Silicon Graphics extension and is only supported on
267             local EFS and XFS file systems.
268 */
269                 
270                 while(IMB_ispic(name) && totframes){
271                         file = open(name, O_BINARY|O_RDONLY, 0);
272                         if (file < 0) return;
273                         picture = (struct pict*)MEM_callocN(sizeof(struct pict), "picture");
274                         if (picture == 0){
275                                 printf("Not enough memory for pict struct \n");
276                                 close(file);
277                                 return;
278                         }
279                         size = BLI_filesize(file);
280
281                         if (size < 1) {
282                                 close(file);
283                                 MEM_freeN(picture);
284                                 return;
285                         }
286
287                         picture->size = size;
288                         picture->IB_flags = IB_rect;
289                                                 
290                         if (fromdisk == FALSE) {
291                                 mem=(char *)MEM_mallocN(size, "build pic list");
292                                 if (mem==0){
293                                         printf("Couldn't get memory\n");
294                                         close(file);
295                                         MEM_freeN(picture);
296                                         return;
297                                 }
298                 
299                                 if (read(file,mem,size) != size){
300                                         printf("Error while reading %s\n",name);
301                                         close(file);
302                                         MEM_freeN(picture);
303                                         MEM_freeN(mem);
304                                         return;
305                                 }
306                         } else mem = 0;
307                         
308                         picture->mem = mem;
309                         picture->name = strdup(name);
310                         close(file);
311                         BLI_addtail(picsbase,picture);
312                         count++;
313                         
314                         pupdate_time();
315                         
316                         if (ptottime > 1.0) {                           
317                                 if (picture->mem) ibuf = IMB_ibImageFromMemory((int *) picture->mem, picture->size, picture->IB_flags);
318                                 else ibuf = IMB_loadiffname(picture->name, picture->IB_flags);
319                                 if (ibuf) {
320                                         toscreen(picture, ibuf);
321                                         IMB_freeImBuf(ibuf);
322                                 }
323                                 pupdate_time();
324                                 ptottime = 0.0;
325                         }
326                         
327                         BLI_newname(name, +fstep);
328                         
329                         while(qtest()){
330                                 switch(qreadN(&val)){
331                                 case ESCKEY:
332                                         if (val) return;
333                                         break;
334                                 }
335                         }
336                         totframes--;
337                 }
338         }
339         return;
340 }
341
342 void playanim(int argc, char **argv)
343 {
344         struct ImBuf *ibuf = 0;
345         struct pict *picture = 0;
346         char name[512];
347         short val = 0, go = TRUE, ibufx = 0, ibufy = 0;
348         int event, stopped = FALSE, maxwinx, maxwiny;
349         short /*  c233 = FALSE, */ /*  yuvx = FALSE, */ once = FALSE, sstep = FALSE, wait2 = FALSE, /*  resetmap = FALSE, */ pause = 0;
350         short pingpong = FALSE, direction = 1, next = 1, turbo = FALSE, /*  doubleb = TRUE, */ noskip = FALSE;
351         int sizex, sizey, ofsx, ofsy, i;
352         /* This was done to disambiguate the name for use under c++. */
353         struct anim * anim = 0;
354         int start_x= 0, start_y= 0;
355         int sfra= -1;
356         int efra= -1;
357         int totblock;
358         
359         while (argc > 1) {
360                 if (argv[1][0] == '-'){
361                         switch(argv[1][1]) {
362                                 case 'm':
363                                         fromdisk = TRUE;
364                                         break;
365                                 case 'p':
366                                         if (argc>3) {
367                                                 start_x= atoi(argv[2]);
368                                                 start_y= atoi(argv[3]);
369                                                 argc-= 2; 
370                                                 argv+= 2;
371                                         } else {
372                                                 printf("too few arguments for -p (need 2): skipping\n");
373                                         }
374                                         break;
375                                 case 'f':
376                                         if (argc>3) {
377                                                 double fps = atof(argv[2]);
378                                                 double fps_base= atof(argv[3]);
379                                                 if (fps == 0) {
380                                                         fps = 1;
381                                                         printf("invalid fps,"
382                                                                "forcing 1\n");
383                                                 }
384                                                 swaptime = fps_base / fps;
385                                                 argc-= 2; 
386                                                 argv+= 2;
387                                         } else {
388                                                 printf("too few arguments for -f (need 2): skipping\n");
389                                         }
390                                         break;
391                                 case 's':
392                                         sfra= MIN2(MAXFRAME, MAX2(1, atoi(argv[2]) ));
393                                         argc--;
394                                         argv++;
395                                         break;
396                                 case 'e':
397                                         efra= MIN2(MAXFRAME, MAX2(1, atoi(argv[2]) ));
398                                         argc--;
399                                         argv++;
400                                         break;
401                                 case 'j':
402                                         fstep= MIN2(MAXFRAME, MAX2(1, atoi(argv[2])));
403                                         swaptime*= fstep;
404                                         argc--;
405                                         argv++;
406                                         break;
407                                 default:
408                                         printf("unknown option '%c': skipping\n", argv[1][1]);
409                                         break;
410                         }
411                         argc--;
412                         argv++;
413                 } else break;
414         }
415         
416 #ifdef WITH_QUICKTIME
417 #if defined (_WIN32) || defined (__APPLE__)
418         /* Initialize QuickTime */
419 #ifndef noErr
420 #define noErr 0
421 #endif
422
423 #ifdef _WIN32   
424         if (InitializeQTML(0) != noErr)
425                 G.have_quicktime = FALSE;
426         else
427                 G.have_quicktime = TRUE;
428 #endif /* _WIN32 */
429         if (EnterMovies() != noErr)
430                 G.have_quicktime = FALSE;
431         else
432 #endif /* _WIN32 || __APPLE__ */
433                 G.have_quicktime = TRUE;
434 #endif /* WITH_QUICKTIME */
435
436         if (argc > 1) strcpy(name,argv[1]);
437         else {
438                 BLI_getwdN(name);
439                 if (name[strlen(name)-1] != '/') strcat(name,"/");
440         }
441                 
442         if (IMB_isanim(name)) {
443                 anim = IMB_open_anim(name, IB_rect);
444                 if (anim) {
445                         ibuf = IMB_anim_absolute(anim, 0);
446                         IMB_close_anim(anim);
447                         anim = NULL;
448                 }
449         } else if (!IMB_ispic(name)) {
450                 exit(1);
451         }
452
453         if (ibuf == 0) ibuf = IMB_loadiffname(name, IB_rect);
454         if (ibuf == 0){
455                 printf("couldn't open %s\n",name);
456                 exit(1);
457         }
458         
459         #if !defined(WIN32) && !defined(__APPLE__)
460         if (fork()) exit(0);
461         #endif
462         
463         winlay_get_screensize(&maxwinx, &maxwiny);
464
465                 /* XXX, fixme zr */
466         {
467                 extern void add_to_mainqueue(Window *win, void *user_data, short evt, short val, char ascii);
468
469                 g_window = window_open("Blender:Anim", start_x, start_y, ibuf->x, ibuf->y, 0);
470                 window_set_handler(g_window, add_to_mainqueue, NULL);
471                 
472                 glMatrixMode(GL_PROJECTION);
473                 glLoadIdentity();
474                 glOrtho(0.0f, 1.0f, 0.0f, 1.0f, -1.0f, 1.0f);
475                 glMatrixMode(GL_MODELVIEW);
476         }
477
478         G.fonts= BMF_GetFont(BMF_kHelvetica10);
479         
480         ibufx = ibuf->x;
481         ibufy = ibuf->y;
482         
483         if (maxwinx % ibuf->x) maxwinx = ibuf->x * (1 + (maxwinx / ibuf->x));
484         if (maxwiny % ibuf->y) maxwiny = ibuf->y * (1 + (maxwiny / ibuf->y));
485         
486         glClearColor(0.0, 0.0, 0.0, 0.0);
487         glClear(GL_COLOR_BUFFER_BIT);
488         
489         window_swap_buffers(g_window);
490         
491         if (sfra == -1 || efra == -1) {
492                 /* one of the frames was invalid, just use all images */
493                 sfra = 1;
494                 efra = MAXFRAME;
495         }
496         
497         build_pict_list(name, (efra - sfra) + 1, fstep);
498         
499         for (i = 2; i < argc; i++){
500                 strcpy(name, argv[i]);
501                 build_pict_list(name, (efra - sfra) + 1, fstep);
502         }
503
504         IMB_freeImBuf(ibuf); 
505         ibuf = 0;
506
507         pupdate_time();
508         ptottime = 0;
509
510         while (go){
511                 if (pingpong) direction = -direction;
512
513                 if (direction == 1) picture = picsbase->first;
514                 else picture = picsbase->last;
515
516                 if (picture == 0){
517                         printf("couldn't find pictures\n");
518                         go = FALSE;
519                 }
520                 if (pingpong){
521                         if (direction == 1) picture = picture->next;
522                         else picture = picture->prev;
523                 }
524                 if (ptottime > 0.0) ptottime = 0.0;
525
526                 while (picture){
527                         if (ibuf != 0 && ibuf->type == 0) IMB_freeImBuf(ibuf);
528
529                         if (picture->ibuf) ibuf = picture->ibuf;
530                         else if (picture->anim) ibuf = IMB_anim_absolute(picture->anim, picture->frame);
531                         else if (picture->mem) ibuf = IMB_ibImageFromMemory((int *) picture->mem, picture->size, picture->IB_flags);
532                         else ibuf = IMB_loadiffname(picture->name, picture->IB_flags);
533                         
534                         if (ibuf){
535                                 strcpy(ibuf->name, picture->name);
536                                 
537 #ifdef _WIN32   
538                                 window_set_title(g_window, picture->name);
539 #endif
540
541                                 while (pupdate_time()) PIL_sleep_ms(1);
542                                 ptottime -= swaptime;
543                                 toscreen(picture, ibuf);
544                         } /* else deleten */
545                         else {
546                                 printf("error: can't play this image type\n");
547                                 exit(0);
548                         }
549                         
550                         if (once){
551                                 if (picture->next == 0) wait2 = TRUE;
552                                 else if (picture->prev == 0) wait2 = TRUE;
553                         }
554                         
555                         next = direction;
556                         
557                         while ((qtest() != 0 ) || ( wait2 != 0)){
558                                 if (wait2 && stopped) {
559                                         stopped = FALSE;
560                                 }
561                         
562                                 event = qreadN(&val);
563                                 /* printf("%d %d\n", event, val); */
564                                 
565                                 if (wait2){
566                                         pupdate_time();
567                                         ptottime = 0;
568                                 }
569                                 switch (event){
570                                 case AKEY:
571                                         if (val)
572                                                 noskip = !noskip;
573                                         break;
574                                 case PKEY:
575                                         if (val)
576                                                 pingpong = !pingpong;
577                                         break;
578                                 case SLASHKEY:
579                                         if (val) {
580                                                 if (qualN & SHIFT) {
581                                                         if (ibuf)
582                                                                 printf(" Name: %s | Speed: %.2f frames/s\n", ibuf->name, fstep / swaptime);
583                                                 } else {
584                                                         swaptime = fstep / 5.0;
585                                                 }
586                                         }
587                                         break;
588                                 case LEFTARROWKEY:
589                                         if (val){
590                                                 sstep = TRUE;
591                                                 wait2 = FALSE;
592                                                 if (qualN & SHIFT) {
593                                                         picture = picsbase->first;
594                                                         next = 0;
595                                                 } else {
596                                                         next = -1;
597                                                 }
598                                         }
599                                         break;
600                                 case DOWNARROWKEY:
601                                         if (val){
602                                                 wait2 = FALSE;
603                                                 if (qualN & SHIFT) {
604                                                         next = direction = -1;
605                                                 } else {
606                                                         next = -10;
607                                                         sstep = TRUE;
608                                                 }
609                                         }
610                                         break;
611                                 case RIGHTARROWKEY:
612                                         if (val){
613                                                 sstep = TRUE;
614                                                 wait2 = FALSE;
615                                                 if (qualN & SHIFT) {
616                                                         picture = picsbase->last;
617                                                         next = 0;
618                                                 } else {
619                                                         next = 1;
620                                                 }
621                                         }
622                                         break;
623                                 case UPARROWKEY:
624                                         if (val){
625                                                 wait2 = FALSE;
626                                                 if (qualN & SHIFT) {
627                                                         next = direction = 1;
628                                                 } else {
629                                                         next = 10;
630                                                         sstep = TRUE;
631                                                 }
632                                         }
633                                         break;
634                                 case LEFTMOUSE:
635                                 case MOUSEX:
636                                         if (qualN & LMOUSE) {
637                                                 window_get_size(g_window,&sizex,&sizey);
638                                                 picture = picsbase->first;
639                                                 i = 0;
640                                                 while (picture){
641                                                         i ++;
642                                                         picture = picture->next;
643                                                 }
644                                                 i = (i * val) / sizex;
645                                                 picture = picsbase->first;
646                                                 for (; i > 0; i--){
647                                                         if (picture->next == 0) break;
648                                                         picture = picture->next;
649                                                 }
650                                                 sstep = TRUE;
651                                                 wait2 = FALSE;
652                                                 next = 0;
653                                         }
654                                         break;
655                                         go= FALSE;
656                                         break;
657                                 case EQUALKEY:
658                                         if (val) {
659                                                 if (qualN & SHIFT) {
660                                                         pause ++;
661                                                         printf("pause:%d\n", pause);
662                                                 } else swaptime /= 1.1;
663                                         }
664                                         break;
665                                 case MINUSKEY:
666                                         if (val) {
667                                                 if (qualN & SHIFT) {
668                                                         pause --;
669                                                         printf("pause:%d\n", pause);
670                                                 } else swaptime *= 1.1;
671                                         }
672                                         break;
673                                 case PAD0:
674                                         if (val){
675                                                 if (once) once = wait2 = FALSE;
676                                                 else {
677                                                         picture = 0;
678                                                         once = TRUE;
679                                                         wait2 = FALSE;
680                                                 }
681                                         }
682                                         break;
683                                 case RETKEY:
684                                 case PADENTER:
685                                         if (val){
686                                                 wait2 = sstep = FALSE;
687                                         }
688                                         break;
689                                 case PADPERIOD:
690                                         if (val){
691                                                 if (sstep) wait2 = FALSE;
692                                                 else {
693                                                         sstep = TRUE;
694                                                         wait2 = !wait2;
695                                                 }
696                                         }
697                                         break;
698                                 case PAD1:
699                                         swaptime = fstep / 60.0;
700                                         break;
701                                 case PAD2:
702                                         swaptime = fstep / 50.0;
703                                         break;
704                                 case PAD3:
705                                         swaptime = fstep / 30.0;
706                                         break;
707                                 case PAD4:
708                                         if (qualN & SHIFT)
709                                                 swaptime = fstep / 24.0;
710                                         else
711                                                 swaptime = fstep / 25.0;
712                                         break;
713                                 case PAD5:
714                                         swaptime = fstep / 20.0;
715                                         break;
716                                 case PAD6:
717                                         swaptime = fstep / 15.0;
718                                         break;
719                                 case PAD7:
720                                         swaptime = fstep / 12.0;
721                                         break;
722                                 case PAD8:
723                                         swaptime = fstep / 10.0;
724                                         break;
725                                 case PAD9:
726                                         swaptime = fstep / 6.0;
727                                         break;
728                                 case PADPLUSKEY:
729                                         if (val == 0) break;
730                                         zoomx += 2.0;
731                                         zoomy += 2.0;
732                                 case PADMINUS:
733                                         if (val == 0) break;
734                                         if (zoomx > 1.0) zoomx -= 1.0;
735                                         if (zoomy > 1.0) zoomy -= 1.0;
736                                         window_get_position(g_window,&ofsx,&ofsy);
737                                         window_get_size(g_window,&sizex,&sizey);
738                                         ofsx += sizex/2;
739                                         ofsy += sizey/2;
740                                         sizex = zoomx * ibufx;
741                                         sizey = zoomy * ibufy;
742                                         ofsx -= sizex/2;
743                                         ofsy -= sizey/2;
744 /*                                      window_set_position(g_window,sizex,sizey); */
745                                         window_set_size(g_window,sizex,sizey);
746                                         break;
747                                 case RESHAPE:
748                                 case REDRAW:
749                                         window_get_size(g_window,&sizex,&sizey);
750                                         window_make_active(g_window);
751                                         
752                                         glViewport(0,  0, sizex, sizey);
753                                         glScissor(0,  0, sizex, sizey);
754
755                                         zoomx = (float) sizex / ibufx;
756                                         zoomy = (float) sizey / ibufy;
757                                         zoomx = floor(zoomx + 0.5);
758                                         zoomy = floor(zoomy + 0.5);
759                                         if (zoomx < 1.0) zoomx = 1.0;
760                                         if (zoomy < 1.0) zoomy = 1.0;
761
762                                         sizex = zoomx * ibufx;
763                                         sizey = zoomy * ibufy;
764
765                                         glPixelZoom(zoomx, zoomy);
766                                         glEnable(GL_DITHER);
767                                         ptottime = 0.0;
768                                         toscreen(picture, ibuf);
769                                         while (qtest()) qreadN(&val);
770                                         
771                                         break;
772                                 case ESCKEY:
773                                 case WINCLOSE:
774                                 case WINQUIT:
775                                         go = FALSE;
776                                         break;
777                                 }
778                                 if (go == FALSE) break;
779                         }
780                         
781                         wait2 = sstep;
782                         
783                         if (wait2 == 0 && stopped == 0) {
784                                 stopped = TRUE;
785                         }
786
787                         pupdate_time();
788                                         
789                         if (picture && next) {
790                                 /* always at least set one step */
791                                 while (picture){
792                                         if (next < 0) picture = picture->prev;
793                                         else picture = picture->next;
794         
795                                         if (once && picture != 0){
796                                                 if (picture->next == 0) wait2 = TRUE;
797                                                 else if (picture->prev == 0) wait2 = TRUE;
798                                         }
799
800                                         if (wait2 || ptottime < swaptime || turbo || noskip) break;
801                                         ptottime -= swaptime;
802                                 }
803                                 if (picture == 0 && sstep) {
804                                         if (next < 0) picture = picsbase->last;
805                                         else if (next > 0) picture = picsbase->first;                                                                   
806                                 }
807                         }
808                         if (go == FALSE) break;
809                 }
810         }
811         picture = picsbase->first;
812         anim = NULL;
813         while (picture) {
814                 if (picture && picture->anim && (anim != picture->anim)) {
815                         // to prevent divx crashes
816                         anim = picture->anim;
817                         IMB_close_anim(anim);
818                 }
819                 if(picture->ibuf) IMB_freeImBuf(picture->ibuf);
820                 if(picture->mem) MEM_freeN(picture->mem);
821                 
822                 picture = picture->next;
823         }
824 #ifdef WITH_QUICKTIME
825 #if defined (_WIN32) || defined (__APPLE__)
826         if(G.have_quicktime) {
827                 ExitMovies();
828 #ifdef _WIN32
829                 TerminateQTML();
830 #endif /* _WIN32 */
831         }
832 #endif /* _WIN32 || __APPLE__ */
833 #endif /* WITH_QUICKTIME */
834
835         /* cleanup */
836         if(ibuf) IMB_freeImBuf(ibuf); 
837         BLI_freelistN(picsbase);
838         free_blender();
839         window_destroy(g_window);
840
841         totblock= MEM_get_memory_blocks_in_use();
842         if(totblock!=0) {
843                 printf("Error Totblock: %d\n",totblock);
844                 MEM_printmemlist();
845         }
846 }
847
848 #endif
849
850 void playanim(int argc, const char **argv)
851 {
852         (void)argc;
853         (void)argv;
854 }