/************************************************************************** OmegaT - Computer Assisted Translation (CAT) tool with fuzzy matching, translation memory, keyword search, glossaries, and translation leveraging into updated projects. Copyright (C) 2008 Alex Buloichik Home page: http://www.omegat.org/ Support center: http://groups.yahoo.com/group/OmegaT/ This file is part of OmegaT. OmegaT 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. OmegaT 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, see <http://www.gnu.org/licenses/>. **************************************************************************/ package org.omegat.filters2.subtitles; import java.io.BufferedReader; import java.io.BufferedWriter; import java.io.IOException; import java.util.HashMap; import java.util.Map; import java.util.regex.Pattern; import org.omegat.filters2.AbstractFilter; import org.omegat.filters2.FilterContext; import org.omegat.filters2.Instance; import org.omegat.filters2.TranslationException; import org.omegat.util.MixedEolHandlingReader; import org.omegat.util.NullBufferedWriter; import org.omegat.util.OStrings; import org.omegat.util.StringUtil; /** * Filter for subtitles files. * * @author Alex Buloichik (alex73mail@gmail.com) * @see <a href="http://en.wikipedia.org/wiki/SubRip">Format description</a> */ public class SrtFilter extends AbstractFilter { protected static final Pattern PATTERN_TIME_INTERVAL = Pattern .compile("([0-9]{2}:[0-9]{2}:[0-9]{2},[0-9]{3})\\s+-->\\s+([0-9]{2}:[0-9]{2}:[0-9]{2},[0-9]{3})"); protected static final String EOL = "\r\n"; enum READ_STATE { WAIT_TIME, WAIT_TEXT }; protected Map<String, String> align; protected String key; protected StringBuilder text = new StringBuilder(); protected BufferedWriter out; protected Pattern getPattern() { return PATTERN_TIME_INTERVAL; } @Override public Instance[] getDefaultInstances() { return new Instance[] { new Instance("*.srt") }; } @Override public String getFileFormatName() { return OStrings.getString("SRTFILTER_FILTER_NAME"); } @Override public boolean isSourceEncodingVariable() { return true; } @Override public boolean isTargetEncodingVariable() { return true; } @Override protected void processFile(BufferedReader inFile, BufferedWriter outFile, FilterContext fc) throws IOException, TranslationException { out = outFile; READ_STATE state = READ_STATE.WAIT_TIME; key = null; text.setLength(0); Pattern pattern = getPattern(); try (MixedEolHandlingReader reader = new MixedEolHandlingReader(inFile)) { String s; while ((s = reader.readLine()) != null) { String trimmed = s.trim(); switch (state) { case WAIT_TIME: if (pattern.matcher(trimmed).matches()) { state = READ_STATE.WAIT_TEXT; } key = trimmed; text.setLength(0); outFile.write(s); outFile.write(EOL); break; case WAIT_TEXT: if (trimmed.isEmpty()) { flush(); outFile.write(EOL); state = READ_STATE.WAIT_TIME; } if (text.length() > 0) { text.append('\n'); } text.append(s); break; } } } flush(); } private void flush() throws IOException { if (text.length() == 0) { return; } if (align != null) { align.put(key, text.toString()); } if (entryParseCallback != null) { entryParseCallback.addEntry(key, text.toString(), null, false, null, null, this, null); } else if (entryTranslateCallback != null) { String tr = entryTranslateCallback.getTranslation(key, text.toString(), null); if (tr == null) { tr = text.toString(); } out.write(tr.replace("\n", EOL)); out.write(EOL); } key = null; text.setLength(0); } @Override protected void alignFile(BufferedReader sourceFile, BufferedReader translatedFile, FilterContext fc) throws Exception { Map<String, String> source = new HashMap<String, String>(); Map<String, String> translated = new HashMap<String, String>(); align = source; processFile(sourceFile, new NullBufferedWriter(), fc); align = translated; processFile(translatedFile, new NullBufferedWriter(), fc); for (Map.Entry<String, String> en : source.entrySet()) { String tr = translated.get(en.getKey()); if (!StringUtil.isEmpty(tr)) { entryAlignCallback.addTranslation(en.getKey(), en.getValue(), tr, false, null, this); } } } }