Browse Source

Initial commit

Olivier Marty 9 years ago
parent
commit
0bf8484ba9
7 changed files with 486 additions and 0 deletions
  1. 79 0
      main.c
  2. 48 0
      parser.c
  3. 38 0
      parser.h
  4. 157 0
      printer.c
  5. 44 0
      printer.h
  6. 84 0
      time.c
  7. 36 0
      time.h

+ 79 - 0
main.c

@@ -0,0 +1,79 @@
+/*
+  Copyright (C) 2014  Olivier Marty <olivier.marty.m@gmail.com>
+
+  This program is free software; you can redistribute it and/or
+  modify it under the terms of the GNU General Public License
+  as published by the Free Software Foundation; either version 2
+  of the License, or (at your option) any later version.
+
+  This program is distributed in the hope that it will be useful,
+  but WITHOUT ANY WARRANTY; without even the implied warranty of
+  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+  GNU General Public License for more details.
+
+  You should have received a copy of the GNU General Public License
+  along with this program; if not, write to the Free Software
+  Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+*/
+
+#include "parser.h"
+#include "time.h"
+#include "printer.h"
+#include <stdlib.h>
+
+int main(int argc, char **argv)
+{
+  int i;
+  FILE *f= NULL;
+  
+  if(argc < 2)
+  {
+    fprintf(stderr, "Usage : subtitles file.srt [shift in seconds [waiting time in seconds]]\n");
+    return 1;
+  }
+  
+  f = fopen(argv[1], "r");
+  if(f == NULL)
+  {
+    perror("fopen()");
+    exit(1);
+  }
+  
+  // open the window
+  struct printerEnv penv = printerOpenWindow(-1, 240, 50);
+  
+  // show a counter before start the clock
+  for(i = (argc > 3) ? atoi(argv[3]) : 5; i > 0; i--)
+  {
+    char t[16];
+    sprintf(t, "%d...\n", i);
+    printf("%s", t);
+    printerShow(penv, t);
+    sleep(1);
+  }
+  printf("0 !\n");
+  printerClean(penv);
+  timeInitialize((argc > 2) ? atoi(argv[2]) : 0);
+  
+  struct SubtitleLine sline;
+  int id = 0;
+  while(!feof(f))
+  {
+    id = next(f, id+1, &sline);
+    timeSleepUntil(sline.begin);
+    
+    // show
+    printf("%s\n", sline.text);
+    printerShow(penv, sline.text);
+    
+    // hide
+    timeSleepUntil(sline.end);
+    // TODO manage when the next subtitle appear before
+    printf("\n");
+    printerClean(penv);
+  }
+  
+  printerCloseWindow(penv);
+  fclose(f);
+}
+

+ 48 - 0
parser.c

@@ -0,0 +1,48 @@
+/*
+  Copyright (C) 2014  Olivier Marty <olivier.marty.m@gmail.com>
+
+  This program is free software; you can redistribute it and/or
+  modify it under the terms of the GNU General Public License
+  as published by the Free Software Foundation; either version 2
+  of the License, or (at your option) any later version.
+
+  This program is distributed in the hope that it will be useful,
+  but WITHOUT ANY WARRANTY; without even the implied warranty of
+  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+  GNU General Public License for more details.
+
+  You should have received a copy of the GNU General Public License
+  along with this program; if not, write to the Free Software
+  Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+*/
+
+#include <string.h>
+
+#include "parser.h"
+
+int next(FILE *f, int expected, struct SubtitleLine *r)
+{
+  int t_h, t_m, t_s, t_ms;
+  fscanf(f, "%d\n", &r->id);
+  if(r->id != expected)
+    fprintf(stderr, "expected : %d; found : %d\n", expected, r->id);
+  
+  fscanf(f, "%d:%d:%d,%d --> ", &t_h, &t_m, &t_s, &t_ms);
+  r->begin = timeCreate(t_h*3600 + t_m*60 + t_s, t_ms*1000000);
+  // TODO and if there are 4 digits ?
+  fscanf(f, "%d:%d:%d,%d\n", &t_h, &t_m, &t_s, &t_ms);
+  r->end = timeCreate(t_h*3600 + t_m*60 + t_s, t_ms*1000000);
+
+  *(r->text) = '\0';
+  char line[1024];
+  while(1)
+  {
+    fgets(line, 1024, f);
+    if(feof(f) || line[0] == '\n' || line[0] == '\0' || (line[0] == '\r' && line[1] == '\n'))
+      break;
+    strcat(r->text, line);
+  }
+  
+  return r->id;
+}
+

