main.c 7.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290
  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();
  128. timeShift(-factor*shift);
  129. int id = 0;
  130. t_events events = eventsInit(8);
  131. t_event event;
  132. event.type = T_SHOW;
  133. event.show.id = -1; // first
  134. while(1)
  135. {
  136. switch(state)
  137. {
  138. case S_RUNNING:
  139. switch(event.type)
  140. {
  141. case T_KEYPRESSED:
  142. if(event.keyPressed.key == ' ')
  143. {
  144. state = S_PAUSED;
  145. printf("paused...\n");
  146. timePause(1);
  147. }
  148. break;
  149. case T_HIDE:
  150. printerHide(&penv, event.hide.id);
  151. free(event.hide.rt->raw);
  152. richTextFree(event.hide.rt);
  153. printf("\n");
  154. break;
  155. case T_SHOW:
  156. if(event.hide.id >= 0)
  157. {
  158. printf("%ds\n", timeFactor(event.show.time, 1./factor).tv_sec);
  159. printf("%s\n", event.show.rt->raw);
  160. printerShow(&penv, event.show.rt, event.show.id);
  161. }
  162. // grab next subtitles
  163. while(1)
  164. {
  165. struct SubtitleLine sline;
  166. if(feof(f))
  167. break;
  168. id = next(f, id+1, &sline);
  169. if(timeInFuture(timeFactor(sline.end, factor)))
  170. {
  171. char *copy = NULL;
  172. struct richText *rt;
  173. copy = malloc(sizeof(char[strlen(sline.text)+1]));
  174. if(copy == NULL)
  175. {
  176. perror("malloc()");
  177. exit(1);
  178. }
  179. strcpy(copy, sline.text);
  180. rt = richTextParse(copy);
  181. // show event
  182. t_event show, hide;
  183. show.type = T_SHOW;
  184. show.show.id = id;
  185. show.show.rt = rt;
  186. show.show.time = timeFactor(sline.begin, factor);
  187. // hide event
  188. hide.type = T_HIDE;
  189. hide.hide.id = id;
  190. hide.hide.rt = rt;
  191. hide.hide.time = timeFactor(sline.end, factor);
  192. eventsPush(&events, show);
  193. eventsPush(&events, hide);
  194. break;
  195. }
  196. else
  197. {
  198. printf("skipped :\n");
  199. printf("%s\n", sline.text);
  200. }
  201. }
  202. break;
  203. }
  204. break;
  205. case S_PAUSED:
  206. switch(event.type)
  207. {
  208. case T_KEYPRESSED:
  209. if(event.keyPressed.key == ' ')
  210. {
  211. state = S_RUNNING;
  212. printf("end\n");
  213. timePause(0);
  214. }
  215. break;
  216. }
  217. break;
  218. }
  219. if(eventsEmpty(events))
  220. state = S_STOP;
  221. if(state == S_STOP)
  222. break;
  223. // sleep until next event
  224. mytime next_event = eventsNextTime(events);
  225. while(1)
  226. {
  227. int value;
  228. fd_set in_fds;
  229. FD_ZERO(&in_fds);
  230. FD_SET(penv.d_fd, &in_fds);
  231. if(state == S_PAUSED) // blocking select
  232. value = pselect(penv.d_fd+1, &in_fds, NULL, NULL, NULL, NULL);
  233. else // timeout
  234. {
  235. struct timespec to_wait = timeDiff(next_event, timeGetRelative());
  236. if(to_wait.tv_sec < 0)
  237. {
  238. to_wait.tv_sec = 0;
  239. to_wait.tv_nsec = 0;
  240. }
  241. value = pselect(penv.d_fd+1, &in_fds, NULL, NULL, &to_wait, NULL);
  242. }
  243. if(value == -1) // TODO tester interruption par un signal : return 0 ou -1
  244. // dans les deux cas c'est foireux
  245. {
  246. perror("pselect()");
  247. exit(1);
  248. }
  249. else if(value > 0) // x event
  250. {
  251. while(XPending(penv.d))
  252. {
  253. event = manageEvent(&penv);
  254. if(event.type == T_KEYPRESSED)
  255. break;
  256. }
  257. if(event.type == T_KEYPRESSED)
  258. break;
  259. }
  260. else // deadline
  261. {
  262. event = eventsPop(&events);
  263. break;
  264. }
  265. }
  266. }
  267. printerCloseWindow(penv);
  268. fclose(f);
  269. }