1 #include <Eina.h>
2 #include <Ecore.h>
3 #include <Evas.h>
4 #include <Ecore_Evas.h>
5 #include <Ecore_File.h>
6 #include <Edje.h>
7 #include <Emotion.h>
8 #include <termios.h>
9 #include <stdio.h>
10 #include <stdlib.h>
11 #include <unistd.h>
12 #include <string.h>
13 #include "private.h"
14 #include "tycommon.h"
15
16 enum {
17 CENTER,
18 FILL,
19 STRETCH,
20 NOIMG
21 };
22
23 #define VIDEO_DECODE_TIMEOUT 1.0
24
25 static Evas *evas = NULL;
26 static struct termios told, tnew;
27 static int tw = 0, th = 0, cw = 0, ch = 0, maxw = 0, maxh = 0, _mode = CENTER;
28 static Ecore_Timer *timeout_t = NULL;
29
30 #include "extns.h"
31
32 static int
echo_off(void)33 echo_off(void)
34 {
35 if (tcgetattr(0, &told) != 0) return -1;
36 tnew = told;
37 tnew.c_lflag &= ~ECHO;
38 if (tcsetattr(0, TCSAFLUSH, &tnew) != 0) return -1;
39 return 0;
40 }
41
42 static int
echo_on(void)43 echo_on(void)
44 {
45 return tcsetattr(0, TCSAFLUSH, &told);
46 }
47
48 static void
scaleterm(int w,int h,int * iw,int * ih)49 scaleterm(int w, int h, int *iw, int *ih)
50 {
51 int width = maxw ? maxw : tw;
52 if (w > (width * cw))
53 {
54 *iw = width;
55 *ih = ((h * (width * cw) / w) + (ch - 1)) / ch;
56 }
57 else
58 {
59 *iw = (w + (cw - 1)) / cw;
60 *ih = (h + (ch - 1)) / ch;
61 }
62 if (maxh && *ih > maxh)
63 {
64 *ih = maxh;
65 *iw = ((w * (maxh * ch) / h) + (cw - 1)) / cw;
66 }
67 }
68
69 static const char *
is_fmt(const char * f,const char ** extn)70 is_fmt(const char *f, const char **extn)
71 {
72 int i, len;
73
74 len = strlen(f);
75 for (i = 0; extn[i]; i++)
76 {
77 int l = strlen(extn[i]);
78 if (len < l) continue;
79 if (!strcasecmp(extn[i], f + len - l)) return extn[i];
80 }
81 return NULL;
82 }
83
84 static void
prnt(const char * path,int w,int h,int mode)85 prnt(const char *path, int w, int h, int mode)
86 {
87 int x, y, i;
88 char *line, buf[4096];
89
90 if ((w >= 512) || (h >= 512)) return;
91 line = malloc(w + 100);
92 if (!line) return;
93 if (mode == CENTER)
94 snprintf(buf, sizeof(buf), "%c}ic#%i;%i;%s", 0x1b, w, h, path);
95 else if (mode == FILL)
96 snprintf(buf, sizeof(buf), "%c}if#%i;%i;%s", 0x1b, w, h, path);
97 else
98 snprintf(buf, sizeof(buf), "%c}is#%i;%i;%s", 0x1b, w, h, path);
99 if (ty_write(1, buf, strlen(buf) + 1) < 0)
100 perror("write");
101 i = 0;
102 line[i++] = 0x1b;
103 line[i++] = '}';
104 line[i++] = 'i';
105 line[i++] = 'b';
106 line[i++] = 0;
107 for (x = 0; x < w; x++) line[i++] = '#';
108 line[i++] = 0x1b;
109 line[i++] = '}';
110 line[i++] = 'i';
111 line[i++] = 'e';
112 line[i++] = 0;
113 line[i++] = '\n';
114 for (y = 0; y < h; y++)
115 {
116 if (ty_write(1, line, i) < 0)
117 perror("write");
118 }
119 free(line);
120 }
121
122 static void
print_usage(const char * argv0)123 print_usage(const char *argv0)
124 {
125 printf("Usage: %s "HELP_ARGUMENT_SHORT" [-s|-f|-c] [-g <width>x<height>] FILE1 [FILE2 ...]\n"
126 "\n"
127 " -s Stretch file to fill nearest character cell size\n"
128 " -f Fill file to totally cover character cells with no gaps\n"
129 " -c Center file in nearest character cells but only scale down (default)\n"
130 " -g <width>x<height> Set maximum geometry for the image (cell count)\n"
131 HELP_ARGUMENT_DOC"\n",
132 argv0);
133 }
134
135 static Eina_Bool
timeout_cb(void * data)136 timeout_cb(void *data)
137 {
138 evas_object_del(data);
139 timeout_t = NULL;
140
141 return ECORE_CALLBACK_CANCEL;
142 }
143
144 static int
handle_image(char * rp)145 handle_image(char *rp)
146 {
147 Evas_Object *o;
148 int w = 0, h = 0;
149 int iw = 0, ih = 0;
150 int r = -1;
151
152 if (!is_fmt(rp, extn_img) &&
153 !is_fmt(rp, extn_scale) &&
154 !is_fmt(rp, extn_mov))
155 return -1;
156
157 o = evas_object_image_add(evas);
158 evas_object_image_file_set(o, rp, NULL);
159 evas_object_image_size_get(o, &w, &h);
160 if ((w >= 0) && (h > 0))
161 {
162 scaleterm(w, h, &iw, &ih);
163 prnt(rp, iw, ih, _mode);
164 r = 0;
165 }
166
167 evas_object_del(o);
168
169 return r;
170 }
171
172 static int
handle_edje(char * rp)173 handle_edje(char *rp)
174 {
175 Evas_Object *o;
176 int iw = 0, ih = 0;
177 int r = -1;
178
179 if (!is_fmt(rp, extn_edj)) return -1;
180
181 o = edje_object_add(evas);
182 if (edje_object_file_set
183 (o, rp, "terminology/background") == EINA_TRUE ||
184 !edje_object_file_set
185 (o, rp, "e/desktop/background"))
186 {
187 Evas_Coord mw = 0, mh = 0;
188 edje_object_size_min_get(o, &mw, &mh);
189 if ((mw <= 0) || (mh <= 0))
190 edje_object_size_min_calc(o, &mw, &mh);
191 if ((mw <= 0) || (mh <= 0))
192 {
193 mw = (tw) * cw;
194 mh = (th - 1) * ch;
195 }
196 scaleterm(mw, mh, &iw, &ih);
197 prnt(rp, iw, ih, _mode);
198 r = 0;
199 }
200
201 evas_object_del(o);
202
203 return r;
204 }
205
206 static void
video_decoded(void * data,Evas_Object * o,void * ei EINA_UNUSED)207 video_decoded(void *data, Evas_Object *o, void *ei EINA_UNUSED)
208 {
209 int w = 0, h = 0;
210 int iw = 0, ih = 0;
211
212 if (emotion_object_video_handled_get(o))
213 {
214 emotion_object_size_get(o, &w, &h);
215 if ((w >= 0) && (h > 0))
216 {
217 scaleterm(w, h, &iw, &ih);
218 prnt(data, iw, ih, _mode);
219 goto done;
220 }
221 else
222 {
223 double ar = emotion_object_ratio_get(o);
224 if (ar > 0.0)
225 {
226 scaleterm(tw * cw, (int) ((tw * cw) / ar), &iw, &ih);
227 prnt(data, iw, ih, _mode);
228 goto done;
229 }
230 }
231 }
232
233 prnt(data, tw, 3, NOIMG);
234
235 done:
236 ecore_timer_del(timeout_t);
237 timeout_t = NULL;
238 evas_object_del(o);
239 free(data);
240 }
241
242 static int
handle_video(char * rp)243 handle_video(char *rp)
244 {
245 Evas_Object *o;
246
247 if (!is_fmt(rp, extn_aud) &&
248 !is_fmt(rp, extn_mov))
249 return -1;
250
251 o = emotion_object_add(evas);
252 if (emotion_object_init(o, NULL) == EINA_TRUE)
253 {
254 if (emotion_object_file_set(o, rp))
255 {
256 emotion_object_audio_mute_set(o, EINA_TRUE);
257 emotion_object_play_set(o, EINA_TRUE);
258 timeout_t = ecore_timer_add(VIDEO_DECODE_TIMEOUT,
259 timeout_cb, o);
260 evas_object_smart_callback_add(o, "frame_decode",
261 video_decoded,
262 strdup(rp));
263 return 0;
264 }
265
266 }
267
268 evas_object_del(o);
269
270 return -1;
271 }
272
273 static Eina_Bool
handle_file(void * data)274 handle_file(void *data)
275 {
276 Eina_List **file_q = data;
277
278 int (*handlers[])(char *rp) = {
279 handle_image,
280 handle_edje,
281 handle_video,
282 NULL
283 };
284 char *rp;
285 int i;
286
287 if (timeout_t) return ECORE_CALLBACK_RENEW;
288 if (!(*file_q))
289 {
290 ecore_main_loop_quit();
291 return ECORE_CALLBACK_CANCEL;
292 }
293
294 rp = eina_list_data_get(*file_q);
295 *file_q = eina_list_remove_list(*file_q, *file_q);
296 if (!rp) return ECORE_CALLBACK_RENEW;
297
298 for (i = 0; handlers[i]; i++)
299 {
300 if (handlers[i](rp) == 0) break;
301 }
302 free(rp);
303
304 return ECORE_CALLBACK_RENEW;
305 }
306
307 int
main(int argc,char ** argv)308 main(int argc, char **argv)
309 {
310 Ecore_Evas *ee;
311 char buf[64];
312 int i;
313 char *rp;
314 Eina_List *file_q = NULL;
315
316 ON_NOT_RUNNING_IN_TERMINOLOGY_EXIT_1();
317 ARGUMENT_ENTRY_CHECK(argc, argv, print_usage);
318 if (argc <= 1)
319 {
320 print_usage(argv[0]);
321 return 0;
322 }
323
324 eina_init();
325 ecore_app_no_system_modules();
326 ecore_init();
327 ecore_file_init();
328 evas_init();
329 ecore_evas_init();
330 edje_init();
331 emotion_init();
332
333 ee = ecore_evas_buffer_new(1, 1);
334 if (!ee)
335 goto shutdown;
336 evas = ecore_evas_get(ee);
337 echo_off();
338 snprintf(buf, sizeof(buf), "%c}qs", 0x1b);
339 if (ty_write(1, buf, strlen(buf) + 1) < 0)
340 {
341 perror("write");
342 echo_on();
343 goto shutdown;
344 }
345 if (scanf("%i;%i;%i;%i", &tw, &th, &cw, &ch) != 4 ||
346 ((tw <= 0) || (th <= 0) || (cw <= 1) || (ch <= 1)))
347 {
348 echo_on();
349 goto shutdown;
350 }
351 echo_on();
352
353 for (i = 1; i < argc; i++)
354 {
355 char *path;
356
357 if (!strcmp(argv[i], "-c"))
358 {
359 _mode = CENTER;
360 i++;
361 if (i >= argc) goto done;
362 }
363 else if (!strcmp(argv[i], "-s"))
364 {
365 _mode = STRETCH;
366 i++;
367 if (i >= argc) goto done;
368 }
369 else if (!strcmp(argv[i], "-f"))
370 {
371 _mode = FILL;
372 i++;
373 if (i >= argc) goto done;
374 }
375
376 if (!strcmp(argv[i], "-g"))
377 {
378 unsigned int width = 0, height = 0;
379 int cnt;
380
381 if (i + 2 >= argc)
382 {
383 print_usage(argv[0]);
384 goto shutdown;
385 }
386 i++;
387 cnt = sscanf(argv[i], "%ux%u", &width, &height);
388 if (cnt != 2)
389 {
390 print_usage(argv[0]);
391 goto done;
392 }
393 if (!width || tw > (int)width) maxw = width;
394 maxh = height;
395 }
396 path = argv[i];
397 rp = ecore_file_realpath(path);
398 if (rp)
399 file_q = eina_list_append(file_q, rp);
400 }
401 if (!file_q) goto done;
402
403 ecore_idler_add(handle_file, &file_q);
404 ecore_main_loop_begin();
405
406 done:
407 EINA_LIST_FREE(file_q, rp)
408 free(rp);
409
410 ecore_evas_free(ee);
411
412 shutdown:
413 emotion_shutdown();
414 edje_shutdown();
415 ecore_evas_shutdown();
416 evas_shutdown();
417 ecore_file_shutdown();
418 ecore_shutdown();
419 eina_shutdown();
420
421 return 0;
422 }
423