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