aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--include/AsyncImageLoader.hpp5
-rw-r--r--src/AsyncImageLoader.cpp52
-rw-r--r--src/FileAnalyzer.cpp12
-rw-r--r--src/Storage.cpp3
-rw-r--r--src/plugins/Matrix.cpp4
5 files changed, 60 insertions, 16 deletions
diff --git a/include/AsyncImageLoader.hpp b/include/AsyncImageLoader.hpp
index 689ec5f..6258b02 100644
--- a/include/AsyncImageLoader.hpp
+++ b/include/AsyncImageLoader.hpp
@@ -26,8 +26,9 @@ namespace QuickMedia {
size_t counter = 0;
};
- // This function is async
- bool create_thumbnail(const Path &thumbnail_path, const Path &thumbnail_path_resized, sf::Vector2i resize_target_size, ContentType content_type);
+ // If |symlink_if_no_resize| is false then a copy is made from |thumbnail_path| to |thumbnail_path_resized| instead of a symlink if |thumbnail_path| is not larger than |resize_target_size|.
+ // One example of why you might not want a symlink is if |thumbnail_path| is a temporary file.
+ 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);
constexpr int NUM_IMAGE_LOAD_THREADS = 4;
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;