main.c 7.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289
  1. /*
  2. Copyright (C) 2014 Olivier Marty <olivier.marty.m at gmail.com>
  3. This program is free software; you can redistribute it and/or
  4. modify it under the terms of the GNU General Public License
  5. as published by the Free Software Foundation; either version 2
  6. of the License, or (at your option) any later version.
  7. This program is distributed in the hope that it will be useful,
  8. but WITHOUT ANY WARRANTY; without even the implied warranty of
  9. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  10. GNU General Public License for more details.
  11. You should have received a copy of the GNU General Public License
  12. along with this program; if not, write to the Free Software
  13. Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
  14. */
  15. #include "parser.h"
  16. #include "time.h"
  17. #include "printer.h"
  18. #include "rich_text.h"
  19. #include "events.h"
  20. #include <stdlib.h>
  21. #include <unistd.h>
  22. #include <string.h>
  23. enum _t_state { S_RUNNING, S_PAUSED, S_STOP };
  24. typedef enum _t_state t_state;
  25. void displayUsage(char *name)
  26. {
  27. printf("Usage : %s file.srt\n", name);
  28. printf("Options :\n");
  29. printf(" -s sec\t: skip the first x seconds\n");
  30. printf(" -d sec\t: wait x seconds before starting (default : 5)\n");
  31. // printf(" -t x\t\t: time factor x1000\n");
  32. printf(" -m px\t\t: margin with the bottom of the screen\n");
  33. printf(" -p px\t\t: padding of the box\n");
  34. printf(" -g px\t\t: gap between two lines\n");
  35. printf(" -f fontname\t: name of the font to use\n");
  36. printf(" -i fontname\t: name of the italic font to use\n");
  37. printf(" -b fontname\t: name of the bold font to use\n");
  38. printf(" -j fontname\t: name of the bold and italic font to use\n");
  39. printf(" -h\t\t: display this help and exit\n");
  40. }
  41. int main(int argc, char **argv)
  42. {
  43. int i, shift = 0, delay = 5, margin_bottom = 50, padding = 5, gap = 5;
  44. float factor = 1.0;
  45. char *font = NULL, *font_i = NULL, *font_b = NULL, *font_bi = NULL;
  46. FILE *f = NULL;
  47. t_state state = S_RUNNING;
  48. // parse arguments
  49. int c;
  50. while((c = getopt (argc, argv, "s:d:t:m:p:g:f:i:b:j:h")) != -1)
  51. switch(c)
  52. {
  53. case 's':
  54. shift = atoi(optarg);
  55. break;
  56. case 'd':
  57. delay = atoi(optarg);
  58. break;
  59. /*case 't':
  60. factor = atoi(optarg)/1000.;
  61. break;
  62. */
  63. case 'm':
  64. margin_bottom = atoi(optarg);
  65. break;
  66. case 'p':
  67. padding = atoi(optarg);
  68. break;
  69. case 'g':
  70. gap = atoi(optarg);
  71. break;
  72. case 'f':
  73. font = malloc(strlen(optarg)+1);
  74. strcpy(font, optarg);
  75. break;
  76. case 'i':
  77. font_i = malloc(strlen(optarg)+1);
  78. strcpy(font_i, optarg);
  79. break;
  80. case 'b':
  81. font_b = malloc(strlen(optarg)+1);
  82. strcpy(font_b, optarg);
  83. break;
  84. case 'j':
  85. font_bi = malloc(strlen(optarg)+1);
  86. strcpy(font_bi, optarg);
  87. break;
  88. case 'h':
  89. displayUsage(argv[0]);
  90. return 0;
  91. //case '?':
  92. default:
  93. return 1;
  94. }
  95. if(optind >= argc)
  96. {
  97. fprintf(stderr, "Missing filename.\n");
  98. displayUsage(argv[0]);
  99. return 1;
  100. }
  101. f = fopen(argv[optind], "r");
  102. if(f == NULL)
  103. {
  104. perror("fopen()");
  105. exit(1);
  106. }
  107. // open the window
  108. struct printerEnv penv = printerOpenWindow(font, font_i, font_b, font_bi);
  109. // set attributes
  110. penv.margin_bottom = margin_bottom;
  111. penv.padding = padding;
  112. penv.gap = gap;
  113. // show a counter before start the clock
  114. for(i = delay; i > 0; i--)
  115. {
  116. struct richText *rt;
  117. char t[16];
  118. sprintf(t, "<i>%d...</i>\n", i);
  119. printf("%s\n", t);
  120. rt = richTextParse(t);
  121. printerShow(&penv, rt, 0);
  122. sleep(1);
  123. printerHide(&penv, 0);
  124. richTextFree(rt);
  125. }
  126. printf("0 !\n");
  127. timeInitialize(-factor*shift);
  128. int id = 0;
  129. t_events events = eventsInit(8);
  130. t_event event;
  131. event.type = T_SHOW;
  132. event.show.id = -1; // first
  133. while(1)
  134. {
  135. switch(state)
  136. {
  137. case S_RUNNING:
  138. switch(event.type)
  139. {
  140. case T_KEYPRESSED:
  141. if(event.keyPressed.key == ' ')
  142. {
  143. state = S_PAUSED;
  144. printf("paused...\n");
  145. timePause(1);
  146. }
  147. break;
  148. case T_HIDE:
  149. printerHide(&penv, event.hide.id);
  150. free(event.hide.rt->raw);
  151. richTextFree(event.hide.rt);
  152. printf("\n");
  153. break;
  154. case T_SHOW:
  155. if(event.hide.id >= 0)
  156. {
  157. printf("%ds\n", timeFactor(event.show.time, 1./factor).tv_sec);
  158. printf("%s\n", event.show.rt->raw);
  159. printerShow(&penv, event.show.rt, event.show.id);
  160. }
  161. // grab next subtitles
  162. while(1)
  163. {
  164. struct SubtitleLine sline;
  165. if(feof(f))
  166. break;
  167. id = next(f, id+1, &sline);
  168. if(timeInFuture(timeFactor(sline.end, factor)))
  169. {
  170. char *copy = NULL;
  171. struct richText *rt;
  172. copy = malloc(sizeof(char[strlen(sline.text)+1]));
  173. if(copy == NULL)
  174. {
  175. perror("malloc()");
  176. exit(1);
  177. }
  178. strcpy(copy, sline.text);
  179. rt = richTextParse(copy);
  180. // show event
  181. t_event show, hide;
  182. show.type = T_SHOW;
  183. show.show.id = id;
  184. show.show.rt = rt;
  185. show.show.time = timeFactor(sline.begin, factor);
  186. // hide event
  187. hide.type = T_HIDE;
  188. hide.hide.id = id;
  189. hide.hide.rt = rt;
  190. hide.hide.time = timeFactor(sline.end, factor);
  191. eventsPush(&events, show);
  192. eventsPush(&events, hide);
  193. break;
  194. }
  195. else
  196. {
  197. printf("skipped :\n");
  198. printf("%s\n", sline.text);
  199. }
  200. }
  201. break;
  202. }
  203. break;
  204. case S_PAUSED:
  205. switch(event.type)
  206. {
  207. case T_KEYPRESSED:
  208. if(event.keyPressed.key == ' ')
  209. {
  210. state = S_RUNNING;
  211. printf("end\n");
  212. timePause(0);
  213. }
  214. break;
  215. }
  216. break;
  217. }
  218. if(eventsEmpty(events))
  219. state = S_STOP;
  220. if(state == S_STOP)
  221. break;
  222. // sleep until next event
  223. mytime next_event = eventsNextTime(events);
  224. while(1)
  225. {
  226. int value;
  227. fd_set in_fds;
  228. FD_ZERO(&in_fds);
  229. FD_SET(penv.d_fd, &in_fds);
  230. if(state == S_PAUSED) // blocking select
  231. value = pselect(penv.d_fd+1, &in_fds, NULL, NULL, NULL, NULL);
  232. else // timeout
  233. {
  234. struct timespec to_wait = timeDiff(next_event, timeGetRelative());
  235. if(to_wait.tv_sec < 0)
  236. {
  237. to_wait.tv_sec = 0;
  238. to_wait.tv_nsec = 0;
  239. }
  240. value = pselect(penv.d_fd+1, &in_fds, NULL, NULL, &to_wait, NULL);
  241. }
  242. if(value == -1) // TODO tester interruption par un signal : return 0 ou -1
  243. // dans les deux cas c'est foireux
  244. {
  245. perror("pselect()");
  246. exit(1);
  247. }
  248. else if(value > 0) // x event
  249. {
  250. while(XPending(penv.d))
  251. {
  252. event = manageEvent(&penv);
  253. if(event.type == T_KEYPRESSED)
  254. break;
  255. }
  256. if(event.type == T_KEYPRESSED)
  257. break;
  258. }
  259. else // deadline
  260. {
  261. event = eventsPop(&events);
  262. break;
  263. }
  264. }
  265. }
  266. printerCloseWindow(penv);
  267. fclose(f);
  268. }