diff options
Diffstat (limited to 'source/blender/imbuf/intern/thumbs.c')
-rw-r--r-- | source/blender/imbuf/intern/thumbs.c | 131 |
1 files changed, 112 insertions, 19 deletions
diff --git a/source/blender/imbuf/intern/thumbs.c b/source/blender/imbuf/intern/thumbs.c index 1fb6c7631b9..95d061bcb75 100644 --- a/source/blender/imbuf/intern/thumbs.c +++ b/source/blender/imbuf/intern/thumbs.c @@ -32,14 +32,20 @@ #include <stdio.h> #include <stdlib.h> +#include "MEM_guardedalloc.h" + #include "BLI_utildefines.h" #include "BLI_string.h" #include "BLI_path_util.h" #include "BLI_fileops.h" +#include "BLI_ghash.h" #include "BLI_hash_md5.h" #include "BLI_system.h" +#include "BLI_threads.h" #include BLI_SYSTEM_PID_H +#include "BLO_readfile.h" + #include "IMB_imbuf_types.h" #include "IMB_imbuf.h" #include "IMB_thumbs.h" @@ -211,7 +217,7 @@ static bool thumbhash_from_path(const char *UNUSED(path), ThumbSource source, ch } } -static int uri_from_filename(const char *path, char *uri) +static bool uri_from_filename(const char *path, char *uri) { char orig_uri[URI_MAX]; const char *dirstart = path; @@ -237,16 +243,9 @@ static int uri_from_filename(const char *path, char *uri) #else BLI_snprintf(orig_uri, URI_MAX, "file://%s", dirstart); #endif - -#ifdef WITH_ICONV - { - char uri_utf8[URI_MAX]; - escape_uri_string(orig_uri, uri_utf8, URI_MAX, UNSAFE_PATH); - BLI_string_to_utf8(uri_utf8, uri, NULL); - } -#else + escape_uri_string(orig_uri, uri, URI_MAX, UNSAFE_PATH); -#endif + return 1; } @@ -310,6 +309,7 @@ void IMB_thumb_makedirs(void) /* create thumbnail for file and returns new imbuf for thumbnail */ static ImBuf *thumb_create_ex( const char *file_path, const char *uri, const char *thumb, const bool use_hash, const char *hash, + const char *blen_group, const char *blen_id, ThumbSize size, ThumbSource source, ImBuf *img) { char desc[URI_MAX + 22]; @@ -367,7 +367,7 @@ static ImBuf *thumb_create_ex( img = IMB_loadiffname(file_path, IB_rect | IB_metadata, NULL); break; case THB_SOURCE_BLEND: - img = IMB_thumb_load_blend(file_path); + img = IMB_thumb_load_blend(file_path, blen_group, blen_id); break; case THB_SOURCE_FONT: img = IMB_thumb_load_font(file_path, tsize, tsize); @@ -460,13 +460,13 @@ static ImBuf *thumb_create_ex( static ImBuf *thumb_create_or_fail( const char *file_path, const char *uri, const char *thumb, const bool use_hash, const char *hash, - ThumbSize size, ThumbSource source) + const char *blen_group, const char *blen_id, ThumbSize size, ThumbSource source) { - ImBuf *img = thumb_create_ex(file_path, uri, thumb, use_hash, hash, size, source, NULL); + ImBuf *img = thumb_create_ex(file_path, uri, thumb, use_hash, hash, blen_group, blen_id, size, source, NULL); if (!img) { /* thumb creation failed, write fail thumb */ - img = thumb_create_ex(file_path, uri, thumb, use_hash, hash, THB_FAIL, source, NULL); + img = thumb_create_ex(file_path, uri, thumb, use_hash, hash, blen_group, blen_id, THB_FAIL, source, NULL); if (img) { /* we don't need failed thumb anymore */ IMB_freeImBuf(img); @@ -482,10 +482,12 @@ ImBuf *IMB_thumb_create(const char *path, ThumbSize size, ThumbSource source, Im char uri[URI_MAX] = ""; char thumb_name[40]; - uri_from_filename(path, uri); + if (!uri_from_filename(path, uri)) { + return NULL; + } thumbname_from_uri(uri, thumb_name, sizeof(thumb_name)); - return thumb_create_ex(path, uri, thumb_name, false, THUMB_DEFAULT_HASH, size, source, img); + return thumb_create_ex(path, uri, thumb_name, false, THUMB_DEFAULT_HASH, NULL, NULL, size, source, img); } /* read thumbnail for file and returns new imbuf for thumbnail */ @@ -531,12 +533,25 @@ ImBuf *IMB_thumb_manage(const char *org_path, ThumbSize size, ThumbSource source char thumb_path[FILE_MAX]; char thumb_name[40]; char uri[URI_MAX]; + char path_buff[FILE_MAX]; const char *file_path; const char *path; BLI_stat_t st; ImBuf *img = NULL; + char *blen_group = NULL, *blen_id = NULL; path = file_path = org_path; + if (source == THB_SOURCE_BLEND) { + if (BLO_library_path_explode(path, path_buff, &blen_group, &blen_id)) { + if (blen_group) { + if (!blen_id) { + /* No preview for blen groups */ + return NULL; + } + file_path = path_buff; /* path needs to be a valid file! */ + } + } + } if (BLI_stat(file_path, &st) == -1) { return NULL; @@ -547,7 +562,7 @@ ImBuf *IMB_thumb_manage(const char *org_path, ThumbSize size, ThumbSource source if (thumbpath_from_uri(uri, thumb_path, sizeof(thumb_path), THB_FAIL)) { /* failure thumb exists, don't try recreating */ if (BLI_exists(thumb_path)) { - /* clear out of date fail case */ + /* clear out of date fail case (note for blen IDs we use blender file itself here) */ if (BLI_file_older(thumb_path, file_path)) { BLI_delete(thumb_path, false, false); } @@ -596,14 +611,16 @@ ImBuf *IMB_thumb_manage(const char *org_path, ThumbSize size, ThumbSource source IMB_thumb_delete(path, THB_NORMAL); IMB_thumb_delete(path, THB_LARGE); IMB_thumb_delete(path, THB_FAIL); - img = thumb_create_or_fail(file_path, uri, thumb_name, use_hash, thumb_hash, size, source); + img = thumb_create_or_fail( + file_path, uri, thumb_name, use_hash, thumb_hash, blen_group, blen_id, size, source); } } else { char thumb_hash[33]; const bool use_hash = thumbhash_from_path(file_path, source, thumb_hash); - img = thumb_create_or_fail(file_path, uri, thumb_name, use_hash, thumb_hash, size, source); + img = thumb_create_or_fail( + file_path, uri, thumb_name, use_hash, thumb_hash, blen_group, blen_id, size, source); } } } @@ -618,3 +635,79 @@ ImBuf *IMB_thumb_manage(const char *org_path, ThumbSize size, ThumbSource source return img; } + +/* ***** Threading ***** */ +/* Thumbnail handling is not really threadsafe in itself. + * However, as long as we do not operate on the same file, we shall have no collision. + * So idea is to 'lock' a given source file path. + */ + +static struct IMBThumbLocks { + GSet *locked_paths; + int lock_counter; + ThreadCondition cond; +} thumb_locks = {0}; + +void IMB_thumb_locks_acquire(void) +{ + BLI_lock_thread(LOCK_IMAGE); + + if (thumb_locks.lock_counter == 0) { + BLI_assert(thumb_locks.locked_paths == NULL); + thumb_locks.locked_paths = BLI_gset_str_new(__func__); + BLI_condition_init(&thumb_locks.cond); + } + thumb_locks.lock_counter++; + + BLI_assert(thumb_locks.locked_paths != NULL); + BLI_assert(thumb_locks.lock_counter > 0); + BLI_unlock_thread(LOCK_IMAGE); +} + +void IMB_thumb_locks_release(void) +{ + BLI_lock_thread(LOCK_IMAGE); + BLI_assert((thumb_locks.locked_paths != NULL) && (thumb_locks.lock_counter > 0)); + + thumb_locks.lock_counter--; + if (thumb_locks.lock_counter == 0) { + BLI_gset_free(thumb_locks.locked_paths, MEM_freeN); + thumb_locks.locked_paths = NULL; + BLI_condition_end(&thumb_locks.cond); + } + + BLI_unlock_thread(LOCK_IMAGE); +} + +void IMB_thumb_path_lock(const char *path) +{ + void *key = BLI_strdup(path); + + BLI_lock_thread(LOCK_IMAGE); + BLI_assert((thumb_locks.locked_paths != NULL) && (thumb_locks.lock_counter > 0)); + + if (thumb_locks.locked_paths) { + while (!BLI_gset_add(thumb_locks.locked_paths, key)) { + BLI_condition_wait_global_mutex(&thumb_locks.cond, LOCK_IMAGE); + } + } + + BLI_unlock_thread(LOCK_IMAGE); +} + +void IMB_thumb_path_unlock(const char *path) +{ + const void *key = path; + + BLI_lock_thread(LOCK_IMAGE); + BLI_assert((thumb_locks.locked_paths != NULL) && (thumb_locks.lock_counter > 0)); + + if (thumb_locks.locked_paths) { + if (!BLI_gset_remove(thumb_locks.locked_paths, key, MEM_freeN)) { + BLI_assert(0); + } + BLI_condition_notify_all(&thumb_locks.cond); + } + + BLI_unlock_thread(LOCK_IMAGE); +} |