;;; srt2vtt --- SRT to WebVTT converter ;;; Copyright © 2015 David Thompson ;;; ;;; srt2vtt 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 3 of the License, or ;;; (at your option) any later version. ;;; ;;; srt2vtt 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 srt2vtt. If not, see . (define-module (srt2vtt subrip) #:use-module (ice-9 match) #:use-module (ice-9 rdelim) #:use-module (ice-9 regex) #:use-module (srfi srfi-1) #:use-module (srfi srfi-11) #:use-module (srfi srfi-26) #:use-module (srt2vtt) #:export (read-subrip read-subrips)) (define parse-time (let ((regexp (make-regexp "^([0-9]+):([0-9]+):([0-9]+),([0-9]+)$"))) (lambda (s) "Parse the SubRip formatted timestamp in the string S into a 4 element list. Valid input looks like '00:00:03.417'." (let ((match (regexp-exec regexp s))) (if match (map (compose string->number (cut match:substring match <>)) '(1 2 3 4)) (error "Invalid SubRip timestamp: " s)))))) (define parse-time-span (let ((regexp (make-regexp "^([0-9:,]+) --> ([0-9:,]+)$"))) (lambda (s) "Parse the SubRip formatted time span in the string S and return two values: the start time and the end time. Valid input looks like '00:00:03.417 --> 00:00:04.936'." (let ((match (regexp-exec regexp s))) (if match (values (parse-time (match:substring match 1)) (parse-time (match:substring match 2))) (error "Invalid SubRip time range: " s)))))) (define (read-subrip port) "Read a SubRip formatted subtitle from PORT." (let-values (((id) (string->number (read-line port))) ((start end) (parse-time-span (read-line port))) ((lines) (let loop ((lines '())) (let ((line (read-line port))) (if (or (eof-object? line) (and (string-null? line) ;; A subtitle may be a blank line! (not (null? lines)))) (reverse lines) (loop (cons line lines))))))) (make-subtitle id start end lines))) (define (read-subrips port) "Read all SubRip formatted subtitles from PORT." (reverse (let loop ((subs '())) (if (eof-object? (peek-char port)) subs (loop (cons (read-subrip port) subs))))))