Color Management, Stage 2: Switch color pipeline to use OpenColorIO
[blender.git] / source / blender / windowmanager / intern / wm_playanim.c
index 273fda00be4d2fb53e86baa5f76d496d583b19f2..bff40faf1d1cbc87de73f98858a37107712cc801 100644 (file)
@@ -36,6 +36,7 @@
 #include <fcntl.h>
 #include <stdlib.h>
 #include <string.h>
 #include <fcntl.h>
 #include <stdlib.h>
 #include <string.h>
+#include <math.h>
 
 #ifndef WIN32
 #  include <unistd.h>
 
 #ifndef WIN32
 #  include <unistd.h>
 
 #include "PIL_time.h"
 
 
 #include "PIL_time.h"
 
-#include <math.h>
-
-#include "BLI_blenlib.h"
-#include "BLI_math.h"
+#include "BLI_fileops.h"
+#include "BLI_listbase.h"
+#include "BLI_path_util.h"
+#include "BLI_rect.h"
+#include "BLI_string.h"
+#include "BLI_utildefines.h"
 
 #include "IMB_imbuf_types.h"
 #include "IMB_imbuf.h"
 
 #include "BKE_blender.h"
 #include "BKE_global.h"
 
 #include "IMB_imbuf_types.h"
 #include "IMB_imbuf.h"
 
 #include "BKE_blender.h"
 #include "BKE_global.h"
-#include "BKE_utildefines.h"
 
 #include "BIF_gl.h"
 #include "BIF_glutil.h"
 
 
 #include "BIF_gl.h"
 #include "BIF_glutil.h"
 
-#ifdef WITH_QUICKTIME
-#  ifdef _WIN32
-#    include <QTML.h>
-#    include <Movies.h>
-#  elif defined(__APPLE__)
-#    include <QuickTime/Movies.h>
-#  endif /* __APPLE__ */
-#endif /* WITH_QUICKTIME */
-
 #include "DNA_scene_types.h"
 #include "DNA_scene_types.h"
-#include "BLI_utildefines.h"
 #include "ED_datafiles.h" /* for fonts */
 #include "ED_datafiles.h" /* for fonts */
-#include "wm_event_types.h"
 #include "GHOST_C-api.h"
 #include "BLF_api.h"
 
 #include "GHOST_C-api.h"
 #include "BLF_api.h"
 
