diff --git a/Makefile b/Makefile index 5a40ffd..9084a34 100644 --- a/Makefile +++ b/Makefile @@ -22,7 +22,7 @@ install: ctpv ctpvclear install $^ $(BINPREFIX) uninstall: - $(RM) $(BINPREFIX)/ctpv + $(RM) $(BINPREFIX)/ctpv $(BINPREFIX)/ctpvclear clean: $(RM) ctpv $(OBJ) $(DEP) $(GEN) diff --git a/clear.sh b/clear.sh index a788662..e624585 100644 --- a/clear.sh +++ b/clear.sh @@ -1,7 +1,3 @@ -fifo="$(get_fifo "$id")" +setup_fifo "" 1 -[ -e "$fifo" ] || exit 1 - -fifo_open "$fifo" && { - printf '{"action": "remove", "identifier": "preview"}\n' > "$fifo" -} +printf '{"action": "remove", "identifier": "preview"}\n' > "$fifo" diff --git a/ctpv.c b/ctpv.c index cca262a..03a977b 100644 --- a/ctpv.c +++ b/ctpv.c @@ -4,6 +4,7 @@ #include #include #include +#include #include "error.h" #include "server.h" @@ -24,6 +25,7 @@ static struct { MODE_END, MODE_LIST, MODE_MIME, + MODE_NEWER, } mode; char *server_id_s; } ctpv = { .mode = MODE_PREVIEW }; @@ -181,18 +183,43 @@ static int mime(int argc, char *argv[]) if (argc > 1) printf("%s: ", f); + printf(".%s ", get_ext(f)); puts(mimetype); } return OK; } +static int newer(int argc, char *argv[]) +{ + char *f1, *f2; + GET_PARG(f1, 0); + GET_PARG(f2, 1); + + if (!f1 || !f2) { + print_error("2 file should be given"); + return ERR; + } + + struct stat stat1, stat2; + ERRCHK_RET(stat(f1, &stat1) == -1, FUNCFAILED("stat"), ERRNOS); + ERRCHK_RET(stat(f2, &stat2) == -1, FUNCFAILED("stat"), ERRNOS); + + int sec_d = stat1.st_mtim.tv_sec - stat2.st_mtim.tv_sec; + if (sec_d < 0) + return ERR; + else if (sec_d == 0 && stat1.st_mtim.tv_nsec <= stat2.st_mtim.tv_nsec) + return ERR; + + return OK; +} + int main(int argc, char *argv[]) { program = argc > 0 ? argv[0] : "ctpv"; int c; - while ((c = getopt(argc, argv, "s:ce:lm")) != -1) { + while ((c = getopt(argc, argv, "s:ce:lmn")) != -1) { switch (c) { case 's': ctpv.mode = MODE_SERVER; @@ -211,6 +238,9 @@ int main(int argc, char *argv[]) case 'm': ctpv.mode = MODE_MIME; break; + case 'n': + ctpv.mode = MODE_NEWER; + break; default: return EXIT_FAILURE; } @@ -239,6 +269,9 @@ int main(int argc, char *argv[]) case MODE_MIME: ret = mime(argc, argv); break; + case MODE_NEWER: + ret = newer(argc, argv); + break; default: PRINTINTERR("unknowm mode: %d", ctpv.mode); ret = ERR; diff --git a/end.sh b/end.sh index 32135ba..38cb31f 100644 --- a/end.sh +++ b/end.sh @@ -1,6 +1,4 @@ -fifo="$(get_fifo "$1")" +setup_fifo "$1" 1 -[ -e "$fifo" ] || exit 1 - -# sending zero byte tells listener to stop -fifo_open "$fifo" && printf '\0' > "$fifo" +# tell ctpv server to exit +printf '\0' > "$fifo" diff --git a/helpers.sh b/helpers.sh index 40bb00a..5d6c0ef 100644 --- a/helpers.sh +++ b/helpers.sh @@ -1,13 +1,40 @@ -get_fifo() { - printf '/tmp/ctpvfifo.%s' "$1" +fifo_open() { + # https://unix.stackexchange.com/a/522940/183147 + dd oflag=nonblock conv=notrunc,nocreat count=0 of="$1" \ + >/dev/null 2>/dev/null +} + +setup_fifo() { + exit_code="${2:-127}" + fifo="$(printf '/tmp/ctpvfifo.%s' "${1:-$id}")" + [ -e "$fifo" ] || exit "$exit_code" + fifo_open "$fifo" || exit "$exit_code" } exists() { command -v "$1" > /dev/null } -fifo_open() { - # https://unix.stackexchange.com/a/522940/183147 - dd oflag=nonblock conv=notrunc,nocreat count=0 of="$1" \ - >/dev/null 2>/dev/null +check_exist() { + [ $? = 127 ] && exit 127 +} + +cache() { + cache_d="${XDG_CACHE_HOME:-$HOME/.cache}/ctpv" + mkdir -p "$cache_d" + cache_f="$cache_d/$(printf '%s' "$f" | md5sum - | cut -d' ' -f1)" + test -e "$cache_f" || return + ctpv -n "$cache_f" "$f" +} + +show_image() { + path="$(printf '%s' "$1" | sed 's/\\/\\\\/g; s/"/\\"/g')" + printf '{ "action": "add", "identifier": "preview", "x": %d, "y": %d, "width": %d, "height": %d, "scaler": "contain", "scaling_position_x": 0.5, "scaling_position_y": 0.5, "path": "%s"}\n' "$x" "$y" "$w" "$h" "$path" > "$fifo" +} + +convert_and_show_image() { + setup_fifo + cache || "$@" || check_exist + show_image "$cache_f" + exit 1 } diff --git a/prev/image.sh b/prev/image.sh index 973a153..4f6a844 100644 --- a/prev/image.sh +++ b/prev/image.sh @@ -1,13 +1,6 @@ -fifo="$(get_fifo "$id")" +# exit 127 on error so ctpv fallbacks to another preview +setup_fifo -# tell ctpv to fallback to another preview -[ -e "$fifo" ] || exit 127 +show_image "$f" -path="$(printf '%s' "$f" | sed 's/\\/\\\\/g; s/"/\\"/g')" - -fifo_open "$fifo" && { - printf '{ "action": "add", "identifier": "preview", "x": %d, "y": %d, "width": %d, "height": %d, "scaler": "contain", "scaling_position_x": 1, "scaling_position_y": 1, "path": "%s"}\n' "$x" "$y" "$w" "$h" "$path" > "$fifo" -} - -# tell lf to disable preview caching exit 1 diff --git a/prev/pdf.sh b/prev/pdf.sh new file mode 100644 index 0000000..3e9b146 --- /dev/null +++ b/prev/pdf.sh @@ -0,0 +1,10 @@ +pdf() { + pdftoppm -f 1 -l 1 \ + -scale-to-x 1920 \ + -scale-to-y -1 \ + -singlefile \ + -jpeg -tiffcompression jpeg \ + -- "$f" "$cache_f" && mv -- "$cache_f.jpg" "$cache_f" +} + +convert_and_show_image pdf diff --git a/prev/video.sh b/prev/video.sh new file mode 100644 index 0000000..f042005 --- /dev/null +++ b/prev/video.sh @@ -0,0 +1,5 @@ +video() { + ffmpegthumbnailer -i "$f" -o "$cache_f" -s 0 -t 50% 2>/dev/null +} + +convert_and_show_image video diff --git a/previews.h b/previews.h index e358449..ca03adb 100644 --- a/previews.h +++ b/previews.h @@ -18,4 +18,6 @@ Preview previews[] = { PR("md", NULL, NULL, markdown), PR(NULL, "application", "json", json), PR(NULL, "image", NULL, image), + PR(NULL, "video", NULL, video), + PR(NULL, "application", "pdf", pdf), };