All Downloads are FREE. Search and download functionalities are using the official Maven repository.

uk.co.caprica.vlcj.subs.parser.SrtParser Maven / Gradle / Ivy

/*
 * This file is part of VLCJ.
 *
 * VLCJ 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.
 *
 * VLCJ 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 VLCJ.  If not, see .
 *
 * Copyright 2009-2019 Caprica Software Limited.
 */

package uk.co.caprica.vlcj.subs.parser;

import uk.co.caprica.vlcj.subs.Spu;

import java.util.regex.Matcher;
import java.util.regex.Pattern;

/**
 * Implementation of an SPU parser for the SRT file format.
 */
public class SrtParser extends LineBasedSpuParser {

    private static final String TIMECODE_PATTERN = "(\\d{2}):(\\d{2}):(\\d{2}),(\\d{3})";

    private static final Pattern timelinePattern = Pattern.compile(TIMECODE_PATTERN + "\\s*-->\\s*" + TIMECODE_PATTERN);

    private enum State {
        NUMBER,
        TIME,
        CAPTION
    }

    private State state;

    private int number;
    private long start;
    private long end;

    private StringBuilder buffer;

    @Override
    protected void begin() throws SpuParseException {
        state = State.NUMBER;
        number = -1;
        start = -1;
        end = -1;
        buffer = new StringBuilder(100);
    }

    @Override
    protected void process(String line) throws SpuParseException {
        switch(state) {
            case NUMBER:
                if (line.length() > 0) {
                    number = Integer.parseInt(line);
                    state = State.TIME;
                }
                break;

            case TIME:
                if (line.length() > 0) {
                    Matcher matcher = timelinePattern.matcher(line);
                    if (matcher.matches()) {
                        start = toMillis(matcher.group(1), matcher.group(2), matcher.group(3), matcher.group(4));
                        end = toMillis(matcher.group(5), matcher.group(6), matcher.group(7), matcher.group(8));
                        state = State.CAPTION;
                    } else {
                        throw new SpuParseException(String.format("Failed to match: %s", line));
                    }
                }
                break;

            case CAPTION:
                if (number == -1 || start == -1 || end == -1) {
                    throw new SpuParseException();
                }
                if (line.length() > 0) {
                    if (buffer.length() > 0) {
                        buffer.append('\n');
                    }
                    buffer.append(line);
                } else {
                    spu(new Spu(number, start, end, buffer.toString()));
                    buffer.setLength(0);
                    state = State.NUMBER;
                }
                break;

            default:
                throw new SpuParseException(String.format("Unexpected state: %s", state));
        }
    }

    @Override
    protected void end() throws SpuParseException {
        if (buffer.length() > 0) {
            spu(new Spu(number, start, end, buffer.toString()));
            buffer.setLength(0);
        }
    }

    private long toMillis(String h, String m, String s, String ms) {
        return toMillis(Integer.parseInt(h), Integer.parseInt(m), Integer.parseInt(s), Integer.parseInt(ms));
    }

    private long toMillis(int h, int m, int s, int ms) {
        return (((h * 3600) + (m * 60) + s) * 1000) + ms;
    }

}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy