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