+ 38 - 0
parser.h

@@ -0,0 +1,38 @@
+/*
+  Copyright (C) 2014  Olivier Marty <olivier.marty.m@gmail.com>
+
+  This program is free software; you can redistribute it and/or
+  modify it under the terms of the GNU General Public License
+  as published by the Free Software Foundation; either version 2
+  of the License, or (at your option) any later version.
+
+  This program is distributed in the hope that it will be useful,
+  but WITHOUT ANY WARRANTY; without even the implied warranty of
+  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+  GNU General Public License for more details.
+
+  You should have received a copy of the GNU General Public License
+  along with this program; if not, write to the Free Software
+  Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+*/
+
+#ifndef H_PARSER
+#define H_PARSER
+
+#include <stdio.h>
+#include "time.h"
+
+struct SubtitleLine
+{
+  int id;
+  char text[4096];
+  mytime begin;
+  mytime end;
+};
+
+// read the next subtitle, expected to be expected-th
+// return the number of the readed subtitle
+int next(FILE *f, int expected, struct SubtitleLine *r);
+
+#endif
+

+ 157 - 0
printer.c

@@ -0,0 +1,157 @@
+/*
+  Copyright (C) 2014  Olivier Marty <olivier.marty.m@gmail.com>
+
+  This program is free software; you can redistribute it and/or
+  modify it under the terms of the GNU General Public License
+  as published by the Free Software Foundation; either version 2
+  of the License, or (at your option) any later version.
+
+  This program is distributed in the hope that it will be useful,
+  but WITHOUT ANY WARRANTY; without even the implied warranty of
+  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+  GNU General Public License for more details.
+
+  You should have received a copy of the GNU General Public License
+  along with this program; if not, write to the Free Software
+  Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+*/
+
+#include "printer.h"
+#include <stdio.h>
+#include <stdlib.h>
+#include <X11/Xlib.h>
+#include <X11/Xutil.h>
+#include <string.h>
+
+struct printerEnv printerOpenWindow(int width, int height, int padding_bottom)
+{
+  struct printerEnv env;
+
+  // open connection
+  env.d = XOpenDisplay(NULL);
+  if (env.d == NULL) {
+      fprintf(stderr, "Unable to open display\n");
+      exit(1);
+  }
+  env.s = DefaultScreen(env.d);
+
+  XVisualInfo vinfo;
+  XMatchVisualInfo(env.d, env.s, 32, TrueColor, &vinfo);
+
+  
+  // size of the screen
+  XWindowAttributes RootAttr;
+  XGetWindowAttributes(env.d, RootWindow(env.d, env.s), &RootAttr);
+  
+  // set window attributes
+  XSetWindowAttributes attr;
+  attr.colormap = XCreateColormap(env.d, RootWindow(env.d, env.s),
+    vinfo.visual, AllocNone);
+  attr.border_pixel = 0;
+  attr.background_pixel = 0;
+  attr.override_redirect = 1; // no window manager border
+  
+  // set colors
+  env.color_text = XWhitePixel(env.d, env.s);
+  XColor tmp;
+  XParseColor(env.d, attr.colormap, "#222222", &tmp);
+  XAllocColor(env.d, attr.colormap, &tmp);
+  env.color_background = tmp.pixel;
+  //env.color_text = -1;
+  //env.color_background = (100 * 256 + 100) * 256 + 100;
+  
+  // create the window
+  env.width = (width < 0) ? RootAttr.width : width;
+  env.height = height;
+  env.w = XCreateWindow(env.d, RootWindow(env.d, env.s),
+    (RootAttr.width - env.width)/2,
+    RootAttr.height - env.height - padding_bottom, env.width, env.height, 0,
+    vinfo.depth, InputOutput, vinfo.visual,
+    CWColormap | CWBorderPixel | CWBackPixel | CWOverrideRedirect, &attr);
+  
+  // set the font in a new GC
+  XGCValues gr_values;
+  env.fontinfo = XLoadQueryFont(env.d, "*x24");
+  gr_values.font = env.fontinfo->fid;
+  gr_values.foreground = XWhitePixel(env.d, env.s);
+  gr_values.background = XBlackPixel(env.d, env.s);
+  env.gc = XCreateGC(env.d, env.w, GCFont | GCForeground, &gr_values);
+  
+  // event to be listened
+  //XSelectInput(env.d, env.w, ExposureMask | KeyPressMask);
+  
+  // display the window
+  XMapWindow(env.d, env.w);
+  XFlush(env.d);
+  
+  return env;
+}
+
+void printerCloseWindow(struct printerEnv env)
+{
+  XCloseDisplay(env.d); // window is destroyed
+}
+
+int printLines(struct printerEnv env, char *text, int gap,
+  int width, int height, int padding) // for the frame
+{
+  if(*text == '\0')
+  {
+    XSetForeground(env.d, env.gc, env.color_background);
+    XFillRectangle(env.d, env.w, env.gc, (env.width - width)/2 - padding,
+      env.height - height - padding, width + 2*padding, height + 2*padding);
+    XSetForeground(env.d, env.gc, env.color_text);
+    return env.height - padding;
+  }
+  
+  char *next;
+  int size;
+  
+  next = strchr(text, '\n');
+  if(next == NULL)
+  {
+    size = strlen(text);
+    next = text + size;
+  }
+  else
+  {
+    size = next-text;
+    if(*(next-1) == '\r')
+      size--; // hide this character
+    next++; // forget \n
+  }
+  
+  // compute the size of the text
+  int font_direction, font_ascent, font_descent, text_y;
+  XCharStruct text_structure;
+  XTextExtents(env.fontinfo, text, size,
+               &font_direction, &font_ascent, &font_descent,
+               &text_structure);
+  
+  // print next line, and this one above
+  if(text_structure.width > width)
+    width = text_structure.width;
+  
+  text_y = printLines(env, next, gap, width,
+    height + text_structure.ascent + text_structure.descent + gap, padding);
+  text_y -= text_structure.descent;
+  
+  XDrawString(env.d, env.w, env.gc, (env.width - text_structure.width)/2,
+    text_y, text, size);
+  
+  return text_y - text_structure.ascent - gap;
+}
+
+void printerShow(struct printerEnv env, char* text)
+{
+  XClearWindow(env.d, env.w);
+  printLines(env, text, 5, 0, 0, 5);
+  XFlush(env.d);
+}
+
+void printerClean(struct printerEnv env)
+{
+  XClearWindow(env.d, env.w);
+  XFlush(env.d);
+}
+

