From c0b3ab6ceb4ca77ec7b05bd5bed090a15705303a Mon Sep 17 00:00:00 2001 From: Andrea Weikert Date: Wed, 10 Mar 2010 19:30:20 +0000 Subject: filebrowser: * move own thread handling for thumbnails to WM_jobs * cleanup of thumbnail creation code * added function to kill the job, which actually allows thread to terminate gracefully vc9 projectfiles: * fixed some missing includes for release target! --- intern/ghost/make/msvc_9_0/ghost.vcproj | 6 +- .../blender/makesrna/RNA_makesrna.vcproj | 10 +- projectfiles_vc9/blender/makesrna/RNA_rna.vcproj | 2 +- .../gameengine/videotexture/TEX_Video.vcproj | 2 +- source/blender/editors/include/ED_fileselect.h | 5 + source/blender/editors/screen/area.c | 9 + source/blender/editors/space_file/file_draw.c | 10 +- source/blender/editors/space_file/file_intern.h | 3 +- source/blender/editors/space_file/file_ops.c | 62 ++---- source/blender/editors/space_file/filelist.c | 241 +++++++++++---------- source/blender/editors/space_file/filelist.h | 5 +- source/blender/editors/space_file/filesel.c | 23 +- source/blender/editors/space_file/space_file.c | 19 +- source/blender/imbuf/IMB_thumbs.h | 8 +- source/blender/imbuf/intern/thumbs.c | 66 +++--- source/blender/makesrna/intern/rna_space.c | 19 +- source/blender/windowmanager/WM_api.h | 1 + source/blender/windowmanager/intern/wm_jobs.c | 14 ++ 18 files changed, 256 insertions(+), 249 deletions(-) diff --git a/intern/ghost/make/msvc_9_0/ghost.vcproj b/intern/ghost/make/msvc_9_0/ghost.vcproj index 05a103791f1..a7779400488 100644 --- a/intern/ghost/make/msvc_9_0/ghost.vcproj +++ b/intern/ghost/make/msvc_9_0/ghost.vcproj @@ -44,7 +44,7 @@ Name="VCCLCompilerTool" Optimization="2" InlineFunctionExpansion="1" - AdditionalIncludeDirectories="..\..;..\..\..\..\..\build\msvc_9\intern\string\include;..\..\..\..\..\lib\windows\wintab\INCLUDE;..\..\..\..\..\build\msvc_9\extern\glew\include" + AdditionalIncludeDirectories="..\..;..\..\..\..\..\build\msvc_9\intern\string\include;..\..\..\..\..\lib\windows\wintab\INCLUDE;..\..\..\..\..\build\msvc_9\extern\glew\include;..\..\..\..\source\blender\imbuf;..\..\..\..\source\blender\makesdna" PreprocessorDefinitions="WIN32,NDEBUG,_LIB" StringPooling="true" RuntimeLibrary="0" @@ -197,7 +197,7 @@ spacedata.first : CTX_wm_space_data(C); + /* Special handling of filebrowser to stop background thread for + thumbnail creation - don't want to waste cpu resources if not showing + the filebrowser */ + if (sl->spacetype == SPACE_FILE) { + ED_fileselect_exit(C, (SpaceFile*)sl); + } + if(sl->next) { /* workaround for case of double prevspace, render window with a file browser on top of it */ diff --git a/source/blender/editors/space_file/file_draw.c b/source/blender/editors/space_file/file_draw.c index af836db398d..a2b4dcbac60 100644 --- a/source/blender/editors/space_file/file_draw.c +++ b/source/blender/editors/space_file/file_draw.c @@ -445,7 +445,7 @@ static void renamebutton_cb(bContext *C, void *arg1, char *oldname) if (!BLI_exists(newname)) { BLI_rename(orgname, newname); /* to make sure we show what is on disk */ - filelist_free(sfile->files); + ED_fileselect_clear(C, sfile); } else { BLI_strncpy(file->relname, oldname, strlen(oldname)+1); } @@ -557,9 +557,6 @@ void file_draw_list(const bContext *C, ARegion *ar) uiSetRoundBox(0); if ( FILE_IMGDISPLAY == params->display ) { - if ( (file->flags & IMAGEFILE) /* || (file->flags & MOVIEFILE) */) { - filelist_loadimage(files, i); - } is_icon = 0; imb = filelist_getimage(files, i); if (!imb) { @@ -624,11 +621,6 @@ void file_draw_list(const bContext *C, ARegion *ar) } } - /* XXX this timer is never removed, cause smooth view operator - to get executed all the time after closing file browser */ - if (!sfile->loadimage_timer) - sfile->loadimage_timer= WM_event_add_timer(CTX_wm_manager(C), CTX_wm_window(C), TIMER1, 1.0/30.0); /* max 30 frames/sec. */ - uiEndBlock(C, block); uiDrawBlock(C, block); diff --git a/source/blender/editors/space_file/file_intern.h b/source/blender/editors/space_file/file_intern.h index 1d239f1741e..8c6709e762c 100644 --- a/source/blender/editors/space_file/file_intern.h +++ b/source/blender/editors/space_file/file_intern.h @@ -58,7 +58,6 @@ void FILE_OT_select_bookmark(struct wmOperatorType *ot); void FILE_OT_bookmark_add(struct wmOperatorType *ot); void FILE_OT_delete_bookmark(struct wmOperatorType *ot); void FILE_OT_hidedot(struct wmOperatorType *ot); -void FILE_OT_loadimages(struct wmOperatorType *ot); void FILE_OT_execute(struct wmOperatorType *ot); void FILE_OT_cancel(struct wmOperatorType *ot); void FILE_OT_parent(struct wmOperatorType *ot); @@ -88,7 +87,7 @@ int file_hilight_set(struct SpaceFile *sfile, struct ARegion *ar, int mx, int my /* filesel.c */ float file_string_width(const char* str); float file_font_pointsize(); -void file_change_dir(struct SpaceFile *sfile, int checkdir); +void file_change_dir(bContext *C, int checkdir); int file_select_match(struct SpaceFile *sfile, const char *pattern); void autocomplete_directory(struct bContext *C, char *str, void *arg_v); diff --git a/source/blender/editors/space_file/file_ops.c b/source/blender/editors/space_file/file_ops.c index 4d9a045e252..ab259f1e1cb 100644 --- a/source/blender/editors/space_file/file_ops.c +++ b/source/blender/editors/space_file/file_ops.c @@ -125,8 +125,10 @@ static void clamp_to_filelist(int numfiles, int *first_file, int *last_file) } } -static FileSelect file_select(SpaceFile* sfile, ARegion* ar, const rcti* rect, short selecting, short toggle_one) +static FileSelect file_select(bContext* C, const rcti* rect, short selecting, short toggle_one) { + ARegion *ar= CTX_wm_region(C); + SpaceFile *sfile= CTX_wm_space_file(C); int first_file = -1; int last_file = -1; int act_file; @@ -184,7 +186,7 @@ static FileSelect file_select(SpaceFile* sfile, ARegion* ar, const rcti* rect, s BLI_add_slash(params->dir); } - file_change_dir(sfile, 0); + file_change_dir(C, 0); retval = FILE_SELECT_DIR; } } @@ -216,7 +218,7 @@ static int file_border_select_exec(bContext *C, wmOperator *op) BLI_isect_rcti(&(ar->v2d.mask), &rect, &rect); - if (FILE_SELECT_DIR == file_select(sfile, ar, &rect, selecting, 0)) { + if (FILE_SELECT_DIR == file_select(C, &rect, selecting, 0)) { WM_event_add_notifier(C, NC_SPACE|ND_SPACE_FILE_LIST, NULL); } else { WM_event_add_notifier(C, NC_SPACE|ND_SPACE_FILE_PARAMS, NULL); @@ -262,7 +264,7 @@ static int file_select_invoke(bContext *C, wmOperator *op, wmEvent *event) /* single select, deselect all selected first */ if (!extend) file_deselect_all(sfile); - if (FILE_SELECT_DIR == file_select(sfile, ar, &rect, 1, extend )) + if (FILE_SELECT_DIR == file_select(C, &rect, 1, extend )) WM_event_add_notifier(C, NC_SPACE|ND_SPACE_FILE_LIST, NULL); else WM_event_add_notifier(C, NC_SPACE|ND_SPACE_FILE_PARAMS, NULL); @@ -346,7 +348,7 @@ static int bookmark_select_exec(bContext *C, wmOperator *op) RNA_string_get(op->ptr, "dir", entry); BLI_strncpy(params->dir, entry, sizeof(params->dir)); BLI_cleanup_dir(G.sce, params->dir); - file_change_dir(sfile, 1); + file_change_dir(C, 1); WM_event_add_notifier(C, NC_SPACE|ND_SPACE_FILE_LIST, NULL); } @@ -434,35 +436,6 @@ void FILE_OT_delete_bookmark(wmOperatorType *ot) RNA_def_int(ot->srna, "index", -1, -1, 20000, "Index", "", -1, 20000); } - -static int loadimages_exec(bContext *C, wmOperator *op) -{ - ScrArea *sa= CTX_wm_area(C); - SpaceFile *sfile= CTX_wm_space_file(C); - if (sfile->files) { - filelist_loadimage_timer(sfile->files); - if (filelist_changed(sfile->files)) { - ED_area_tag_redraw(sa); - } - } - - return OPERATOR_FINISHED; -} - -void FILE_OT_loadimages(wmOperatorType *ot) -{ - - /* identifiers */ - ot->name= "Load Images"; - ot->description= "Load selected image(s)"; - ot->idname= "FILE_OT_loadimages"; - - /* api callbacks */ - ot->exec= loadimages_exec; - - ot->poll= ED_operator_file_active; -} - int file_hilight_set(SpaceFile *sfile, ARegion *ar, int mx, int my) { FileSelectParams* params; @@ -528,8 +501,7 @@ int file_cancel_exec(bContext *C, wmOperator *unused) sfile->op = NULL; if (sfile->files) { - filelist_freelib(sfile->files); - filelist_free(sfile->files); + ED_fileselect_clear(C, sfile); MEM_freeN(sfile->files); sfile->files= NULL; } @@ -634,8 +606,7 @@ int file_exec(bContext *C, wmOperator *exec_op) fsmenu_write_file(fsmenu_get(), name); WM_event_fileselect_event(C, op, EVT_FILESELECT_EXEC); - filelist_freelib(sfile->files); - filelist_free(sfile->files); + ED_fileselect_clear(C, sfile); MEM_freeN(sfile->files); sfile->files= NULL; } @@ -666,7 +637,7 @@ int file_parent_exec(bContext *C, wmOperator *unused) if (BLI_has_parent(sfile->params->dir)) { BLI_parent_dir(sfile->params->dir); BLI_cleanup_dir(G.sce, sfile->params->dir); - file_change_dir(sfile, 0); + file_change_dir(C, 0); WM_event_add_notifier(C, NC_SPACE|ND_SPACE_FILE_LIST, NULL); } } @@ -693,7 +664,7 @@ int file_refresh_exec(bContext *C, wmOperator *unused) { SpaceFile *sfile= CTX_wm_space_file(C); - file_change_dir(sfile, 1); + file_change_dir(C, 1); WM_event_add_notifier(C, NC_SPACE|ND_SPACE_FILE_LIST, NULL); @@ -725,7 +696,7 @@ int file_previous_exec(bContext *C, wmOperator *unused) folderlist_popdir(sfile->folders_prev, sfile->params->dir); folderlist_pushdir(sfile->folders_next, sfile->params->dir); - file_change_dir(sfile, 1); + file_change_dir(C, 1); } WM_event_add_notifier(C, NC_SPACE|ND_SPACE_FILE_LIST, NULL); @@ -757,7 +728,7 @@ int file_next_exec(bContext *C, wmOperator *unused) // update folder_prev so we can check for it in folderlist_clear_next() folderlist_pushdir(sfile->folders_prev, sfile->params->dir); - file_change_dir(sfile, 1); + file_change_dir(C, 1); } WM_event_add_notifier(C, NC_SPACE|ND_SPACE_FILE_LIST, NULL); @@ -860,7 +831,7 @@ int file_directory_exec(bContext *C, wmOperator *unused) #endif BLI_cleanup_dir(G.sce, sfile->params->dir); BLI_add_slash(sfile->params->dir); - file_change_dir(sfile, 1); + file_change_dir(C, 1); WM_event_add_notifier(C, NC_SPACE|ND_SPACE_FILE_LIST, NULL); } @@ -903,13 +874,11 @@ int file_hidedot_exec(bContext *C, wmOperator *unused) if(sfile->params) { sfile->params->flag ^= FILE_HIDE_DOT; - filelist_free(sfile->files); - sfile->params->active_file = -1; + ED_fileselect_clear(C, sfile); WM_event_add_notifier(C, NC_SPACE|ND_SPACE_FILE_LIST, NULL); } return OPERATOR_FINISHED; - } @@ -1089,6 +1058,7 @@ int file_delete_exec(bContext *C, wmOperator *op) file = filelist_file(sfile->files, sfile->params->active_file); BLI_make_file_string(G.sce, str, sfile->params->dir, file->relname); BLI_delete(str, 0, 0); + ED_fileselect_clear(C, sfile); WM_event_add_notifier(C, NC_SPACE|ND_SPACE_FILE_LIST, NULL); return OPERATOR_FINISHED; diff --git a/source/blender/editors/space_file/filelist.c b/source/blender/editors/space_file/filelist.c index 3631e0743da..b90bb47e6ce 100644 --- a/source/blender/editors/space_file/filelist.c +++ b/source/blender/editors/space_file/filelist.c @@ -55,6 +55,7 @@ #include "BLI_winstuff.h" #endif +#include "BKE_context.h" #include "BKE_utildefines.h" #include "BKE_global.h" #include "BKE_library.h" @@ -85,6 +86,9 @@ #include "UI_interface.h" +#include "WM_api.h" +#include "WM_types.h" + #include "filelist.h" /* Elubie: VERY, really very ugly and evil! Remove asap!!! */ @@ -100,12 +104,21 @@ struct FileList; typedef struct FileImage { struct FileImage *next, *prev; + char path[FILE_MAX]; + unsigned int flags; int index; - short lock; short done; - struct FileList* filelist; + ImBuf *img; } FileImage; +typedef struct ThumbnailJob { + ListBase loadimages; + short *stop; + short *do_update; + struct FileList* filelist; + ReportList reports; +} ThumbnailJob; + typedef struct FileList { struct direntry *filelist; @@ -124,8 +137,6 @@ typedef struct FileList void (*read)(struct FileList *); - ListBase loadimages; - ListBase threads; } FileList; typedef struct FolderList @@ -501,9 +512,6 @@ void filelist_free(struct FileList* filelist) printf("Attempting to delete empty filelist.\n"); return; } - - BLI_end_threads(&filelist->threads); - BLI_freelistN(&filelist->loadimages); if (filelist->fidx) { MEM_freeN(filelist->fidx); @@ -566,123 +574,33 @@ void filelist_imgsize(struct FileList* filelist, short w, short h) filelist->prv_h = h; } - -static void *exec_loadimages(void *list_v) -{ - FileImage* img = (FileImage*)list_v; - struct FileList *filelist = img->filelist; - - ImBuf *imb = NULL; - int fidx = img->index; - - if ( filelist->filelist[fidx].flags & IMAGEFILE ) { - imb = IMB_thumb_manage(filelist->dir, filelist->filelist[fidx].relname, THB_NORMAL, THB_SOURCE_IMAGE); - } else if ( filelist->filelist[fidx].flags & MOVIEFILE ) { - imb = IMB_thumb_manage(filelist->dir, filelist->filelist[fidx].relname, THB_NORMAL, THB_SOURCE_MOVIE); - if (!imb) { - /* remember that file can't be loaded via IMB_open_anim */ - filelist->filelist[fidx].flags &= ~MOVIEFILE; - filelist->filelist[fidx].flags |= MOVIEFILE_ICON; - } - } - if (imb) { - IMB_freeImBuf(imb); - } - img->done=1; - return 0; -} - short filelist_changed(struct FileList* filelist) { return filelist->changed; } -void filelist_loadimage_timer(struct FileList* filelist) -{ - FileImage *limg = filelist->loadimages.first; - short refresh=0; - - // as long as threads are available and there is work to do - while (limg) { - if (BLI_available_threads(&filelist->threads)>0) { - if (!limg->lock) { - limg->lock=1; - BLI_insert_thread(&filelist->threads, limg); - } - } - if (limg->done) { - FileImage *oimg = limg; - BLI_remove_thread(&filelist->threads, oimg); - /* brecht: keep failed images in the list, otherwise - it keeps trying to load them over and over? - BLI_remlink(&filelist->loadimages, oimg); - MEM_freeN(oimg);*/ - limg = oimg->next; - refresh = 1; - } else { - limg= limg->next; - } - } - filelist->changed=refresh; -} - -void filelist_loadimage(struct FileList* filelist, int index) +struct ImBuf * filelist_loadimage(struct FileList* filelist, int index) { ImBuf *imb = NULL; - int imgwidth = filelist->prv_w; - int imgheight = filelist->prv_h; - short ex, ey, dx, dy; - float scaledx, scaledy; int fidx = 0; if ( (index < 0) || (index >= filelist->numfiltered) ) { - return; + return NULL; } fidx = filelist->fidx[index]; - - if (!filelist->filelist[fidx].image) + imb = filelist->filelist[fidx].image; + if (!imb) { - - if ( (filelist->filelist[fidx].flags & IMAGEFILE) || (filelist->filelist[fidx].flags & MOVIEFILE) ) { - imb = IMB_thumb_read(filelist->dir, filelist->filelist[fidx].relname, THB_NORMAL); + if ( (filelist->filelist[fidx].flags & IMAGEFILE) || (filelist->filelist[fidx].flags & MOVIEFILE) ) { + char path[FILE_MAX]; + BLI_join_dirfile(path, filelist->dir, filelist->filelist[fidx].relname); + imb = IMB_thumb_read(path, THB_NORMAL); } if (imb) { - if (imb->x > imb->y) { - scaledx = (float)imgwidth; - scaledy = ( (float)imb->y/(float)imb->x )*imgwidth; - } - else { - scaledy = (float)imgheight; - scaledx = ( (float)imb->x/(float)imb->y )*imgheight; - } - ex = (short)scaledx; - ey = (short)scaledy; - - dx = imgwidth - ex; - dy = imgheight - ey; - - // IMB_scaleImBuf(imb, ex, ey); filelist->filelist[fidx].image = imb; - } else { - /* prevent loading image twice */ - FileImage* limg = filelist->loadimages.first; - short found= 0; - while(limg) { - if (limg->index == fidx) { - found= 1; - break; - } - limg= limg->next; - } - if (!found) { - FileImage* limg = MEM_callocN(sizeof(struct FileImage), "loadimage"); - limg->index= fidx; - limg->lock= 0; - limg->filelist= filelist; - BLI_addtail(&filelist->loadimages, limg); - } - } + } } + return imb; } struct ImBuf * filelist_getimage(struct FileList* filelist, int index) @@ -804,10 +722,6 @@ static void filelist_read_dir(struct FileList* filelist) if(!chdir(wdir)) /* fix warning about not checking return value */; filelist_setfiletypes(filelist, G.have_quicktime); filelist_filter(filelist); - - if (!filelist->threads.first) { - BLI_init_threads(&filelist->threads, exec_loadimages, 2); - } } static void filelist_read_main(struct FileList* filelist) @@ -876,9 +790,7 @@ void filelist_setfiletypes(struct FileList* filelist, short has_quicktime) /* Don't check extensions for directories */ if (file->type & S_IFDIR) continue; - - - + if(BLO_has_bfile_extension(file->relname)) { file->flags |= BLENDERFILE; } else if(BLI_testextensie(file->relname, ".py")) { @@ -1315,3 +1227,104 @@ void filelist_from_main(struct FileList *filelist) filelist_filter(filelist); } +static void thumbnail_joblist_free(ThumbnailJob *tj) +{ + FileImage* limg = tj->loadimages.first; + + /* free the images not yet copied to the filelist -> these will get freed with the filelist */ + while (limg != tj->loadimages.last) { + if ((limg->img) && (!limg->done)) { + IMB_freeImBuf(limg->img); + } + limg = limg->next; + } + BLI_freelistN(&tj->loadimages); +} + +static void thumbnails_startjob(void *tjv, short *stop, short *do_update) +{ + ThumbnailJob *tj= tjv; + FileImage* limg = tj->loadimages.first; + + tj->stop= stop; + tj->do_update= do_update; + + while ( (*stop==0) && (limg) ) { + if ( limg->flags & IMAGEFILE ) { + limg->img = IMB_thumb_manage(limg->path, THB_NORMAL, THB_SOURCE_IMAGE); + } else if ( limg->flags & MOVIEFILE ) { + limg->img = IMB_thumb_manage(limg->path, THB_NORMAL, THB_SOURCE_MOVIE); + if (!limg->img) { + /* remember that file can't be loaded via IMB_open_anim */ + limg->flags &= ~MOVIEFILE; + limg->flags |= MOVIEFILE_ICON; + } + } + *do_update = 1; + PIL_sleep_ms(10); + limg = limg->next; + } +} + +static void thumbnails_update(void *tjv) +{ + ThumbnailJob *tj= tjv; + + if (tj->filelist && tj->filelist->filelist) { + FileImage* limg = tj->loadimages.first; + while (limg) { + if (!limg->done && limg->img) { + tj->filelist->filelist[limg->index].image = limg->img; + tj->filelist->filelist[limg->index].flags = limg->flags; + limg->done=1; + } + limg = limg->next; + } + } +} + +static void thumbnails_free(void *tjv) +{ + ThumbnailJob *tj= tjv; + thumbnail_joblist_free(tj); + MEM_freeN(tj); +} + + +void thumbnails_start(struct FileList* filelist, const struct bContext* C) +{ + wmJob *steve; + ThumbnailJob *tj; + int idx; + + /* prepare job data */ + tj= MEM_callocN(sizeof(ThumbnailJob), "thumbnails\n"); + tj->filelist = filelist; + for (idx = 0; idx < filelist->numfiles;idx++) { + if (!filelist->filelist[idx].image) { + if ( (filelist->filelist[idx].flags & IMAGEFILE) || (filelist->filelist[idx].flags & MOVIEFILE) ) { + FileImage* limg = MEM_callocN(sizeof(struct FileImage), "loadimage"); + BLI_join_dirfile(limg->path, filelist->dir, filelist->filelist[idx].relname); + limg->index= idx; + limg->flags= filelist->filelist[idx].flags; + BLI_addtail(&tj->loadimages, limg); + } + } + } + + BKE_reports_init(&tj->reports, RPT_PRINT); + + /* setup job */ + steve= WM_jobs_get(CTX_wm_manager(C), CTX_wm_window(C), filelist, 0); + WM_jobs_customdata(steve, tj, thumbnails_free); + WM_jobs_timer(steve, 0.5, NC_WINDOW, NC_WINDOW); + WM_jobs_callbacks(steve, thumbnails_startjob, NULL, thumbnails_update); + + /* start the job */ + WM_jobs_start(CTX_wm_manager(C), steve); +} + +void thumbnails_stop(struct FileList* filelist, const struct bContext* C) +{ + WM_jobs_kill(CTX_wm_manager(C), filelist); +} \ No newline at end of file diff --git a/source/blender/editors/space_file/filelist.h b/source/blender/editors/space_file/filelist.h index 8a0e5ebdbc3..e75a3143817 100644 --- a/source/blender/editors/space_file/filelist.h +++ b/source/blender/editors/space_file/filelist.h @@ -61,8 +61,6 @@ void filelist_setfilter(struct FileList* filelist, unsigned int filter); void filelist_filter(struct FileList* filelist); void filelist_swapselect(struct FileList* filelist); void filelist_imgsize(struct FileList* filelist, short w, short h); -void filelist_loadimage(struct FileList* filelist, int index); -void filelist_loadimage_timer(struct FileList* filelist); struct ImBuf * filelist_getimage(struct FileList* filelist, int index); struct ImBuf * filelist_geticon(struct FileList* filelist, int index); short filelist_changed(struct FileList* filelist); @@ -86,6 +84,9 @@ void folderlist_popdir(struct ListBase* folderlist, char *dir); void folderlist_pushdir(struct ListBase* folderlist, const char *dir); int folderlist_clear_next(struct SpaceFile* sfile); +void thumbnails_stop(struct FileList* filelist, const struct bContext* C); +void thumbnails_start(struct FileList* filelist, const struct bContext* C); + #ifdef __cplusplus } #endif diff --git a/source/blender/editors/space_file/filesel.c b/source/blender/editors/space_file/filesel.c index 51058c0e90b..868e28207c5 100644 --- a/source/blender/editors/space_file/filesel.c +++ b/source/blender/editors/space_file/filesel.c @@ -391,15 +391,18 @@ FileLayout* ED_fileselect_get_layout(struct SpaceFile *sfile, struct ARegion *ar return sfile->layout; } -void file_change_dir(struct SpaceFile *sfile, int checkdir) +void file_change_dir(bContext *C, int checkdir) { + SpaceFile *sfile= CTX_wm_space_file(C); + if (sfile->params) { + ED_fileselect_clear(C, sfile); + if(checkdir && BLI_is_dir(sfile->params->dir)==0) { BLI_strncpy(sfile->params->dir, filelist_dir(sfile->files), sizeof(sfile->params->dir)); /* could return but just refresh the current dir */ } - filelist_setdir(sfile->files, sfile->params->dir); if(folderlist_clear_next(sfile)) @@ -407,8 +410,6 @@ void file_change_dir(struct SpaceFile *sfile, int checkdir) folderlist_pushdir(sfile->folders_prev, sfile->params->dir); - filelist_free(sfile->files); - sfile->params->active_file = -1; } } @@ -460,3 +461,17 @@ void autocomplete_directory(struct bContext *C, char *str, void *arg_v) } } } + +void ED_fileselect_clear(struct bContext *C, struct SpaceFile *sfile) +{ + thumbnails_stop(sfile->files, C); + filelist_freelib(sfile->files); + filelist_free(sfile->files); + sfile->params->active_file = -1; + WM_event_add_notifier(C, NC_SPACE|ND_SPACE_FILE_LIST, NULL); +} + +void ED_fileselect_exit(struct bContext *C, struct SpaceFile *sfile) +{ + thumbnails_stop(sfile->files, C); +} diff --git a/source/blender/editors/space_file/space_file.c b/source/blender/editors/space_file/space_file.c index 3996c6135a0..105ece8e95f 100644 --- a/source/blender/editors/space_file/space_file.c +++ b/source/blender/editors/space_file/space_file.c @@ -120,6 +120,7 @@ static void file_free(SpaceLink *sl) SpaceFile *sfile= (SpaceFile *) sl; if(sfile->files) { + // XXXXX would need to do thumbnails_stop here, but no context available filelist_freelib(sfile->files); filelist_free(sfile->files); MEM_freeN(sfile->files); @@ -170,18 +171,18 @@ static SpaceLink *file_duplicate(SpaceLink *sl) /* clear or remove stuff from old */ sfilen->op = NULL; /* file window doesn't own operators */ - if (sfileo->params) + if (sfileo->params) { sfilen->files = filelist_new(sfileo->params->type); + sfilen->params= MEM_dupallocN(sfileo->params); + filelist_setdir(sfilen->files, sfilen->params->dir); + } + if(sfileo->folders_prev) sfilen->folders_prev = folderlist_duplicate(sfileo->folders_prev); if(sfileo->folders_next) sfilen->folders_next = folderlist_duplicate(sfileo->folders_next); - - if(sfileo->params) { - sfilen->params= MEM_dupallocN(sfileo->params); - file_change_dir(sfilen, 0); - } + if (sfileo->layout) { sfilen->layout= MEM_dupallocN(sfileo->layout); } @@ -197,7 +198,7 @@ static void file_refresh(const bContext *C, ScrArea *sa) sfile->folders_prev = folderlist_new(); if (!sfile->files) { sfile->files = filelist_new(params->type); - file_change_dir(sfile, 0); + filelist_setdir(sfile->files, params->dir); params->active_file = -1; // added this so it opens nicer (ton) } filelist_hidedot(sfile->files, params->flag & FILE_HIDE_DOT); @@ -205,6 +206,7 @@ static void file_refresh(const bContext *C, ScrArea *sa) if (filelist_empty(sfile->files)) { filelist_readdir(sfile->files); + thumbnails_start(sfile->files, C); BLI_strncpy(params->dir, filelist_dir(sfile->files), FILE_MAX); } if(params->sort!=FILE_SORT_NONE) filelist_sort(sfile->files, params->sort); @@ -232,7 +234,6 @@ static void file_listener(ScrArea *sa, wmNotifier *wmn) case NC_SPACE: switch (wmn->data) { case ND_SPACE_FILE_LIST: - if (sfile->files) filelist_free(sfile->files); ED_area_tag_refresh(sa); ED_area_tag_redraw(sa); break; @@ -345,7 +346,6 @@ void file_operatortypes(void) WM_operatortype_append(FILE_OT_select_all_toggle); WM_operatortype_append(FILE_OT_select_border); WM_operatortype_append(FILE_OT_select_bookmark); - WM_operatortype_append(FILE_OT_loadimages); WM_operatortype_append(FILE_OT_highlight); WM_operatortype_append(FILE_OT_execute); WM_operatortype_append(FILE_OT_cancel); @@ -390,7 +390,6 @@ void file_keymap(struct wmKeyConfig *keyconf) WM_keymap_add_item(keymap, "FILE_OT_select_border", EVT_TWEAK_L, KM_ANY, 0, 0); WM_keymap_add_item(keymap, "FILE_OT_rename", LEFTMOUSE, KM_PRESS, KM_CTRL, 0); WM_keymap_add_item(keymap, "FILE_OT_highlight", MOUSEMOVE, KM_ANY, KM_ANY, 0); - WM_keymap_add_item(keymap, "FILE_OT_loadimages", TIMER1, KM_ANY, KM_ANY, 0); kmi = WM_keymap_add_item(keymap, "FILE_OT_filenum", PADPLUSKEY, KM_PRESS, 0, 0); RNA_int_set(kmi->ptr, "increment", 1); kmi = WM_keymap_add_item(keymap, "FILE_OT_filenum", PADPLUSKEY, KM_PRESS, KM_SHIFT, 0); diff --git a/source/blender/imbuf/IMB_thumbs.h b/source/blender/imbuf/IMB_thumbs.h index 8855c003818..165accc9e17 100644 --- a/source/blender/imbuf/IMB_thumbs.h +++ b/source/blender/imbuf/IMB_thumbs.h @@ -56,16 +56,16 @@ typedef enum ThumbSource { // IB_imginfo /* create thumbnail for file and returns new imbuf for thumbnail */ -ImBuf* IMB_thumb_create(const char* dir, const char* file, ThumbSize size, ThumbSource source); +ImBuf* IMB_thumb_create(const char* path, ThumbSize size, ThumbSource source); /* read thumbnail for file and returns new imbuf for thumbnail */ -ImBuf* IMB_thumb_read(const char* dir, const char* file, ThumbSize size); +ImBuf* IMB_thumb_read(const char* path, ThumbSize size); /* delete all thumbs for the file */ -void IMB_thumb_delete(const char* dir, const char* file, ThumbSize size); +void IMB_thumb_delete(const char* path, ThumbSize size); /* return the state of the thumb, needed to determine how to manage the thumb */ -ImBuf* IMB_thumb_manage(const char* dir, const char* file, ThumbSize size, ThumbSource source); +ImBuf* IMB_thumb_manage(const char* path, ThumbSize size, ThumbSource source); /* create the necessary dirs to store the thumbnails */ void IMB_thumb_makedirs(); diff --git a/source/blender/imbuf/intern/thumbs.c b/source/blender/imbuf/intern/thumbs.c index 99b9f8eaef6..5e0504155dc 100644 --- a/source/blender/imbuf/intern/thumbs.c +++ b/source/blender/imbuf/intern/thumbs.c @@ -164,22 +164,22 @@ void to_hex_char(char* hexbytes, const unsigned char* bytes, int len) /** ----- end of adapted code from glib --- */ -static int uri_from_filename( const char *dir, const char *file, char *uri ) +static int uri_from_filename( const char *path, char *uri ) { char orig_uri[URI_MAX]; - const char* dirstart = dir; + const char* dirstart = path; #ifdef WIN32 { char vol[3]; BLI_strncpy(orig_uri, "file:///", FILE_MAX); - if (strlen(dir) < 2 && dir[1] != ':') { + if (strlen(path) < 2 && path[1] != ':') { /* not a correct absolute path */ return 0; } /* on windows, using always uppercase drive/volume letter in uri */ - vol[0] = (unsigned char)toupper(dir[0]); + vol[0] = (unsigned char)toupper(path[0]); vol[1] = ':'; vol[2] = '\0'; strcat(orig_uri, vol); @@ -189,7 +189,6 @@ static int uri_from_filename( const char *dir, const char *file, char *uri ) BLI_strncpy(orig_uri, "file://", FILE_MAX); #endif strcat(orig_uri, dirstart); - strcat(orig_uri, file); BLI_char_switch(orig_uri, '\\', '/'); #ifdef WITH_ICONV @@ -242,14 +241,13 @@ void IMB_thumb_makedirs() } /* create thumbnail for file and returns new imbuf for thumbnail */ -ImBuf* IMB_thumb_create(const char* dir, const char* file, ThumbSize size, ThumbSource source) +ImBuf* IMB_thumb_create(const char* path, ThumbSize size, ThumbSource source) { ImBuf *img = 0; char uri[URI_MAX]; char desc[URI_MAX+22]; char tpath[FILE_MAX]; char tdir[FILE_MAX]; - char wdir[FILE_MAX]; char temp[FILE_MAX]; char mtime[40]; char cwidth[40]; @@ -274,13 +272,13 @@ ImBuf* IMB_thumb_create(const char* dir, const char* file, ThumbSize size, Thumb return 0; /* unknown size */ } - uri_from_filename(dir, file,uri); + uri_from_filename(path, uri); thumbname_from_uri(uri, thumb); if (get_thumb_dir(tdir, size)) { BLI_snprintf(tpath, FILE_MAX, "%s%s", tdir, thumb); thumb[8] = '\0'; /* shorten for tempname, not needed anymore */ BLI_snprintf(temp, FILE_MAX, "%sblender_%d_%s.png", tdir, abs(getpid()), thumb); - if (strncmp(thumb, dir, strlen(dir)) == 0) { + if (strncmp(path, tdir, strlen(tdir)) == 0) { return NULL; } if (size == THB_FAIL) { @@ -288,34 +286,28 @@ ImBuf* IMB_thumb_create(const char* dir, const char* file, ThumbSize size, Thumb if (!img) return 0; } else { if (THB_SOURCE_IMAGE == source) { - BLI_getwdN(wdir); - if(chdir(dir) != 0) return 0; - img = IMB_loadiffname(file, IB_rect | IB_imginfo); + img = IMB_loadiffname(path, IB_rect | IB_imginfo); if (img != NULL) { - stat(file, &info); + stat(path, &info); sprintf(mtime, "%ld", info.st_mtime); sprintf(cwidth, "%d", img->x); sprintf(cheight, "%d", img->y); } - if(chdir(wdir) != 0) /* unlikely to happen, just silence warning */; } else if (THB_SOURCE_MOVIE == source) { struct anim * anim = NULL; - BLI_getwdN(wdir); - if(chdir(dir) != 0) return 0; - anim = IMB_open_anim(file, IB_rect | IB_imginfo); + anim = IMB_open_anim(path, IB_rect | IB_imginfo); if (anim != NULL) { img = IMB_anim_absolute(anim, 0); if (img == NULL) { - printf("not an anim; %s\n", file); + printf("not an anim; %s\n", path); } else { IMB_freeImBuf(img); img = IMB_anim_previewframe(anim); } IMB_free_anim(anim); } - stat(file, &info); + stat(path, &info); sprintf(mtime, "%ld", info.st_mtime); - if(chdir(wdir) != 0) /* unlikely to happen, just silence warning */; } if (!img) return 0; @@ -356,13 +348,13 @@ ImBuf* IMB_thumb_create(const char* dir, const char* file, ThumbSize size, Thumb } /* read thumbnail for file and returns new imbuf for thumbnail */ -ImBuf* IMB_thumb_read(const char* dir, const char* file, ThumbSize size) +ImBuf* IMB_thumb_read(const char* path, ThumbSize size) { char thumb[FILE_MAX]; char uri[FILE_MAX*3+8]; ImBuf *img = 0; - if (!uri_from_filename(dir, file,uri)) { + if (!uri_from_filename(path,uri)) { return NULL; } if (thumbpath_from_uri(uri, thumb, size)) { @@ -373,16 +365,16 @@ ImBuf* IMB_thumb_read(const char* dir, const char* file, ThumbSize size) } /* delete all thumbs for the file */ -void IMB_thumb_delete(const char* dir, const char* file, ThumbSize size) +void IMB_thumb_delete(const char* path, ThumbSize size) { char thumb[FILE_MAX]; char uri[FILE_MAX*3+8]; - if (!uri_from_filename(dir, file,uri)) { + if (!uri_from_filename(path ,uri)) { return; } if (thumbpath_from_uri(uri, thumb, size)) { - if (strncmp(thumb, dir, strlen(dir)) == 0) { + if (strncmp(path, thumb, strlen(thumb)) == 0) { return; } if (BLI_exists(thumb)) { @@ -393,19 +385,17 @@ void IMB_thumb_delete(const char* dir, const char* file, ThumbSize size) /* create the thumb if necessary and manage failed and old thumbs */ -ImBuf* IMB_thumb_manage(const char* dir, const char* file, ThumbSize size, ThumbSource source) +ImBuf* IMB_thumb_manage(const char* path, ThumbSize size, ThumbSource source) { - char path[FILE_MAX]; char thumb[FILE_MAX]; char uri[FILE_MAX*3+8]; struct stat st; ImBuf* img = NULL; - - BLI_join_dirfile(path, dir, file); + if (stat(path, &st)) { return NULL; } - if (!uri_from_filename(dir, file,uri)) { + if (!uri_from_filename(path,uri)) { return NULL; } if (thumbpath_from_uri(uri, thumb, THB_FAIL)) { @@ -416,7 +406,7 @@ ImBuf* IMB_thumb_manage(const char* dir, const char* file, ThumbSize size, Thumb } if (thumbpath_from_uri(uri, thumb, size)) { - if (strncmp(thumb, dir, strlen(dir)) == 0) { + if (strncmp(path, thumb, strlen(thumb)) == 0) { img = IMB_loadiffname(path, IB_rect); } else { img = IMB_loadiffname(thumb, IB_rect | IB_imginfo); @@ -432,13 +422,13 @@ ImBuf* IMB_thumb_manage(const char* dir, const char* file, ThumbSize size, Thumb /* recreate all thumbs */ IMB_freeImBuf(img); img = 0; - IMB_thumb_delete(dir, file, THB_NORMAL); - IMB_thumb_delete(dir, file, THB_LARGE); - IMB_thumb_delete(dir, file, THB_FAIL); - img = IMB_thumb_create(dir, file, size, source); + IMB_thumb_delete(path, THB_NORMAL); + IMB_thumb_delete(path, THB_LARGE); + IMB_thumb_delete(path, THB_FAIL); + img = IMB_thumb_create(path, size, source); if(!img){ /* thumb creation failed, write fail thumb */ - img = IMB_thumb_create(dir, file, THB_FAIL, source); + img = IMB_thumb_create(path, THB_FAIL, source); if (img) { /* we don't need failed thumb anymore */ IMB_freeImBuf(img); @@ -448,10 +438,10 @@ ImBuf* IMB_thumb_manage(const char* dir, const char* file, ThumbSize size, Thumb } } } else { - img = IMB_thumb_create(dir, file, size, source); + img = IMB_thumb_create(path, size, source); if(!img){ /* thumb creation failed, write fail thumb */ - img = IMB_thumb_create(dir, file, THB_FAIL, source); + img = IMB_thumb_create(path, THB_FAIL, source); if (img) { /* we don't need failed thumb anymore */ IMB_freeImBuf(img); diff --git a/source/blender/makesrna/intern/rna_space.c b/source/blender/makesrna/intern/rna_space.c index 7a224cf5b49..9b7e6b5bc05 100644 --- a/source/blender/makesrna/intern/rna_space.c +++ b/source/blender/makesrna/intern/rna_space.c @@ -1838,7 +1838,7 @@ static void rna_def_fileselect_params(BlenderRNA *brna) prop= RNA_def_property(srna, "do_filter", PROP_BOOLEAN, PROP_NONE); RNA_def_property_boolean_sdna(prop, NULL, "flag", FILE_FILTER); RNA_def_property_ui_text(prop, "Filter Files", "Enable filtering of files"); - RNA_def_property_update(prop, NC_SPACE|ND_SPACE_FILE_LIST, NULL); + RNA_def_property_update(prop, NC_SPACE|ND_SPACE_FILE_PARAMS, NULL); prop= RNA_def_property(srna, "hide_dot", PROP_BOOLEAN, PROP_NONE); RNA_def_property_boolean_sdna(prop, NULL, "flag", FILE_HIDE_DOT); @@ -1855,51 +1855,50 @@ static void rna_def_fileselect_params(BlenderRNA *brna) RNA_def_property_boolean_sdna(prop, NULL, "filter", IMAGEFILE); RNA_def_property_ui_text(prop, "Filter Images", "Show image files"); RNA_def_property_ui_icon(prop, ICON_FILE_IMAGE, 0); - RNA_def_property_update(prop, NC_SPACE|ND_SPACE_FILE_LIST, NULL); + RNA_def_property_update(prop, NC_SPACE|ND_SPACE_FILE_PARAMS, NULL); prop= RNA_def_property(srna, "filter_blender", PROP_BOOLEAN, PROP_NONE); RNA_def_property_boolean_sdna(prop, NULL, "filter", BLENDERFILE); RNA_def_property_ui_text(prop, "Filter Blender", "Show .blend files"); RNA_def_property_ui_icon(prop, ICON_FILE_BLEND, 0); - RNA_def_property_update(prop, NC_SPACE|ND_SPACE_FILE_LIST, NULL); + RNA_def_property_update(prop, NC_SPACE|ND_SPACE_FILE_PARAMS, NULL); prop= RNA_def_property(srna, "filter_movie", PROP_BOOLEAN, PROP_NONE); RNA_def_property_boolean_sdna(prop, NULL, "filter", MOVIEFILE); RNA_def_property_ui_text(prop, "Filter Movies", "Show movie files"); RNA_def_property_ui_icon(prop, ICON_FILE_MOVIE, 0); - RNA_def_property_update(prop, NC_SPACE|ND_SPACE_FILE_LIST, NULL); + RNA_def_property_update(prop, NC_SPACE|ND_SPACE_FILE_PARAMS, NULL); prop= RNA_def_property(srna, "filter_script", PROP_BOOLEAN, PROP_NONE); RNA_def_property_boolean_sdna(prop, NULL, "filter", PYSCRIPTFILE); RNA_def_property_ui_text(prop, "Filter Script", "Show script files"); RNA_def_property_ui_icon(prop, ICON_FILE_SCRIPT, 0); - RNA_def_property_update(prop, NC_SPACE|ND_SPACE_FILE_LIST, NULL); + RNA_def_property_update(prop, NC_SPACE|ND_SPACE_FILE_PARAMS, NULL); prop= RNA_def_property(srna, "filter_font", PROP_BOOLEAN, PROP_NONE); RNA_def_property_boolean_sdna(prop, NULL, "filter", FTFONTFILE); RNA_def_property_ui_text(prop, "Filter Fonts", "Show font files"); RNA_def_property_ui_icon(prop, ICON_FILE_FONT, 0); - RNA_def_property_update(prop, NC_SPACE|ND_SPACE_FILE_LIST, NULL); + RNA_def_property_update(prop, NC_SPACE|ND_SPACE_FILE_PARAMS, NULL); prop= RNA_def_property(srna, "filter_sound", PROP_BOOLEAN, PROP_NONE); RNA_def_property_boolean_sdna(prop, NULL, "filter", SOUNDFILE); RNA_def_property_ui_text(prop, "Filter Sound", "Show sound files"); RNA_def_property_ui_icon(prop, ICON_FILE_SOUND, 0); - RNA_def_property_update(prop, NC_SPACE|ND_SPACE_FILE_LIST, NULL); + RNA_def_property_update(prop, NC_SPACE|ND_SPACE_FILE_PARAMS, NULL); prop= RNA_def_property(srna, "filter_text", PROP_BOOLEAN, PROP_NONE); RNA_def_property_boolean_sdna(prop, NULL, "filter", TEXTFILE); RNA_def_property_ui_text(prop, "Filter Text", "Show text files"); RNA_def_property_ui_icon(prop, ICON_FILE_BLANK, 0); - RNA_def_property_update(prop, NC_SPACE|ND_SPACE_FILE_LIST, NULL); + RNA_def_property_update(prop, NC_SPACE|ND_SPACE_FILE_PARAMS, NULL); prop= RNA_def_property(srna, "filter_folder", PROP_BOOLEAN, PROP_NONE); RNA_def_property_boolean_sdna(prop, NULL, "filter", FOLDERFILE); RNA_def_property_ui_text(prop, "Filter Folder", "Show folders"); RNA_def_property_ui_icon(prop, ICON_FILE_FOLDER, 0); - RNA_def_property_update(prop, NC_SPACE|ND_SPACE_FILE_LIST, NULL); + RNA_def_property_update(prop, NC_SPACE|ND_SPACE_FILE_PARAMS, NULL); - } static void rna_def_space_filebrowser(BlenderRNA *brna) diff --git a/source/blender/windowmanager/WM_api.h b/source/blender/windowmanager/WM_api.h index 7a1a14b645d..07f1368db23 100644 --- a/source/blender/windowmanager/WM_api.h +++ b/source/blender/windowmanager/WM_api.h @@ -309,6 +309,7 @@ void WM_jobs_callbacks(struct wmJob *, void WM_jobs_start(struct wmWindowManager *wm, struct wmJob *); void WM_jobs_stop(struct wmWindowManager *wm, void *owner); +void WM_jobs_kill(struct wmWindowManager *wm, void *owner); void WM_jobs_stop_all(struct wmWindowManager *wm); /* clipboard */ diff --git a/source/blender/windowmanager/intern/wm_jobs.c b/source/blender/windowmanager/intern/wm_jobs.c index 6613598a102..cb229c301b2 100644 --- a/source/blender/windowmanager/intern/wm_jobs.c +++ b/source/blender/windowmanager/intern/wm_jobs.c @@ -303,6 +303,20 @@ void WM_jobs_stop(wmWindowManager *wm, void *owner) steve->stop= 1; } +/* actually terminate thread and job timer */ +void WM_jobs_kill(wmWindowManager *wm, void *owner) +{ + wmJob *steve; + + for(steve= wm->jobs.first; steve; steve= steve->next) + if(steve->owner==owner) + break; + + if (steve) + wm_jobs_kill_job(wm, steve); +} + + /* kill job entirely, also removes timer itself */ void wm_jobs_timer_ended(wmWindowManager *wm, wmTimer *wt) { -- cgit v1.2.3