1
0
mirror of https://github.com/mitb-archive/filebot synced 2024-11-13 21:05:01 -05:00

* 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; package net.sourceforge.filebot.ui.panel.subtitle;
public enum ArchiveType { import java.io.IOException;
ZIP, import java.nio.ByteBuffer;
RAR, import java.util.Collections;
UNKNOWN; 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) { public static ArchiveType forName(String name) {
if (name == null) if (name == null)
return UNKNOWN; return UNDEFINED;
if (name.equalsIgnoreCase("zip")) if (name.equalsIgnoreCase("zip"))
return ZIP; return ZIP;
@ -17,10 +49,13 @@ public enum ArchiveType {
if (name.equalsIgnoreCase("rar")) if (name.equalsIgnoreCase("rar"))
return RAR; return RAR;
return UNKNOWN; return UNDEFINED;
} }
public abstract Archive fromData(ByteBuffer data);
public String getExtension() { public String getExtension() {
return toString().toLowerCase(); 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 //TODO download + progress
progressBar.setVisible(false); progressBar.setVisible(false);
progressBar.setString(subtitle.getDownloadTask().getState().toString().toLowerCase()); progressBar.setString(subtitle.getDownload().getState().toString().toLowerCase());
titleLabel.setForeground(isSelected ? list.getSelectionForeground() : list.getForeground()); titleLabel.setForeground(isSelected ? list.getSelectionForeground() : list.getForeground());
languageLabel.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; package net.sourceforge.filebot.ui.panel.subtitle;
import java.nio.ByteBuffer;
import java.util.HashMap; import java.util.HashMap;
import java.util.Locale; import java.util.Locale;
import java.util.Map; import java.util.Map;
import java.util.ResourceBundle; import java.util.ResourceBundle;
import javax.swing.SwingWorker;
import net.sourceforge.filebot.web.SubtitleDescriptor; import net.sourceforge.filebot.web.SubtitleDescriptor;
import net.sourceforge.tuned.DownloadTask;
public class SubtitlePackage { public class SubtitlePackage {
@ -17,14 +19,14 @@ public class SubtitlePackage {
private final Language language; private final Language language;
private final DownloadTask downloadTask; private final SwingWorker<ByteBuffer, ?> download;
public SubtitlePackage(SubtitleDescriptor subtitleDescriptor) { public SubtitlePackage(SubtitleDescriptor subtitleDescriptor) {
this.subtitleDescriptor = subtitleDescriptor; this.subtitleDescriptor = subtitleDescriptor;
this.language = new Language(languageCodeByName.get(subtitleDescriptor.getLanguageName()), subtitleDescriptor.getLanguageName()); 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() { public SwingWorker<ByteBuffer, ?> getDownload() {
return downloadTask; 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.Holder;
import javax.xml.ws.WebServiceException; import javax.xml.ws.WebServiceException;
import redstone.xmlrpc.util.Base64;
import net.sourceforge.filebot.ResourceManager; import net.sourceforge.filebot.ResourceManager;
import net.sourceforge.tuned.Timer; import net.sourceforge.tuned.Timer;
import net.sublight.webservice.ArrayOfGenre; import net.sublight.webservice.ArrayOfGenre;
@ -97,7 +99,7 @@ public class SublightSubtitleClient implements SubtitleProvider {
// retrieve subtitles by name and year // retrieve subtitles by name and year
for (Subtitle subtitle : getSubtitleList(null, movie.getName(), movie.getYear(), languageName)) { for (Subtitle subtitle : getSubtitleList(null, movie.getName(), movie.getYear(), languageName)) {
subtitles.add(new SublightSubtitleDescriptor(subtitle)); subtitles.add(new SublightSubtitleDescriptor(subtitle, this));
} }
return subtitles; return subtitles;
@ -111,7 +113,7 @@ public class SublightSubtitleClient implements SubtitleProvider {
for (Subtitle subtitle : getSubtitleList(SublightVideoHasher.computeHash(videoFile), null, null, languageName)) { for (Subtitle subtitle : getSubtitleList(SublightVideoHasher.computeHash(videoFile), null, null, languageName)) {
// only keep linked subtitles // only keep linked subtitles
if (subtitle.isIsLinked()) { 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")) if (languageName.equalsIgnoreCase("Serbian"))
return SubtitleLanguage.SERBIAN_LATIN; return SubtitleLanguage.SERBIAN_LATIN;
// unkown language // unknown language
throw new IllegalArgumentException("Illegal language: " + languageName); 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 @Override
public URI getSubtitleListLink(SearchResult searchResult, String languageName) { public URI getSubtitleListLink(SearchResult searchResult, String languageName) {
return null; return null;

View File

@ -2,17 +2,22 @@
package net.sourceforge.filebot.web; package net.sourceforge.filebot.web;
import net.sourceforge.tuned.DownloadTask; import java.nio.ByteBuffer;
import javax.swing.SwingWorker;
import net.sublight.webservice.Subtitle; import net.sublight.webservice.Subtitle;
public class SublightSubtitleDescriptor implements SubtitleDescriptor { public class SublightSubtitleDescriptor implements SubtitleDescriptor {
private final Subtitle subtitle; private final Subtitle subtitle;
private final SublightSubtitleClient source;
public SublightSubtitleDescriptor(Subtitle subtitle) { public SublightSubtitleDescriptor(Subtitle subtitle, SublightSubtitleClient source) {
this.subtitle = subtitle; 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 @Override
public String getLanguageName() { public String getLanguageName() {
return subtitle.getLanguage().value(); return subtitle.getLanguage().value();
@ -46,9 +45,20 @@ public class SublightSubtitleDescriptor implements SubtitleDescriptor {
@Override @Override
public DownloadTask createDownloadTask() { public String getArchiveType() {
// TODO support return "zip";
return new DownloadTask(null); }
@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 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][]; byte[][] hash = new byte[4][];
// 1 byte = 0 (reserved) // 1 byte = 0 (reserved)
@ -80,12 +80,11 @@ public final class SublightVideoHasher {
} }
protected static long getDuration(File file, TimeUnit unit) throws IOException { protected static long getDuration(File file, TimeUnit unit) throws IOException, LinkageError {
try {
MediaInfo mediaInfo = new MediaInfo(); MediaInfo mediaInfo = new MediaInfo();
if (!mediaInfo.open(file)) if (!mediaInfo.open(file))
throw new IllegalArgumentException("Failed to open file: " + file); throw new IOException("Failed to open file: " + file);
// get media info // get media info
String duration = mediaInfo.get(StreamKind.General, 0, "Duration"); String duration = mediaInfo.get(StreamKind.General, 0, "Duration");
@ -95,9 +94,6 @@ public final class SublightVideoHasher {
// convert from milliseconds to given unit // convert from milliseconds to given unit
return unit.convert(Long.parseLong(duration), TimeUnit.MILLISECONDS); return unit.convert(Long.parseLong(duration), TimeUnit.MILLISECONDS);
} catch (Exception e) {
throw new IOException("Failed to get video duration", e);
}
} }

View File

@ -2,7 +2,9 @@
package net.sourceforge.filebot.web; package net.sourceforge.filebot.web;
import net.sourceforge.tuned.DownloadTask; import java.nio.ByteBuffer;
import javax.swing.SwingWorker;
public interface SubtitleDescriptor { public interface SubtitleDescriptor {
@ -16,6 +18,6 @@ public interface SubtitleDescriptor {
public String getArchiveType(); 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 static org.junit.Assert.*;
import java.io.ByteArrayInputStream;
import java.util.List; import java.util.List;
import java.util.zip.ZipEntry;
import java.util.zip.ZipInputStream;
import net.sublight.webservice.Subtitle; 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 @AfterClass
public static void logout() { public static void logout() {
// logout manually // logout manually