Welcome to mirror list, hosted at ThFree Co, Russian Federation.

git.blender.org/blender.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
Diffstat (limited to 'source/blender/imbuf/intern/thumbs.c')
-rw-r--r--source/blender/imbuf/intern/thumbs.c131
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);
+}