/* return path for restart */ static char *wm_main_playanim_intern(int argc, const char **argv) { struct ImBuf *ibuf = NULL; static char filepath[FILE_MAX]; /* abused to return dropped file path */ GHOST_TUns32 maxwinx, maxwiny; int i; /* This was done to disambiguate the name for use under c++. */ struct anim *anim = NULL; int start_x = 0, start_y = 0; int sfra = -1; int efra = -1; int totblock; PlayState ps = {0}; /* ps.doubleb = TRUE;*/ /* UNUSED */ ps.go = TRUE; ps.direction = TRUE; ps.next_frame = 1; ps.once = FALSE; ps.turbo = FALSE; ps.pingpong = FALSE; ps.noskip = FALSE; ps.sstep = FALSE; ps.wait2 = FALSE; ps.stopped = FALSE; ps.picture = NULL; ps.dropped_file[0] = 0; ps.zoom = 1.0f; /* resetmap = FALSE */ ps.fstep = 1; ps.fontid = -1; while (argc > 1) { if (argv[1][0] == '-') { switch (argv[1][1]) { case 'm': fromdisk = TRUE; break; case 'p': if (argc > 3) { start_x = atoi(argv[2]); start_y = atoi(argv[3]); argc -= 2; argv += 2; } else { printf("too few arguments for -p (need 2): skipping\n"); } break; case 'f': if (argc > 3) { double fps = atof(argv[2]); double fps_base = atof(argv[3]); if (fps == 0.0) { fps = 1; printf("invalid fps," "forcing 1\n"); } swaptime = fps_base / fps; argc -= 2; argv += 2; } else { printf("too few arguments for -f (need 2): skipping\n"); } break; case 's': sfra = MIN2(MAXFRAME, MAX2(1, atoi(argv[2]) )); argc--; argv++; break; case 'e': efra = MIN2(MAXFRAME, MAX2(1, atoi(argv[2]) )); argc--; argv++; break; case 'j': ps.fstep = MIN2(MAXFRAME, MAX2(1, atoi(argv[2]))); swaptime *= ps.fstep; argc--; argv++; break; default: printf("unknown option '%c': skipping\n", argv[1][1]); break; } argc--; argv++; } else { break; } } if (argc > 1) { BLI_strncpy(filepath, argv[1], sizeof(filepath)); } else { BLI_current_working_dir(filepath, sizeof(filepath)); BLI_add_slash(filepath); } if (IMB_isanim(filepath)) { /* 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); anim = NULL; } } else if (!IMB_ispic(filepath)) { printf("%s: '%s' not an image file\n", __func__, filepath); exit(1); } if (ibuf == NULL) { /* OCIO_TODO: support different input color space */ ibuf = IMB_loadiffname(filepath, IB_rect, NULL); } if (ibuf == NULL) { printf("%s: '%s' couldn't open\n", __func__, filepath); exit(1); } #if 0 //XXX25 #if !defined(WIN32) && !defined(__APPLE__) if (fork()) exit(0); #endif #endif //XXX25 { GHOST_EventConsumerHandle consumer = GHOST_CreateEventConsumer(ghost_event_proc, &ps); 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); /* unified matrix, note it affects offset for drawing */ glMatrixMode(GL_PROJECTION); glLoadIdentity(); glOrtho(0.0f, 1.0f, 0.0f, 1.0f, -1.0f, 1.0f); glMatrixMode(GL_MODELVIEW); } GHOST_GetMainDisplayDimensions(g_WS.ghost_system, &maxwinx, &maxwiny); //GHOST_ActivateWindowDrawingContext(g_WS.ghost_window); /* initialize the font */ BLF_init(11, 72); ps.fontid = BLF_load_mem("monospace", (unsigned char *)datatoc_bmonofont_ttf, datatoc_bmonofont_ttf_size); BLF_size(ps.fontid, 11, 72); ps.ibufx = ibuf->x; ps.ibufy = ibuf->y; ps.win_x = ps.ibufx; ps.win_y = ps.ibufy; if (maxwinx % ibuf->x) maxwinx = ibuf->x * (1 + (maxwinx / ibuf->x)); if (maxwiny % ibuf->y) maxwiny = ibuf->y * (1 + (maxwiny / ibuf->y)); glClearColor(0.1, 0.1, 0.1, 0.0); glClear(GL_COLOR_BUFFER_BIT); GHOST_SwapWindowBuffers(g_WS.ghost_window); if (sfra == -1 || efra == -1) { /* one of the frames was invalid, just use all images */ sfra = 1; efra = MAXFRAME; } build_pict_list(&ps, filepath, (efra - sfra) + 1, ps.fstep, ps.fontid); for (i = 2; i < argc; i++) { BLI_strncpy(filepath, argv[i], sizeof(filepath)); build_pict_list(&ps, filepath, (efra - sfra) + 1, ps.fstep, ps.fontid); } IMB_freeImBuf(ibuf); ibuf = NULL; 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) { ps.picture = picsbase.first; } else { ps.picture = picsbase.last; } if (ps.picture == NULL) { printf("couldn't find pictures\n"); ps.go = FALSE; } if (ps.pingpong) { if (ps.direction == 1) { ps.picture = ps.picture->next; } else { ps.picture = ps.picture->prev; } } if (ptottime > 0.0) ptottime = 0.0; while (ps.picture) { int hasevent; #ifndef USE_IMB_CACHE if (ibuf != NULL && ibuf->ftype == 0) IMB_freeImBuf(ibuf); #endif if (ps.picture->ibuf) { ibuf = ps.picture->ibuf; } else if (ps.picture->anim) { 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, ps.picture->IB_flags, NULL, ps.picture->name); } else { /* use correct colorspace here */ ibuf = IMB_loadiffname(ps.picture->name, ps.picture->IB_flags, NULL); } 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 GHOST_SetTitle(g_WS.ghost_window, ps.picture->name); #endif while (pupdate_time()) PIL_sleep_ms(1); ptottime -= swaptime; playanim_toscreen(&ps, ps.picture, ibuf, ps.fontid, ps.fstep); } /* else delete */ else { printf("error: can't play this image type\n"); exit(0); } if (ps.once) { if (ps.picture->next == NULL) { ps.wait2 = TRUE; } else if (ps.picture->prev == NULL) { ps.wait2 = TRUE; } } ps.next_frame = ps.direction; while ( (hasevent = GHOST_ProcessEvents(g_WS.ghost_system, 0)) || ps.wait2 != 0) { if (hasevent) { GHOST_DispatchEvents(g_WS.ghost_system); } /* Note, this still draws for mousemoves on pause */ if (ps.wait2) { if (hasevent) { if (ibuf) { while (pupdate_time()) PIL_sleep_ms(1); ptottime -= swaptime; playanim_toscreen(&ps, ps.picture, ibuf, ps.fontid, ps.fstep); } } } if (!ps.go) { break; } } ps.wait2 = ps.sstep; if (ps.wait2 == 0 && ps.stopped == 0) { ps.stopped = TRUE; } pupdate_time(); if (ps.picture && ps.next_frame) { /* always at least set one step */ while (ps.picture) { ps.picture = playanim_step(ps.picture, ps.next_frame); if (ps.once && ps.picture != NULL) { if (ps.picture->next == NULL) { ps.wait2 = TRUE; } else if (ps.picture->prev == NULL) { ps.wait2 = TRUE; } } if (ps.wait2 || ptottime < swaptime || ps.turbo || ps.noskip) break; ptottime -= swaptime; } if (ps.picture == NULL && ps.sstep) { ps.picture = playanim_step(ps.picture, ps.next_frame); } } if (ps.go == FALSE) { break; } } } ps.picture = picsbase.first; anim = NULL; while (ps.picture) { if (ps.picture && ps.picture->anim && (anim != ps.picture->anim)) { // to prevent divx crashes anim = ps.picture->anim; IMB_close_anim(anim); } if (ps.picture->ibuf) { IMB_freeImBuf(ps.picture->ibuf); } if (ps.picture->mem) { MEM_freeN(ps.picture->mem); } ps.picture = ps.picture->next; } /* cleanup */ #ifndef USE_IMB_CACHE if (ibuf) IMB_freeImBuf(ibuf); #endif BLI_freelistN(&picsbase); #if 0 // XXX25 free_blender(); #else /* we still miss freeing a lot!, * but many areas could skip initialization too for anim play */ BLF_exit(); #endif GHOST_DisposeWindow(g_WS.ghost_system, g_WS.ghost_window); /* early exit, IMB and BKE should be exited only in end */ if (ps.dropped_file[0]) { BLI_strncpy(filepath, ps.dropped_file, sizeof(filepath)); return filepath; } IMB_exit(); BKE_images_exit(); 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(); #endif } return NULL; }
/* called in creator.c even... tsk, split this! */ void WM_exit(bContext *C) { wmWindow *win; sound_exit(); /* first wrap up running stuff, we assume only the active WM is running */ /* modal handlers are on window level freed, others too? */ /* note; same code copied in wm_files.c */ if(C && CTX_wm_manager(C)) { WM_jobs_stop_all(CTX_wm_manager(C)); for(win= CTX_wm_manager(C)->windows.first; win; win= win->next) { CTX_wm_window_set(C, win); /* needed by operator close callbacks */ WM_event_remove_handlers(C, &win->handlers); WM_event_remove_handlers(C, &win->modalhandlers); ED_screen_exit(C, win, win->screen); } } wm_operatortype_free(); WM_menutype_free(); /* all non-screen and non-space stuff editors did, like editmode */ if(C) ED_editors_exit(C); // XXX // BIF_GlobalReebFree(); // BIF_freeRetarget(); BIF_freeTemplates(C); free_ttfont(); /* bke_font.h */ free_openrecent(); BKE_freecubetable(); fastshade_free_render(); /* shaded view */ ED_preview_free_dbase(); /* frees a Main dbase, before free_blender! */ if(C && CTX_wm_manager(C)) wm_free_reports(C); /* before free_blender! - since the ListBases get freed there */ free_blender(); /* blender.c, does entire library and spacetypes */ // free_matcopybuf(); free_anim_copybuf(); free_anim_drivers_copybuf(); free_posebuf(); // free_vertexpaint(); // free_imagepaint(); // fsmenu_free(); BLF_exit(); RE_FreeAllRender(); RE_engines_exit(); // free_txt_data(); #ifndef DISABLE_PYTHON /* XXX - old note */ /* before free_blender so py's gc happens while library still exists */ /* needed at least for a rare sigsegv that can happen in pydrivers */ /* Update for blender 2.5, move after free_blender because blender now holds references to PyObject's * so decref'ing them after python ends causes bad problems every time * the pyDriver bug can be fixed if it happens again we can deal with it then */ BPY_end_python(); #endif libtiff_exit(); #ifdef WITH_QUICKTIME quicktime_exit(); #endif if (!G.background) { // XXX UI_filelist_free_icons(); } GPU_buffer_pool_free(0); GPU_extensions_exit(); // if (copybuf) MEM_freeN(copybuf); // if (copybufinfo) MEM_freeN(copybufinfo); BKE_undo_save_quit(); // saves quit.blend if global undo is on BKE_reset_undo(); ED_file_exit(); /* for fsmenu */ UI_exit(); BKE_userdef_free(); RNA_exit(); /* should be after BPY_end_python so struct python slots are cleared */ wm_ghost_exit(); CTX_free(C); SYS_DeleteSystem(SYS_GetSystem()); if(MEM_get_memory_blocks_in_use()!=0) { printf("Error Totblock: %d\n", MEM_get_memory_blocks_in_use()); MEM_printmemlist(); } wm_autosave_delete(); printf("\nBlender quit\n"); #ifdef WIN32 /* ask user to press enter when in debug mode */ if(G.f & G_DEBUG) { printf("press enter key to exit...\n\n"); getchar(); } #endif exit(G.afbreek==1); }
/* note, doesnt run exit() call WM_exit() for that */ void WM_exit_ext(bContext *C, const bool do_python) { wmWindowManager *wm = C ? CTX_wm_manager(C) : NULL; BKE_sound_exit(); /* first wrap up running stuff, we assume only the active WM is running */ /* modal handlers are on window level freed, others too? */ /* note; same code copied in wm_files.c */ if (C && wm) { wmWindow *win; if (!G.background) { if ((U.uiflag2 & USER_KEEP_SESSION) || BKE_undo_is_valid(NULL)) { /* save the undo state as quit.blend */ char filename[FILE_MAX]; bool has_edited; int fileflags = G.fileflags & ~(G_FILE_COMPRESS | G_FILE_AUTOPLAY | G_FILE_HISTORY); BLI_make_file_string("/", filename, BKE_tempdir_base(), BLENDER_QUIT_FILE); has_edited = ED_editors_flush_edits(C, false); if ((has_edited && BLO_write_file(CTX_data_main(C), filename, fileflags, NULL, NULL)) || BKE_undo_save_file(filename)) { printf("Saved session recovery to '%s'\n", filename); } } } WM_jobs_kill_all(wm); for (win = wm->windows.first; win; win = win->next) { CTX_wm_window_set(C, win); /* needed by operator close callbacks */ WM_event_remove_handlers(C, &win->handlers); WM_event_remove_handlers(C, &win->modalhandlers); ED_screen_exit(C, win, win->screen); } } BKE_addon_pref_type_free(); wm_operatortype_free(); wm_dropbox_free(); WM_menutype_free(); WM_uilisttype_free(); /* all non-screen and non-space stuff editors did, like editmode */ if (C) ED_editors_exit(C); // XXX // BIF_GlobalReebFree(); // BIF_freeRetarget(); BIF_freeTemplates(C); free_openrecent(); BKE_mball_cubeTable_free(); /* render code might still access databases */ RE_FreeAllRender(); RE_engines_exit(); ED_preview_free_dbase(); /* frees a Main dbase, before free_blender! */ if (C && wm) wm_free_reports(C); /* before free_blender! - since the ListBases get freed there */ BKE_sequencer_free_clipboard(); /* sequencer.c */ BKE_tracking_clipboard_free(); BKE_mask_clipboard_free(); #ifdef WITH_COMPOSITOR COM_deinitialize(); #endif free_blender(); /* blender.c, does entire library and spacetypes */ // free_matcopybuf(); free_anim_copybuf(); free_anim_drivers_copybuf(); free_fmodifiers_copybuf(); ED_gpencil_strokes_copybuf_free(); ED_clipboard_posebuf_free(); BKE_node_clipboard_clear(); BLF_exit(); #ifdef WITH_INTERNATIONAL BLF_free_unifont(); BLF_free_unifont_mono(); BLT_lang_free(); #endif ANIM_keyingset_infos_exit(); // free_txt_data(); #ifdef WITH_PYTHON /* option not to close python so we can use 'atexit' */ if (do_python) { /* XXX - old note */ /* before free_blender so py's gc happens while library still exists */ /* needed at least for a rare sigsegv that can happen in pydrivers */ /* Update for blender 2.5, move after free_blender because blender now holds references to PyObject's * so decref'ing them after python ends causes bad problems every time * the pyDriver bug can be fixed if it happens again we can deal with it then */ BPY_python_end(); } #else (void)do_python; #endif #ifdef WITH_OPENSUBDIV openSubdiv_cleanup(); #endif if (!G.background) { GPU_global_buffer_pool_free(); GPU_free_unused_buffers(); GPU_exit(); } BKE_undo_reset(); ED_file_exit(); /* for fsmenu */ UI_exit(); BKE_userdef_free(); RNA_exit(); /* should be after BPY_python_end so struct python slots are cleared */ wm_ghost_exit(); CTX_free(C); #ifdef WITH_GAMEENGINE SYS_DeleteSystem(SYS_GetSystem()); #endif GHOST_DisposeSystemPaths(); BLI_threadapi_exit(); if (MEM_get_memory_blocks_in_use() != 0) { size_t mem_in_use = MEM_get_memory_in_use() + MEM_get_memory_in_use(); printf("Error: Not freed memory blocks: %u, total unfreed memory %f MB\n", MEM_get_memory_blocks_in_use(), (double)mem_in_use / 1024 / 1024); MEM_printmemlist(); } wm_autosave_delete(); BKE_tempdir_session_purge(); }
/* note, doesnt run exit() call WM_exit() for that */ void WM_exit_ext(bContext *C, const short do_python) { wmWindow *win; sound_exit(); /* first wrap up running stuff, we assume only the active WM is running */ /* modal handlers are on window level freed, others too? */ /* note; same code copied in wm_files.c */ if (C && CTX_wm_manager(C)) { WM_jobs_stop_all(CTX_wm_manager(C)); for (win = CTX_wm_manager(C)->windows.first; win; win = win->next) { CTX_wm_window_set(C, win); /* needed by operator close callbacks */ WM_event_remove_handlers(C, &win->handlers); WM_event_remove_handlers(C, &win->modalhandlers); ED_screen_exit(C, win, win->screen); } } wm_operatortype_free(); wm_dropbox_free(); WM_menutype_free(); /* all non-screen and non-space stuff editors did, like editmode */ if (C) ED_editors_exit(C); // XXX // BIF_GlobalReebFree(); // BIF_freeRetarget(); BIF_freeTemplates(C); BKE_vfont_free_global_ttf(); /* bke_font.h */ free_openrecent(); BKE_mball_cubeTable_free(); ED_preview_free_dbase(); /* frees a Main dbase, before free_blender! */ if (C && CTX_wm_manager(C)) wm_free_reports(C); /* before free_blender! - since the ListBases get freed there */ seq_free_clipboard(); /* sequencer.c */ BKE_tracking_clipboard_free(); free_blender(); /* blender.c, does entire library and spacetypes */ // free_matcopybuf(); free_anim_copybuf(); free_anim_drivers_copybuf(); free_fmodifiers_copybuf(); free_posebuf(); BLF_exit(); #ifdef WITH_INTERNATIONAL BLF_free_unifont(); #endif ANIM_keyingset_infos_exit(); RE_FreeAllRender(); RE_engines_exit(); // free_txt_data(); #ifdef WITH_PYTHON /* option not to close python so we can use 'atexit' */ if (do_python) { /* XXX - old note */ /* before free_blender so py's gc happens while library still exists */ /* needed at least for a rare sigsegv that can happen in pydrivers */ /* Update for blender 2.5, move after free_blender because blender now holds references to PyObject's * so decref'ing them after python ends causes bad problems every time * the pyDriver bug can be fixed if it happens again we can deal with it then */ BPY_python_end(); } #else (void)do_python; #endif GPU_global_buffer_pool_free(); GPU_free_unused_buffers(); GPU_extensions_exit(); if (!G.background) { BKE_undo_save_quit(); /* saves quit.blend if global undo is on */ } BKE_reset_undo(); ED_file_exit(); /* for fsmenu */ UI_exit(); BKE_userdef_free(); RNA_exit(); /* should be after BPY_python_end so struct python slots are cleared */ wm_ghost_exit(); CTX_free(C); #ifdef WITH_GAMEENGINE SYS_DeleteSystem(SYS_GetSystem()); #endif GHOST_DisposeSystemPaths(); if (MEM_get_memory_blocks_in_use() != 0) { printf("Error: Not freed memory blocks: %d\n", MEM_get_memory_blocks_in_use()); MEM_printmemlist(); } wm_autosave_delete(); printf("\nBlender quit\n"); #ifdef WIN32 /* ask user to press a key when in debug mode */ if (G.debug & G_DEBUG) { printf("Press any key to exit . . .\n\n"); wait_for_console_key(); } #endif }