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 
input_cb(int fd,unsigned int epevents,int * key_code)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 
clear()51 static void clear()
52 {
53     gr_color(0, 0, 0, 0);
54     gr_clear();
55     gr_flip();
56 }
57 
draw(const char * resname)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 
usage()79 int usage()
80 {
81     LOGE("usage: slideshow [-t timeout] image.png [image2.png ...] last.png\n");
82     return EXIT_FAILURE;
83 }
84 
main(int argc,char ** argv)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