Support for external commands like mogrify & jpegtran

This commit is contained in:
Bert 2011-03-01 18:49:02 +01:00
parent 955c39a5c5
commit c05fd44bdd
6 changed files with 115 additions and 12 deletions

24
commands.h Normal file
View file

@ -0,0 +1,24 @@
#define FILENAME (const char*) 0x1
typedef struct {
KeySym ksym;
const char **cmdline;
Bool reload;
} command_t;
static const char *cmdline_1[] = { "jpegtran", "-rotate", "270", "-copy", "all",
"-outfile", FILENAME, FILENAME, NULL };
static const char *cmdline_2[] = { "jpegtran", "-rotate", "90", "-copy", "all",
"-outfile", FILENAME, FILENAME, NULL };
static const char *cmdline_3[] = { "mogrify", "-rotate", "-90", FILENAME,
NULL };
static const char *cmdline_4[] = { "mogrify", "-rotate", "+90", FILENAME,
NULL };
static command_t commands[] = {
/* key command-line reload? */
{ XK_a, cmdline_1, True },
{ XK_s, cmdline_2, True },
{ XK_A, cmdline_3, True },
{ XK_S, cmdline_4, True },
};

View file

@ -99,10 +99,13 @@ int img_load(img_t *img, const char *filename) {
return 1;
}
void img_close(img_t *img) {
void img_close(img_t *img, int decache) {
if (img && img->im) {
imlib_context_set_image(img->im);
imlib_free_image();
if (decache)
imlib_free_image_and_decache();
else
imlib_free_image();
img->im = NULL;
}
}

View file

@ -57,7 +57,7 @@ void img_free(img_t*);
int img_check(const char*);
int img_load(img_t*, const char*);
void img_close(img_t*);
void img_close(img_t*, int);
void img_render(img_t*, win_t*);

84
main.c
View file

@ -23,6 +23,8 @@
#include <sys/select.h>
#include <sys/stat.h>
#include <sys/time.h>
#include <sys/wait.h>
#include <unistd.h>
#include <X11/Xlib.h>
#include <X11/Xutil.h>
@ -33,6 +35,7 @@
#include "thumbs.h"
#include "util.h"
#include "window.h"
#include "commands.h"
typedef enum {
MODE_NORMAL = 0,
@ -62,7 +65,7 @@ void cleanup() {
static int in = 0;
if (!in++) {
img_close(&img);
img_close(&img, 0);
img_free(&img);
tns_free(&tns, &win);
win_close(&win);
@ -73,7 +76,7 @@ int load_image(int new) {
struct stat fstats;
if (new >= 0 && new < filecnt) {
img_close(&img);
img_close(&img, 0);
fileidx = new;
if (!stat(filenames[fileidx], &fstats))
filesize = fstats.st_size;
@ -270,6 +273,60 @@ void read_dir_rec(const char *dirname) {
free(dirnames);
}
int run_command(const char **cmdline, Bool reload) {
int argc, i;
const char **argv;
pid_t pid;
int error, ret, status;
if (!cmdline)
return 0;
argc = 1;
while (cmdline[argc-1])
++argc;
if (argc < 2)
return 0;
argv = (const char**) s_malloc(argc * sizeof(const char*));
error = ret = 0;
for (i = 0; i < argc; ++i) {
if (cmdline[i] != FILENAME)
argv[i] = cmdline[i];
else
argv[i] = filenames[mode == MODE_NORMAL ? fileidx : tns.sel];
}
if ((pid = fork()) == 0) {
execvp(argv[0], (char **const) argv);
warn("could not exec %s", argv[0]);
exit(1);
} else if (pid < 0 && !options->quiet) {
warn("could not fork. command line was:");
error = 1;
} else if (reload) {
waitpid(pid, &status, 0);
if (WIFEXITED(status) && WEXITSTATUS(status) == 0) {
ret = 1;
} else if (!options->quiet) {
warn("child exited with non-zero return value: %d. command line was:",
WEXITSTATUS(status));
error = 1;
}
}
if (error) {
for (i = 0; i < argc && argv[i]; ++i)
fprintf(stderr, "%s%s", i > 0 ? " " : "", argv[i]);
fprintf(stderr, "\n");
}
free(argv);
return ret;
}
/* event handling */
@ -293,7 +350,7 @@ void redraw() {
}
void on_keypress(XKeyEvent *kev) {
int x, y;
int i, x, y;
unsigned int w, h;
char key;
KeySym ksym;
@ -305,6 +362,25 @@ void on_keypress(XKeyEvent *kev) {
XLookupString(kev, &key, 1, &ksym, NULL);
changed = 0;
/* external commands from commands.h */
for (i = 0; i < LEN(commands); ++i) {
if (commands[i].ksym == ksym) {
win_set_cursor(&win, CURSOR_WATCH);
if (run_command(commands[i].cmdline, commands[i].reload)) {
if (mode == MODE_NORMAL) {
img_close(&img, 1);
load_image(fileidx);
tns_load(&tns, &win, fileidx, filenames[fileidx]);
} else {
tns_load(&tns, &win, tns.sel, filenames[tns.sel]);
}
redraw();
}
win_set_cursor(&win, mode == MODE_NORMAL ? CURSOR_NONE : CURSOR_ARROW);
return;
}
}
if (mode == MODE_NORMAL) {
switch (ksym) {
/* navigate image list */
@ -395,7 +471,7 @@ void on_keypress(XKeyEvent *kev) {
case XK_Return:
if (!tns.thumbs)
tns_init(&tns, filecnt);
img_close(&img);
img_close(&img, 0);
mode = MODE_THUMBS;
win_set_cursor(&win, CURSOR_ARROW);
timo_cursor = 0;

View file

@ -66,12 +66,10 @@ void tns_load(tns_t *tns, win_t *win, int n, const char *filename) {
else if (n >= tns->cnt)
tns->cnt = n + 1;
if ((im = imlib_load_image(filename))) {
if ((im = imlib_load_image(filename)))
imlib_context_set_image(im);
imlib_image_set_changes_on_disk();
} else {
else
imlib_context_set_image(im_broken);
}
w = imlib_image_get_width();
h = imlib_image_get_height();
@ -95,7 +93,7 @@ void tns_load(tns_t *tns, win_t *win, int n, const char *filename) {
tns->dirty = 1;
if (im)
imlib_free_image();
imlib_free_image_and_decache();
}
void tns_check_view(tns_t *tns, Bool scrolled) {

View file

@ -331,4 +331,6 @@ void win_set_cursor(win_t *win, win_cur_t cursor) {
XDefineCursor(win->env.dpy, win->xwin, carrow);
break;
}
XFlush(win->env.dpy);
}