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 23 #include <functional> 24 25 #include <cutils/klog.h> 26 #include <minui/minui.h> 27 #include <utils/SystemClock.h> 28 29 #define NEXT_TIMEOUT_MS 5000 30 #define LAST_TIMEOUT_MS 30000 31 32 #define LOGE(x...) do { KLOG_ERROR("slideshow", x); } while (0) 33 34 static int input_cb(int fd, unsigned int epevents, int *key_code) 35 { 36 struct input_event ev; 37 38 *key_code = -1; 39 40 if (ev_get_input(fd, epevents, &ev)) { 41 return -1; 42 } 43 44 if (ev.type == EV_KEY && ev.value == 1) { 45 *key_code = ev.code; 46 } 47 48 return 0; 49 } 50 51 static void clear() 52 { 53 gr_color(0, 0, 0, 0); 54 gr_clear(); 55 gr_flip(); 56 } 57 58 static void draw(const char *resname) 59 { 60 GRSurface* surface; 61 int w, h, x, y; 62 63 if (res_create_display_surface(resname, &surface) < 0) { 64 LOGE("failed to create surface for %s\n", resname); 65 return; 66 } 67 68 w = gr_get_width(surface); 69 h = gr_get_height(surface); 70 x = (gr_fb_width() - w) / 2; 71 y = (gr_fb_height() - h) / 2; 72 73 gr_blit(surface, 0, 0, w, h, x, y); 74 gr_flip(); 75 76 res_free_surface(surface); 77 } 78 79 int usage() 80 { 81 LOGE("usage: slideshow [-t timeout] image.png [image2.png ...] last.png\n"); 82 return EXIT_FAILURE; 83 } 84 85 int main(int argc, char **argv) 86 { 87 int key_code = -1; 88 int input = false; 89 int opt; 90 long int timeout = NEXT_TIMEOUT_MS; 91 int64_t start; 92 93 while ((opt = getopt(argc, argv, "t:")) != -1) { 94 switch (opt) { 95 case 't': 96 timeout = strtol(optarg, NULL, 0); 97 98 if (timeout < 0 || timeout >= LONG_MAX) { 99 timeout = NEXT_TIMEOUT_MS; 100 LOGE("invalid timeout %s, defaulting to %ld\n", optarg, 101 timeout); 102 } 103 break; 104 default: 105 return usage(); 106 } 107 } 108 109 if (optind >= argc) { 110 return usage(); 111 } 112 113 if (gr_init() == -1 || ev_init(std::bind(&input_cb, std::placeholders::_1, 114 std::placeholders::_2, &key_code)) == -1) { 115 LOGE("failed to initialize minui\n"); 116 return EXIT_FAILURE; 117 } 118 119 /* display all images except the last one, switch to next image after 120 * timeout or user input */ 121 122 while (optind < argc - 1) { 123 draw(argv[optind++]); 124 125 start = android::uptimeMillis(); 126 long int timeout_remaining = timeout; 127 do { 128 if (ev_wait(timeout_remaining) == 0) { 129 ev_dispatch(); 130 131 if (key_code != -1) { 132 input = true; 133 break; 134 } 135 } 136 timeout_remaining -= android::uptimeMillis() - start; 137 } while (timeout_remaining > 0); 138 }; 139 140 /* if there was user input while showing the images, display the last 141 * image and wait until the power button is pressed or LAST_TIMEOUT_MS 142 * has elapsed */ 143 144 if (input) { 145 start = android::uptimeMillis(); 146 147 draw(argv[optind]); 148 149 do { 150 if (ev_wait(timeout) == 0) { 151 ev_dispatch(); 152 } 153 154 if (android::uptimeMillis() - start >= LAST_TIMEOUT_MS) { 155 break; 156 } 157 } while (key_code != KEY_POWER); 158 } 159 160 clear(); 161 gr_exit(); 162 ev_exit(); 163 164 return EXIT_SUCCESS; 165 } 166