TubeLab-App-Android/torrentStream/src/main/java/com/github/se_bastiaan/torrentstream/TorrentInputStream.java

116 lines
2.6 KiB
Java

package com.github.se_bastiaan.torrentstream;
import com.frostwire.jlibtorrent.AlertListener;
import com.frostwire.jlibtorrent.alerts.Alert;
import com.frostwire.jlibtorrent.alerts.AlertType;
import java.io.FilterInputStream;
import java.io.IOException;
import java.io.InputStream;
class TorrentInputStream extends FilterInputStream implements AlertListener {
private final Torrent torrent;
private boolean stopped;
private long location;
TorrentInputStream(Torrent torrent, InputStream inputStream) {
super(inputStream);
this.torrent = torrent;
}
@Override
protected void finalize() throws Throwable {
synchronized (this) {
stopped = true;
notifyAll();
}
super.finalize();
}
private synchronized boolean waitForPiece(long offset) {
while (!Thread.currentThread().isInterrupted() && !stopped) {
try {
if (torrent.hasBytes(offset)) {
return true;
}
wait();
} catch (InterruptedException ex) {
Thread.currentThread().interrupt();
}
}
return false;
}
@Override
public synchronized int read() throws IOException {
if (!waitForPiece(location)) {
return -1;
}
location++;
return super.read();
}
@Override
public synchronized int read(byte[] buffer, int offset, int length) throws IOException {
int pieceLength = torrent.getTorrentHandle().torrentFile().pieceLength();
for (int i = 0; i < length; i += pieceLength) {
if (!waitForPiece(location + i)) {
return -1;
}
}
location += length;
return super.read(buffer, offset, length);
}
@Override
public void close() throws IOException {
synchronized (this) {
stopped = true;
notifyAll();
}
super.close();
}
@Override
public synchronized long skip(long n) throws IOException {
location += n;
return super.skip(n);
}
@Override
public boolean markSupported() {
return false;
}
private synchronized void pieceFinished() {
notifyAll();
}
@Override
public int[] types() {
return new int[]{
AlertType.PIECE_FINISHED.swig(),
};
}
@Override
public void alert(Alert<?> alert) {
switch (alert.type()) {
case PIECE_FINISHED:
pieceFinished();
break;
default:
break;
}
}
}