+ 44 - 0
printer.h

@@ -0,0 +1,44 @@
+/*
+  Copyright (C) 2014  Olivier Marty <olivier.marty.m@gmail.com>
+
+  This program is free software; you can redistribute it and/or
+  modify it under the terms of the GNU General Public License
+  as published by the Free Software Foundation; either version 2
+  of the License, or (at your option) any later version.
+
+  This program is distributed in the hope that it will be useful,
+  but WITHOUT ANY WARRANTY; without even the implied warranty of
+  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+  GNU General Public License for more details.
+
+  You should have received a copy of the GNU General Public License
+  along with this program; if not, write to the Free Software
+  Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+*/
+
+#ifndef H_PRINTER
+#define H_PRINTER
+
+#include <X11/Xlib.h>
+
+struct printerEnv
+{
+  Display *d;
+  int s;
+  Window w;
+  GC gc;
+  XFontStruct *fontinfo;
+  int width, height;
+  unsigned long color_background, color_text;
+};
+
+
+// if width < 0 the window will be as larger as possible
+struct printerEnv printerOpenWindow(int width, int height, int padding_bottom);
+void printerCloseWindow(struct printerEnv env);
+
+void printerShow(struct printerEnv env, char* text);
+void printerClean(struct printerEnv env);
+
+#endif
+