-#define WINCLOSE -1
-#define REDRAW -3
-#define RESHAPE -2
-#define WINQUIT -4
+#include "wm_event_types.h"
+
+#include "WM_api.h"  /* only for WM_main_playanim */
 
 
-/* use */
 typedef struct PlayState {
 typedef struct PlayState {
+
+       /* playback state */
        short direction;
        short next;
        short once;
        short direction;
        short next;
        short once;
@@ -98,6 +89,7 @@ typedef struct PlayState {
        short stopped;
        short go;
 
        short stopped;
        short go;
 
+       /* current picture */
        struct PlayAnimPict *picture;
 
        /* set once at the start */
        struct PlayAnimPict *picture;
 
        /* set once at the start */
@@ -108,31 +100,53 @@ typedef struct PlayState {
        struct ImBuf *curframe_ibuf;
 } PlayState;
 
        struct ImBuf *curframe_ibuf;
 } PlayState;
 
-/* ***************** gl_util.c ****************** */
-
-static GHOST_SystemHandle g_system = NULL;
-static void *g_window = NULL;
-
-static int qualN = 0;
-
-#define LSHIFT  (1 << 0)
-#define RSHIFT  (1 << 1)
-#define SHIFT   (LSHIFT | RSHIFT)
-#define LALT    (1 << 2)
-#define RALT    (1 << 3)
-#define ALT (LALT | RALT)
-#define LCTRL   (1 << 4)
-#define RCTRL   (1 << 5)
-#define LMOUSE  (1 << 16)
-#define MMOUSE  (1 << 17)
-#define RMOUSE  (1 << 18)
-#define MOUSE   (LMOUSE | MMOUSE | RMOUSE)
-
-unsigned short screen_qread(short *val, char *ascii);
+/* for debugging */
+#if 0
+void print_ps(PlayState *ps)
+{
+       printf("ps:\n");
+       printf("    direction=%d,\n", (int)ps->direction);
+       printf("    next=%d,\n", ps->next);
+       printf("    once=%d,\n", ps->once);
+       printf("    turbo=%d,\n", ps->turbo);
+       printf("    pingpong=%d,\n", ps->pingpong);
+       printf("    noskip=%d,\n", ps->noskip);
+       printf("    sstep=%d,\n", ps->sstep);
+       printf("    pause=%d,\n", ps->pause);
+       printf("    wait2=%d,\n", ps->wait2);
+       printf("    stopped=%d,\n", ps->stopped);
+       printf("    go=%d,\n\n", ps->go);
+       fflush(stdout);
+}
+#endif
 
 
-void playanim_window_get_size(int *width_r, int *height_r)
+/* global for window and events */
+typedef enum eWS_Qual {
+       WS_QUAL_LSHIFT  = (1 << 0),
+       WS_QUAL_RSHIFT  = (1 << 1),
+       WS_QUAL_SHIFT   = (WS_QUAL_LSHIFT | WS_QUAL_RSHIFT),
+       WS_QUAL_LALT    = (1 << 2),
+       WS_QUAL_RALT    = (1 << 3),
+       WS_QUAL_ALT     = (WS_QUAL_LALT | WS_QUAL_RALT),
+       WS_QUAL_LCTRL   = (1 << 4),
+       WS_QUAL_RCTRL   = (1 << 5),
+       WS_QUAL_LMOUSE  = (1 << 16),
+       WS_QUAL_MMOUSE  = (1 << 17),
+       WS_QUAL_RMOUSE  = (1 << 18),
+       WS_QUAL_MOUSE   = (WS_QUAL_LMOUSE | WS_QUAL_MMOUSE | WS_QUAL_RMOUSE)
+} eWS_Qual;
+
+static struct WindowStateGlobal {
+       GHOST_SystemHandle ghost_system;
+       void *ghost_window;
+
+       /* events */
+       eWS_Qual qual;
+} g_WS = {NULL};
+
+static void playanim_window_get_size(int *width_r, int *height_r)
 {
 {
-       GHOST_RectangleHandle bounds = GHOST_GetClientBounds(g_window);
+       GHOST_RectangleHandle bounds = GHOST_GetClientBounds(g_WS.ghost_window);
        *width_r = GHOST_GetWidthRectangle(bounds);
        *height_r = GHOST_GetHeightRectangle(bounds);
        GHOST_DisposeRectangle(bounds);
        *width_r = GHOST_GetWidthRectangle(bounds);
        *height_r = GHOST_GetHeightRectangle(bounds);
        GHOST_DisposeRectangle(bounds);
@@ -144,46 +158,46 @@ static void playanim_event_qual_update(void)
        int val;
 
        /* Shift */
        int val;
 
        /* Shift */
-       GHOST_GetModifierKeyState(g_system, GHOST_kModifierKeyLeftShift, &val);
-       if (val) qualN |=  LSHIFT;
-       else     qualN &= ~LSHIFT;
+       GHOST_GetModifierKeyState(g_WS.ghost_system, GHOST_kModifierKeyLeftShift, &val);
+       if (val) g_WS.qual |=  WS_QUAL_LSHIFT;
+       else     g_WS.qual &= ~WS_QUAL_LSHIFT;
 
 
-       GHOST_GetModifierKeyState(g_system, GHOST_kModifierKeyRightShift, &val);
-       if (val) qualN |=  RSHIFT;
-       else     qualN &= ~RSHIFT;
+       GHOST_GetModifierKeyState(g_WS.ghost_system, GHOST_kModifierKeyRightShift, &val);
+       if (val) g_WS.qual |=  WS_QUAL_RSHIFT;
+       else     g_WS.qual &= ~WS_QUAL_RSHIFT;
 
        /* Control */
 
        /* Control */
-       GHOST_GetModifierKeyState(g_system, GHOST_kModifierKeyLeftControl, &val);
-       if (val) qualN |=  LCTRL;
-       else     qualN &= ~LCTRL;
+       GHOST_GetModifierKeyState(g_WS.ghost_system, GHOST_kModifierKeyLeftControl, &val);
+       if (val) g_WS.qual |=  WS_QUAL_LCTRL;
+       else     g_WS.qual &= ~WS_QUAL_LCTRL;
 
 
-       GHOST_GetModifierKeyState(g_system, GHOST_kModifierKeyRightControl, &val);
-       if (val) qualN |=  RCTRL;
-       else     qualN &= ~RCTRL;
+       GHOST_GetModifierKeyState(g_WS.ghost_system, GHOST_kModifierKeyRightControl, &val);
+       if (val) g_WS.qual |=  WS_QUAL_RCTRL;
+       else     g_WS.qual &= ~WS_QUAL_RCTRL;
 
        /* Alt */
 
        /* Alt */
-       GHOST_GetModifierKeyState(g_system, GHOST_kModifierKeyLeftAlt, &val);
-       if (val) qualN |=  LCTRL;
-       else     qualN &= ~LCTRL;
+       GHOST_GetModifierKeyState(g_WS.ghost_system, GHOST_kModifierKeyLeftAlt, &val);
+       if (val) g_WS.qual |=  WS_QUAL_LCTRL;
+       else     g_WS.qual &= ~WS_QUAL_LCTRL;
 
 
-       GHOST_GetModifierKeyState(g_system, GHOST_kModifierKeyRightAlt, &val);
-       if (val) qualN |=  RCTRL;
-       else     qualN &= ~RCTRL;
+       GHOST_GetModifierKeyState(g_WS.ghost_system, GHOST_kModifierKeyRightAlt, &val);
+       if (val) g_WS.qual |=  WS_QUAL_RCTRL;
+       else     g_WS.qual &= ~WS_QUAL_RCTRL;
 
        /* LMB */
 
        /* LMB */
-       GHOST_GetButtonState(g_system, GHOST_kButtonMaskLeft, &val);
-       if (val) qualN |=  LMOUSE;
-       else     qualN &= ~LMOUSE;
+       GHOST_GetButtonState(g_WS.ghost_system, GHOST_kButtonMaskLeft, &val);
+       if (val) g_WS.qual |=  WS_QUAL_LMOUSE;
+       else     g_WS.qual &= ~WS_QUAL_LMOUSE;
 
        /* MMB */
 
        /* MMB */
-       GHOST_GetButtonState(g_system, GHOST_kButtonMaskMiddle, &val);
-       if (val) qualN |=  MMOUSE;
-       else     qualN &= ~MMOUSE;
+       GHOST_GetButtonState(g_WS.ghost_system, GHOST_kButtonMaskMiddle, &val);
+       if (val) g_WS.qual |=  WS_QUAL_MMOUSE;
+       else     g_WS.qual &= ~WS_QUAL_MMOUSE;
 
        /* RMB */
 
        /* RMB */
-       GHOST_GetButtonState(g_system, GHOST_kButtonMaskRight, &val);
-       if (val) qualN |=  RMOUSE;
-       else     qualN &= ~RMOUSE;
+       GHOST_GetButtonState(g_WS.ghost_system, GHOST_kButtonMaskRight, &val);
+       if (val) g_WS.qual |=  WS_QUAL_RMOUSE;
+       else     g_WS.qual &= ~WS_QUAL_RMOUSE;
 }
 
 typedef struct PlayAnimPict {
 }
 
 typedef struct PlayAnimPict {
@@ -197,8 +211,7 @@ typedef struct PlayAnimPict {
        int IB_flags;
 } PlayAnimPict;
 
        int IB_flags;
 } PlayAnimPict;
 
-static struct ListBase _picsbase = {NULL, NULL};
-static struct ListBase *picsbase = &_picsbase;
+static struct ListBase picsbase = {NULL, NULL};
 static int fromdisk = FALSE;
 static int fstep = 1;
 static float zoomx = 1.0, zoomy = 1.0;
 static int fromdisk = FALSE;
 static int fstep = 1;
 static float zoomx = 1.0, zoomy = 1.0;
@@ -216,7 +229,7 @@ static int pupdate_time(void)
        return (ptottime < 0);
 }
 
        return (ptottime < 0);
 }
 
-static void toscreen(PlayAnimPict *picture, struct ImBuf *ibuf, int fontid)
+static void playanim_toscreen(PlayAnimPict *picture, struct ImBuf *ibuf, int fontid)
 {
 
        if (ibuf == NULL) {
 {
 
        if (ibuf == NULL) {
@@ -230,7 +243,7 @@ static void toscreen(PlayAnimPict *picture, struct ImBuf *ibuf, int fontid)
        if (ibuf->rect == NULL)
                return;
 
        if (ibuf->rect == NULL)
                return;
 
-       GHOST_ActivateWindowDrawingContext(g_window);
+       GHOST_ActivateWindowDrawingContext(g_WS.ghost_window);
 
        glRasterPos2f(0.0f, 0.0f);
 
 
        glRasterPos2f(0.0f, 0.0f);
 
@@ -238,14 +251,12 @@ static void toscreen(PlayAnimPict *picture, struct ImBuf *ibuf, int fontid)
 
        pupdate_time();
 
 
        pupdate_time();
 
-       if (picture && (qualN & (SHIFT | LMOUSE)) && (fontid != -1)) {
+       if (picture && (g_WS.qual & (WS_QUAL_SHIFT | WS_QUAL_LMOUSE)) && (fontid != -1)) {
                int sizex, sizey;
                float fsizex_inv, fsizey_inv;
                char str[32 + FILE_MAX];
                cpack(-1);
                int sizex, sizey;
                float fsizex_inv, fsizey_inv;
                char str[32 + FILE_MAX];
                cpack(-1);
-//             glRasterPos2f(0.02f, 0.03f);
                BLI_snprintf(str, sizeof(str), "%s | %.2f frames/s", picture->name, fstep / swaptime);
                BLI_snprintf(str, sizeof(str), "%s | %.2f frames/s", picture->name, fstep / swaptime);
-//             BMF_DrawString(font, str);
 
                playanim_window_get_size(&sizex, &sizey);
                fsizex_inv = 1.0f / sizex;
 
                playanim_window_get_size(&sizex, &sizey);
                fsizex_inv = 1.0f / sizex;
@@ -254,11 +265,10 @@ static void toscreen(PlayAnimPict *picture, struct ImBuf *ibuf, int fontid)
                BLF_enable(fontid, BLF_ASPECT);
                BLF_aspect(fontid, fsizex_inv, fsizey_inv, 1.0f);
                BLF_position(fontid, 10.0f * fsizex_inv, 10.0f * fsizey_inv, 0.0f);
                BLF_enable(fontid, BLF_ASPECT);
                BLF_aspect(fontid, fsizex_inv, fsizey_inv, 1.0f);
                BLF_position(fontid, 10.0f * fsizex_inv, 10.0f * fsizey_inv, 0.0f);
-               BLF_draw(fontid, str, 256); // XXX
-               // printf("Drawing text '%s'\n", str);
+               BLF_draw(fontid, str, sizeof(str));
        }
 
        }
 
-       GHOST_SwapWindowBuffers(g_window);
+       GHOST_SwapWindowBuffers(g_WS.ghost_window);
 }
 
 static void build_pict_list(char *first, int totframes, int fstep, int fontid)
 }
 
 static void build_pict_list(char *first, int totframes, int fstep, int fontid)
@@ -271,12 +281,13 @@ static void build_pict_list(char *first, int totframes, int fstep, int fontid)
        struct anim *anim;
 
        if (IMB_isanim(first)) {
        struct anim *anim;
 
        if (IMB_isanim(first)) {
-               anim = IMB_open_anim(first, IB_rect, 0);
+               /* OCIO_TODO: support different input color space */
+               anim = IMB_open_anim(first, IB_rect, 0, NULL);
                if (anim) {
                        int pic;
                        ibuf = IMB_anim_absolute(anim, 0, IMB_TC_NONE, IMB_PROXY_NONE);
                        if (ibuf) {
                if (anim) {
                        int pic;
                        ibuf = IMB_anim_absolute(anim, 0, IMB_TC_NONE, IMB_PROXY_NONE);
                        if (ibuf) {
-                               toscreen(NULL, ibuf, fontid);
+                               playanim_toscreen(NULL, ibuf, fontid);
                                IMB_freeImBuf(ibuf);
                        }
 
                                IMB_freeImBuf(ibuf);
                        }
 
@@ -287,7 +298,7 @@ static void build_pict_list(char *first, int totframes, int fstep, int fontid)
                                picture->IB_flags = IB_rect;
                                BLI_snprintf(str, sizeof(str), "%s : %4.d", first, pic + 1);
                                picture->name = strdup(str);
                                picture->IB_flags = IB_rect;
                                BLI_snprintf(str, sizeof(str), "%s : %4.d", first, pic + 1);
                                picture->name = strdup(str);
-                               BLI_addtail(picsbase, picture);
+                               BLI_addtail(&picsbase, picture);
                        }
                }
                else {
                        }
                }
                else {
@@ -318,10 +329,14 @@ static void build_pict_list(char *first, int totframes, int fstep, int fontid)
                        int file;
 
                        file = open(filepath, O_BINARY | O_RDONLY, 0);
                        int file;
 
                        file = open(filepath, O_BINARY | O_RDONLY, 0);
-                       if (file < 0) return;
+                       if (file < 0) {
+                               /* print errno? */
+                               return;
+                       }
+
                        picture = (PlayAnimPict *)MEM_callocN(sizeof(PlayAnimPict), "picture");
                        if (picture == NULL) {
                        picture = (PlayAnimPict *)MEM_callocN(sizeof(PlayAnimPict), "picture");
                        if (picture == NULL) {
-                               printf("Not enough memory for pict struct \n");
+                               printf("Not enough memory for pict struct '%s'\n", filepath);
                                close(file);
                                return;
                        }
                                close(file);
                                return;
                        }
@@ -360,21 +375,22 @@ static void build_pict_list(char *first, int totframes, int fstep, int fontid)
                        picture->mem = mem;
                        picture->name = strdup(filepath);
                        close(file);
                        picture->mem = mem;
                        picture->name = strdup(filepath);
                        close(file);
-                       BLI_addtail(picsbase, picture);
+                       BLI_addtail(&picsbase, picture);
                        count++;
 
                        pupdate_time();
 
                        if (ptottime > 1.0) {
                        count++;
 
                        pupdate_time();
 
                        if (ptottime > 1.0) {
+                               /* OCIO_TODO: support different input color space */
                                if (picture->mem) {
                                        ibuf = IMB_ibImageFromMemory((unsigned char *)picture->mem, picture->size,
                                if (picture->mem) {
                                        ibuf = IMB_ibImageFromMemory((unsigned char *)picture->mem, picture->size,
-                                                                    picture->IB_flags, picture->name);
+                                                                    picture->IB_flags, NULL, picture->name);
                                }
                                else {
                                }
                                else {
-                                       ibuf = IMB_loadiffname(picture->name, picture->IB_flags);
+                                       ibuf = IMB_loadiffname(picture->name, picture->IB_flags, NULL);
                                }
                                if (ibuf) {
                                }
                                if (ibuf) {
-                                       toscreen(picture, ibuf, fontid);
+                                       playanim_toscreen(picture, ibuf, fontid);
                                        IMB_freeImBuf(ibuf);
                                }
                                pupdate_time();
                                        IMB_freeImBuf(ibuf);
                                }
                                pupdate_time();
@@ -401,10 +417,11 @@ static void build_pict_list(char *first, int totframes, int fstep, int fontid)
 static int ghost_event_proc(GHOST_EventHandle evt, GHOST_TUserDataPtr ps_void)
 {
        PlayState *ps = (PlayState *)ps_void;
 static int ghost_event_proc(GHOST_EventHandle evt, GHOST_TUserDataPtr ps_void)
 {
        PlayState *ps = (PlayState *)ps_void;
-
        GHOST_TEventType type = GHOST_GetEventType(evt);
        int val;
 
        GHOST_TEventType type = GHOST_GetEventType(evt);
        int val;
 
+       // print_ps(ps);
+
        playanim_event_qual_update();
 
        /* convert ghost event into value keyboard or mouse */
        playanim_event_qual_update();
 
        /* convert ghost event into value keyboard or mouse */
@@ -438,7 +455,7 @@ static int ghost_event_proc(GHOST_EventHandle evt, GHOST_TUserDataPtr ps_void)
                                        if (val) swaptime = fstep / 30.0;
                                        break;
                                case GHOST_kKeyNumpad4:
                                        if (val) swaptime = fstep / 30.0;
                                        break;
                                case GHOST_kKeyNumpad4:
-                                       if (qualN & SHIFT)
+                                       if (g_WS.qual & WS_QUAL_SHIFT)
                                                swaptime = fstep / 24.0;
                                        else
                                                swaptime = fstep / 25.0;
                                                swaptime = fstep / 24.0;
                                        else
                                                swaptime = fstep / 25.0;
@@ -462,8 +479,8 @@ static int ghost_event_proc(GHOST_EventHandle evt, GHOST_TUserDataPtr ps_void)
                                        if (val) {
                                                ps->sstep = TRUE;
                                                ps->wait2 = FALSE;
                                        if (val) {
                                                ps->sstep = TRUE;
                                                ps->wait2 = FALSE;
-                                               if (qualN & SHIFT) {
-                                                       ps->picture = picsbase->first;
+                                               if (g_WS.qual & WS_QUAL_SHIFT) {
+                                                       ps->picture = picsbase.first;
                                                        ps->next = 0;
                                                }
                                                else {
                                                        ps->next = 0;
                                                }
                                                else {
@@ -474,7 +491,7 @@ static int ghost_event_proc(GHOST_EventHandle evt, GHOST_TUserDataPtr ps_void)
                                case GHOST_kKeyDownArrow:
                                        if (val) {
                                                ps->wait2 = FALSE;
                                case GHOST_kKeyDownArrow:
                                        if (val) {
                                                ps->wait2 = FALSE;
-                                               if (qualN & SHIFT) {
+                                               if (g_WS.qual & WS_QUAL_SHIFT) {
                                                        ps->next = ps->direction = -1;
                                                }
                                                else {
                                                        ps->next = ps->direction = -1;
                                                }
                                                else {
@@ -487,8 +504,8 @@ static int ghost_event_proc(GHOST_EventHandle evt, GHOST_TUserDataPtr ps_void)
                                        if (val) {
                                                ps->sstep = TRUE;
                                                ps->wait2 = FALSE;
                                        if (val) {
                                                ps->sstep = TRUE;
                                                ps->wait2 = FALSE;
-                                               if (qualN & SHIFT) {
-                                                       ps->picture = picsbase->last;
+                                               if (g_WS.qual & WS_QUAL_SHIFT) {
+                                                       ps->picture = picsbase.last;
                                                        ps->next = 0;
                                                }
                                                else {
                                                        ps->next = 0;
                                                }
                                                else {
@@ -499,7 +516,7 @@ static int ghost_event_proc(GHOST_EventHandle evt, GHOST_TUserDataPtr ps_void)
                                case GHOST_kKeyUpArrow:
                                        if (val) {
                                                ps->wait2 = FALSE;
                                case GHOST_kKeyUpArrow:
                                        if (val) {
                                                ps->wait2 = FALSE;
-                                               if (qualN & SHIFT) {
+                                               if (g_WS.qual & WS_QUAL_SHIFT) {
                                                        ps->next = ps->direction = 1;
                                                }
                                                else {
                                                        ps->next = ps->direction = 1;
                                                }
                                                else {
@@ -512,7 +529,7 @@ static int ghost_event_proc(GHOST_EventHandle evt, GHOST_TUserDataPtr ps_void)
                                case GHOST_kKeySlash:
                                case GHOST_kKeyNumpadSlash:
                                        if (val) {
                                case GHOST_kKeySlash:
                                case GHOST_kKeyNumpadSlash:
                                        if (val) {
-                                               if (qualN & SHIFT) {
+                                               if (g_WS.qual & WS_QUAL_SHIFT) {
                                                        if (ps->curframe_ibuf)
                                                                printf(" Name: %s | Speed: %.2f frames/s\n", ps->curframe_ibuf->name, fstep / swaptime);
                                                }
                                                        if (ps->curframe_ibuf)
                                                                printf(" Name: %s | Speed: %.2f frames/s\n", ps->curframe_ibuf->name, fstep / swaptime);
                                                }
@@ -523,7 +540,7 @@ static int ghost_event_proc(GHOST_EventHandle evt, GHOST_TUserDataPtr ps_void)
                                        break;
                                case GHOST_kKeyEqual:
                                        if (val) {
                                        break;
                                case GHOST_kKeyEqual:
                                        if (val) {
-                                               if (qualN & SHIFT) {
+                                               if (g_WS.qual & WS_QUAL_SHIFT) {
                                                        ps->pause++;
                                                        printf("pause:%d\n", ps->pause);
                                                }
                                                        ps->pause++;
                                                        printf("pause:%d\n", ps->pause);
                                                }
@@ -534,7 +551,7 @@ static int ghost_event_proc(GHOST_EventHandle evt, GHOST_TUserDataPtr ps_void)
                                        break;
                                case GHOST_kKeyMinus:
                                        if (val) {
                                        break;
                                case GHOST_kKeyMinus:
                                        if (val) {
-                                               if (qualN & SHIFT) {
+                                               if (g_WS.qual & WS_QUAL_SHIFT) {
                                                        ps->pause--;
                                                        printf("pause:%d\n", ps->pause);
                                                }
                                                        ps->pause--;
                                                        printf("pause:%d\n", ps->pause);
                                                }
@@ -591,8 +608,8 @@ static int ghost_event_proc(GHOST_EventHandle evt, GHOST_TUserDataPtr ps_void)
                                        sizey = zoomy * ps->ibufy;
                                        /* ofsx -= sizex / 2; */ /* UNUSED */
                                        /* ofsy -= sizey / 2; */ /* UNUSED */
                                        sizey = zoomy * ps->ibufy;
                                        /* ofsx -= sizex / 2; */ /* UNUSED */
                                        /* ofsy -= sizey / 2; */ /* UNUSED */
-                                       // window_set_position(g_window,sizex,sizey);
-                                       GHOST_SetClientSize(g_window, sizex, sizey);
+                                       // window_set_position(g_WS.ghost_window,sizex,sizey);
+                                       GHOST_SetClientSize(g_WS.ghost_window, sizex, sizey);
                                        break;
                                }
                                case GHOST_kKeyEsc:
                                        break;
                                }
                                case GHOST_kKeyEsc:
@@ -605,17 +622,17 @@ static int ghost_event_proc(GHOST_EventHandle evt, GHOST_TUserDataPtr ps_void)
                }
                case GHOST_kEventCursorMove:
                {
                }
                case GHOST_kEventCursorMove:
                {
-                       if (qualN & LMOUSE) {
+                       if (g_WS.qual & WS_QUAL_LMOUSE) {
                                int sizex, sizey;
                                int i;
 
                                GHOST_TEventCursorData *cd = GHOST_GetEventData(evt);
                                int cx, cy;
 
                                int sizex, sizey;
                                int i;
 
                                GHOST_TEventCursorData *cd = GHOST_GetEventData(evt);
                                int cx, cy;
 
-                               GHOST_ScreenToClient(g_window, cd->x, cd->y, &cx, &cy);
+                               GHOST_ScreenToClient(g_WS.ghost_window, cd->x, cd->y, &cx, &cy);
 
                                playanim_window_get_size(&sizex, &sizey);
 
                                playanim_window_get_size(&sizex, &sizey);
-                               ps->picture = picsbase->first;
+                               ps->picture = picsbase.first;
                                /* TODO - store in ps direct? */
                                i = 0;
                                while (ps->picture) {
                                /* TODO - store in ps direct? */
                                i = 0;
                                while (ps->picture) {
@@ -623,7 +640,7 @@ static int ghost_event_proc(GHOST_EventHandle evt, GHOST_TUserDataPtr ps_void)
                                        ps->picture = ps->picture->next;
                                }
                                i = (i * cx) / sizex;
                                        ps->picture = ps->picture->next;
                                }
                                i = (i * cx) / sizex;
-                               ps->picture = picsbase->first;
+                               ps->picture = picsbase.first;
                                for (; i > 0; i--) {
                                        if (ps->picture->next == NULL) break;
                                        ps->picture = ps->picture->next;
                                for (; i > 0; i--) {
                                        if (ps->picture->next == NULL) break;
                                        ps->picture = ps->picture->next;
@@ -640,7 +657,7 @@ static int ghost_event_proc(GHOST_EventHandle evt, GHOST_TUserDataPtr ps_void)
                        int sizex, sizey;
 
                        playanim_window_get_size(&sizex, &sizey);
                        int sizex, sizey;
 
                        playanim_window_get_size(&sizex, &sizey);
-                       GHOST_ActivateWindowDrawingContext(g_window);
+                       GHOST_ActivateWindowDrawingContext(g_WS.ghost_window);
 
                        glViewport(0, 0, sizex, sizey);
                        glScissor(0, 0, sizex, sizey);
 
                        glViewport(0, 0, sizex, sizey);
                        glScissor(0, 0, sizex, sizey);
@@ -658,8 +675,7 @@ static int ghost_event_proc(GHOST_EventHandle evt, GHOST_TUserDataPtr ps_void)
                        glPixelZoom(zoomx, zoomy);
                        glEnable(GL_DITHER);
                        ptottime = 0.0;
                        glPixelZoom(zoomx, zoomy);
                        glEnable(GL_DITHER);
                        ptottime = 0.0;
-                       toscreen(ps->picture, ps->curframe_ibuf, ps->fontid);
-                       //XXX25                         while (qtest()) qreadN(&val);
+                       playanim_toscreen(ps->picture, ps->curframe_ibuf, ps->fontid);
 
                        break;
                }
 
                        break;
                }
@@ -677,12 +693,12 @@ static int ghost_event_proc(GHOST_EventHandle evt, GHOST_TUserDataPtr ps_void)
        return 1;
 }
 
        return 1;
 }
 
-void playanim_window_open(const char *title, int posx, int posy, int sizex, int sizey, int start_maximized)
+static void playanim_window_open(const char *title, int posx, int posy, int sizex, int sizey, int start_maximized)
 {
        GHOST_TWindowState inital_state;
        GHOST_TUns32 scr_w, scr_h;
 
 {
        GHOST_TWindowState inital_state;
        GHOST_TUns32 scr_w, scr_h;
 
-       GHOST_GetMainDisplayDimensions(g_system, &scr_w, &scr_h);
+       GHOST_GetMainDisplayDimensions(g_WS.ghost_system, &scr_w, &scr_h);
 
        posy = (scr_h - posy - sizey);
 
 
        posy = (scr_h - posy - sizey);
 
@@ -690,31 +706,25 @@ void playanim_window_open(const char *title, int posx, int posy, int sizex, int
                inital_state = start_maximized ? GHOST_kWindowStateFullScreen : GHOST_kWindowStateNormal;
        else
                inital_state = start_maximized ? GHOST_kWindowStateMaximized : GHOST_kWindowStateNormal;
                inital_state = start_maximized ? GHOST_kWindowStateFullScreen : GHOST_kWindowStateNormal;
        else
                inital_state = start_maximized ? GHOST_kWindowStateMaximized : GHOST_kWindowStateNormal;
-#if defined(__APPLE__) && !defined(GHOST_COCOA)
-       {
-               extern int macPrefState; /* creator.c */
-               initial_state += macPrefState;
-       }
-#endif
 
 
-       g_window = GHOST_CreateWindow(g_system,
-                                     title,
-                                     posx, posy, sizex, sizey,
-                                     inital_state,
-                                     GHOST_kDrawingContextTypeOpenGL,
-                                     FALSE /* no stereo */, FALSE);
+       g_WS.ghost_window = GHOST_CreateWindow(g_WS.ghost_system,
+                                              title,
+                                              posx, posy, sizex, sizey,
+                                              inital_state,
+                                              GHOST_kDrawingContextTypeOpenGL,
+                                              FALSE /* no stereo */, FALSE);
 
        //if (ghostwin) {
        //if (win) {
        // GHOST_SetWindowUserData(ghostwin, win);
        //} else {
 
        //if (ghostwin) {
        //if (win) {
        // GHOST_SetWindowUserData(ghostwin, win);
        //} else {
-       //      GHOST_DisposeWindow(g_system, ghostwin);
+       //      GHOST_DisposeWindow(g_WS.ghost_system, ghostwin);
        //}
        //}
 }
 
 
        //}
        //}
 }
 
 
-void playanim(int argc, const char **argv)
+void WM_main_playanim(int argc, const char **argv)
 {
        struct ImBuf *ibuf = NULL;
        char filepath[FILE_MAX];
 {
        struct ImBuf *ibuf = NULL;
        char filepath[FILE_MAX];
@@ -809,26 +819,6 @@ void playanim(int argc, const char **argv)
                }
        }
 
                }
        }
 
-#ifdef WITH_QUICKTIME
-#if defined(_WIN32) || defined(__APPLE__) && !defined(GHOST_COCOA)
-       /* Initialize QuickTime */
-#ifndef noErr
-#define noErr 0
-#endif
-
-#ifdef _WIN32
-       if (InitializeQTML(0) != noErr)
-               G.have_quicktime = FALSE;
-       else
-               G.have_quicktime = TRUE;
-#endif /* _WIN32 */
-       if (EnterMovies() != noErr)
-               G.have_quicktime = FALSE;
-       else
-#endif /* _WIN32 || __APPLE__  && !defined(GHOST_COCOA)*/
-       G.have_quicktime = TRUE;
-#endif /* WITH_QUICKTIME */
-
        if (argc > 1) {
                BLI_strncpy(filepath, argv[1], sizeof(filepath));
        }
        if (argc > 1) {
                BLI_strncpy(filepath, argv[1], sizeof(filepath));
        }
@@ -838,7 +828,8 @@ void playanim(int argc, const char **argv)
        }
 
        if (IMB_isanim(filepath)) {
        }
 
        if (IMB_isanim(filepath)) {
-               anim = IMB_open_anim(filepath, IB_rect, 0);
+               /* OCIO_TODO: support different input color spaces */
+               anim = IMB_open_anim(filepath, IB_rect, 0, NULL);
                if (anim) {
                        ibuf = IMB_anim_absolute(anim, 0, IMB_TC_NONE, IMB_PROXY_NONE);
                        IMB_close_anim(anim);
                if (anim) {
                        ibuf = IMB_anim_absolute(anim, 0, IMB_TC_NONE, IMB_PROXY_NONE);
                        IMB_close_anim(anim);
@@ -850,7 +841,8 @@ void playanim(int argc, const char **argv)
        }
 
        if (ibuf == NULL) {
        }
 
        if (ibuf == NULL) {
-               ibuf = IMB_loadiffname(filepath, IB_rect);
+               /* OCIO_TODO: support different input color space */
+               ibuf = IMB_loadiffname(filepath, IB_rect, NULL);
        }
 
        if (ibuf == NULL) {
        }
 
        if (ibuf == NULL) {
@@ -870,13 +862,13 @@ void playanim(int argc, const char **argv)
 
                GHOST_EventConsumerHandle consumer = GHOST_CreateEventConsumer(ghost_event_proc, &ps);
 
 
                GHOST_EventConsumerHandle consumer = GHOST_CreateEventConsumer(ghost_event_proc, &ps);
 
-               g_system = GHOST_CreateSystem();
-               GHOST_AddEventConsumer(g_system, consumer);
+               g_WS.ghost_system = GHOST_CreateSystem();
+               GHOST_AddEventConsumer(g_WS.ghost_system, consumer);
 
 
 
                playanim_window_open("Blender:Anim", start_x, start_y, ibuf->x, ibuf->y, 0);
 
 
 
                playanim_window_open("Blender:Anim", start_x, start_y, ibuf->x, ibuf->y, 0);
-//XXX25                window_set_handler(g_window, add_to_mainqueue, NULL);
+//XXX25                window_set_handler(g_WS.ghost_window, add_to_mainqueue, NULL);
 
                glMatrixMode(GL_PROJECTION);
                glLoadIdentity();
 
                glMatrixMode(GL_PROJECTION);
                glLoadIdentity();
@@ -884,9 +876,9 @@ void playanim(int argc, const char **argv)
                glMatrixMode(GL_MODELVIEW);
        }
 
                glMatrixMode(GL_MODELVIEW);
        }
 
-       GHOST_GetMainDisplayDimensions(g_system, &maxwinx, &maxwiny);
+       GHOST_GetMainDisplayDimensions(g_WS.ghost_system, &maxwinx, &maxwiny);
 
 
-       //GHOST_ActivateWindowDrawingContext(g_window);
+       //GHOST_ActivateWindowDrawingContext(g_WS.ghost_window);
 
        /* initialize the font */
        BLF_init(11, 72);
 
        /* initialize the font */
        BLF_init(11, 72);
@@ -902,7 +894,7 @@ void playanim(int argc, const char **argv)
        glClearColor(0.0, 0.0, 0.0, 0.0);
        glClear(GL_COLOR_BUFFER_BIT);
 
        glClearColor(0.0, 0.0, 0.0, 0.0);
        glClear(GL_COLOR_BUFFER_BIT);
 
-       GHOST_SwapWindowBuffers(g_window);
+       GHOST_SwapWindowBuffers(g_WS.ghost_window);
 
        if (sfra == -1 || efra == -1) {
                /* one of the frames was invalid, just use all images */
 
        if (sfra == -1 || efra == -1) {
                /* one of the frames was invalid, just use all images */
@@ -923,15 +915,18 @@ void playanim(int argc, const char **argv)
        pupdate_time();
        ptottime = 0;
 
        pupdate_time();
        ptottime = 0;
 
+       /* newly added in 2.6x, without this images never get freed */
+#define USE_IMB_CACHE
+
        while (ps.go) {
                if (ps.pingpong)
                        ps.direction = -ps.direction;
 
                if (ps.direction == 1) {
        while (ps.go) {
                if (ps.pingpong)
                        ps.direction = -ps.direction;
 
                if (ps.direction == 1) {
-                       ps.picture = picsbase->first;
+                       ps.picture = picsbase.first;
                }
                else {
                }
                else {
-                       ps.picture = picsbase->last;
+                       ps.picture = picsbase.last;
                }
 
                if (ps.picture == NULL) {
                }
 
                if (ps.picture == NULL) {
@@ -949,8 +944,9 @@ void playanim(int argc, const char **argv)
                if (ptottime > 0.0) ptottime = 0.0;
 
                while (ps.picture) {
                if (ptottime > 0.0) ptottime = 0.0;
 
                while (ps.picture) {
+#ifndef USE_IMB_CACHE
                        if (ibuf != NULL && ibuf->ftype == 0) IMB_freeImBuf(ibuf);
                        if (ibuf != NULL && ibuf->ftype == 0) IMB_freeImBuf(ibuf);
-
+#endif
                        if (ps.picture->ibuf) {
                                ibuf = ps.picture->ibuf;
                        }
                        if (ps.picture->ibuf) {
                                ibuf = ps.picture->ibuf;
                        }
@@ -958,24 +954,31 @@ void playanim(int argc, const char **argv)
                                ibuf = IMB_anim_absolute(ps.picture->anim, ps.picture->frame, IMB_TC_NONE, IMB_PROXY_NONE);
                        }
                        else if (ps.picture->mem) {
                                ibuf = IMB_anim_absolute(ps.picture->anim, ps.picture->frame, IMB_TC_NONE, IMB_PROXY_NONE);
                        }
                        else if (ps.picture->mem) {
+                               /* use correct colorspace here */
                                ibuf = IMB_ibImageFromMemory((unsigned char *) ps.picture->mem, ps.picture->size,
                                ibuf = IMB_ibImageFromMemory((unsigned char *) ps.picture->mem, ps.picture->size,
-                                                            ps.picture->IB_flags, ps.picture->name);
+                                                            ps.picture->IB_flags, NULL, ps.picture->name);
                        }
                        else {
                        }
                        else {
-                               ibuf = IMB_loadiffname(ps.picture->name, ps.picture->IB_flags);
+                               /* use correct colorspace here */
+                               ibuf = IMB_loadiffname(ps.picture->name, ps.picture->IB_flags, NULL);
                        }
 
                        if (ibuf) {
                        }
 
                        if (ibuf) {
+
+#ifdef USE_IMB_CACHE
+                               ps.picture->ibuf = ibuf;
+#endif
+
                                BLI_strncpy(ibuf->name, ps.picture->name, sizeof(ibuf->name));
 
                                /* why only windows? (from 2.4x) - campbell */
 #ifdef _WIN32
                                BLI_strncpy(ibuf->name, ps.picture->name, sizeof(ibuf->name));
 
                                /* why only windows? (from 2.4x) - campbell */
 #ifdef _WIN32
-                               GHOST_SetTitle(g_window, ps.picture->name);
+                               GHOST_SetTitle(g_WS.ghost_window, ps.picture->name);
 #endif
 
                                while (pupdate_time()) PIL_sleep_ms(1);
                                ptottime -= swaptime;
 #endif
 
                                while (pupdate_time()) PIL_sleep_ms(1);
                                ptottime -= swaptime;
-                               toscreen(ps.picture, ibuf, ps.fontid);
+                               playanim_toscreen(ps.picture, ibuf, ps.fontid);
                        } /* else deleten */
                        else {
                                printf("error: can't play this image type\n");
                        } /* else deleten */
                        else {
                                printf("error: can't play this image type\n");
@@ -995,16 +998,19 @@ void playanim(int argc, const char **argv)
 
 
                        {
 
 
                        {
-                               int hasevent = GHOST_ProcessEvents(g_system, 0);
+                               int hasevent = GHOST_ProcessEvents(g_WS.ghost_system, 0);
                                if (hasevent) {
                                if (hasevent) {
-                                       GHOST_DispatchEvents(g_system);
+                                       GHOST_DispatchEvents(g_WS.ghost_system);
                                }
                        }
 
                        /* XXX25 - we should not have to do this, but it makes scrubbing functional! */
                                }
                        }
 
                        /* XXX25 - we should not have to do this, but it makes scrubbing functional! */
-                       if (qualN & LMOUSE) {
+                       if (g_WS.qual & WS_QUAL_LMOUSE) {
                                ps.next = 0;
                        }
                                ps.next = 0;
                        }
+                       else {
+                               ps.sstep = 0;
+                       }
 
                        ps.wait2 = ps.sstep;
 
 
                        ps.wait2 = ps.sstep;
 
@@ -1038,10 +1044,10 @@ void playanim(int argc, const char **argv)
                                }
                                if (ps.picture == NULL && ps.sstep) {
                                        if (ps.next < 0) {
                                }
                                if (ps.picture == NULL && ps.sstep) {
                                        if (ps.next < 0) {
-                                               ps.picture = picsbase->last;
+                                               ps.picture = picsbase.last;
                                        }
                                        else if (ps.next > 0) {
                                        }
                                        else if (ps.next > 0) {
-                                               ps.picture = picsbase->first;
+                                               ps.picture = picsbase.first;
                                        }
                                }
                        }
                                        }
                                }
                        }
@@ -1050,7 +1056,7 @@ void playanim(int argc, const char **argv)
                        }
                }
        }
                        }
                }
        }
-       ps.picture = picsbase->first;
+       ps.picture = picsbase.first;
        anim = NULL;
        while (ps.picture) {
                if (ps.picture && ps.picture->anim && (anim != ps.picture->anim)) {
        anim = NULL;
        while (ps.picture) {
                if (ps.picture && ps.picture->anim && (anim != ps.picture->anim)) {
@@ -1068,20 +1074,13 @@ void playanim(int argc, const char **argv)
 
                ps.picture = ps.picture->next;
        }
 
                ps.picture = ps.picture->next;
        }
-#ifdef WITH_QUICKTIME
-#if defined(_WIN32) || defined(__APPLE__) && !defined(GHOST_COCOA)
-       if (G.have_quicktime) {
-               ExitMovies();
-#ifdef _WIN32
-               TerminateQTML();
-#endif /* _WIN32 */
-       }
-#endif /* _WIN32 || __APPLE__ && !defined(GHOST_COCOA) */
-#endif /* WITH_QUICKTIME */
 
        /* cleanup */
 
        /* cleanup */
+#ifndef USE_IMB_CACHE
        if (ibuf) IMB_freeImBuf(ibuf);
        if (ibuf) IMB_freeImBuf(ibuf);
-       BLI_freelistN(picsbase);
+#endif
+
+       BLI_freelistN(&picsbase);
 #if 0 // XXX25
        free_blender();
 #else
 #if 0 // XXX25
        free_blender();
 #else
@@ -1090,11 +1089,14 @@ void playanim(int argc, const char **argv)
        IMB_exit();
        BLF_exit();
 #endif
        IMB_exit();
        BLF_exit();
 #endif
-       GHOST_DisposeWindow(g_system, g_window);
+       GHOST_DisposeWindow(g_WS.ghost_system, g_WS.ghost_window);
 
        totblock = MEM_get_memory_blocks_in_use();
        if (totblock != 0) {
 
        totblock = MEM_get_memory_blocks_in_use();
        if (totblock != 0) {
+               /* prints many bAKey, bArgument's which are tricky to fix */
+#if 0
                printf("Error Totblock: %d\n", totblock);
                MEM_printmemlist();
                printf("Error Totblock: %d\n", totblock);
                MEM_printmemlist();
+#endif
        }
 }
        }
 }