/* * Copyright (C) 1999-2000, Michael Jennings * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to * deal in the Software without restriction, including without limitation the * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or * sell copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies of the Software, its documentation and marketing & publicity * materials, and acknowledgment shall be given in the documentation, materials * and software packages that this Software was used. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL * THE AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ #include #include "config.h" #include "epplet.h" #if 0 #define D(x) do {printf("%10s | %7d: [debug] ", __FILE__, __LINE__); printf x; fflush(stdout);} while (0) #else #define D(x) ((void) 0) #endif #define BEGMATCH(a, b) (!strncasecmp((a), (b), (sizeof(b) - 1))) #define NONULL(x) ((x) ? (x) : ("")) #define PREV_PIC() do {if (idx == 1) idx = image_cnt - 1; else if (idx == 0) idx = image_cnt - 2; else idx -= 2;} while (0) #define CUR_PIC() ((idx == 0) ? (image_cnt - 1) : (idx - 1)) #define NEXT_PIC() ((void) 0) #define INC_PIC() do {idx++; if (idx == image_cnt) idx = 0;} while (0) #define AUTOBG_OFF 0 #define AUTOBG_TILED 1 #define AUTOBG_SCALED 2 #define AUTOBG_PSCALED 3 static Epplet_gadget close_button, play_button, pause_button, prev_button, next_button, cfg_button, cfg_popup, picture; static Epplet_gadget cfg_tb_path, cfg_tb_delay, cfg_tb_zoom; static unsigned long idx = 0, image_cnt = 0; static double delay = 5.0; static const char *zoom_cmd; static char **filenames = NULL, *path; static unsigned char paused = 0, randomize = 0, auto_setbg = AUTOBG_OFF, maintain_aspect = 0; static int cfg_auto_setbg = AUTOBG_OFF, cfg_maintain_aspect = 0, cfg_randomize = 0; static Window config_win = None; static int w = 3, h = 3; static char **randomize_file_list(char **names, unsigned long num); static char **sort_file_list(char **names, unsigned long num); static void config_cb(void *data); static unsigned char get_images(char *image_path); static char ** dirscan(char *dir, unsigned long *num) { unsigned long i, dirlen; DIR *dirp; char **names; struct dirent *dp; struct stat filestat; char fullname[1024]; D(("dirscan(\"%s\", %8p) called.\n", dir, num)); if ((!dir) || (!*dir)) { *num = 0; return ((char **)NULL); } dirp = opendir(dir); if (!dirp) { *num = 0; return ((char **)NULL); } /* count # of entries in dir (worst case) */ for (dirlen = 0; (dp = readdir(dirp)); dirlen++); D((" -> Got %d entries.\n", dirlen)); if (!dirlen) { closedir(dirp); *num = 0; return ((char **)NULL); } names = malloc(dirlen * sizeof(char *)); D((" -> Storing names at %8p.\n", names)); if (!names) { *num = 0; return ((char **)NULL); } rewinddir(dirp); for (i = 0; (dp = readdir(dirp));) { if ((strcmp(dp->d_name, ".")) && (strcmp(dp->d_name, ".."))) { snprintf(fullname, sizeof(fullname), "%s/%s", dir, dp->d_name); D((" -> About to stat() %s\n", fullname)); if (stat(fullname, &filestat)) { D((" -> Couldn't stat() file %s -- %s\n", dp->d_name, strerror(errno))); } else { if (S_ISREG(filestat.st_mode)) { D((" -> Adding name \"%s\" at index %d (%8p)\n", dp->d_name, i, names + i)); names[i] = strdup(dp->d_name); i++; } else if (S_ISDIR(filestat.st_mode)) { /* Recurse directories here at some point, maybe? */ } } } } if (i < dirlen) { dirlen = i; } if (!dirlen) { closedir(dirp); *num = 0; return ((char **)NULL); } closedir(dirp); *num = dirlen; names = realloc(names, dirlen * sizeof(char *)); D((" -> Final directory length is %lu. List moved to %8p\n", *num, names)); if (randomize) { randomize_file_list(names, dirlen); } else { sort_file_list(names, dirlen); } return (names); } static char ** randomize_file_list(char **names, unsigned long len) { int r; unsigned long i; char *tmp; for (i = 0; i < len - 1; i++) { r = (int)((len - i - 1) * ((float)rand()) / (RAND_MAX + 1.0)) + i + 1; tmp = names[i]; names[i] = names[r]; names[r] = tmp; } return (names); } static char ** sort_file_list(char **names, unsigned long len) { unsigned long i; unsigned char done = 0; while (!done) { done = 1; for (i = 0; i < len - 1; i++) { if (strcmp(names[i], names[i + 1]) > 0) { char *tmp; tmp = names[i]; names[i] = names[i + 1]; names[i + 1] = tmp; done = 0; } } } return (names); } static void set_background(int tiled, int keep_aspect) { unsigned char current_desk = 0; char *reply, *ptr, bg_name[64]; Epplet_send_ipc("desk ?"); reply = Epplet_wait_for_ipc(); if (!reply) return; if ((ptr = strchr(reply, ':'))) current_desk = atoi(++ptr); free(reply); snprintf(bg_name, sizeof(bg_name), "E_SLIDES_BG_%s", filenames[CUR_PIC()]); Epplet_send_ipc("bg set %s bg.file %s/%s", bg_name, path, filenames[CUR_PIC()]); Epplet_send_ipc("bg set %s bg.solid 0 0 0", bg_name); Epplet_send_ipc("bg set %s bg.tile %d", bg_name, tiled); Epplet_send_ipc("bg set %s bg.keep_aspect %d", bg_name, keep_aspect); Epplet_send_ipc("bg set %s bg.xperc %d", bg_name, (tiled ? 0 : 1024)); Epplet_send_ipc("bg set %s bg.yperc %d", bg_name, (tiled ? 0 : 1024)); Epplet_send_ipc("bg set %s bg.xjust %d", bg_name, (tiled ? 0 : 512)); Epplet_send_ipc("bg set %s bg.yjust %d", bg_name, (tiled ? 0 : 512)); Epplet_send_ipc("bg use %s %d", bg_name, current_desk); Esync(); } static void change_image(void *data __UNUSED__) { Imlib_Image *im = NULL; double ratio = 0.0; unsigned long first = idx; int new_w = 0, new_h = 0, new_x = 3, new_y = 3; if (!filenames) return; /* Test-load each image to make sure it's a valid image file. */ for (; ((!filenames[idx]) || (!(im = imlib_load_image(filenames[idx]))));) { /* It isn't, so NULL out its name. */ filenames[idx] = NULL; INC_PIC(); if (idx == first) { /* They're all NULL now. Time to give up. */ Epplet_dialog_ok ("There don't seem to be any images in \"%s\". Please choose another directory.\n", path); Esync(); config_cb(NULL); return; } } new_w = (w * 16 - 6); new_h = (h * 16 - 6); imlib_context_set_image(im); if (maintain_aspect) { ratio = ((double)imlib_image_get_width() / imlib_image_get_height()) / ((double)new_w / new_h); if (ratio > 1.0) { new_h /= ratio; } else if (ratio != 1.0) { new_w *= ratio; } } imlib_free_image(); /* Destroy the image, but keep it in cache. */ new_x = ((w * 16) / 2) - (new_w / 2); new_y = ((h * 16) / 2) - (new_h / 2); Epplet_move_change_image(picture, new_x, new_y, new_w, new_h, filenames[idx]); INC_PIC(); switch (auto_setbg) { case AUTOBG_TILED: set_background(1, 1); break; case AUTOBG_SCALED: set_background(0, 0); break; case AUTOBG_PSCALED: set_background(0, 1); break; default: break; } Epplet_remove_timer("CHANGE_IMAGE"); if (!paused) { Epplet_timer(change_image, NULL, delay, "CHANGE_IMAGE"); } } static void close_cb(void *data __UNUSED__) { Epplet_Exit(0); } static void zoom_cb(void *data __UNUSED__) { char buff[1024]; snprintf(buff, sizeof(buff), zoom_cmd, filenames[CUR_PIC()]); Epplet_spawn_command(buff); } static void cfg_popup_cb(void *data) { int n = (int)(long)data; switch (n) { case 0: set_background(0, 0); break; case 1: set_background(1, 1); break; case 2: set_background(0, 1); break; case 3: zoom_cb(NULL); break; case 4: config_cb(NULL); break; default: break; } } static void play_cb(void *data) { int op = (int)(long)data; switch (op) { case -1: /* Previous image */ PREV_PIC(); change_image(NULL); break; case 0: /* Pause */ Epplet_remove_timer("CHANGE_IMAGE"); paused = 1; Epplet_gadget_hide(pause_button); Epplet_gadget_show(play_button); break; case 1: /* Play */ paused = 0; Epplet_gadget_hide(play_button); Epplet_gadget_show(pause_button); change_image(NULL); break; case 2: /* Next image */ NEXT_PIC(); change_image(NULL); break; default: break; } } static void in_cb(void *data __UNUSED__, Window win) { if (win == Epplet_get_main_window()) { Epplet_gadget_show(close_button); Epplet_gadget_show(cfg_button); Epplet_gadget_show(prev_button); Epplet_gadget_show(next_button); if (paused) { Epplet_gadget_show(play_button); } else { Epplet_gadget_show(pause_button); } } } static void out_cb(void *data __UNUSED__, Window win) { if (win == Epplet_get_main_window()) { Epplet_gadget_hide(close_button); Epplet_gadget_hide(cfg_button); Epplet_gadget_hide(prev_button); Epplet_gadget_hide(next_button); Epplet_gadget_hide(play_button); Epplet_gadget_hide(pause_button); } } static int delete_cb(void *data __UNUSED__, Window win __UNUSED__) { config_win = None; return 1; } static void apply_config(void) { char buff[1024]; auto_setbg = cfg_auto_setbg; if (auto_setbg == AUTOBG_TILED) { Epplet_modify_config("auto_setbg", "tiled"); } else if (auto_setbg == AUTOBG_SCALED) { Epplet_modify_config("auto_setbg", "scaled"); } else if (auto_setbg == AUTOBG_PSCALED) { Epplet_modify_config("auto_setbg", "scaled_with_aspect"); } else { Epplet_modify_config("auto_setbg", "off"); } strcpy(buff, Epplet_textbox_contents(cfg_tb_path)); if (strcmp(path, buff)) { if (get_images(buff)) { free(path); path = strdup(buff); Epplet_modify_config("image_dir", path); idx = 0; } } strcpy(buff, Epplet_textbox_contents(cfg_tb_delay)); if ((delay = atof(buff)) != 0.0) { Epplet_modify_config("delay", buff); } else { delay = atof(Epplet_query_config_def("delay", "2.0")); } zoom_cmd = Epplet_textbox_contents(cfg_tb_zoom); Epplet_modify_config("zoom_prog", zoom_cmd); if (randomize != cfg_randomize) { if (cfg_randomize) { randomize_file_list(filenames, image_cnt); } else { sort_file_list(filenames, image_cnt); } idx = 0; } randomize = cfg_randomize; sprintf(buff, "%d", randomize); Epplet_modify_config("randomize", buff); maintain_aspect = cfg_maintain_aspect; sprintf(buff, "%d", maintain_aspect); Epplet_modify_config("maintain_aspect", buff); change_image(NULL); } static void ok_cb(void *data __UNUSED__) { apply_config(); Epplet_save_config(); Epplet_window_destroy(config_win); config_win = None; } static void apply_cb(void *data __UNUSED__) { apply_config(); } static void cancel_cb(void *data __UNUSED__) { Epplet_window_destroy(config_win); config_win = None; } static void auto_popup_cb(void *data) { cfg_auto_setbg = (int)(long)data; } static void config_cb(void *data __UNUSED__) { char buff[128]; Epplet_gadget auto_popup; if (config_win) return; config_win = Epplet_create_window_config(200, 250, "E-Slides Configuration", ok_cb, NULL, apply_cb, NULL, cancel_cb, NULL); Epplet_gadget_show(Epplet_create_label (4, 4, "Directory to scan for images:", 2)); Epplet_gadget_show(cfg_tb_path = Epplet_create_textbox(NULL, path, 4, 18, 192, 20, 2, NULL, NULL)); sprintf(buff, "%3.2f", delay); Epplet_gadget_show(Epplet_create_label (4, 50, "Delay between images (seconds):", 2)); Epplet_gadget_show(cfg_tb_delay = Epplet_create_textbox(NULL, buff, 4, 64, 192, 20, 2, NULL, NULL)); Epplet_gadget_show(Epplet_create_label (4, 96, "Zoom program command line:", 2)); Epplet_gadget_show(cfg_tb_zoom = Epplet_create_textbox(NULL, zoom_cmd, 4, 110, 192, 20, 2, NULL, NULL)); auto_popup = Epplet_create_popup(); Epplet_add_popup_entry(auto_popup, "Tiled", NULL, auto_popup_cb, (void *)AUTOBG_TILED); Epplet_add_popup_entry(auto_popup, "Scaled", NULL, auto_popup_cb, (void *)AUTOBG_SCALED); Epplet_add_popup_entry(auto_popup, "Scaled, Keep Aspect", NULL, auto_popup_cb, (void *)AUTOBG_PSCALED); Epplet_add_popup_entry(auto_popup, "Off", NULL, auto_popup_cb, (void *)AUTOBG_OFF); Epplet_gadget_show(Epplet_create_popupbutton (NULL, NULL, 4, 142, 12, 12, "ARROW_UP", auto_popup)); Epplet_gadget_show(Epplet_create_label (20, 142, "Automatically set desktop", 2)); Epplet_gadget_show(Epplet_create_label (20, 156, "background when image changes?", 2)); cfg_maintain_aspect = maintain_aspect; Epplet_gadget_show(Epplet_create_togglebutton (NULL, NULL, 4, 175, 12, 12, &cfg_maintain_aspect, NULL, NULL)); Epplet_gadget_show(Epplet_create_label (20, 175, "Maintain aspect ratio when", 2)); Epplet_gadget_show(Epplet_create_label (20, 190, "displaying images in epplet?", 2)); cfg_randomize = randomize; Epplet_gadget_show(Epplet_create_togglebutton (NULL, NULL, 4, 210, 12, 12, &cfg_randomize, NULL, NULL)); Epplet_gadget_show(Epplet_create_label(20, 210, "Randomize image list?", 2)); Epplet_window_show(config_win); Epplet_window_pop_context(); } static void parse_config(void) { const char *s; char buff[1024]; s = Epplet_query_config("image_dir"); if (!s) { snprintf(buff, sizeof(buff), "%s/backgrounds", Epplet_e16_user_dir()); path = strdup(buff); Epplet_add_config("image_dir", buff); } else { path = strdup(s); } s = Epplet_query_config("delay"); if (s) { delay = atof(s); } else { Epplet_add_config("delay", "5.0"); } zoom_cmd = Epplet_query_config_def("zoom_prog", "ee %s"); s = Epplet_query_config_def("auto_setbg", "off"); if (!strcasecmp(s, "tiled")) { auto_setbg = AUTOBG_TILED; } else if (!strcasecmp(s, "scaled")) { auto_setbg = AUTOBG_SCALED; } else if (!strcasecmp(s, "scaled_with_aspect")) { auto_setbg = AUTOBG_PSCALED; } maintain_aspect = atoi(Epplet_query_config_def("maintain_aspect", "0")); randomize = atoi(Epplet_query_config_def("randomize", "0")); } static unsigned char get_images(char *image_path) { char **temp; unsigned long cnt; temp = dirscan(image_path, &cnt); if (cnt == 0) { Epplet_dialog_ok("Unable to find any files in %s!", image_path); Esync(); return 0; } else if (idx >= cnt) { idx = 0; } chdir(image_path); if (filenames) { unsigned int i; for (i = 0; i < image_cnt; i++) free(filenames[i]); free(filenames); } image_cnt = cnt; filenames = temp; return 1; } int main(int argc, char **argv) { int j = 0; Epplet_adjust_priority(10); srand(getpid() * time(NULL) % ((unsigned int)-1)); for (j = 1; j < argc; j++) { if ((!strcmp("-w", argv[j])) && (argc - j > 1)) { w = atoi(argv[++j]); if (w < 3) { w = 3; } } else if ((!strcmp("-h", argv[j])) && (argc - j > 1)) { h = atoi(argv[++j]); if (h < 3) { h = 3; } } } Epplet_Init("E-Slides", "0.3", "Enlightenment Slideshow Epplet", w, h, argc, argv, 0); Epplet_load_config(); parse_config(); cfg_popup = Epplet_create_popup(); Epplet_add_popup_entry(cfg_popup, "Set Background", NULL, cfg_popup_cb, (void *)0); Epplet_add_popup_entry(cfg_popup, "Tile as Background", NULL, cfg_popup_cb, (void *)1); Epplet_add_popup_entry(cfg_popup, "Set Background, Keep Aspect", NULL, cfg_popup_cb, (void *)2); Epplet_add_popup_entry(cfg_popup, "Open Image Viewer", NULL, cfg_popup_cb, (void *)3); Epplet_add_popup_entry(cfg_popup, "Configure E-Slides", NULL, cfg_popup_cb, (void *)4); close_button = Epplet_create_button(NULL, NULL, 3, 3, 0, 0, "CLOSE", 0, NULL, close_cb, NULL); prev_button = Epplet_create_button(NULL, NULL, 3, ((16 * h) - 15), 0, 0, "PREVIOUS", 0, NULL, play_cb, (void *)(-1)); play_button = Epplet_create_button(NULL, NULL, ((16 * w / 2) - 6), ((16 * h) - 15), 0, 0, "PLAY", 0, NULL, play_cb, (void *)(1)); pause_button = Epplet_create_button(NULL, NULL, ((16 * w / 2) - 6), ((16 * h) - 15), 0, 0, "PAUSE", 0, NULL, play_cb, (void *)(0)); cfg_button = Epplet_create_popupbutton(NULL, NULL, ((16 * w) - 15), 3, 0, 0, "CONFIGURE", cfg_popup); next_button = Epplet_create_button(NULL, NULL, ((16 * w) - 15), ((16 * h) - 15), 0, 0, "NEXT", 0, NULL, play_cb, (void *)(2)); Epplet_gadget_show(picture = Epplet_create_image(3, 3, ((w * 16) - 6), ((h * 16) - 6), NULL)); Epplet_show(); Epplet_register_focus_in_handler(in_cb, NULL); Epplet_register_focus_out_handler(out_cb, NULL); Epplet_register_delete_event_handler(delete_cb, NULL); if (get_images(path)) { change_image(NULL); } else { config_cb(NULL); } Epplet_Loop(); return 0; }