+ 84 - 0
time.c

@@ -0,0 +1,84 @@
+/*
+  Copyright (C) 2014  Olivier Marty <olivier.marty.m@gmail.com>
+
+  This program is free software; you can redistribute it and/or
+  modify it under the terms of the GNU General Public License
+  as published by the Free Software Foundation; either version 2
+  of the License, or (at your option) any later version.
+
+  This program is distributed in the hope that it will be useful,
+  but WITHOUT ANY WARRANTY; without even the implied warranty of
+  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+  GNU General Public License for more details.
+
+  You should have received a copy of the GNU General Public License
+  along with this program; if not, write to the Free Software
+  Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+*/
+
+#include "time.h"
+#include <errno.h>
+#include <stdlib.h>
+
+int timeNanoSleep(struct timespec t)
+{
+  int r;
+  if(t.tv_sec >= 0)
+  {
+    do
+    {
+      r = nanosleep(&t, &t);
+    } while(errno == EINTR);
+  }
+  return r;
+}
+
+struct timespec timeDiff(struct timespec a, struct timespec b)
+{
+  struct timespec r;
+  r.tv_sec = a.tv_sec - b.tv_sec;
+  r.tv_nsec = a.tv_nsec - b.tv_nsec;
+  if(r.tv_nsec < 0)
+  {
+    r.tv_nsec += 1000000000;
+    r.tv_sec -= 1;
+  }
+  return r;
+}
+
+struct timespec begin;
+void timeInitialize(int rel)
+{
+  if(clock_gettime(CLOCK_REALTIME, &begin) < 0)
+  {
+    perror("clock_gettime()");
+    exit(1);
+  }
+  begin.tv_sec += rel;
+}
+
+struct timespec timeGetRelative()
+{
+  struct timespec r;
+  if(clock_gettime(CLOCK_REALTIME, &r) < 0)
+  {
+    perror("clock_gettime()");
+    exit(1);
+  }
+  return timeDiff(r, begin);
+}
+
+int timeSleepUntil(struct timespec t)
+{
+  struct timespec current = timeGetRelative();
+  return timeNanoSleep(timeDiff(t, current));
+}
+
+struct timespec timeCreate(time_t s, long ns)
+{
+  struct timespec r;
+  r.tv_sec = s;
+  r.tv_nsec = ns;
+  return r;
+}
+

+ 36 - 0
time.h

@@ -0,0 +1,36 @@
+/*
+  Copyright (C) 2014  Olivier Marty <olivier.marty.m@gmail.com>
+
+  This program is free software; you can redistribute it and/or
+  modify it under the terms of the GNU General Public License
+  as published by the Free Software Foundation; either version 2
+  of the License, or (at your option) any later version.
+
+  This program is distributed in the hope that it will be useful,
+  but WITHOUT ANY WARRANTY; without even the implied warranty of
+  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+  GNU General Public License for more details.
+
+  You should have received a copy of the GNU General Public License
+  along with this program; if not, write to the Free Software
+  Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+*/
+
+#ifndef H_TIME
+#define H_TIME
+
+#include <time.h>
+
+typedef struct timespec mytime;
+
+void timeInitialize(int rel); // add rel seconds to the clock
+mytime timeGetRelative();
+int timeSleepUntil(mytime t);
+
+mytime timeCreate(time_t s, long ns);
+
+int timeNanoSleep(mytime t);
+mytime timeDiff(mytime a, mytime b);
+
+#endif
+