/*
* (C) Copyright 2014 Boni Garcia (http://bonigarcia.github.io/)
*
* 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 3 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, see <http://www.gnu.org/licenses/>.
*/
package io.github.bonigarcia.dualsub.srt;
import java.io.BufferedInputStream;
import java.io.BufferedReader;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.Reader;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Properties;
import java.util.TreeMap;
import java.util.prefs.Preferences;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import io.github.bonigarcia.dualsub.gui.DualSub;
import io.github.bonigarcia.dualsub.translate.Translator;
import io.github.bonigarcia.dualsub.util.Charset;
/**
* Srt.
*
* @author Boni Garcia (boni.gg@gmail.com)
* @since 1.0.0
*/
public class Srt {
private static final Logger log = LoggerFactory.getLogger(Merger.class);
private Map<String, Entry> subtitles;
private String fileName;
private String charset;
public Srt(String fileName) throws IOException {
this.fileName = fileName;
this.subtitles = new TreeMap<String, Entry>();
this.readSrt(fileName);
}
public Srt(Srt inputSrt, String fromLang, String toLang, String charset,
DualSub parent) throws IOException {
this.subtitles = new TreeMap<String, Entry>();
Map<String, Entry> subtitlesToTranslate = inputSrt.getSubtitles();
String lineToTranslate;
Entry translatedEntry;
Preferences preferences;
Properties properties;
if (parent != null) {
preferences = parent.getPreferences();
properties = parent.getProperties();
} else {
preferences = Preferences.userNodeForPackage(DualSub.class);
properties = new Properties();
InputStream inputStream = Thread.currentThread()
.getContextClassLoader()
.getResourceAsStream("dualsub.properties");
Reader reader = new InputStreamReader(inputStream,
Charset.ISO88591);
properties.load(reader);
}
Translator.getInstance().setPreferences(preferences);
List<String> inputLines = new ArrayList<String>();
for (String time : subtitlesToTranslate.keySet()) {
lineToTranslate = "";
for (String line : subtitlesToTranslate.get(time)
.getSubtitleLines()) {
lineToTranslate += line + " ";
}
inputLines.add(lineToTranslate);
}
int max = Integer
.parseInt(properties.getProperty("maxTranslationBatch"));
int size = inputLines.size();
int rounds = 1 + (size / max);
log.trace("Number of rounds {} (total lines {})", rounds, size);
List<String> translations = new ArrayList<String>();
for (int i = 0; i < rounds; i++) {
int fromIndex = i * max;
int toIndex = fromIndex + max;
if (toIndex > size) {
toIndex = size;
}
log.trace("Round {}/{} ... from {} to {}", i + 1, rounds, fromIndex,
toIndex);
List<String> roundTranslation = Translator.getInstance().translate(
inputLines.subList(fromIndex, toIndex), fromLang, toLang);
log.trace("Adding {} translation to result",
roundTranslation.size());
log.trace("Translation list {} ", roundTranslation);
translations.addAll(roundTranslation);
}
Iterator<String> iterator = translations.iterator();
for (String time : subtitlesToTranslate.keySet()) {
translatedEntry = new Entry();
translatedEntry.add(iterator.next());
subtitles.put(time, translatedEntry);
}
}
/**
* Converts a subtitle file (SRT) into a Map, in which key in the timing of
* each subtitle entry, and the value is a List of String with the content
* of the entry.
*
* @param file
* @throws IOException
*/
private void readSrt(String file) throws IOException {
Entry entry = new Entry();
int i = 0;
String time = "";
InputStream isForDetection = readSrtInputStream(file);
InputStream isForReading = readSrtInputStream(file);
charset = Charset.detect(isForDetection);
log.info(file + " detected charset " + charset);
BufferedReader br = new BufferedReader(
new InputStreamReader(isForReading, charset));
try {
String line = br.readLine();
while (line != null) {
if (line.isEmpty()) {
if (entry.size() > 0) {
subtitles.put(time, entry);
entry = new Entry();
i = 0;
time = "";
}
} else {
if (i == 1) {
time = line;
}
if (i >= 2) {
// Not adding first two lines of subtitles (index and
// time)
if (line.indexOf(SrtUtils.TAG_INIT) != -1
&& line.indexOf(SrtUtils.TAG_END) != -1) {
line = removeTags(line);
}
entry.add(line);
log.debug(line);
}
i++;
}
line = br.readLine();
}
} finally {
br.close();
isForReading.close();
}
}
public InputStream readSrtInputStream(String file)
throws FileNotFoundException {
InputStream inputStream = Thread.currentThread().getContextClassLoader()
.getResourceAsStream(file);
if (inputStream == null) {
inputStream = new BufferedInputStream(new FileInputStream(file));
}
return inputStream;
}
public static String removeTags(String line) {
Pattern pattern = Pattern.compile("<([^>]+)>");
Matcher matcher = pattern.matcher(line);
return matcher.replaceAll("");
}
public void log() {
Entry list;
for (String time : subtitles.keySet()) {
list = subtitles.get(time);
for (int i = 0; i < list.size(); i++) {
log.info(time + " " + list.get(i) + " ");
}
log.info("");
}
}
public Map<String, Entry> getSubtitles() {
return subtitles;
}
public void resetSubtitles() {
subtitles.clear();
}
public String getFileName() {
return fileName;
}
public String getCharset() {
return charset;
}
}