* added support for downloading subtitles from Sublight

* added ZipArchive and RarArchive
This commit is contained in:
Reinhard Pointner 2009-06-02 15:14:12 +00:00
parent 094b37bcb8
commit c49b68c836
11 changed files with 261 additions and 48 deletions

View File

@ -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;
}

View File

@ -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();
}

View File

@ -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;
}
}

View File

@ -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());

View File

@ -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;
}

View File

@ -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;
}
}

View File

@ -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;

View File

@ -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));
}
};
}

View File

@ -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,24 +80,20 @@ public final class SublightVideoHasher {
}
protected static long getDuration(File file, TimeUnit unit) throws IOException {
try {
MediaInfo mediaInfo = new MediaInfo();
if (!mediaInfo.open(file))
throw new IllegalArgumentException("Failed to open file: " + file);
// get media info
String duration = mediaInfo.get(StreamKind.General, 0, "Duration");
// close handle
mediaInfo.close();
// 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);
}
protected static long getDuration(File file, TimeUnit unit) throws IOException, LinkageError {
MediaInfo mediaInfo = new MediaInfo();
if (!mediaInfo.open(file))
throw new IOException("Failed to open file: " + file);
// get media info
String duration = mediaInfo.get(StreamKind.General, 0, "Duration");
// close handle
mediaInfo.close();
// convert from milliseconds to given unit
return unit.convert(Long.parseLong(duration), TimeUnit.MILLISECONDS);
}

View File

@ -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();
}

View File

@ -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