From bbd2196326bbcb4cb96e8a8e3d68c25e414510d5 Mon Sep 17 00:00:00 2001 From: Thomas Osterland Date: Wed, 21 Mar 2018 15:59:45 +0100 Subject: [PATCH 1/8] added slideshow functionality --- i3lock.c | 104 +++++++++++++++++++++++++++++++++++++-------- unlock_indicator.c | 20 +++++++++ 2 files changed, 106 insertions(+), 18 deletions(-) diff --git a/i3lock.c b/i3lock.c index 72d8ab8..e68d60e 100644 --- a/i3lock.c +++ b/i3lock.c @@ -17,6 +17,7 @@ #include #include #include +#include #include #include #include @@ -91,6 +92,7 @@ int screen_number = 0; int internal_line_source = 0; /* bool for showing the clock; why am I commenting this? */ bool show_clock = false; +bool slideshow_enabled = false; bool always_show_clock = false; bool show_indicator = false; float refresh_rate = 1.0; @@ -200,6 +202,10 @@ static int randr_base = -1; cairo_surface_t *img = NULL; cairo_surface_t *blur_img = NULL; +cairo_surface_t *img_slideshow[256]; +int slideshow_image_count = 0; +int slideshow_interval = 10; + bool tile = false; bool ignore_empty_password = false; bool skip_repeated_empty_password = false; @@ -234,6 +240,15 @@ bool bar_reversed = false; /* isutf, u8_dec © 2005 Jeff Bezanson, public domain */ #define isutf(c) (((c)&0xC0) != 0x80) +/* + * Checks if the given path leads to an actual file or something else, e.g. a directory + */ +int is_regular_file(const char *path) { + struct stat path_stat; + stat(path, &path_stat); + return S_ISREG(path_stat.st_mode); +} + /* * Decrements i to point to the previous unicode glyph * @@ -1046,6 +1061,44 @@ static void raise_loop(xcb_window_t window) { } } +/* + * Loads the images from the provided directory and stores them in the pointer array + * img_slideshow + */ +void load_slideshow_images(const char *path) { + slideshow_enabled = true; + DIR *d; + struct dirent *dir; + int file_count = 0; + + d = opendir(path); + if (d == NULL) { + printf("Could not open directory: %s\n", path); + exit(0); + } + + while ((dir = readdir(d)) != NULL) { + if (file_count >= 256) { + break; + } + + char path_to_image[256]; + strcpy(path_to_image, path); + strcat(path_to_image, "/"); + strcat(path_to_image, dir->d_name); + + if (verify_png_image(path_to_image)) { + img_slideshow[file_count] = cairo_image_surface_create_from_png(path_to_image); + ++file_count; + } + + } + + slideshow_image_count = file_count; + + closedir(d); +} + int main(int argc, char *argv[]) { struct passwd *pw; char *username; @@ -1166,6 +1219,9 @@ int main(int argc, char *argv[]) { {"refresh-rate", required_argument, NULL, 901}, {"composite", no_argument, NULL, 902}, + /* slideshow options */ + {"slideshow-interval", required_argument, NULL, 1000}, + {NULL, no_argument, NULL, 0}}; if ((pw = getpwuid(getuid())) == NULL) @@ -1619,6 +1675,13 @@ int main(int argc, char *argv[]) { case 999: debug_mode = true; break; + case 1000: + slideshow_interval = atoi(optarg); + + if (slideshow_interval < 0) { + slideshow_interval = 10; + } + break; default: errx(EXIT_FAILURE, "Syntax: i3lock [-v] [-n] [-b] [-d] [-c color] [-u] [-p win|default]" " [-i image.png] [-t] [-e] [-f]\n" @@ -1743,23 +1806,28 @@ int main(int argc, char *argv[]) { (uint32_t[]){XCB_EVENT_MASK_STRUCTURE_NOTIFY}); init_colors_once(); - if (verify_png_image(image_path)) { - /* Create a pixmap to render on, fill it with the background color */ - img = cairo_image_surface_create_from_png(image_path); - } else if (file_is_jpg(image_path)) { - DEBUG("Image looks like a jpeg, decoding\n"); - unsigned char* jpg_data = read_JPEG_file(image_path, &jpg_info); - if (jpg_data != NULL) { - img = cairo_image_surface_create_for_data(jpg_data, - CAIRO_FORMAT_ARGB32, jpg_info.width, jpg_info.height, - jpg_info.stride); - } - } - /* In case loading failed, we just pretend no -i was specified. */ - if (img && cairo_surface_status(img) != CAIRO_STATUS_SUCCESS) { - fprintf(stderr, "Could not load image \"%s\": %s\n", - image_path, cairo_status_to_string(cairo_surface_status(img))); - img = NULL; + if (is_regular_file(image_path)) { + if (verify_png_image(image_path)) { + /* Create a pixmap to render on, fill it with the background color */ + img = cairo_image_surface_create_from_png(image_path); + } else if (file_is_jpg(image_path)) { + DEBUG("Image looks like a jpeg, decoding\n"); + unsigned char* jpg_data = read_JPEG_file(image_path, &jpg_info); + if (jpg_data != NULL) { + img = cairo_image_surface_create_for_data(jpg_data, + CAIRO_FORMAT_ARGB32, jpg_info.width, jpg_info.height, + jpg_info.stride); + } + } + /* In case loading failed, we just pretend no -i was specified. */ + if (img && cairo_surface_status(img) != CAIRO_STATUS_SUCCESS) { + fprintf(stderr, "Could not load image \"%s\": %s\n", + image_path, cairo_status_to_string(cairo_surface_status(img))); + img = NULL; + } + } else { + /* Path to a directory is provided -> use slideshow mode */ + load_slideshow_images(image_path); } free(image_path); @@ -1881,7 +1949,7 @@ int main(int argc, char *argv[]) { * file descriptor becomes readable). */ ev_invoke(main_loop, xcb_check, 0); - if (show_clock || bar_enabled) { + if (show_clock || bar_enabled || slideshow_enabled) { if (redraw_thread) { struct timespec ts; double s; diff --git a/unlock_indicator.c b/unlock_indicator.c index 528e406..dbd8ba0 100644 --- a/unlock_indicator.c +++ b/unlock_indicator.c @@ -59,6 +59,11 @@ extern char *modifier_string; /* A Cairo surface containing the specified image (-i), if any. */ extern cairo_surface_t *img; extern cairo_surface_t *blur_img; +extern cairo_surface_t *img_slideshow[256]; +extern int slideshow_image_count; +extern int slideshow_interval; + +unsigned long lastCheck = -1; /* Whether the image should be tiled. */ extern bool tile; @@ -144,6 +149,8 @@ static struct ev_periodic *time_redraw_tick; /* Cache the screen’s visual, necessary for creating a Cairo context. */ static xcb_visualtype_t *vistype; +int current_slideshow_index = 0; + /* Maintain the current unlock/PAM state to draw the appropriate unlock * indicator. */ unlock_state_t unlock_state; @@ -678,6 +685,19 @@ xcb_pixmap_t draw_image(uint32_t *resolution) { cairo_surface_t *xcb_output = cairo_xcb_surface_create(conn, bg_pixmap, vistype, resolution[0], resolution[1]); cairo_t *xcb_ctx = cairo_create(xcb_output); + /*update image according to the slideshow_interval*/ + if (slideshow_image_count > 0) { + unsigned long now = (unsigned long)time(NULL); + if (-1 == lastCheck || now - lastCheck >= slideshow_interval) { + img = img_slideshow[current_slideshow_index++]; + + if (current_slideshow_index >= slideshow_image_count) { + current_slideshow_index = 0; + } + lastCheck = now; + } + } + if (blur_img || img) { if (blur_img) { cairo_set_source_surface(xcb_ctx, blur_img, 0, 0); From 74e6dfe497d1f8729759d0f264039978c0df3145 Mon Sep 17 00:00:00 2001 From: Thomas Osterland Date: Thu, 22 Mar 2018 07:55:22 +0100 Subject: [PATCH 2/8] moved slideshow flags into misc (1000 -> 903) --- i3lock.c | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/i3lock.c b/i3lock.c index e68d60e..d5b269d 100644 --- a/i3lock.c +++ b/i3lock.c @@ -1220,7 +1220,7 @@ int main(int argc, char *argv[]) { {"composite", no_argument, NULL, 902}, /* slideshow options */ - {"slideshow-interval", required_argument, NULL, 1000}, + {"slideshow-interval", required_argument, NULL, 903}, {NULL, no_argument, NULL, 0}}; @@ -1672,16 +1672,16 @@ int main(int argc, char *argv[]) { case 902: composite = true; break; - case 999: - debug_mode = true; - break; - case 1000: + case 903: slideshow_interval = atoi(optarg); if (slideshow_interval < 0) { slideshow_interval = 10; } break; + case 999: + debug_mode = true; + break; default: errx(EXIT_FAILURE, "Syntax: i3lock [-v] [-n] [-b] [-d] [-c color] [-u] [-p win|default]" " [-i image.png] [-t] [-e] [-f]\n" From c28c13990be983baf4d540157ea5fa1d0621fb73 Mon Sep 17 00:00:00 2001 From: Thomas Osterland Date: Thu, 22 Mar 2018 08:02:20 +0100 Subject: [PATCH 3/8] fixed seg fault if no file or directory path is provided --- i3lock.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/i3lock.c b/i3lock.c index d5b269d..2d1cad2 100644 --- a/i3lock.c +++ b/i3lock.c @@ -1825,7 +1825,7 @@ int main(int argc, char *argv[]) { image_path, cairo_status_to_string(cairo_surface_status(img))); img = NULL; } - } else { + } else if (image_path != NULL) { /* Path to a directory is provided -> use slideshow mode */ load_slideshow_images(image_path); } From fa0bf7bc4d9295b3e268a2def7d2d88597f3440a Mon Sep 17 00:00:00 2001 From: Thomas Osterland Date: Thu, 22 Mar 2018 20:43:29 +0100 Subject: [PATCH 4/8] initialize lastCheck variable in init_colors_once to replace -1 check --- unlock_indicator.c | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/unlock_indicator.c b/unlock_indicator.c index dbd8ba0..c8bcb5a 100644 --- a/unlock_indicator.c +++ b/unlock_indicator.c @@ -63,7 +63,7 @@ extern cairo_surface_t *img_slideshow[256]; extern int slideshow_image_count; extern int slideshow_interval; -unsigned long lastCheck = -1; +unsigned long lastCheck; /* Whether the image should be tiled. */ extern bool tile; @@ -581,6 +581,10 @@ static void colorgen_rgb(rgb_str_t *tmp, const char *src, rgb_t *dest) { } void init_colors_once(void) { + + /* initialize for slideshow time interval */ + lastCheck = (unsigned long)time(NULL); + rgba_str_t tmp; rgb_str_t tmp_rgb; @@ -688,7 +692,7 @@ xcb_pixmap_t draw_image(uint32_t *resolution) { /*update image according to the slideshow_interval*/ if (slideshow_image_count > 0) { unsigned long now = (unsigned long)time(NULL); - if (-1 == lastCheck || now - lastCheck >= slideshow_interval) { + if (img == NULL || now - lastCheck >= slideshow_interval) { img = img_slideshow[current_slideshow_index++]; if (current_slideshow_index >= slideshow_image_count) { From 933c3b80aefcc953a6a9ab371e9c84fda1de2dde Mon Sep 17 00:00:00 2001 From: Thomas Osterland Date: Thu, 22 Mar 2018 21:02:26 +0100 Subject: [PATCH 5/8] added functionality to randomly select images during slideshow --- i3lock.c | 5 +++++ unlock_indicator.c | 11 ++++++++--- 2 files changed, 13 insertions(+), 3 deletions(-) diff --git a/i3lock.c b/i3lock.c index 2d1cad2..1138360 100644 --- a/i3lock.c +++ b/i3lock.c @@ -205,6 +205,7 @@ cairo_surface_t *blur_img = NULL; cairo_surface_t *img_slideshow[256]; int slideshow_image_count = 0; int slideshow_interval = 10; +bool slideshow_random_selection = false; bool tile = false; bool ignore_empty_password = false; @@ -1221,6 +1222,7 @@ int main(int argc, char *argv[]) { /* slideshow options */ {"slideshow-interval", required_argument, NULL, 903}, + {"slideshow-random-selection", no_argument, NULL, 904}, {NULL, no_argument, NULL, 0}}; @@ -1679,6 +1681,9 @@ int main(int argc, char *argv[]) { slideshow_interval = 10; } break; + case 904: + slideshow_random_selection = true; + break; case 999: debug_mode = true; break; diff --git a/unlock_indicator.c b/unlock_indicator.c index c8bcb5a..f4fe176 100644 --- a/unlock_indicator.c +++ b/unlock_indicator.c @@ -62,6 +62,7 @@ extern cairo_surface_t *blur_img; extern cairo_surface_t *img_slideshow[256]; extern int slideshow_image_count; extern int slideshow_interval; +extern bool slideshow_random_selection; unsigned long lastCheck; @@ -693,10 +694,14 @@ xcb_pixmap_t draw_image(uint32_t *resolution) { if (slideshow_image_count > 0) { unsigned long now = (unsigned long)time(NULL); if (img == NULL || now - lastCheck >= slideshow_interval) { - img = img_slideshow[current_slideshow_index++]; + if (slideshow_random_selection) { + img = img_slideshow[rand() % slideshow_image_count]; + } else { + img = img_slideshow[current_slideshow_index++]; - if (current_slideshow_index >= slideshow_image_count) { - current_slideshow_index = 0; + if (current_slideshow_index >= slideshow_image_count) { + current_slideshow_index = 0; + } } lastCheck = now; } From 9c547309741f3e903b1d2115d3ef301e2691a773 Mon Sep 17 00:00:00 2001 From: Thomas Osterland Date: Sat, 24 Mar 2018 09:57:14 +0100 Subject: [PATCH 6/8] slideshow support for jpg and introduced load_image function --- i3lock.c | 52 ++++++++++++++++++++++++++++++++-------------------- 1 file changed, 32 insertions(+), 20 deletions(-) diff --git a/i3lock.c b/i3lock.c index 1138360..0fb2194 100644 --- a/i3lock.c +++ b/i3lock.c @@ -1062,6 +1062,36 @@ static void raise_loop(xcb_window_t window) { } } +/* + * Loads an image from the given path. Handles JPEG and PNG. Returns NULL in case of error. + */ +cairo_surface_t* load_image(char* image_path) { + cairo_surface_t *img = NULL; + JPEG_INFO jpg_info; + + if (verify_png_image(image_path)) { + /* Create a pixmap to render on, fill it with the background color */ + img = cairo_image_surface_create_from_png(image_path); + } else if (file_is_jpg(image_path)) { + DEBUG("Image looks like a jpeg, decoding\n"); + unsigned char* jpg_data = read_JPEG_file(image_path, &jpg_info); + if (jpg_data != NULL) { + img = cairo_image_surface_create_for_data(jpg_data, + CAIRO_FORMAT_ARGB32, jpg_info.width, jpg_info.height, + jpg_info.stride); + } + } + + /* In case loading failed, we just pretend no -i was specified. */ + if (img && cairo_surface_status(img) != CAIRO_STATUS_SUCCESS) { + fprintf(stderr, "Could not load image \"%s\": %s\n", + image_path, cairo_status_to_string(cairo_surface_status(img))); + img = NULL; + } + + return img; +} + /* * Loads the images from the provided directory and stores them in the pointer array * img_slideshow @@ -1089,7 +1119,7 @@ void load_slideshow_images(const char *path) { strcat(path_to_image, dir->d_name); if (verify_png_image(path_to_image)) { - img_slideshow[file_count] = cairo_image_surface_create_from_png(path_to_image); + img_slideshow[file_count] = load_image(path_to_image); ++file_count; } @@ -1104,7 +1134,6 @@ int main(int argc, char *argv[]) { struct passwd *pw; char *username; char *image_path = NULL; - JPEG_INFO jpg_info; #ifndef __OpenBSD__ int ret; struct pam_conv conv = {conv_callback, NULL}; @@ -1812,24 +1841,7 @@ int main(int argc, char *argv[]) { init_colors_once(); if (is_regular_file(image_path)) { - if (verify_png_image(image_path)) { - /* Create a pixmap to render on, fill it with the background color */ - img = cairo_image_surface_create_from_png(image_path); - } else if (file_is_jpg(image_path)) { - DEBUG("Image looks like a jpeg, decoding\n"); - unsigned char* jpg_data = read_JPEG_file(image_path, &jpg_info); - if (jpg_data != NULL) { - img = cairo_image_surface_create_for_data(jpg_data, - CAIRO_FORMAT_ARGB32, jpg_info.width, jpg_info.height, - jpg_info.stride); - } - } - /* In case loading failed, we just pretend no -i was specified. */ - if (img && cairo_surface_status(img) != CAIRO_STATUS_SUCCESS) { - fprintf(stderr, "Could not load image \"%s\": %s\n", - image_path, cairo_status_to_string(cairo_surface_status(img))); - img = NULL; - } + img = load_image(image_path); } else if (image_path != NULL) { /* Path to a directory is provided -> use slideshow mode */ load_slideshow_images(image_path); From b2e296e4fed8075201c64b960d4375c5d91ce88e Mon Sep 17 00:00:00 2001 From: Thomas Osterland Date: Sat, 24 Mar 2018 10:02:02 +0100 Subject: [PATCH 7/8] removed if -> now slideshow supports jpeg --- i3lock.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/i3lock.c b/i3lock.c index 0fb2194..b29dce0 100644 --- a/i3lock.c +++ b/i3lock.c @@ -1118,11 +1118,11 @@ void load_slideshow_images(const char *path) { strcat(path_to_image, "/"); strcat(path_to_image, dir->d_name); - if (verify_png_image(path_to_image)) { - img_slideshow[file_count] = load_image(path_to_image); + img_slideshow[file_count] = load_image(path_to_image); + + if (img_slideshow[file_count] != NULL) { ++file_count; } - } slideshow_image_count = file_count; From 9f27a7684fed7b4a53c9228012ef646c5f6c6d60 Mon Sep 17 00:00:00 2001 From: Thomas Osterland Date: Sat, 7 Apr 2018 09:52:12 +0200 Subject: [PATCH 8/8] moved NULL check --- i3lock.c | 15 +++++++++------ 1 file changed, 9 insertions(+), 6 deletions(-) diff --git a/i3lock.c b/i3lock.c index b29dce0..2d29e52 100644 --- a/i3lock.c +++ b/i3lock.c @@ -1840,13 +1840,16 @@ int main(int argc, char *argv[]) { (uint32_t[]){XCB_EVENT_MASK_STRUCTURE_NOTIFY}); init_colors_once(); - if (is_regular_file(image_path)) { - img = load_image(image_path); - } else if (image_path != NULL) { - /* Path to a directory is provided -> use slideshow mode */ - load_slideshow_images(image_path); + if (image_path != NULL) { + if (is_regular_file(image_path)) { + img = load_image(image_path); + } else { + /* Path to a directory is provided -> use slideshow mode */ + load_slideshow_images(image_path); + } + + free(image_path); } - free(image_path); xcb_pixmap_t* blur_pixmap = NULL; if (blur) {