* added support for downloading subtitles from Sublight
* added ZipArchive and RarArchive
This commit is contained in:
parent
094b37bcb8
commit
c49b68c836
|
@ -0,0 +1,14 @@
|
|||
|
||||
package net.sourceforge.filebot.ui.panel.subtitle;
|
||||
|
||||
|
||||
import java.io.IOException;
|
||||
import java.nio.ByteBuffer;
|
||||
import java.util.Map;
|
||||
|
||||
|
||||
interface Archive {
|
||||
|
||||
Map<String, ByteBuffer> extract() throws IOException;
|
||||
|
||||
}
|
|
@ -2,14 +2,46 @@
|
|||
package net.sourceforge.filebot.ui.panel.subtitle;
|
||||
|
||||
|
||||
public enum ArchiveType {
|
||||
ZIP,
|
||||
RAR,
|
||||
UNKNOWN;
|
||||
import java.io.IOException;
|
||||
import java.nio.ByteBuffer;
|
||||
import java.util.Collections;
|
||||
import java.util.Map;
|
||||
|
||||
|
||||
enum ArchiveType {
|
||||
ZIP {
|
||||
|
||||
@Override
|
||||
public Archive fromData(ByteBuffer data) {
|
||||
return new ZipArchive(data);
|
||||
}
|
||||
},
|
||||
RAR {
|
||||
|
||||
@Override
|
||||
public Archive fromData(ByteBuffer data) {
|
||||
return new RarArchive(data);
|
||||
}
|
||||
},
|
||||
UNDEFINED {
|
||||
|
||||
@Override
|
||||
public Archive fromData(ByteBuffer data) {
|
||||
// cannot extract data, return empty archive
|
||||
return new Archive() {
|
||||
|
||||
@Override
|
||||
public Map<String, ByteBuffer> extract() throws IOException {
|
||||
return Collections.emptyMap();
|
||||
}
|
||||
};
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
public static ArchiveType forName(String name) {
|
||||
if (name == null)
|
||||
return UNKNOWN;
|
||||
return UNDEFINED;
|
||||
|
||||
if (name.equalsIgnoreCase("zip"))
|
||||
return ZIP;
|
||||
|
@ -17,10 +49,13 @@ public enum ArchiveType {
|
|||
if (name.equalsIgnoreCase("rar"))
|
||||
return RAR;
|
||||
|
||||
return UNKNOWN;
|
||||
return UNDEFINED;
|
||||
}
|
||||
|
||||
|
||||
public abstract Archive fromData(ByteBuffer data);
|
||||
|
||||
|
||||
public String getExtension() {
|
||||
return toString().toLowerCase();
|
||||
}
|
||||
|
|
|
@ -0,0 +1,53 @@
|
|||
|
||||
package net.sourceforge.filebot.ui.panel.subtitle;
|
||||
|
||||
|
||||
import java.io.IOException;
|
||||
import java.nio.ByteBuffer;
|
||||
import java.util.LinkedHashMap;
|
||||
import java.util.Map;
|
||||
|
||||
import net.sourceforge.tuned.ByteBufferOutputStream;
|
||||
|
||||
import de.innosystec.unrar.exception.RarException;
|
||||
import de.innosystec.unrar.rarfile.FileHeader;
|
||||
|
||||
|
||||
class RarArchive implements Archive {
|
||||
|
||||
private final ByteBuffer data;
|
||||
|
||||
|
||||
public RarArchive(ByteBuffer data) {
|
||||
this.data = data.duplicate();
|
||||
}
|
||||
|
||||
|
||||
public Map<String, ByteBuffer> extract() throws IOException {
|
||||
Map<String, ByteBuffer> vfs = new LinkedHashMap<String, ByteBuffer>();
|
||||
|
||||
try {
|
||||
de.innosystec.unrar.Archive rar = new de.innosystec.unrar.Archive(data.duplicate());
|
||||
|
||||
for (FileHeader header : rar.getFileHeaders()) {
|
||||
// ignore directory entries
|
||||
if (header.isDirectory()) {
|
||||
continue;
|
||||
}
|
||||
|
||||
ByteBufferOutputStream buffer = new ByteBufferOutputStream(header.getDataSize());
|
||||
|
||||
// write contents to buffer
|
||||
rar.extractFile(header, buffer);
|
||||
|
||||
// add memory file
|
||||
vfs.put(header.getFileNameString(), buffer.getByteBuffer());
|
||||
}
|
||||
} catch (RarException e) {
|
||||
throw new IOException(e);
|
||||
}
|
||||
|
||||
return vfs;
|
||||
}
|
||||
|
||||
}
|
|
@ -56,7 +56,7 @@ public class SubtitleListCellRenderer extends AbstractFancyListCellRenderer {
|
|||
|
||||
//TODO download + progress
|
||||
progressBar.setVisible(false);
|
||||
progressBar.setString(subtitle.getDownloadTask().getState().toString().toLowerCase());
|
||||
progressBar.setString(subtitle.getDownload().getState().toString().toLowerCase());
|
||||
|
||||
titleLabel.setForeground(isSelected ? list.getSelectionForeground() : list.getForeground());
|
||||
languageLabel.setForeground(isSelected ? list.getSelectionForeground() : list.getForeground());
|
||||
|
|
|
@ -2,13 +2,15 @@
|
|||
package net.sourceforge.filebot.ui.panel.subtitle;
|
||||
|
||||
|
||||
import java.nio.ByteBuffer;
|
||||
import java.util.HashMap;
|
||||
import java.util.Locale;
|
||||
import java.util.Map;
|
||||
import java.util.ResourceBundle;
|
||||
|
||||
import javax.swing.SwingWorker;
|
||||
|
||||
import net.sourceforge.filebot.web.SubtitleDescriptor;
|
||||
import net.sourceforge.tuned.DownloadTask;
|
||||
|
||||
|
||||
public class SubtitlePackage {
|
||||
|
@ -17,14 +19,14 @@ public class SubtitlePackage {
|
|||
|
||||
private final Language language;
|
||||
|
||||
private final DownloadTask downloadTask;
|
||||
private final SwingWorker<ByteBuffer, ?> download;
|
||||
|
||||
|
||||
public SubtitlePackage(SubtitleDescriptor subtitleDescriptor) {
|
||||
this.subtitleDescriptor = subtitleDescriptor;
|
||||
|
||||
this.language = new Language(languageCodeByName.get(subtitleDescriptor.getLanguageName()), subtitleDescriptor.getLanguageName());
|
||||
this.downloadTask = subtitleDescriptor.createDownloadTask();
|
||||
this.download = subtitleDescriptor.createDownloadTask();
|
||||
}
|
||||
|
||||
|
||||
|
@ -43,8 +45,8 @@ public class SubtitlePackage {
|
|||
}
|
||||
|
||||
|
||||
public DownloadTask getDownloadTask() {
|
||||
return downloadTask;
|
||||
public SwingWorker<ByteBuffer, ?> getDownload() {
|
||||
return download;
|
||||
}
|
||||
|
||||
|
||||
|
|
|
@ -0,0 +1,52 @@
|
|||
|
||||
package net.sourceforge.filebot.ui.panel.subtitle;
|
||||
|
||||
|
||||
import java.io.IOException;
|
||||
import java.nio.ByteBuffer;
|
||||
import java.nio.channels.Channels;
|
||||
import java.nio.channels.ReadableByteChannel;
|
||||
import java.util.LinkedHashMap;
|
||||
import java.util.Map;
|
||||
import java.util.zip.ZipEntry;
|
||||
import java.util.zip.ZipInputStream;
|
||||
|
||||
import net.sourceforge.tuned.ByteBufferInputStream;
|
||||
import net.sourceforge.tuned.ByteBufferOutputStream;
|
||||
|
||||
|
||||
class ZipArchive implements Archive {
|
||||
|
||||
private final ByteBuffer data;
|
||||
|
||||
|
||||
public ZipArchive(ByteBuffer data) {
|
||||
this.data = data.duplicate();
|
||||
}
|
||||
|
||||
|
||||
public Map<String, ByteBuffer> extract() throws IOException {
|
||||
Map<String, ByteBuffer> vfs = new LinkedHashMap<String, ByteBuffer>();
|
||||
|
||||
// read first zip entry
|
||||
ZipInputStream zipInputStream = new ZipInputStream(new ByteBufferInputStream(data.duplicate()));
|
||||
ZipEntry zipEntry;
|
||||
|
||||
try {
|
||||
while ((zipEntry = zipInputStream.getNextEntry()) != null) {
|
||||
ByteBufferOutputStream buffer = new ByteBufferOutputStream((int) zipEntry.getSize());
|
||||
ReadableByteChannel fileChannel = Channels.newChannel(zipInputStream);
|
||||
|
||||
// write contents to buffer
|
||||
while (buffer.transferFrom(fileChannel) >= 0);
|
||||
|
||||
// add memory file
|
||||
vfs.put(zipEntry.getName(), buffer.getByteBuffer());
|
||||
}
|
||||
} finally {
|
||||
zipInputStream.close();
|
||||
}
|
||||
|
||||
return vfs;
|
||||
}
|
||||
}
|
|
@ -16,6 +16,8 @@ import javax.swing.Icon;
|
|||
import javax.xml.ws.Holder;
|
||||
import javax.xml.ws.WebServiceException;
|
||||
|
||||
import redstone.xmlrpc.util.Base64;
|
||||
|
||||
import net.sourceforge.filebot.ResourceManager;
|
||||
import net.sourceforge.tuned.Timer;
|
||||
import net.sublight.webservice.ArrayOfGenre;
|
||||
|
@ -97,7 +99,7 @@ public class SublightSubtitleClient implements SubtitleProvider {
|
|||
|
||||
// retrieve subtitles by name and year
|
||||
for (Subtitle subtitle : getSubtitleList(null, movie.getName(), movie.getYear(), languageName)) {
|
||||
subtitles.add(new SublightSubtitleDescriptor(subtitle));
|
||||
subtitles.add(new SublightSubtitleDescriptor(subtitle, this));
|
||||
}
|
||||
|
||||
return subtitles;
|
||||
|
@ -111,7 +113,7 @@ public class SublightSubtitleClient implements SubtitleProvider {
|
|||
for (Subtitle subtitle : getSubtitleList(SublightVideoHasher.computeHash(videoFile), null, null, languageName)) {
|
||||
// only keep linked subtitles
|
||||
if (subtitle.isIsLinked()) {
|
||||
subtitles.add(new SublightSubtitleDescriptor(subtitle));
|
||||
subtitles.add(new SublightSubtitleDescriptor(subtitle, this));
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -186,11 +188,34 @@ public class SublightSubtitleClient implements SubtitleProvider {
|
|||
if (languageName.equalsIgnoreCase("Serbian"))
|
||||
return SubtitleLanguage.SERBIAN_LATIN;
|
||||
|
||||
// unkown language
|
||||
// unknown language
|
||||
throw new IllegalArgumentException("Illegal language: " + languageName);
|
||||
}
|
||||
|
||||
|
||||
protected byte[] getZipArchive(Subtitle subtitle) throws WebServiceException {
|
||||
// require login
|
||||
login();
|
||||
|
||||
Holder<String> ticket = new Holder<String>();
|
||||
Holder<String> data = new Holder<String>();
|
||||
Holder<String> error = new Holder<String>();
|
||||
|
||||
webservice.getDownloadTicket(session, null, subtitle.getSubtitleID(), null, ticket, null, error);
|
||||
|
||||
// abort if something went wrong
|
||||
checkError(error);
|
||||
|
||||
webservice.downloadByID3(session, subtitle.getSubtitleID(), -1, false, ticket.value, null, data, error);
|
||||
|
||||
// abort if something went wrong
|
||||
checkError(error);
|
||||
|
||||
// return zip file bytes
|
||||
return Base64.decode(data.value.getBytes());
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public URI getSubtitleListLink(SearchResult searchResult, String languageName) {
|
||||
return null;
|
||||
|
|
|
@ -2,17 +2,22 @@
|
|||
package net.sourceforge.filebot.web;
|
||||
|
||||
|
||||
import net.sourceforge.tuned.DownloadTask;
|
||||
import java.nio.ByteBuffer;
|
||||
|
||||
import javax.swing.SwingWorker;
|
||||
|
||||
import net.sublight.webservice.Subtitle;
|
||||
|
||||
|
||||
public class SublightSubtitleDescriptor implements SubtitleDescriptor {
|
||||
|
||||
private final Subtitle subtitle;
|
||||
private final SublightSubtitleClient source;
|
||||
|
||||
|
||||
public SublightSubtitleDescriptor(Subtitle subtitle) {
|
||||
public SublightSubtitleDescriptor(Subtitle subtitle, SublightSubtitleClient source) {
|
||||
this.subtitle = subtitle;
|
||||
this.source = source;
|
||||
}
|
||||
|
||||
|
||||
|
@ -33,12 +38,6 @@ public class SublightSubtitleDescriptor implements SubtitleDescriptor {
|
|||
}
|
||||
|
||||
|
||||
@Override
|
||||
public String getArchiveType() {
|
||||
return subtitle.getSubtitleType().value().toLowerCase();
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public String getLanguageName() {
|
||||
return subtitle.getLanguage().value();
|
||||
|
@ -46,9 +45,20 @@ public class SublightSubtitleDescriptor implements SubtitleDescriptor {
|
|||
|
||||
|
||||
@Override
|
||||
public DownloadTask createDownloadTask() {
|
||||
// TODO support
|
||||
return new DownloadTask(null);
|
||||
public String getArchiveType() {
|
||||
return "zip";
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public SwingWorker<ByteBuffer, ?> createDownloadTask() {
|
||||
return new SwingWorker<ByteBuffer, Void>() {
|
||||
|
||||
@Override
|
||||
protected ByteBuffer doInBackground() throws Exception {
|
||||
return ByteBuffer.wrap(source.getZipArchive(subtitle));
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
|
||||
|
|
|
@ -33,7 +33,7 @@ import net.sourceforge.filebot.mediainfo.MediaInfo.StreamKind;
|
|||
public final class SublightVideoHasher {
|
||||
|
||||
|
||||
public static String computeHash(File file) throws IOException {
|
||||
public static String computeHash(File file) throws IOException, LinkageError {
|
||||
byte[][] hash = new byte[4][];
|
||||
|
||||
// 1 byte = 0 (reserved)
|
||||
|
@ -80,12 +80,11 @@ public final class SublightVideoHasher {
|
|||
}
|
||||
|
||||
|
||||
protected static long getDuration(File file, TimeUnit unit) throws IOException {
|
||||
try {
|
||||
protected static long getDuration(File file, TimeUnit unit) throws IOException, LinkageError {
|
||||
MediaInfo mediaInfo = new MediaInfo();
|
||||
|
||||
if (!mediaInfo.open(file))
|
||||
throw new IllegalArgumentException("Failed to open file: " + file);
|
||||
throw new IOException("Failed to open file: " + file);
|
||||
|
||||
// get media info
|
||||
String duration = mediaInfo.get(StreamKind.General, 0, "Duration");
|
||||
|
@ -95,9 +94,6 @@ public final class SublightVideoHasher {
|
|||
|
||||
// convert from milliseconds to given unit
|
||||
return unit.convert(Long.parseLong(duration), TimeUnit.MILLISECONDS);
|
||||
} catch (Exception e) {
|
||||
throw new IOException("Failed to get video duration", e);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
|
|
@ -2,7 +2,9 @@
|
|||
package net.sourceforge.filebot.web;
|
||||
|
||||
|
||||
import net.sourceforge.tuned.DownloadTask;
|
||||
import java.nio.ByteBuffer;
|
||||
|
||||
import javax.swing.SwingWorker;
|
||||
|
||||
|
||||
public interface SubtitleDescriptor {
|
||||
|
@ -16,6 +18,6 @@ public interface SubtitleDescriptor {
|
|||
public String getArchiveType();
|
||||
|
||||
|
||||
public DownloadTask createDownloadTask();
|
||||
public SwingWorker<ByteBuffer, ?> createDownloadTask();
|
||||
|
||||
}
|
||||
|
|
|
@ -4,7 +4,10 @@ package net.sourceforge.filebot.web;
|
|||
|
||||
import static org.junit.Assert.*;
|
||||
|
||||
import java.io.ByteArrayInputStream;
|
||||
import java.util.List;
|
||||
import java.util.zip.ZipEntry;
|
||||
import java.util.zip.ZipInputStream;
|
||||
|
||||
import net.sublight.webservice.Subtitle;
|
||||
|
||||
|
@ -82,6 +85,27 @@ public class SublightSubtitleClientTest {
|
|||
}
|
||||
|
||||
|
||||
@Test
|
||||
public void getZipArchive() throws Exception {
|
||||
Subtitle subtitle = new Subtitle();
|
||||
subtitle.setSubtitleID("1b4e9868-dded-49d0-b6e2-2d145328f6d4");
|
||||
|
||||
byte[] zip = client.getZipArchive(subtitle);
|
||||
|
||||
// read first zip entry
|
||||
ZipInputStream zipInputStream = new ZipInputStream(new ByteArrayInputStream(zip));
|
||||
|
||||
try {
|
||||
ZipEntry entry = zipInputStream.getNextEntry();
|
||||
|
||||
assertEquals("Terminator The Sarah Connor Chronicles.srt", entry.getName());
|
||||
assertEquals(38959, entry.getSize(), 0);
|
||||
} finally {
|
||||
zipInputStream.close();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@AfterClass
|
||||
public static void logout() {
|
||||
// logout manually
|
||||
|
|
Loading…
Reference in New Issue