Blender  V2.93
wm_playanim.c
Go to the documentation of this file.
1 /*
2  * This program is free software; you can redistribute it and/or
3  * modify it under the terms of the GNU General Public License
4  * as published by the Free Software Foundation; either version 2
5  * of the License, or (at your option) any later version.
6  *
7  * This program is distributed in the hope that it will be useful,
8  * but WITHOUT ANY WARRANTY; without even the implied warranty of
9  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
10  * GNU General Public License for more details.
11  *
12  * You should have received a copy of the GNU General Public License
13  * along with this program; if not, write to the Free Software Foundation,
14  * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
15  *
16  * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV.
17  * All rights reserved.
18  */
19 
30 #include <fcntl.h>
31 #include <math.h>
32 #include <stdlib.h>
33 #include <string.h>
34 #include <sys/types.h>
35 
36 #ifndef WIN32
37 # include <sys/times.h>
38 # include <sys/wait.h>
39 # include <unistd.h>
40 #else
41 # include <io.h>
42 #endif
43 #include "MEM_guardedalloc.h"
44 
45 #include "PIL_time.h"
46 
47 #include "BLI_fileops.h"
48 #include "BLI_listbase.h"
49 #include "BLI_path_util.h"
50 #include "BLI_rect.h"
51 #include "BLI_string.h"
52 #include "BLI_utildefines.h"
53 
54 #include "IMB_colormanagement.h"
55 #include "IMB_imbuf.h"
56 #include "IMB_imbuf_types.h"
57 
58 #include "BKE_image.h"
59 
60 #include "BIF_glutil.h"
61 
62 #include "GPU_context.h"
63 #include "GPU_framebuffer.h"
64 #include "GPU_immediate.h"
65 #include "GPU_immediate_util.h"
66 #include "GPU_init_exit.h"
67 #include "GPU_matrix.h"
68 #include "GPU_state.h"
69 
70 #include "BLF_api.h"
71 #include "DNA_scene_types.h"
72 #include "ED_datafiles.h" /* for fonts */
73 #include "GHOST_C-api.h"
74 
75 #include "DEG_depsgraph.h"
76 
77 #include "WM_api.h" /* only for WM_main_playanim */
78 
79 #ifdef WITH_AUDASPACE
80 # include <AUD_Device.h>
81 # include <AUD_Handle.h>
82 # include <AUD_Sound.h>
83 # include <AUD_Special.h>
84 
85 static AUD_Sound *source = NULL;
86 static AUD_Handle *playback_handle = NULL;
87 static AUD_Handle *scrub_handle = NULL;
88 static AUD_Device *audio_device = NULL;
89 #endif
90 
91 /* simple limiter to avoid flooding memory */
92 #define USE_FRAME_CACHE_LIMIT
93 #ifdef USE_FRAME_CACHE_LIMIT
94 # define PLAY_FRAME_CACHE_MAX 30
95 #endif
96 
97 struct PlayState;
98 static void playanim_window_zoom(struct PlayState *ps, const float zoom_offset);
99 
100 typedef struct PlayState {
101 
102  /* window and viewport size */
103  int win_x, win_y;
104 
105  /* current zoom level */
106  float zoom;
107 
108  /* playback state */
109  short direction;
110  short next_frame;
111 
112  bool once;
113  bool turbo;
114  bool pingpong;
115  bool noskip;
116  bool indicator;
117  bool sstep;
118  bool wait2;
119  bool stopped;
120  bool go;
121  /* waiting for images to load */
122  bool loading;
123  /* x/y image flip */
124  bool draw_flip[2];
125 
126  int fstep;
127 
128  /* current picture */
130 
131  /* set once at the start */
132  int ibufx, ibufy;
133  int fontid;
134 
135  /* restarts player for file drop */
137 
140 
144 
145 /* for debugging */
146 #if 0
147 void print_ps(PlayState *ps)
148 {
149  printf("ps:\n");
150  printf(" direction=%d,\n", (int)ps->direction);
151  printf(" next=%d,\n", ps->next);
152  printf(" once=%d,\n", ps->once);
153  printf(" turbo=%d,\n", ps->turbo);
154  printf(" pingpong=%d,\n", ps->pingpong);
155  printf(" noskip=%d,\n", ps->noskip);
156  printf(" sstep=%d,\n", ps->sstep);
157  printf(" pause=%d,\n", ps->pause);
158  printf(" wait2=%d,\n", ps->wait2);
159  printf(" stopped=%d,\n", ps->stopped);
160  printf(" go=%d,\n\n", ps->go);
161  fflush(stdout);
162 }
163 #endif
164 
165 /* global for window and events */
166 typedef enum eWS_Qual {
167  WS_QUAL_LSHIFT = (1 << 0),
168  WS_QUAL_RSHIFT = (1 << 1),
170  WS_QUAL_LALT = (1 << 2),
171  WS_QUAL_RALT = (1 << 3),
173  WS_QUAL_LCTRL = (1 << 4),
174  WS_QUAL_RCTRL = (1 << 5),
176  WS_QUAL_LMOUSE = (1 << 16),
177  WS_QUAL_MMOUSE = (1 << 17),
178  WS_QUAL_RMOUSE = (1 << 18),
181 
182 static struct WindowStateGlobal {
183  GHOST_SystemHandle ghost_system;
186 
187  /* events */
189 } g_WS = {NULL};
190 
191 static void playanim_window_get_size(int *r_width, int *r_height)
192 {
193  GHOST_RectangleHandle bounds = GHOST_GetClientBounds(g_WS.ghost_window);
194  *r_width = GHOST_GetWidthRectangle(bounds);
195  *r_height = GHOST_GetHeightRectangle(bounds);
197 }
198 
199 static void playanim_gl_matrix(void)
200 {
201  /* unified matrix, note it affects offset for drawing */
202  /* note! cannot use GPU_matrix_ortho_2d_set here because shader ignores. */
203  GPU_matrix_ortho_set(0.0f, 1.0f, 0.0f, 1.0f, -1.0, 1.0f);
204 }
205 
206 /* implementation */
207 static void playanim_event_qual_update(void)
208 {
209  int val;
210 
211  /* Shift */
214 
217 
218  /* Control */
221 
224 
225  /* Alt */
228 
231 }
232 
233 typedef struct PlayAnimPict {
234  struct PlayAnimPict *next, *prev;
236  int size;
237  const char *name;
238  struct ImBuf *ibuf;
239  struct anim *anim;
240  int frame;
241  int IB_flags;
242 
243 #ifdef USE_FRAME_CACHE_LIMIT
247 #endif
249 
250 static struct ListBase picsbase = {NULL, NULL};
251 /* frames in memory - store them here to for easy deallocation later */
252 static bool fromdisk = false;
253 static double ptottime = 0.0, swaptime = 0.04;
254 #ifdef WITH_AUDASPACE
255 static double fps_movie;
256 #endif
257 
258 #ifdef USE_FRAME_CACHE_LIMIT
259 static struct {
261  struct ListBase pics;
263  int pics_len;
267  size_t memory_limit;
268 } g_frame_cache = {
269  .pics = {NULL, NULL},
270  .pics_len = 0,
271  .pics_size_in_memory = 0,
272  .memory_limit = 0,
273 };
274 
275 static void frame_cache_add(PlayAnimPict *pic)
276 {
279  g_frame_cache.pics_len++;
280 
281  if (g_frame_cache.memory_limit != 0) {
282  BLI_assert(pic->size_in_memory == 0);
284  g_frame_cache.pics_size_in_memory += pic->size_in_memory;
285  }
286 }
287 
289 {
291  IMB_freeImBuf(pic->ibuf);
292  if (g_frame_cache.memory_limit != 0) {
293  BLI_assert(pic->size_in_memory != 0);
294  g_frame_cache.pics_size_in_memory -= pic->size_in_memory;
295  pic->size_in_memory = 0;
296  }
297  pic->ibuf = NULL;
298  pic->frame_cache_node = NULL;
300  g_frame_cache.pics_len--;
301 }
302 
303 /* Don't free the current frame by moving it to the head of the list. */
305 {
306  BLI_assert(pic->frame_cache_node->data == pic);
309 }
310 
311 static bool frame_cache_limit_exceeded(void)
312 {
313  return g_frame_cache.memory_limit ?
314  (g_frame_cache.pics_size_in_memory > g_frame_cache.memory_limit) :
315  (g_frame_cache.pics_len > PLAY_FRAME_CACHE_MAX);
316 }
317 
318 static void frame_cache_limit_apply(ImBuf *ibuf_keep)
319 {
320  /* Really basic memory conservation scheme. Keep frames in a FIFO queue. */
321  LinkData *node = g_frame_cache.pics.last;
322  while (node && frame_cache_limit_exceeded()) {
323  PlayAnimPict *pic = node->data;
325 
326  node = node->prev;
327  if (pic->ibuf && pic->ibuf != ibuf_keep) {
328  frame_cache_remove(pic);
329  }
330  }
331 }
332 
333 #endif /* USE_FRAME_CACHE_LIMIT */
334 
336 {
337  ImBuf *ibuf = NULL;
338 
339  if (pic->ibuf) {
340  ibuf = pic->ibuf;
341  }
342  else if (pic->anim) {
344  }
345  else if (pic->mem) {
346  /* use correct colorspace here */
347  ibuf = IMB_ibImageFromMemory(pic->mem, pic->size, pic->IB_flags, NULL, pic->name);
348  }
349  else {
350  /* use correct colorspace here */
351  ibuf = IMB_loadiffname(pic->name, pic->IB_flags, NULL);
352  }
353 
354  return ibuf;
355 }
356 
357 static PlayAnimPict *playanim_step(PlayAnimPict *playanim, int step)
358 {
359  if (step > 0) {
360  while (step-- && playanim) {
361  playanim = playanim->next;
362  }
363  }
364  else if (step < 0) {
365  while (step++ && playanim) {
366  playanim = playanim->prev;
367  }
368  }
369  return playanim;
370 }
371 
372 static int pupdate_time(void)
373 {
374  static double ltime;
375 
376  double time = PIL_check_seconds_timer();
377 
378  ptottime += (time - ltime);
379  ltime = time;
380  return (ptottime < 0);
381 }
382 
384  ImBuf *ibuf,
385  bool *r_glsl_used,
386  eGPUTextureFormat *r_format,
387  eGPUDataFormat *r_data,
388  void **r_buffer_cache_handle)
389 {
390  void *display_buffer;
391  bool force_fallback = false;
392  *r_glsl_used = false;
393  force_fallback |= (ED_draw_imbuf_method(ibuf) != IMAGE_DRAW_METHOD_GLSL);
394  force_fallback |= (ibuf->dither != 0.0f);
395 
396  /* Default */
397  *r_format = GPU_RGBA8;
398  *r_data = GPU_DATA_UBYTE;
399 
400  /* Fallback to CPU based color space conversion. */
401  if (force_fallback) {
402  *r_glsl_used = false;
403  display_buffer = NULL;
404  }
405  else if (ibuf->rect_float) {
406  display_buffer = ibuf->rect_float;
407 
408  *r_data = GPU_DATA_FLOAT;
409  if (ibuf->channels == 4) {
410  *r_format = GPU_RGBA16F;
411  }
412  else if (ibuf->channels == 3) {
413  /* Alpha is implicitly 1. */
414  *r_format = GPU_RGB16F;
415  }
416 
417  if (ibuf->float_colorspace) {
419  &ps->display_settings,
420  ibuf->float_colorspace,
421  ibuf->dither,
422  false,
423  false);
424  }
425  else {
427  &ps->view_settings, &ps->display_settings, ibuf->dither, false);
428  }
429  }
430  else if (ibuf->rect) {
431  display_buffer = ibuf->rect;
433  &ps->display_settings,
434  ibuf->rect_colorspace,
435  ibuf->dither,
436  false,
437  false);
438  }
439  else {
440  display_buffer = NULL;
441  }
442 
443  /* There is data to be displayed, but GLSL is not initialized
444  * properly, in this case we fallback to CPU-based display transform. */
445  if ((ibuf->rect || ibuf->rect_float) && !*r_glsl_used) {
446  display_buffer = IMB_display_buffer_acquire(
447  ibuf, &ps->view_settings, &ps->display_settings, r_buffer_cache_handle);
448  *r_format = GPU_RGBA8;
449  *r_data = GPU_DATA_UBYTE;
450  }
451 
452  return display_buffer;
453 }
454 
455 static void draw_display_buffer(PlayState *ps, ImBuf *ibuf)
456 {
457  void *display_buffer;
458 
459  /* Format needs to be created prior to any #immBindShader call.
460  * Do it here because OCIO binds its own shader. */
463  bool glsl_used = false;
464  GPUVertFormat *imm_format = immVertexFormat();
465  uint pos = GPU_vertformat_attr_add(imm_format, "pos", GPU_COMP_F32, 2, GPU_FETCH_FLOAT);
466  uint texCoord = GPU_vertformat_attr_add(
467  imm_format, "texCoord", GPU_COMP_F32, 2, GPU_FETCH_FLOAT);
468 
469  void *buffer_cache_handle = NULL;
470  display_buffer = ocio_transform_ibuf(ps, ibuf, &glsl_used, &format, &data, &buffer_cache_handle);
471 
472  GPUTexture *texture = GPU_texture_create_2d("display_buf", ibuf->x, ibuf->y, 1, format, NULL);
473  GPU_texture_update(texture, data, display_buffer);
475 
477 
478  if (!glsl_used) {
480  immUniformColor3f(1.0f, 1.0f, 1.0f);
481  immUniform1i("image", 0);
482  }
483 
485 
486  rctf preview;
487  rctf canvas;
488 
489  BLI_rctf_init(&canvas, 0.0f, 1.0f, 0.0f, 1.0f);
490  BLI_rctf_init(&preview, 0.0f, 1.0f, 0.0f, 1.0f);
491 
492  if (ps->draw_flip[0]) {
493  SWAP(float, canvas.xmin, canvas.xmax);
494  }
495  if (ps->draw_flip[1]) {
496  SWAP(float, canvas.ymin, canvas.ymax);
497  }
498 
499  immAttr2f(texCoord, canvas.xmin, canvas.ymin);
500  immVertex2f(pos, preview.xmin, preview.ymin);
501 
502  immAttr2f(texCoord, canvas.xmin, canvas.ymax);
503  immVertex2f(pos, preview.xmin, preview.ymax);
504 
505  immAttr2f(texCoord, canvas.xmax, canvas.ymax);
506  immVertex2f(pos, preview.xmax, preview.ymax);
507 
508  immAttr2f(texCoord, canvas.xmax, canvas.ymin);
509  immVertex2f(pos, preview.xmax, preview.ymin);
510 
511  immEnd();
512 
515 
516  if (!glsl_used) {
518  }
519  else {
521  }
522 
523  if (buffer_cache_handle) {
524  IMB_display_buffer_release(buffer_cache_handle);
525  }
526 }
527 
528 static void playanim_toscreen(
529  PlayState *ps, PlayAnimPict *picture, struct ImBuf *ibuf, int fontid, int fstep)
530 {
531  if (ibuf == NULL) {
532  printf("%s: no ibuf for picture '%s'\n", __func__, picture ? picture->name : "<NIL>");
533  return;
534  }
535 
537 
538  /* size within window */
539  float span_x = (ps->zoom * ibuf->x) / (float)ps->win_x;
540  float span_y = (ps->zoom * ibuf->y) / (float)ps->win_y;
541 
542  /* offset within window */
543  float offs_x = 0.5f * (1.0f - span_x);
544  float offs_y = 0.5f * (1.0f - span_y);
545 
546  CLAMP(offs_x, 0.0f, 1.0f);
547  CLAMP(offs_y, 0.0f, 1.0f);
548 
549  GPU_clear_color(0.1f, 0.1f, 0.1f, 0.0f);
550 
551  /* checkerboard for case alpha */
552  if (ibuf->planes == 32) {
554 
556  offs_y,
557  offs_x + span_x,
558  offs_y + span_y,
559  (const float[4]){0.15, 0.15, 0.15, 1.0},
560  (const float[4]){0.20, 0.20, 0.20, 1.0},
561  8);
562  }
563 
564  draw_display_buffer(ps, ibuf);
565 
567 
568  pupdate_time();
569 
570  if (picture && (g_WS.qual & (WS_QUAL_SHIFT | WS_QUAL_LMOUSE)) && (fontid != -1)) {
571  int sizex, sizey;
572  float fsizex_inv, fsizey_inv;
573  char str[32 + FILE_MAX];
574  BLI_snprintf(str, sizeof(str), "%s | %.2f frames/s", picture->name, fstep / swaptime);
575 
576  playanim_window_get_size(&sizex, &sizey);
577  fsizex_inv = 1.0f / sizex;
578  fsizey_inv = 1.0f / sizey;
579 
580  BLF_color4f(fontid, 1.0, 1.0, 1.0, 1.0);
581  BLF_enable(fontid, BLF_ASPECT);
582  BLF_aspect(fontid, fsizex_inv, fsizey_inv, 1.0f);
583  BLF_position(fontid, 10.0f * fsizex_inv, 10.0f * fsizey_inv, 0.0f);
584  BLF_draw(fontid, str, sizeof(str));
585  }
586 
587  if (ps->indicator) {
588  float fac = ps->picture->frame / (double)(((PlayAnimPict *)picsbase.last)->frame -
589  ((PlayAnimPict *)picsbase.first)->frame);
590 
591  fac = 2.0f * fac - 1.0f;
594  GPU_matrix_push();
596 
598 
600  immUniformColor3ub(0, 255, 0);
601 
603  immVertex2f(pos, fac, -1.0f);
604  immVertex2f(pos, fac, 1.0f);
605  immEnd();
606 
608 
609  GPU_matrix_pop();
611  }
612 
614 }
615 
616 static void build_pict_list_ex(
617  PlayState *ps, const char *first, int totframes, int fstep, int fontid)
618 {
619  if (IMB_isanim(first)) {
620  /* OCIO_TODO: support different input color space */
621  struct anim *anim = IMB_open_anim(first, IB_rect, 0, NULL);
622  if (anim) {
623  int pic;
625  if (ibuf) {
626  playanim_toscreen(ps, NULL, ibuf, fontid, fstep);
627  IMB_freeImBuf(ibuf);
628  }
629 
630  for (pic = 0; pic < IMB_anim_get_duration(anim, IMB_TC_NONE); pic++) {
631  PlayAnimPict *picture = (PlayAnimPict *)MEM_callocN(sizeof(PlayAnimPict), "Pict");
632  picture->anim = anim;
633  picture->frame = pic;
634  picture->IB_flags = IB_rect;
635  picture->name = BLI_sprintfN("%s : %4.d", first, pic + 1);
636  BLI_addtail(&picsbase, picture);
637  }
638  }
639  else {
640  printf("couldn't open anim %s\n", first);
641  }
642  }
643  else {
644  /* Load images into cache until the cache is full,
645  * this resolves choppiness for images that are slow to load, see: T81751. */
646 #ifdef USE_FRAME_CACHE_LIMIT
647  bool fill_cache = true;
648 #else
649  bool fill_cache = false;
650 #endif
651 
652  int count = 0;
653 
654  int fp_framenr;
655  struct {
656  char head[FILE_MAX], tail[FILE_MAX];
657  unsigned short digits;
658  } fp_decoded;
659 
660  char filepath[FILE_MAX];
661  BLI_strncpy(filepath, first, sizeof(filepath));
662  fp_framenr = BLI_path_sequence_decode(
663  filepath, fp_decoded.head, fp_decoded.tail, &fp_decoded.digits);
664 
665  pupdate_time();
666  ptottime = 1.0;
667 
668  /* O_DIRECT
669  *
670  * If set, all reads and writes on the resulting file descriptor will
671  * be performed directly to or from the user program buffer, provided
672  * appropriate size and alignment restrictions are met. Refer to the
673  * F_SETFL and F_DIOINFO commands in the fcntl(2) manual entry for
674  * information about how to determine the alignment constraints.
675  * O_DIRECT is a Silicon Graphics extension and is only supported on
676  * local EFS and XFS file systems.
677  */
678 
679  while (IMB_ispic(filepath) && totframes) {
680  bool has_event;
681  size_t size;
682  int file;
683 
684  file = BLI_open(filepath, O_BINARY | O_RDONLY, 0);
685  if (file < 0) {
686  /* print errno? */
687  return;
688  }
689 
690  PlayAnimPict *picture = (PlayAnimPict *)MEM_callocN(sizeof(PlayAnimPict), "picture");
691  if (picture == NULL) {
692  printf("Not enough memory for pict struct '%s'\n", filepath);
693  close(file);
694  return;
695  }
697 
698  if (size < 1) {
699  close(file);
700  MEM_freeN(picture);
701  return;
702  }
703 
704  picture->size = size;
705  picture->IB_flags = IB_rect;
706 
707  uchar *mem;
708  if (fromdisk == false) {
709  mem = MEM_mallocN(size, "build pic list");
710  if (mem == NULL) {
711  printf("Couldn't get memory\n");
712  close(file);
713  MEM_freeN(picture);
714  return;
715  }
716 
717  if (read(file, mem, size) != size) {
718  printf("Error while reading %s\n", filepath);
719  close(file);
720  MEM_freeN(picture);
721  MEM_freeN(mem);
722  return;
723  }
724  }
725  else {
726  mem = NULL;
727  }
728 
729  picture->mem = mem;
730  picture->name = BLI_strdup(filepath);
731  picture->frame = count;
732  close(file);
733  BLI_addtail(&picsbase, picture);
734  count++;
735 
736  pupdate_time();
737 
738  const bool display_imbuf = ptottime > 1.0;
739 
740  if (display_imbuf || fill_cache) {
741  /* OCIO_TODO: support different input color space */
742  ImBuf *ibuf = ibuf_from_picture(picture);
743 
744  if (ibuf) {
745  if (display_imbuf) {
746  playanim_toscreen(ps, picture, ibuf, fontid, fstep);
747  }
748 #ifdef USE_FRAME_CACHE_LIMIT
749  if (fill_cache) {
750  picture->ibuf = ibuf;
751  frame_cache_add(picture);
752  fill_cache = !frame_cache_limit_exceeded();
753  }
754  else
755 #endif
756  {
757  IMB_freeImBuf(ibuf);
758  }
759  }
760 
761  if (display_imbuf) {
762  pupdate_time();
763  ptottime = 0.0;
764  }
765  }
766 
767  /* create a new filepath each time */
768  fp_framenr += fstep;
770  filepath, fp_decoded.head, fp_decoded.tail, fp_decoded.digits, fp_framenr);
771 
772  while ((has_event = GHOST_ProcessEvents(g_WS.ghost_system, false))) {
774  if (ps->loading == false) {
775  return;
776  }
777  }
778 
779  totframes--;
780  }
781  }
782 }
783 
784 static void build_pict_list(PlayState *ps, const char *first, int totframes, int fstep, int fontid)
785 {
786  ps->loading = true;
787  build_pict_list_ex(ps, first, totframes, fstep, fontid);
788  ps->loading = false;
789 }
790 
791 static void update_sound_fps(void)
792 {
793 #ifdef WITH_AUDASPACE
794  if (playback_handle) {
795  /* swaptime stores the 1.0/fps ratio */
796  double speed = 1.0 / (swaptime * fps_movie);
797 
798  AUD_Handle_setPitch(playback_handle, speed);
799  }
800 #endif
801 }
802 
803 static void tag_change_frame(PlayState *ps, int cx)
804 {
805  ps->need_frame_update = true;
806  ps->frame_cursor_x = cx;
807 }
808 
809 static void change_frame(PlayState *ps)
810 {
811  if (!ps->need_frame_update) {
812  return;
813  }
814 
815  int sizex, sizey;
816  int i, i_last;
817 
819  return;
820  }
821 
822  playanim_window_get_size(&sizex, &sizey);
823  i_last = ((struct PlayAnimPict *)picsbase.last)->frame;
824  i = (i_last * ps->frame_cursor_x) / sizex;
825  CLAMP(i, 0, i_last);
826 
827 #ifdef WITH_AUDASPACE
828  if (scrub_handle) {
829  AUD_Handle_stop(scrub_handle);
830  scrub_handle = NULL;
831  }
832 
833  if (playback_handle) {
834  AUD_Status status = AUD_Handle_getStatus(playback_handle);
835  if (status != AUD_STATUS_PLAYING) {
836  AUD_Handle_stop(playback_handle);
837  playback_handle = AUD_Device_play(audio_device, source, 1);
838  if (playback_handle) {
839  AUD_Handle_setPosition(playback_handle, i / fps_movie);
840  scrub_handle = AUD_pauseAfter(playback_handle, 1 / fps_movie);
841  }
843  }
844  else {
845  AUD_Handle_setPosition(playback_handle, i / fps_movie);
846  scrub_handle = AUD_pauseAfter(playback_handle, 1 / fps_movie);
847  }
848  }
849  else if (source) {
850  playback_handle = AUD_Device_play(audio_device, source, 1);
851  if (playback_handle) {
852  AUD_Handle_setPosition(playback_handle, i / fps_movie);
853  scrub_handle = AUD_pauseAfter(playback_handle, 1 / fps_movie);
854  }
856  }
857 #endif
858 
859  ps->picture = BLI_findlink(&picsbase, i);
860  BLI_assert(ps->picture != NULL);
861 
862  ps->sstep = true;
863  ps->wait2 = false;
864  ps->next_frame = 0;
865 
866  ps->need_frame_update = false;
867 }
868 
869 static int ghost_event_proc(GHOST_EventHandle evt, GHOST_TUserDataPtr ps_void)
870 {
871  PlayState *ps = (PlayState *)ps_void;
873  int val;
874 
875  // print_ps(ps);
876 
878 
879  /* convert ghost event into value keyboard or mouse */
881 
882  /* first check if we're busy loading files */
883  if (ps->loading) {
884  switch (type) {
885  case GHOST_kEventKeyDown:
886  case GHOST_kEventKeyUp: {
887  GHOST_TEventKeyData *key_data;
888 
889  key_data = (GHOST_TEventKeyData *)GHOST_GetEventData(evt);
890  switch (key_data->key) {
891  case GHOST_kKeyEsc:
892  ps->loading = false;
893  break;
894  default:
895  break;
896  }
897  break;
898  }
899  default:
900  break;
901  }
902  return 1;
903  }
904 
905  if (ps->wait2 && ps->stopped) {
906  ps->stopped = false;
907  }
908 
909  if (ps->wait2) {
910  pupdate_time();
911  ptottime = 0;
912  }
913 
914  switch (type) {
915  case GHOST_kEventKeyDown:
916  case GHOST_kEventKeyUp: {
917  GHOST_TEventKeyData *key_data;
918 
919  key_data = (GHOST_TEventKeyData *)GHOST_GetEventData(evt);
920  switch (key_data->key) {
921  case GHOST_kKeyA:
922  if (val) {
923  ps->noskip = !ps->noskip;
924  }
925  break;
926  case GHOST_kKeyI:
927  if (val) {
928  ps->indicator = !ps->indicator;
929  }
930  break;
931  case GHOST_kKeyP:
932  if (val) {
933  ps->pingpong = !ps->pingpong;
934  }
935  break;
936  case GHOST_kKeyF: {
937  if (val) {
938  int axis = (g_WS.qual & WS_QUAL_SHIFT) ? 1 : 0;
939  ps->draw_flip[axis] = !ps->draw_flip[axis];
940  }
941  break;
942  }
943  case GHOST_kKey1:
944  case GHOST_kKeyNumpad1:
945  if (val) {
946  swaptime = ps->fstep / 60.0;
948  }
949  break;
950  case GHOST_kKey2:
951  case GHOST_kKeyNumpad2:
952  if (val) {
953  swaptime = ps->fstep / 50.0;
955  }
956  break;
957  case GHOST_kKey3:
958  case GHOST_kKeyNumpad3:
959  if (val) {
960  swaptime = ps->fstep / 30.0;
962  }
963  break;
964  case GHOST_kKey4:
965  case GHOST_kKeyNumpad4:
966  if (g_WS.qual & WS_QUAL_SHIFT) {
967  swaptime = ps->fstep / 24.0;
969  }
970  else {
971  swaptime = ps->fstep / 25.0;
973  }
974  break;
975  case GHOST_kKey5:
976  case GHOST_kKeyNumpad5:
977  if (val) {
978  swaptime = ps->fstep / 20.0;
980  }
981  break;
982  case GHOST_kKey6:
983  case GHOST_kKeyNumpad6:
984  if (val) {
985  swaptime = ps->fstep / 15.0;
987  }
988  break;
989  case GHOST_kKey7:
990  case GHOST_kKeyNumpad7:
991  if (val) {
992  swaptime = ps->fstep / 12.0;
994  }
995  break;
996  case GHOST_kKey8:
997  case GHOST_kKeyNumpad8:
998  if (val) {
999  swaptime = ps->fstep / 10.0;
1000  update_sound_fps();
1001  }
1002  break;
1003  case GHOST_kKey9:
1004  case GHOST_kKeyNumpad9:
1005  if (val) {
1006  swaptime = ps->fstep / 6.0;
1007  update_sound_fps();
1008  }
1009  break;
1010  case GHOST_kKeyLeftArrow:
1011  if (val) {
1012  ps->sstep = true;
1013  ps->wait2 = false;
1014  if (g_WS.qual & WS_QUAL_SHIFT) {
1015  ps->picture = picsbase.first;
1016  ps->next_frame = 0;
1017  }
1018  else {
1019  ps->next_frame = -1;
1020  }
1021  }
1022  break;
1023  case GHOST_kKeyDownArrow:
1024  if (val) {
1025  ps->wait2 = false;
1026  if (g_WS.qual & WS_QUAL_SHIFT) {
1027  ps->next_frame = ps->direction = -1;
1028  }
1029  else {
1030  ps->next_frame = -10;
1031  ps->sstep = true;
1032  }
1033  }
1034  break;
1035  case GHOST_kKeyRightArrow:
1036  if (val) {
1037  ps->sstep = true;
1038  ps->wait2 = false;
1039  if (g_WS.qual & WS_QUAL_SHIFT) {
1040  ps->picture = picsbase.last;
1041  ps->next_frame = 0;
1042  }
1043  else {
1044  ps->next_frame = 1;
1045  }
1046  }
1047  break;
1048  case GHOST_kKeyUpArrow:
1049  if (val) {
1050  ps->wait2 = false;
1051  if (g_WS.qual & WS_QUAL_SHIFT) {
1052  ps->next_frame = ps->direction = 1;
1053  }
1054  else {
1055  ps->next_frame = 10;
1056  ps->sstep = true;
1057  }
1058  }
1059  break;
1060 
1061  case GHOST_kKeySlash:
1062  case GHOST_kKeyNumpadSlash:
1063  if (val) {
1064  if (g_WS.qual & WS_QUAL_SHIFT) {
1065  if (ps->picture && ps->picture->ibuf) {
1066  printf(" Name: %s | Speed: %.2f frames/s\n",
1067  ps->picture->ibuf->name,
1068  ps->fstep / swaptime);
1069  }
1070  }
1071  else {
1072  swaptime = ps->fstep / 5.0;
1073  update_sound_fps();
1074  }
1075  }
1076  break;
1077  case GHOST_kKey0:
1078  case GHOST_kKeyNumpad0:
1079  if (val) {
1080  if (ps->once) {
1081  ps->once = ps->wait2 = false;
1082  }
1083  else {
1084  ps->picture = NULL;
1085  ps->once = true;
1086  ps->wait2 = false;
1087  }
1088  }
1089  break;
1090 
1091  case GHOST_kKeySpace:
1092  if (val) {
1093  if (ps->wait2 || ps->sstep) {
1094  ps->wait2 = ps->sstep = false;
1095 #ifdef WITH_AUDASPACE
1096  {
1097  PlayAnimPict *picture = picsbase.first;
1098  /* TODO - store in ps direct? */
1099  int i = 0;
1100 
1101  while (picture && picture != ps->picture) {
1102  i++;
1103  picture = picture->next;
1104  }
1105  if (playback_handle) {
1106  AUD_Handle_stop(playback_handle);
1107  }
1108  playback_handle = AUD_Device_play(audio_device, source, 1);
1109  if (playback_handle) {
1110  AUD_Handle_setPosition(playback_handle, i / fps_movie);
1111  }
1112  update_sound_fps();
1113  }
1114 #endif
1115  }
1116  else {
1117  ps->sstep = true;
1118  ps->wait2 = true;
1119 #ifdef WITH_AUDASPACE
1120  if (playback_handle) {
1121  AUD_Handle_stop(playback_handle);
1122  playback_handle = NULL;
1123  }
1124 #endif
1125  }
1126  }
1127  break;
1128  case GHOST_kKeyEnter:
1129  case GHOST_kKeyNumpadEnter:
1130  if (val) {
1131  ps->wait2 = ps->sstep = false;
1132 #ifdef WITH_AUDASPACE
1133  {
1134  PlayAnimPict *picture = picsbase.first;
1135  /* TODO - store in ps direct? */
1136  int i = 0;
1137  while (picture && picture != ps->picture) {
1138  i++;
1139  picture = picture->next;
1140  }
1141  if (playback_handle) {
1142  AUD_Handle_stop(playback_handle);
1143  }
1144  playback_handle = AUD_Device_play(audio_device, source, 1);
1145  if (playback_handle) {
1146  AUD_Handle_setPosition(playback_handle, i / fps_movie);
1147  }
1148  update_sound_fps();
1149  }
1150 #endif
1151  }
1152  break;
1153  case GHOST_kKeyPeriod:
1155  if (val) {
1156  if (ps->sstep) {
1157  ps->wait2 = false;
1158  }
1159  else {
1160  ps->sstep = true;
1161  ps->wait2 = !ps->wait2;
1162 #ifdef WITH_AUDASPACE
1163  if (playback_handle) {
1164  AUD_Handle_stop(playback_handle);
1165  playback_handle = NULL;
1166  }
1167 #endif
1168  }
1169  }
1170  break;
1171  case GHOST_kKeyEqual:
1172  case GHOST_kKeyPlus:
1173  case GHOST_kKeyNumpadPlus: {
1174  if (val == 0) {
1175  break;
1176  }
1177  if (g_WS.qual & WS_QUAL_CTRL) {
1178  playanim_window_zoom(ps, 0.1f);
1179  }
1180  else {
1181  if (swaptime > ps->fstep / 60.0) {
1182  swaptime /= 1.1;
1183  update_sound_fps();
1184  }
1185  }
1186  break;
1187  }
1188  case GHOST_kKeyMinus:
1189  case GHOST_kKeyNumpadMinus: {
1190  if (val == 0) {
1191  break;
1192  }
1193  if (g_WS.qual & WS_QUAL_CTRL) {
1194  playanim_window_zoom(ps, -0.1f);
1195  }
1196  else {
1197  if (swaptime < ps->fstep / 5.0) {
1198  swaptime *= 1.1;
1199  update_sound_fps();
1200  }
1201  }
1202  break;
1203  }
1204  case GHOST_kKeyEsc:
1205  ps->go = false;
1206  break;
1207  default:
1208  break;
1209  }
1210  break;
1211  }
1213  case GHOST_kEventButtonUp: {
1215  int cx, cy, sizex, sizey, inside_window;
1216 
1218  GHOST_ScreenToClient(g_WS.ghost_window, cx, cy, &cx, &cy);
1219  playanim_window_get_size(&sizex, &sizey);
1220 
1221  inside_window = (cx >= 0 && cx < sizex && cy >= 0 && cy <= sizey);
1222 
1223  if (bd->button == GHOST_kButtonMaskLeft) {
1224  if (type == GHOST_kEventButtonDown) {
1225  if (inside_window) {
1227  tag_change_frame(ps, cx);
1228  }
1229  }
1230  else {
1231  g_WS.qual &= ~WS_QUAL_LMOUSE;
1232  }
1233  }
1234  else if (bd->button == GHOST_kButtonMaskMiddle) {
1235  if (type == GHOST_kEventButtonDown) {
1236  if (inside_window) {
1238  }
1239  }
1240  else {
1241  g_WS.qual &= ~WS_QUAL_MMOUSE;
1242  }
1243  }
1244  else if (bd->button == GHOST_kButtonMaskRight) {
1245  if (type == GHOST_kEventButtonDown) {
1246  if (inside_window) {
1248  }
1249  }
1250  else {
1251  g_WS.qual &= ~WS_QUAL_RMOUSE;
1252  }
1253  }
1254  break;
1255  }
1256  case GHOST_kEventCursorMove: {
1257  if (g_WS.qual & WS_QUAL_LMOUSE) {
1259  int cx, cy;
1260 
1261  /* Ignore 'in-between' events, since they can make scrubbing lag.
1262  *
1263  * Ideally we would keep into the event queue and see if this is the last motion event.
1264  * however the API currently doesn't support this. */
1265  {
1266  int x_test, y_test;
1267  GHOST_GetCursorPosition(g_WS.ghost_system, &x_test, &y_test);
1268  if (x_test != cd->x || y_test != cd->y) {
1269  /* we're not the last event... skipping */
1270  break;
1271  }
1272  }
1273 
1274  GHOST_ScreenToClient(g_WS.ghost_window, cd->x, cd->y, &cx, &cy);
1275 
1276  tag_change_frame(ps, cx);
1277  }
1278  break;
1279  }
1282  g_WS.qual &= ~WS_QUAL_MOUSE;
1283  break;
1284  }
1286  case GHOST_kEventWindowMove: {
1287  float zoomx, zoomy;
1288 
1289  playanim_window_get_size(&ps->win_x, &ps->win_y);
1291 
1292  zoomx = (float)ps->win_x / ps->ibufx;
1293  zoomy = (float)ps->win_y / ps->ibufy;
1294 
1295  /* zoom always show entire image */
1296  ps->zoom = MIN2(zoomx, zoomy);
1297 
1298  GPU_viewport(0, 0, ps->win_x, ps->win_y);
1299  GPU_scissor(0, 0, ps->win_x, ps->win_y);
1300 
1302 
1303  ptottime = 0.0;
1305  ps, ps->picture, ps->picture ? ps->picture->ibuf : NULL, ps->fontid, ps->fstep);
1306 
1307  break;
1308  }
1310  case GHOST_kEventWindowClose: {
1311  ps->go = false;
1312  break;
1313  }
1316 
1318  GHOST_TStringArray *stra = ddd->data;
1319  int a;
1320 
1321  for (a = 0; a < stra->count; a++) {
1322  BLI_strncpy(ps->dropped_file, (char *)stra->strings[a], sizeof(ps->dropped_file));
1323  ps->go = false;
1324  printf("drop file %s\n", stra->strings[a]);
1325  break; /* only one drop element supported now */
1326  }
1327  }
1328  break;
1329  }
1330  default:
1331  /* quiet warnings */
1332  break;
1333  }
1334 
1335  return 1;
1336 }
1337 
1338 static void playanim_window_open(const char *title, int posx, int posy, int sizex, int sizey)
1339 {
1340  GHOST_GLSettings glsettings = {0};
1341  GHOST_TUns32 scr_w, scr_h;
1342 
1344 
1345  posy = (scr_h - posy - sizey);
1346 
1348  NULL,
1349  title,
1350  posx,
1351  posy,
1352  sizex,
1353  sizey,
1354  /* could optionally start fullscreen */
1356  false,
1358  glsettings);
1359 }
1360 
1361 static void playanim_window_zoom(PlayState *ps, const float zoom_offset)
1362 {
1363  int sizex, sizey;
1364  /* int ofsx, ofsy; */ /* UNUSED */
1365 
1366  if (ps->zoom + zoom_offset > 0.0f) {
1367  ps->zoom += zoom_offset;
1368  }
1369 
1370  // playanim_window_get_position(&ofsx, &ofsy);
1371  playanim_window_get_size(&sizex, &sizey);
1372  /* ofsx += sizex / 2; */ /* UNUSED */
1373  /* ofsy += sizey / 2; */ /* UNUSED */
1374  sizex = ps->zoom * ps->ibufx;
1375  sizey = ps->zoom * ps->ibufy;
1376  /* ofsx -= sizex / 2; */ /* UNUSED */
1377  /* ofsy -= sizey / 2; */ /* UNUSED */
1378  // window_set_position(g_WS.ghost_window, sizex, sizey);
1379  GHOST_SetClientSize(g_WS.ghost_window, sizex, sizey);
1380 }
1381 
1382 /* return path for restart */
1383 static char *wm_main_playanim_intern(int argc, const char **argv)
1384 {
1385  struct ImBuf *ibuf = NULL;
1386  static char filepath[FILE_MAX]; /* abused to return dropped file path */
1387  GHOST_TUns32 maxwinx, maxwiny;
1388  int i;
1389  /* This was done to disambiguate the name for use under c++. */
1390  int start_x = 0, start_y = 0;
1391  int sfra = -1;
1392  int efra = -1;
1393  int totblock;
1394 
1395  PlayState ps = {0};
1396 
1397  ps.go = true;
1398  ps.direction = true;
1399  ps.next_frame = 1;
1400  ps.once = false;
1401  ps.turbo = false;
1402  ps.pingpong = false;
1403  ps.noskip = false;
1404  ps.sstep = false;
1405  ps.wait2 = false;
1406  ps.stopped = false;
1407  ps.loading = false;
1408  ps.picture = NULL;
1409  ps.indicator = false;
1410  ps.dropped_file[0] = 0;
1411  ps.zoom = 1.0f;
1412  ps.draw_flip[0] = false;
1413  ps.draw_flip[1] = false;
1414 
1415  ps.fstep = 1;
1416 
1417  ps.fontid = -1;
1418 
1422 
1423  while (argc > 1) {
1424  if (argv[1][0] == '-') {
1425  switch (argv[1][1]) {
1426  case 'm':
1427  fromdisk = true;
1428  break;
1429  case 'p':
1430  if (argc > 3) {
1431  start_x = atoi(argv[2]);
1432  start_y = atoi(argv[3]);
1433  argc -= 2;
1434  argv += 2;
1435  }
1436  else {
1437  printf("too few arguments for -p (need 2): skipping\n");
1438  }
1439  break;
1440  case 'f':
1441  if (argc > 3) {
1442  double fps = atof(argv[2]);
1443  double fps_base = atof(argv[3]);
1444  if (fps == 0.0) {
1445  fps = 1;
1446  printf(
1447  "invalid fps,"
1448  "forcing 1\n");
1449  }
1450  swaptime = fps_base / fps;
1451  argc -= 2;
1452  argv += 2;
1453  }
1454  else {
1455  printf("too few arguments for -f (need 2): skipping\n");
1456  }
1457  break;
1458  case 's':
1459  sfra = atoi(argv[2]);
1460  CLAMP(sfra, 1, MAXFRAME);
1461  argc--;
1462  argv++;
1463  break;
1464  case 'e':
1465  efra = atoi(argv[2]);
1466  CLAMP(efra, 1, MAXFRAME);
1467  argc--;
1468  argv++;
1469  break;
1470  case 'j':
1471  ps.fstep = atoi(argv[2]);
1472  CLAMP(ps.fstep, 1, MAXFRAME);
1473  swaptime *= ps.fstep;
1474  argc--;
1475  argv++;
1476  break;
1477  case 'c': {
1478 #ifdef USE_FRAME_CACHE_LIMIT
1479  const int memory_in_mb = max_ii(0, atoi(argv[2]));
1480  g_frame_cache.memory_limit = (size_t)memory_in_mb * (1024 * 1024);
1481 #endif
1482  argc--;
1483  argv++;
1484  break;
1485  }
1486  default:
1487  printf("unknown option '%c': skipping\n", argv[1][1]);
1488  break;
1489  }
1490  argc--;
1491  argv++;
1492  }
1493  else {
1494  break;
1495  }
1496  }
1497 
1498  if (argc > 1) {
1499  BLI_strncpy(filepath, argv[1], sizeof(filepath));
1500  }
1501  else {
1502  printf("%s: no filepath argument given\n", __func__);
1503  exit(1);
1504  }
1505 
1506  if (IMB_isanim(filepath)) {
1507  /* OCIO_TODO: support different input color spaces */
1508  struct anim *anim;
1509  anim = IMB_open_anim(filepath, IB_rect, 0, NULL);
1510  if (anim) {
1513  anim = NULL;
1514  }
1515  }
1516  else if (!IMB_ispic(filepath)) {
1517  printf("%s: '%s' not an image file\n", __func__, filepath);
1518  exit(1);
1519  }
1520 
1521  if (ibuf == NULL) {
1522  /* OCIO_TODO: support different input color space */
1523  ibuf = IMB_loadiffname(filepath, IB_rect, NULL);
1524  }
1525 
1526  if (ibuf == NULL) {
1527  printf("%s: '%s' couldn't open\n", __func__, filepath);
1528  exit(1);
1529  }
1530 
1531  {
1532 
1533  GHOST_EventConsumerHandle consumer = GHOST_CreateEventConsumer(ghost_event_proc, &ps);
1534 
1537 
1538  playanim_window_open("Blender Animation Player", start_x, start_y, ibuf->x, ibuf->y);
1539  }
1540 
1541  GHOST_GetMainDisplayDimensions(g_WS.ghost_system, &maxwinx, &maxwiny);
1542 
1543  // GHOST_ActivateWindowDrawingContext(g_WS.ghost_window);
1544 
1545  /* initialize OpenGL immediate mode */
1547  GPU_init();
1548 
1549  /* initialize the font */
1550  BLF_init();
1551  ps.fontid = BLF_load_mono_default(false);
1552  BLF_size(ps.fontid, 11, 72);
1553 
1554  ps.ibufx = ibuf->x;
1555  ps.ibufy = ibuf->y;
1556 
1557  ps.win_x = ps.ibufx;
1558  ps.win_y = ps.ibufy;
1559 
1560  if (maxwinx % ibuf->x) {
1561  maxwinx = ibuf->x * (1 + (maxwinx / ibuf->x));
1562  }
1563  if (maxwiny % ibuf->y) {
1564  maxwiny = ibuf->y * (1 + (maxwiny / ibuf->y));
1565  }
1566 
1567  GPU_clear_color(0.1f, 0.1f, 0.1f, 0.0f);
1568 
1569  int win_x, win_y;
1570  playanim_window_get_size(&win_x, &win_y);
1571  GPU_viewport(0, 0, win_x, win_y);
1572  GPU_scissor(0, 0, win_x, win_y);
1574 
1576 
1577  if (sfra == -1 || efra == -1) {
1578  /* one of the frames was invalid, just use all images */
1579  sfra = 1;
1580  efra = MAXFRAME;
1581  }
1582 
1583  build_pict_list(&ps, filepath, (efra - sfra) + 1, ps.fstep, ps.fontid);
1584 
1585 #ifdef WITH_AUDASPACE
1586  source = AUD_Sound_file(filepath);
1587  {
1588  struct anim *anim_movie = ((struct PlayAnimPict *)picsbase.first)->anim;
1589  if (anim_movie) {
1590  short frs_sec = 25;
1591  float frs_sec_base = 1.0;
1592 
1593  IMB_anim_get_fps(anim_movie, &frs_sec, &frs_sec_base, true);
1594 
1595  fps_movie = (double)frs_sec / (double)frs_sec_base;
1596  /* enforce same fps for movie as sound */
1597  swaptime = ps.fstep / fps_movie;
1598  }
1599  }
1600 #endif
1601 
1602  for (i = 2; i < argc; i++) {
1603  BLI_strncpy(filepath, argv[i], sizeof(filepath));
1604  build_pict_list(&ps, filepath, (efra - sfra) + 1, ps.fstep, ps.fontid);
1605  }
1606 
1608  ibuf = NULL;
1609 
1610  pupdate_time();
1611  ptottime = 0;
1612 
1613  /* newly added in 2.6x, without this images never get freed */
1614 #define USE_IMB_CACHE
1615 
1616  while (ps.go) {
1617  if (ps.pingpong) {
1618  ps.direction = -ps.direction;
1619  }
1620 
1621  if (ps.direction == 1) {
1622  ps.picture = picsbase.first;
1623  }
1624  else {
1625  ps.picture = picsbase.last;
1626  }
1627 
1628  if (ps.picture == NULL) {
1629  printf("couldn't find pictures\n");
1630  ps.go = false;
1631  }
1632  if (ps.pingpong) {
1633  if (ps.direction == 1) {
1634  ps.picture = ps.picture->next;
1635  }
1636  else {
1637  ps.picture = ps.picture->prev;
1638  }
1639  }
1640  if (ptottime > 0.0) {
1641  ptottime = 0.0;
1642  }
1643 
1644 #ifdef WITH_AUDASPACE
1645  if (playback_handle) {
1646  AUD_Handle_stop(playback_handle);
1647  }
1648  playback_handle = AUD_Device_play(audio_device, source, 1);
1649  update_sound_fps();
1650 #endif
1651 
1652  while (ps.picture) {
1653  bool has_event;
1654 #ifndef USE_IMB_CACHE
1655  if (ibuf != NULL && ibuf->ftype == IMB_FTYPE_NONE) {
1657  }
1658 #endif
1659 
1661 
1662  if (ibuf) {
1663 #ifdef USE_IMB_CACHE
1664  ps.picture->ibuf = ibuf;
1665 #endif
1666 
1667 #ifdef USE_FRAME_CACHE_LIMIT
1668  if (ps.picture->frame_cache_node == NULL) {
1670  }
1671  else {
1673  }
1675 
1676 #endif /* USE_FRAME_CACHE_LIMIT */
1677 
1678  BLI_strncpy(ibuf->name, ps.picture->name, sizeof(ibuf->name));
1679 
1680  /* why only windows? (from 2.4x) - campbell */
1681 #ifdef _WIN32
1683 #endif
1684 
1685  while (pupdate_time()) {
1686  PIL_sleep_ms(1);
1687  }
1688  ptottime -= swaptime;
1689  playanim_toscreen(&ps, ps.picture, ibuf, ps.fontid, ps.fstep);
1690  } /* else delete */
1691  else {
1692  printf("error: can't play this image type\n");
1693  exit(0);
1694  }
1695 
1696  if (ps.once) {
1697  if (ps.picture->next == NULL) {
1698  ps.wait2 = true;
1699  }
1700  else if (ps.picture->prev == NULL) {
1701  ps.wait2 = true;
1702  }
1703  }
1704 
1705  ps.next_frame = ps.direction;
1706 
1707  while ((has_event = GHOST_ProcessEvents(g_WS.ghost_system, false))) {
1709  }
1710  if (ps.go == false) {
1711  break;
1712  }
1713  change_frame(&ps);
1714  if (!has_event) {
1715  PIL_sleep_ms(1);
1716  }
1717  if (ps.wait2) {
1718  continue;
1719  }
1720 
1721  ps.wait2 = ps.sstep;
1722 
1723  if (ps.wait2 == false && ps.stopped == false) {
1724  ps.stopped = true;
1725  }
1726 
1727  pupdate_time();
1728 
1729  if (ps.picture && ps.next_frame) {
1730  /* always at least set one step */
1731  while (ps.picture) {
1732  ps.picture = playanim_step(ps.picture, ps.next_frame);
1733 
1734  if (ps.once && ps.picture != NULL) {
1735  if (ps.picture->next == NULL) {
1736  ps.wait2 = true;
1737  }
1738  else if (ps.picture->prev == NULL) {
1739  ps.wait2 = true;
1740  }
1741  }
1742 
1743  if (ps.wait2 || ptottime < swaptime || ps.turbo || ps.noskip) {
1744  break;
1745  }
1746  ptottime -= swaptime;
1747  }
1748  if (ps.picture == NULL && ps.sstep) {
1749  ps.picture = playanim_step(ps.picture, ps.next_frame);
1750  }
1751  }
1752  if (ps.go == false) {
1753  break;
1754  }
1755  }
1756  }
1757  while ((ps.picture = BLI_pophead(&picsbase))) {
1758  if (ps.picture->anim) {
1759  if ((ps.picture->next == NULL) || (ps.picture->next->anim != ps.picture->anim)) {
1761  }
1762  }
1763 
1764  if (ps.picture->ibuf) {
1765  IMB_freeImBuf(ps.picture->ibuf);
1766  }
1767  if (ps.picture->mem) {
1768  MEM_freeN(ps.picture->mem);
1769  }
1770 
1771  MEM_freeN((void *)ps.picture->name);
1772  MEM_freeN(ps.picture);
1773  }
1774 
1775  /* cleanup */
1776 #ifndef USE_IMB_CACHE
1777  if (ibuf) {
1779  }
1780 #endif
1781 
1783 
1784 #ifdef USE_FRAME_CACHE_LIMIT
1786  g_frame_cache.pics_len = 0;
1787  g_frame_cache.pics_size_in_memory = 0;
1788 #endif
1789 
1790 #ifdef WITH_AUDASPACE
1791  if (playback_handle) {
1792  AUD_Handle_stop(playback_handle);
1793  playback_handle = NULL;
1794  }
1795  if (scrub_handle) {
1796  AUD_Handle_stop(scrub_handle);
1797  scrub_handle = NULL;
1798  }
1799  AUD_Sound_free(source);
1800  source = NULL;
1801 #endif
1802  /* we still miss freeing a lot!,
1803  * but many areas could skip initialization too for anim play */
1804 
1806 
1807  if (g_WS.gpu_context) {
1810  g_WS.gpu_context = NULL;
1811  }
1812 
1813  BLF_exit();
1814 
1815  GPU_exit();
1816 
1818 
1819  /* early exit, IMB and BKE should be exited only in end */
1820  if (ps.dropped_file[0]) {
1821  BLI_strncpy(filepath, ps.dropped_file, sizeof(filepath));
1822  return filepath;
1823  }
1824 
1825  IMB_exit();
1826  BKE_images_exit();
1828 
1830  if (totblock != 0) {
1831  /* prints many bAKey, bArgument's which are tricky to fix */
1832 #if 0
1833  printf("Error Totblock: %d\n", totblock);
1834  MEM_printmemlist();
1835 #endif
1836  }
1837 
1838  return NULL;
1839 }
1840 
1841 void WM_main_playanim(int argc, const char **argv)
1842 {
1843  const char *argv_next[2];
1844  bool looping = true;
1845 
1846 #ifdef WITH_AUDASPACE
1847  {
1848  AUD_DeviceSpecs specs;
1849 
1850  specs.rate = AUD_RATE_48000;
1851  specs.format = AUD_FORMAT_S16;
1852  specs.channels = AUD_CHANNELS_STEREO;
1853 
1854  AUD_initOnce();
1855 
1856  if (!(audio_device = AUD_init(NULL, specs, 1024, "Blender"))) {
1857  audio_device = AUD_init("None", specs, 0, "Blender");
1858  }
1859  }
1860 #endif
1861 
1862  while (looping) {
1863  const char *filepath = wm_main_playanim_intern(argc, argv);
1864 
1865  if (filepath) { /* use simple args */
1866  argv_next[0] = argv[0];
1867  argv_next[1] = filepath;
1868  argc = 2;
1869 
1870  /* continue with new args */
1871  argv = argv_next;
1872  }
1873  else {
1874  looping = false;
1875  }
1876  }
1877 
1878 #ifdef WITH_AUDASPACE
1879  AUD_exit(audio_device);
1880  AUD_exitOnce();
1881 #endif
1882 }
typedef float(TangentPoint)[2]
int ED_draw_imbuf_method(struct ImBuf *ibuf)
Definition: glutil.c:566
void BKE_images_exit(void)
Definition: image.c:436
void BLF_aspect(int fontid, float x, float y, float z)
Definition: blf.c:292
int BLF_init(void)
Definition: blf.c:81
#define BLF_ASPECT
Definition: BLF_api.h:274
void BLF_draw(int fontid, const char *str, size_t len) ATTR_NONNULL(2)
Definition: blf.c:542
int BLF_load_mono_default(const bool unique)
void BLF_exit(void)
Definition: blf.c:92
void BLF_size(int fontid, int size, int dpi)
Definition: blf.c:367
void BLF_enable(int fontid, int option)
Definition: blf.c:274
void BLF_color4f(int fontid, float r, float g, float b, float a)
Definition: blf.c:450
void BLF_position(int fontid, float x, float y, float z)
Definition: blf.c:312
#define BLI_assert(a)
Definition: BLI_assert.h:58
File and directory operations.
int BLI_open(const char *filename, int oflag, int pmode) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL()
Definition: fileops.c:1017
#define O_BINARY
Definition: BLI_fileops.h:182
size_t BLI_file_descriptor_size(int file) ATTR_WARN_UNUSED_RESULT
Definition: storage.c:207
BLI_INLINE bool BLI_listbase_is_empty(const struct ListBase *lb)
Definition: BLI_listbase.h:124
void * BLI_pophead(ListBase *listbase) ATTR_NONNULL(1)
Definition: listbase.c:257
void BLI_addhead(struct ListBase *listbase, void *vlink) ATTR_NONNULL(1)
Definition: listbase.c:87
void BLI_freelinkN(struct ListBase *listbase, void *vlink) ATTR_NONNULL(1)
Definition: listbase.c:281
struct LinkData * BLI_genericNodeN(void *data)
Definition: listbase.c:923
void void BLI_freelistN(struct ListBase *listbase) ATTR_NONNULL(1)
Definition: listbase.c:547
void BLI_addtail(struct ListBase *listbase, void *vlink) ATTR_NONNULL(1)
Definition: listbase.c:110
void BLI_remlink(struct ListBase *listbase, void *vlink) ATTR_NONNULL(1)
Definition: listbase.c:133
void * BLI_findlink(const struct ListBase *listbase, int number) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL(1)
MINLINE int max_ii(int a, int b)
#define FILE_MAX
int BLI_path_sequence_decode(const char *string, char *head, char *tail, unsigned short *r_num_len)
Definition: path_util.c:83
void BLI_path_sequence_encode(char *string, const char *head, const char *tail, unsigned short numlen, int pic)
Definition: path_util.c:154
void BLI_rctf_init(struct rctf *rect, float xmin, float xmax, float ymin, float ymax)
Definition: rct.c:436
size_t size_t char * BLI_sprintfN(const char *__restrict format,...) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL(1) ATTR_MALLOC ATTR_PRINTF_FORMAT(1
#define STRNCPY(dst, src)
Definition: BLI_string.h:163
char * BLI_strdup(const char *str) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL() ATTR_MALLOC
Definition: string.c:70
size_t BLI_snprintf(char *__restrict dst, size_t maxncpy, const char *__restrict format,...) ATTR_NONNULL(1
char * BLI_strncpy(char *__restrict dst, const char *__restrict src, const size_t maxncpy) ATTR_NONNULL()
Definition: string.c:108
unsigned char uchar
Definition: BLI_sys_types.h:86
unsigned int uint
Definition: BLI_sys_types.h:83
#define SWAP(type, a, b)
#define SET_FLAG_FROM_TEST(value, test, flag)
#define ELEM(...)
#define MIN2(a, b)
typedef double(DMatrix)[4][4]
void DEG_free_node_types(void)
#define MAXFRAME
@ IMAGE_DRAW_METHOD_GLSL
GHOST C-API function and type declarations.
int GHOST_ProcessEvents(GHOST_SystemHandle systemhandle, int waitForEvent)
GHOST_TInt32 GHOST_GetHeightRectangle(GHOST_RectangleHandle rectanglehandle)
void GHOST_ScreenToClient(GHOST_WindowHandle windowhandle, GHOST_TInt32 inX, GHOST_TInt32 inY, GHOST_TInt32 *outX, GHOST_TInt32 *outY)
GHOST_SystemHandle GHOST_CreateSystem(void)
Definition: GHOST_C-api.cpp:40
GHOST_TSuccess GHOST_AddEventConsumer(GHOST_SystemHandle systemhandle, GHOST_EventConsumerHandle consumerhandle)
GHOST_WindowHandle GHOST_CreateWindow(GHOST_SystemHandle systemhandle, GHOST_WindowHandle parent_windowhandle, const char *title, GHOST_TInt32 left, GHOST_TInt32 top, GHOST_TUns32 width, GHOST_TUns32 height, GHOST_TWindowState state, bool is_dialog, GHOST_TDrawingContextType type, GHOST_GLSettings glSettings)
GHOST_TSuccess GHOST_SetClientSize(GHOST_WindowHandle windowhandle, GHOST_TUns32 width, GHOST_TUns32 height)
void GHOST_DisposeRectangle(GHOST_RectangleHandle rectanglehandle)
void GHOST_SetTitle(GHOST_WindowHandle windowhandle, const char *title)
GHOST_TSuccess GHOST_DisposeWindow(GHOST_SystemHandle systemhandle, GHOST_WindowHandle windowhandle)
GHOST_TInt32 GHOST_GetWidthRectangle(GHOST_RectangleHandle rectanglehandle)
GHOST_TSuccess GHOST_SwapWindowBuffers(GHOST_WindowHandle windowhandle)
GHOST_TSuccess GHOST_GetCursorPosition(GHOST_SystemHandle systemhandle, GHOST_TInt32 *x, GHOST_TInt32 *y)
GHOST_TEventDataPtr GHOST_GetEventData(GHOST_EventHandle eventhandle)
GHOST_TSuccess GHOST_ActivateWindowDrawingContext(GHOST_WindowHandle windowhandle)
GHOST_TSuccess GHOST_GetModifierKeyState(GHOST_SystemHandle systemhandle, GHOST_TModifierKeyMask mask, int *isDown)
GHOST_TEventType GHOST_GetEventType(GHOST_EventHandle eventhandle)
void GHOST_DispatchEvents(GHOST_SystemHandle systemhandle)
void GHOST_GetMainDisplayDimensions(GHOST_SystemHandle systemhandle, GHOST_TUns32 *width, GHOST_TUns32 *height)
GHOST_EventConsumerHandle GHOST_CreateEventConsumer(GHOST_EventCallbackProcPtr eventCallback, GHOST_TUserDataPtr userdata)
Definition: GHOST_C-api.cpp:74
GHOST_RectangleHandle GHOST_GetClientBounds(GHOST_WindowHandle windowhandle)
@ GHOST_kWindowStateNormal
Definition: GHOST_Types.h:145
void * GHOST_TUserDataPtr
Definition: GHOST_Types.h:89
unsigned int GHOST_TUns32
Definition: GHOST_Types.h:64
GHOST_TEventType
Definition: GHOST_Types.h:177
@ GHOST_kEventWindowClose
Definition: GHOST_Types.h:197
@ GHOST_kEventWindowMove
Definition: GHOST_Types.h:202
@ GHOST_kEventWindowSize
Definition: GHOST_Types.h:201
@ GHOST_kEventDraggingDropDone
Definition: GHOST_Types.h:208
@ GHOST_kEventCursorMove
Definition: GHOST_Types.h:180
@ GHOST_kEventButtonUp
Mouse button event.
Definition: GHOST_Types.h:182
@ GHOST_kEventWindowActivate
Definition: GHOST_Types.h:198
@ GHOST_kEventWindowDeactivate
Definition: GHOST_Types.h:199
@ GHOST_kEventButtonDown
Mouse move event.
Definition: GHOST_Types.h:181
@ GHOST_kEventKeyDown
Trackpad event.
Definition: GHOST_Types.h:191
@ GHOST_kEventKeyUp
Definition: GHOST_Types.h:192
@ GHOST_kEventQuitRequest
Definition: GHOST_Types.h:195
@ GHOST_kKey5
Definition: GHOST_Types.h:290
@ GHOST_kKey4
Definition: GHOST_Types.h:289
@ GHOST_kKeyNumpad3
Definition: GHOST_Types.h:365
@ GHOST_kKeyNumpad1
Definition: GHOST_Types.h:363
@ GHOST_kKey3
Definition: GHOST_Types.h:288
@ GHOST_kKeyI
Definition: GHOST_Types.h:308
@ GHOST_kKeyEnter
Definition: GHOST_Types.h:273
@ GHOST_kKeyP
Definition: GHOST_Types.h:315
@ GHOST_kKeyNumpadSlash
Definition: GHOST_Types.h:377
@ GHOST_kKeyRightArrow
Definition: GHOST_Types.h:347
@ GHOST_kKeyNumpad4
Definition: GHOST_Types.h:366
@ GHOST_kKeyMinus
Definition: GHOST_Types.h:279
@ GHOST_kKey6
Definition: GHOST_Types.h:291
@ GHOST_kKey0
Definition: GHOST_Types.h:285
@ GHOST_kKeyDownArrow
Definition: GHOST_Types.h:349
@ GHOST_kKeyNumpadPeriod
Definition: GHOST_Types.h:372
@ GHOST_kKeyF
Definition: GHOST_Types.h:305
@ GHOST_kKey1
Definition: GHOST_Types.h:286
@ GHOST_kKey8
Definition: GHOST_Types.h:293
@ GHOST_kKeyNumpad2
Definition: GHOST_Types.h:364
@ GHOST_kKeyPeriod
Definition: GHOST_Types.h:281
@ GHOST_kKeyNumpadPlus
Definition: GHOST_Types.h:374
@ GHOST_kKey9
Definition: GHOST_Types.h:294
@ GHOST_kKeyNumpad5
Definition: GHOST_Types.h:367
@ GHOST_kKeyLeftArrow
Definition: GHOST_Types.h:346
@ GHOST_kKeyEqual
Definition: GHOST_Types.h:297
@ GHOST_kKey7
Definition: GHOST_Types.h:292
@ GHOST_kKeyNumpad6
Definition: GHOST_Types.h:368
@ GHOST_kKeyNumpad8
Definition: GHOST_Types.h:370
@ GHOST_kKeyNumpad9
Definition: GHOST_Types.h:371
@ GHOST_kKeyUpArrow
Definition: GHOST_Types.h:348
@ GHOST_kKeyNumpad0
Definition: GHOST_Types.h:362
@ GHOST_kKeyA
Definition: GHOST_Types.h:300
@ GHOST_kKey2
Definition: GHOST_Types.h:287
@ GHOST_kKeyNumpad7
Definition: GHOST_Types.h:369
@ GHOST_kKeyEsc
Definition: GHOST_Types.h:275
@ GHOST_kKeyPlus
Definition: GHOST_Types.h:280
@ GHOST_kKeySlash
Definition: GHOST_Types.h:282
@ GHOST_kKeyNumpadEnter
Definition: GHOST_Types.h:373
@ GHOST_kKeyNumpadMinus
Definition: GHOST_Types.h:375
@ GHOST_kKeySpace
Definition: GHOST_Types.h:276
@ GHOST_kDrawingContextTypeOpenGL
Definition: GHOST_Types.h:158
@ GHOST_kButtonMaskRight
Definition: GHOST_Types.h:168
@ GHOST_kButtonMaskLeft
Definition: GHOST_Types.h:166
@ GHOST_kButtonMaskMiddle
Definition: GHOST_Types.h:167
@ GHOST_kModifierKeyRightControl
Definition: GHOST_Types.h:139
@ GHOST_kModifierKeyLeftControl
Definition: GHOST_Types.h:138
@ GHOST_kModifierKeyRightAlt
Definition: GHOST_Types.h:137
@ GHOST_kModifierKeyRightShift
Definition: GHOST_Types.h:135
@ GHOST_kModifierKeyLeftAlt
Definition: GHOST_Types.h:136
@ GHOST_kModifierKeyLeftShift
Definition: GHOST_Types.h:134
@ GHOST_kDragnDropTypeFilenames
Definition: GHOST_Types.h:479
struct GPUContext GPUContext
Definition: GPU_context.h:44
void GPU_context_discard(GPUContext *)
Definition: gpu_context.cc:113
GPUContext * GPU_context_create(void *ghost_window)
Definition: gpu_context.cc:99
void GPU_context_active_set(GPUContext *)
Definition: gpu_context.cc:121
void immUniformColor3ub(unsigned char r, unsigned char g, unsigned char b)
void immUnbindProgram(void)
void immVertex2f(uint attr_id, float x, float y)
void immBindBuiltinProgram(eGPUBuiltinShader shader_id)
void immUniform1i(const char *name, int x)
GPUVertFormat * immVertexFormat(void)
void immUniformColor3f(float r, float g, float b)
void immAttr2f(uint attr_id, float x, float y)
void immBegin(GPUPrimType, uint vertex_len)
void immEnd(void)
void imm_draw_box_checker_2d_ex(float x1, float y1, float x2, float y2, const float color_primary[4], const float color_secondary[4], int checker_size)
void GPU_init(void)
Definition: gpu_init_exit.c:43
void GPU_exit(void)
Definition: gpu_init_exit.c:62
_GL_VOID GLfloat value _GL_VOID_RET _GL_VOID const GLuint GLboolean *residences _GL_BOOL_RET _GL_VOID GLsizei GLfloat GLfloat GLfloat GLfloat const GLubyte *bitmap _GL_VOID_RET _GL_VOID GLenum type
void GPU_matrix_pop(void)
Definition: gpu_matrix.cc:142
void GPU_matrix_ortho_set(float left, float right, float bottom, float top, float near, float far)
Definition: gpu_matrix.cc:415
void GPU_matrix_identity_projection_set(void)
Definition: gpu_matrix.cc:170
void GPU_matrix_pop_projection(void)
Definition: gpu_matrix.cc:156
void GPU_matrix_push(void)
Definition: gpu_matrix.cc:135
void GPU_matrix_identity_set(void)
Definition: gpu_matrix.cc:184
void GPU_matrix_push_projection(void)
Definition: gpu_matrix.cc:149
@ GPU_PRIM_TRI_FAN
Definition: GPU_primitive.h:41
@ GPU_PRIM_LINES
Definition: GPU_primitive.h:36
void GPU_shader_free_builtin_shaders(void)
@ GPU_SHADER_2D_UNIFORM_COLOR
Definition: GPU_shader.h:171
@ GPU_SHADER_2D_IMAGE_COLOR
Definition: GPU_shader.h:187
@ GPU_BLEND_NONE
Definition: GPU_state.h:55
@ GPU_BLEND_ALPHA
Definition: GPU_state.h:57
void GPU_blend(eGPUBlend blend)
Definition: gpu_state.cc:55
void GPU_scissor(int x, int y, int width, int height)
Definition: gpu_state.cc:204
void GPU_viewport(int x, int y, int width, int height)
Definition: gpu_state.cc:210
struct GPUTexture GPUTexture
Definition: GPU_texture.h:33
eGPUDataFormat
Definition: GPU_texture.h:171
@ GPU_DATA_UBYTE
Definition: GPU_texture.h:175
@ GPU_DATA_FLOAT
Definition: GPU_texture.h:172
void GPU_texture_update(GPUTexture *tex, eGPUDataFormat data_format, const void *data)
Definition: gpu_texture.cc:391
void GPU_texture_free(GPUTexture *tex)
Definition: gpu_texture.cc:508
void GPU_texture_filter_mode(GPUTexture *tex, bool use_filter)
Definition: gpu_texture.cc:468
void GPU_texture_unbind(GPUTexture *tex)
Definition: gpu_texture.cc:421
GPUTexture * GPU_texture_create_2d(const char *name, int w, int h, int mip_len, eGPUTextureFormat format, const float *data)
Definition: gpu_texture.cc:250
eGPUTextureFormat
Definition: GPU_texture.h:84
@ GPU_RGBA16F
Definition: GPU_texture.h:94
@ GPU_RGB16F
Definition: GPU_texture.h:128
@ GPU_RGBA8
Definition: GPU_texture.h:88
void GPU_texture_bind(GPUTexture *tex, int unit)
Definition: gpu_texture.cc:415
@ GPU_FETCH_FLOAT
uint GPU_vertformat_attr_add(GPUVertFormat *, const char *name, GPUVertCompType, uint comp_len, GPUVertFetchMode)
@ GPU_COMP_F32
void IMB_display_buffer_release(void *cache_handle)
bool IMB_colormanagement_setup_glsl_draw(const struct ColorManagedViewSettings *view_settings, const struct ColorManagedDisplaySettings *display_settings, float dither, bool predivide)
void IMB_colormanagement_init_default_view_settings(struct ColorManagedViewSettings *view_settings, const struct ColorManagedDisplaySettings *display_settings)
unsigned char * IMB_display_buffer_acquire(struct ImBuf *ibuf, const struct ColorManagedViewSettings *view_settings, const struct ColorManagedDisplaySettings *display_settings, void **cache_handle)
const char * IMB_colormanagement_role_colorspace_name_get(int role)
@ COLOR_ROLE_DEFAULT_BYTE
void IMB_colormanagement_finish_glsl_draw(void)
bool IMB_colormanagement_setup_glsl_draw_from_space(const struct ColorManagedViewSettings *view_settings, const struct ColorManagedDisplaySettings *display_settings, struct ColorSpace *colorspace, float dither, bool predivide, bool do_overlay_merge)
bool IMB_anim_get_fps(struct anim *anim, short *frs_sec, float *frs_sec_base, bool no_av_base)
Definition: anim_movie.c:1691
@ IMB_PROXY_NONE
Definition: IMB_imbuf.h:318
void IMB_freeImBuf(struct ImBuf *ibuf)
Definition: allocimbuf.c:211
void IMB_close_anim(struct anim *anim)
Definition: anim_movie.c:229
size_t IMB_get_size_in_memory(struct ImBuf *ibuf)
Definition: allocimbuf.c:629
struct anim * IMB_open_anim(const char *name, int ib_flags, int streamindex, char colorspace[IM_MAX_SPACE])
Definition: anim_movie.c:282
void IMB_exit(void)
Definition: module.c:39
struct ImBuf * IMB_loadiffname(const char *filepath, int flags, char colorspace[IM_MAX_SPACE])
Definition: readimage.c:224
bool IMB_isanim(const char *filepath)
Definition: util.c:399
struct ImBuf * IMB_ibImageFromMemory(const unsigned char *mem, size_t size, int flags, char colorspace[IM_MAX_SPACE], const char *descr)
Definition: readimage.c:99
bool IMB_ispic(const char *filepath)
Definition: util.c:197
struct ImBuf * IMB_anim_absolute(struct anim *anim, int position, IMB_Timecode_Type tc, IMB_Proxy_Size preview_size)
Definition: anim_movie.c:1580
int IMB_anim_get_duration(struct anim *anim, IMB_Timecode_Type tc)
Definition: anim_movie.c:1671
@ IMB_TC_NONE
Definition: IMB_imbuf.h:300
Contains defines and structs used throughout the imbuf module.
@ IB_rect
#define IMB_FTYPE_NONE
Read Guarded memory(de)allocation.
Group RGB to Bright Vector Camera CLAMP
Platform independent time functions.
static DBVT_INLINE btScalar size(const btDbvtVolume &a)
Definition: btDbvt.cpp:52
static btDbvtVolume bounds(btDbvtNode **leaves, int count)
Definition: btDbvt.cpp:299
OperationNode * node
FILE * file
double time
#define str(s)
uint pos
void GPU_clear_color(float red, float green, float blue, float alpha)
int count
format
Definition: logImageCore.h:47
void(* MEM_freeN)(void *vmemh)
Definition: mallocn.c:41
unsigned int(* MEM_get_memory_blocks_in_use)(void)
Definition: mallocn.c:60
void *(* MEM_callocN)(size_t len, const char *str)
Definition: mallocn.c:45
void *(* MEM_mallocN)(size_t len, const char *str)
Definition: mallocn.c:47
void(* MEM_printmemlist)(void)
Definition: mallocn.c:53
static unsigned int totblock
static unsigned a[3]
Definition: RandGen.cpp:92
GHOST_TButtonMask button
Definition: GHOST_Types.h:443
GHOST_TEventDataPtr data
Definition: GHOST_Types.h:492
GHOST_TDragnDropTypes dataType
Definition: GHOST_Types.h:490
GHOST_TUns8 ** strings
Definition: GHOST_Types.h:513
int channels
struct ColorSpace * rect_colorspace
float dither
unsigned char planes
char name[IMB_FILENAME_SIZE]
enum eImbFileType ftype
unsigned int * rect
float * rect_float
struct ColorSpace * float_colorspace
void * data
Definition: DNA_listBase.h:42
void * last
Definition: DNA_listBase.h:47
void * first
Definition: DNA_listBase.h:47
struct anim * anim
Definition: wm_playanim.c:239
struct PlayAnimPict * prev
Definition: wm_playanim.c:234
struct ImBuf * ibuf
Definition: wm_playanim.c:238
size_t size_in_memory
Definition: wm_playanim.c:246
LinkData * frame_cache_node
Definition: wm_playanim.c:245
struct PlayAnimPict * next
Definition: wm_playanim.c:234
uchar * mem
Definition: wm_playanim.c:235
const char * name
Definition: wm_playanim.c:237
short next_frame
Definition: wm_playanim.c:110
ColorManagedViewSettings view_settings
Definition: wm_playanim.c:141
bool wait2
Definition: wm_playanim.c:118
bool sstep
Definition: wm_playanim.c:117
struct PlayAnimPict * picture
Definition: wm_playanim.c:129
bool pingpong
Definition: wm_playanim.c:114
char dropped_file[FILE_MAX]
Definition: wm_playanim.c:136
bool stopped
Definition: wm_playanim.c:119
float zoom
Definition: wm_playanim.c:106
bool draw_flip[2]
Definition: wm_playanim.c:124
short direction
Definition: wm_playanim.c:109
bool turbo
Definition: wm_playanim.c:113
bool noskip
Definition: wm_playanim.c:115
ColorManagedDisplaySettings display_settings
Definition: wm_playanim.c:142
bool indicator
Definition: wm_playanim.c:116
bool need_frame_update
Definition: wm_playanim.c:138
bool loading
Definition: wm_playanim.c:122
int frame_cursor_x
Definition: wm_playanim.c:139
GPUContext * gpu_context
Definition: wm_playanim.c:185
GHOST_SystemHandle ghost_system
Definition: wm_playanim.c:183
Definition: IMB_anim.h:87
char first[1024]
Definition: IMB_anim.h:100
float xmax
Definition: DNA_vec_types.h:85
float xmin
Definition: DNA_vec_types.h:85
float ymax
Definition: DNA_vec_types.h:86
float ymin
Definition: DNA_vec_types.h:86
void PIL_sleep_ms(int ms)
Definition: time.c:100
double PIL_check_seconds_timer(void)
Definition: time.c:80
static void playanim_gl_matrix(void)
Definition: wm_playanim.c:199
static char * wm_main_playanim_intern(int argc, const char **argv)
Definition: wm_playanim.c:1383
static int ghost_event_proc(GHOST_EventHandle evt, GHOST_TUserDataPtr ps_void)
Definition: wm_playanim.c:869
struct PlayAnimPict PlayAnimPict
void WM_main_playanim(int argc, const char **argv)
Definition: wm_playanim.c:1841
size_t memory_limit
Definition: wm_playanim.c:267
static void frame_cache_remove(PlayAnimPict *pic)
Definition: wm_playanim.c:288
static struct WindowStateGlobal g_WS
static void playanim_window_open(const char *title, int posx, int posy, int sizex, int sizey)
Definition: wm_playanim.c:1338
static bool fromdisk
Definition: wm_playanim.c:252
static struct ListBase picsbase
Definition: wm_playanim.c:250
static void frame_cache_touch(PlayAnimPict *pic)
Definition: wm_playanim.c:304
static void build_pict_list_ex(PlayState *ps, const char *first, int totframes, int fstep, int fontid)
Definition: wm_playanim.c:616
static double swaptime
Definition: wm_playanim.c:253
static int pupdate_time(void)
Definition: wm_playanim.c:372
static void frame_cache_add(PlayAnimPict *pic)
Definition: wm_playanim.c:275
static bool frame_cache_limit_exceeded(void)
Definition: wm_playanim.c:311
static void playanim_window_get_size(int *r_width, int *r_height)
Definition: wm_playanim.c:191
static void playanim_window_zoom(struct PlayState *ps, const float zoom_offset)
Definition: wm_playanim.c:1361
static ImBuf * ibuf_from_picture(PlayAnimPict *pic)
Definition: wm_playanim.c:335
static PlayAnimPict * playanim_step(PlayAnimPict *playanim, int step)
Definition: wm_playanim.c:357
static void change_frame(PlayState *ps)
Definition: wm_playanim.c:809
static void frame_cache_limit_apply(ImBuf *ibuf_keep)
Definition: wm_playanim.c:318
size_t pics_size_in_memory
Definition: wm_playanim.c:265
int pics_len
Definition: wm_playanim.c:263
static void update_sound_fps(void)
Definition: wm_playanim.c:791
struct PlayState PlayState
eWS_Qual
Definition: wm_playanim.c:166
@ WS_QUAL_LCTRL
Definition: wm_playanim.c:173
@ WS_QUAL_RMOUSE
Definition: wm_playanim.c:178
@ WS_QUAL_MOUSE
Definition: wm_playanim.c:179
@ WS_QUAL_CTRL
Definition: wm_playanim.c:175
@ WS_QUAL_RALT
Definition: wm_playanim.c:171
@ WS_QUAL_MMOUSE
Definition: wm_playanim.c:177
@ WS_QUAL_LMOUSE
Definition: wm_playanim.c:176
@ WS_QUAL_LALT
Definition: wm_playanim.c:170
@ WS_QUAL_ALT
Definition: wm_playanim.c:172
@ WS_QUAL_SHIFT
Definition: wm_playanim.c:169
@ WS_QUAL_RCTRL
Definition: wm_playanim.c:174
@ WS_QUAL_LSHIFT
Definition: wm_playanim.c:167
@ WS_QUAL_RSHIFT
Definition: wm_playanim.c:168
static void tag_change_frame(PlayState *ps, int cx)
Definition: wm_playanim.c:803
static void playanim_toscreen(PlayState *ps, PlayAnimPict *picture, struct ImBuf *ibuf, int fontid, int fstep)
Definition: wm_playanim.c:528
#define PLAY_FRAME_CACHE_MAX
Definition: wm_playanim.c:94
static double ptottime
Definition: wm_playanim.c:253
static void draw_display_buffer(PlayState *ps, ImBuf *ibuf)
Definition: wm_playanim.c:455
static struct @1163 g_frame_cache
static void playanim_event_qual_update(void)
Definition: wm_playanim.c:207
static void * ocio_transform_ibuf(PlayState *ps, ImBuf *ibuf, bool *r_glsl_used, eGPUTextureFormat *r_format, eGPUDataFormat *r_data, void **r_buffer_cache_handle)
Definition: wm_playanim.c:383
static void build_pict_list(PlayState *ps, const char *first, int totframes, int fstep, int fontid)
Definition: wm_playanim.c:784
struct ListBase pics
Definition: wm_playanim.c:261