1 /* 2 * Copyright (C) 2015 The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17 #include <unistd.h> 18 #include <stdlib.h> 19 #include <limits.h> 20 #include <time.h> 21 #include <linux/input.h> 22 #include <cutils/klog.h> 23 #include <utils/SystemClock.h> 24 #include "minui/minui.h" 25 26 #define NEXT_TIMEOUT_MS 5000 27 #define LAST_TIMEOUT_MS 30000 28 29 #define LOGE(x...) do { KLOG_ERROR("slideshow", x); } while (0) 30 31 static int input_cb(int fd, unsigned int epevents, void *data) 32 { 33 struct input_event ev; 34 int *key_code = (int *)data; 35 36 *key_code = -1; 37 38 if (ev_get_input(fd, epevents, &ev)) { 39 return -1; 40 } 41 42 if (ev.type == EV_KEY && ev.value == 1) { 43 *key_code = ev.code; 44 } 45 46 return 0; 47 } 48 49 static void clear() 50 { 51 gr_color(0, 0, 0, 0); 52 gr_clear(); 53 gr_flip(); 54 } 55 56 static void draw(const char *resname) 57 { 58 GRSurface* surface; 59 int w, h, x, y; 60 61 if (res_create_display_surface(resname, &surface) < 0) { 62 LOGE("failed to create surface for %s\n", resname); 63 return; 64 } 65 66 w = gr_get_width(surface); 67 h = gr_get_height(surface); 68 x = (gr_fb_width() - w) / 2; 69 y = (gr_fb_height() - h) / 2; 70 71 gr_blit(surface, 0, 0, w, h, x, y); 72 gr_flip(); 73 74 res_free_surface(surface); 75 } 76 77 int usage() 78 { 79 LOGE("usage: slideshow [-t timeout] image.png [image2.png ...] last.png\n"); 80 return EXIT_FAILURE; 81 } 82 83 int main(int argc, char **argv) 84 { 85 int key_code = -1; 86 int input = false; 87 int opt; 88 long int timeout = NEXT_TIMEOUT_MS; 89 int64_t start; 90 91 while ((opt = getopt(argc, argv, "t:")) != -1) { 92 switch (opt) { 93 case 't': 94 timeout = strtol(optarg, NULL, 0); 95 96 if (timeout < 0 || timeout >= LONG_MAX) { 97 timeout = NEXT_TIMEOUT_MS; 98 LOGE("invalid timeout %s, defaulting to %ld\n", optarg, 99 timeout); 100 } 101 break; 102 default: 103 return usage(); 104 } 105 } 106 107 if (optind >= argc) { 108 return usage(); 109 } 110 111 if (gr_init() == -1 || ev_init(input_cb, &key_code) == -1) { 112 LOGE("failed to initialize minui\n"); 113 return EXIT_FAILURE; 114 } 115 116 /* display all images except the last one, switch to next image after 117 * timeout or user input */ 118 119 while (optind < argc - 1) { 120 draw(argv[optind++]); 121 122 start = android::uptimeMillis(); 123 long int timeout_remaining = timeout; 124 do { 125 if (ev_wait(timeout_remaining) == 0) { 126 ev_dispatch(); 127 128 if (key_code != -1) { 129 input = true; 130 break; 131 } 132 } 133 timeout_remaining -= android::uptimeMillis() - start; 134 } while (timeout_remaining > 0); 135 }; 136 137 /* if there was user input while showing the images, display the last 138 * image and wait until the power button is pressed or LAST_TIMEOUT_MS 139 * has elapsed */ 140 141 if (input) { 142 start = android::uptimeMillis(); 143 144 draw(argv[optind]); 145 146 do { 147 if (ev_wait(timeout) == 0) { 148 ev_dispatch(); 149 } 150 151 if (android::uptimeMillis() - start >= LAST_TIMEOUT_MS) { 152 break; 153 } 154 } while (key_code != KEY_POWER); 155 } 156 157 clear(); 158 gr_exit(); 159 ev_exit(); 160 161 return EXIT_SUCCESS; 162 } 163