diff options
author | dec05eba <dec05eba@protonmail.com> | 2021-08-08 10:48:55 +0200 |
---|---|---|
committer | dec05eba <dec05eba@protonmail.com> | 2021-08-08 10:48:55 +0200 |
commit | 23ab8cc08d2d6281ef56c184f1e1e905e70a2a22 (patch) | |
tree | df1c2d59db08da7ea12e9359b7583e622a8ff0f2 /src | |
parent | 244ee01df48d702ff126a73ee36911b43adfdba8 (diff) |
Matrix: fix thumbnail upload of small thumbnails, fix small thumbnail creation if webp
Diffstat (limited to 'src')
-rw-r--r-- | src/AsyncImageLoader.cpp | 52 | ||||
-rw-r--r-- | src/FileAnalyzer.cpp | 12 | ||||
-rw-r--r-- | src/Storage.cpp | 3 | ||||
-rw-r--r-- | src/plugins/Matrix.cpp | 4 |
4 files changed, 57 insertions, 14 deletions
diff --git a/src/AsyncImageLoader.cpp b/src/AsyncImageLoader.cpp index ccf9f42..a871078 100644 --- a/src/AsyncImageLoader.cpp +++ b/src/AsyncImageLoader.cpp @@ -10,6 +10,8 @@ #include <sys/prctl.h> #include <sys/stat.h> #include <sys/wait.h> +#include <sys/sendfile.h> +#include <fcntl.h> #include <signal.h> #include <malloc.h> #include <assert.h> @@ -24,7 +26,7 @@ namespace QuickMedia { return exec_program(args, nullptr, nullptr) == 0; } - bool create_thumbnail(const Path &thumbnail_path, const Path &thumbnail_path_resized, sf::Vector2i resize_target_size, ContentType content_type) { + bool create_thumbnail(const Path &thumbnail_path, const Path &thumbnail_path_resized, sf::Vector2i resize_target_size, ContentType content_type, bool symlink_if_no_resize) { Path input_path = thumbnail_path; if(content_type == ContentType::IMAGE_WEBP) { @@ -62,10 +64,47 @@ namespace QuickMedia { result_path_tmp.append(".tmp.png"); if(image.getSize().x <= (unsigned int)resize_target_size.x && image.getSize().y <= (unsigned int)resize_target_size.y) { - int res = symlink(input_path.data.c_str(), result_path_tmp.data.c_str()); - if(res == -1 && errno != EEXIST) { - fprintf(stderr, "Failed to save %s\n", thumbnail_path_resized.data.c_str()); - _exit(1); + if(content_type == ContentType::IMAGE_WEBP) { + if(rename_atomic(input_path.data.c_str(), thumbnail_path_resized.data.c_str()) == 0) + _exit(0); + else + _exit(1); + } else if(symlink_if_no_resize) { + int res = symlink(thumbnail_path.data.c_str(), result_path_tmp.data.c_str()); + if(res == -1 && errno != EEXIST) { + fprintf(stderr, "Failed to symlink %s to %s\n", thumbnail_path_resized.data.c_str(), thumbnail_path.data.c_str()); + _exit(1); + } + } else { + // TODO: When mac is supported (or other OS than linux), then fix this for them. Mac for example needs fcopyfile instead of sendfile + int input_file = open(thumbnail_path.data.c_str(), O_RDONLY); + if(input_file == -1) { + fprintf(stderr, "Failed to save %s\n", thumbnail_path_resized.data.c_str()); + _exit(1); + } + + int output_file = creat(result_path_tmp.data.c_str(), 0660); + if(output_file == -1) { + fprintf(stderr, "Failed to save %s\n", thumbnail_path_resized.data.c_str()); + _exit(1); + } + + off_t bytes_copied = 0; + struct stat file_stat; + memset(&file_stat, 0, sizeof(file_stat)); + if(fstat(input_file, &file_stat) == -1) { + fprintf(stderr, "Failed to save %s\n", thumbnail_path_resized.data.c_str()); + _exit(1); + } + + // No need to retry, small files + if(sendfile(output_file, input_file, &bytes_copied, file_stat.st_size) == -1) { + fprintf(stderr, "Failed to save %s\n", thumbnail_path_resized.data.c_str()); + _exit(1); + } + + close(input_file); + close(output_file); } } else { sf::Vector2u clamped_size = clamp_to_size(image.getSize(), sf::Vector2u(resize_target_size.x, resize_target_size.y)); @@ -121,7 +160,7 @@ namespace QuickMedia { return; } - if(create_thumbnail(thumbnail_path, thumbnail_path_resized, resize_target_size, file_analyzer.get_content_type())) { + if(create_thumbnail(thumbnail_path, thumbnail_path_resized, resize_target_size, file_analyzer.get_content_type(), true)) { load_image_from_file(*thumbnail_data->image, thumbnail_path_resized.data); } else { load_image_from_file(*thumbnail_data->image, thumbnail_path.data); @@ -198,6 +237,7 @@ namespace QuickMedia { Path thumbnail_path = get_cache_dir().join("thumbnails").join(sha256.getHash()); if(local) { struct stat file_stat; + memset(&file_stat, 0, sizeof(file_stat)); if(stat(url.c_str(), &file_stat) != 0 || !S_ISREG(file_stat.st_mode)) { thumbnail_data->image = std::make_unique<sf::Image>(); thumbnail_data->loading_state = LoadingState::FINISHED_LOADING; diff --git a/src/FileAnalyzer.cpp b/src/FileAnalyzer.cpp index a24906f..f1f9369 100644 --- a/src/FileAnalyzer.cpp +++ b/src/FileAnalyzer.cpp @@ -137,13 +137,12 @@ namespace QuickMedia { if(width > 0 && height > 0) { FileAnalyzer file_analyzer; - if(file_analyzer.load_file(destination_path_tmp.data.c_str(), false) && create_thumbnail(destination_path_tmp, destination_path, sf::Vector2i(width, height), file_analyzer.get_content_type())) { - remove(destination_path_tmp.data.c_str()); - return true; - } + const bool success = file_analyzer.load_file(destination_path_tmp.data.c_str(), false) && create_thumbnail(destination_path_tmp, destination_path, sf::Vector2i(width, height), file_analyzer.get_content_type(), false); + remove(destination_path_tmp.data.c_str()); + return success; + } else { + return rename_atomic(destination_path_tmp.data.c_str(), destination_path) == 0; } - - return rename_atomic(destination_path_tmp.data.c_str(), destination_path) == 0; } // TODO: Remove dependency on ffprobe @@ -221,6 +220,7 @@ namespace QuickMedia { duration_seconds = std::nullopt; struct stat stat; + memset(&stat, 0, sizeof(stat)); if(fstat(fileno(file), &stat) == -1) { perror(filepath); fclose(file); diff --git a/src/Storage.cpp b/src/Storage.cpp index 9a1c492..375be57 100644 --- a/src/Storage.cpp +++ b/src/Storage.cpp @@ -127,6 +127,7 @@ namespace QuickMedia { FileType get_file_type(const Path &path) { struct stat file_stat; + memset(&file_stat, 0, sizeof(file_stat)); int ret; EINTR_RETRY(ret, stat(path.data.c_str(), &file_stat)); if(ret == 0) @@ -160,6 +161,7 @@ namespace QuickMedia { int file_get_size(const Path &path, size_t *size) { struct stat file_stat; + memset(&file_stat, 0, sizeof(file_stat)); int ret; EINTR_RETRY(ret, stat(path.data.c_str(), &file_stat)); if(ret == 0 && S_ISREG(file_stat.st_mode)) { @@ -172,6 +174,7 @@ namespace QuickMedia { bool file_get_last_modified_time_seconds(const char *path, time_t *result) { struct stat file_stat; + memset(&file_stat, 0, sizeof(file_stat)); int ret; EINTR_RETRY(ret, stat(path, &file_stat)); if(ret == 0) { diff --git a/src/plugins/Matrix.cpp b/src/plugins/Matrix.cpp index 64796eb..b471522 100644 --- a/src/plugins/Matrix.cpp +++ b/src/plugins/Matrix.cpp @@ -3553,7 +3553,7 @@ namespace QuickMedia { if(upload_thumbnail_result != PluginResult::OK) { close(tmp_file); remove(tmp_filename); - return upload_thumbnail_result; + show_notification("QuickMedia", "Video was uploaded without a thumbnail, error: " + err_msg, Urgency::CRITICAL); } } else { fprintf(stderr, "Failed to get first frame of video, ignoring thumbnail...\n"); @@ -3568,7 +3568,7 @@ namespace QuickMedia { int tmp_file = mkstemp(tmp_filename); if(tmp_file != -1) { std::string thumbnail_path; - if(create_thumbnail(filepath, tmp_filename, thumbnail_max_size, file_analyzer.get_content_type())) + if(create_thumbnail(filepath, tmp_filename, thumbnail_max_size, file_analyzer.get_content_type(), true)) thumbnail_path = tmp_filename; else thumbnail_path = filepath; |