diff --git a/app/build.gradle b/app/build.gradle index 7ab9949..f80ddad 100644 --- a/app/build.gradle +++ b/app/build.gradle @@ -148,7 +148,6 @@ dependencies { implementation 'androidx.lifecycle:lifecycle-extensions:2.2.0' implementation 'androidx.browser:browser:1.4.0' implementation 'androidx.documentfile:documentfile:1.0.1' - implementation project(path: ':torrentStream') testImplementation 'junit:junit:4.13.2' androidTestImplementation 'androidx.test.ext:junit:1.1.3' androidTestImplementation 'androidx.test.espresso:espresso-core:3.4.0' diff --git a/app/src/main/java/app/fedilab/fedilabtube/activities/PeertubeActivity.java b/app/src/main/java/app/fedilab/fedilabtube/activities/PeertubeActivity.java index 93111a6..e38a949 100644 --- a/app/src/main/java/app/fedilab/fedilabtube/activities/PeertubeActivity.java +++ b/app/src/main/java/app/fedilab/fedilabtube/activities/PeertubeActivity.java @@ -84,12 +84,6 @@ import androidx.recyclerview.widget.LinearLayoutManager; import androidx.recyclerview.widget.RecyclerView; import com.bumptech.glide.Glide; -import com.frostwire.jlibtorrent.SessionManager; -import com.github.se_bastiaan.torrentstream.StreamStatus; -import com.github.se_bastiaan.torrentstream.Torrent; -import com.github.se_bastiaan.torrentstream.TorrentOptions; -import com.github.se_bastiaan.torrentstream.TorrentStream; -import com.github.se_bastiaan.torrentstream.listeners.TorrentListener; import com.github.vkay94.dtpv.youtube.YouTubeOverlay; import com.google.android.exoplayer2.C; import com.google.android.exoplayer2.ExoPlaybackException; @@ -110,9 +104,7 @@ import com.google.android.exoplayer2.ui.AspectRatioFrameLayout; import com.google.android.exoplayer2.ui.DefaultTimeBar; import com.google.android.exoplayer2.ui.PlayerControlView; import com.google.android.exoplayer2.upstream.DataSource; -import com.google.android.exoplayer2.upstream.DataSpec; import com.google.android.exoplayer2.upstream.DefaultDataSourceFactory; -import com.google.android.exoplayer2.upstream.FileDataSource; import com.google.android.exoplayer2.util.MimeTypes; import com.google.android.exoplayer2.util.Util; import com.google.android.exoplayer2.video.VideoListener; @@ -127,8 +119,6 @@ import java.util.LinkedHashMap; import java.util.List; import java.util.Map; import java.util.Objects; -import java.util.Timer; -import java.util.TimerTask; import java.util.regex.Matcher; import java.util.regex.Pattern; @@ -177,7 +167,7 @@ import app.fedilab.fedilabtube.webview.MastalabWebViewClient; import es.dmoral.toasty.Toasty; -public class PeertubeActivity extends BasePeertubeActivity implements CommentListAdapter.AllCommentRemoved, Player.EventListener, VideoListener, TorrentListener, MenuAdapter.ItemClicked, MenuItemAdapter.ItemAction { +public class PeertubeActivity extends BasePeertubeActivity implements CommentListAdapter.AllCommentRemoved, Player.EventListener, VideoListener, MenuAdapter.ItemClicked, MenuItemAdapter.ItemAction { public static String video_id; public static List playedVideos = new ArrayList<>(); @@ -203,7 +193,6 @@ public class PeertubeActivity extends BasePeertubeActivity implements CommentLis private BroadcastReceiver mPowerKeyReceiver = null; private boolean isPlayInMinimized; private VideoData.Video nextVideo; - private TorrentStream torrentStream; private String show_more_content; private videoOrientation videoOrientationType; private int initialOrientation; @@ -231,74 +220,6 @@ public class PeertubeActivity extends BasePeertubeActivity implements CommentLis } } - @Override - public void onStreamPrepared(Torrent torrent) { - Log.v(Helper.TAG,"onStreamPrepared: " + torrent); - torrent.startDownload(); - } - - @Override - public void onStreamStarted(Torrent torrent) { - Log.v(Helper.TAG,"onStreamStarted: " + torrent); - - } - - @Override - public void onStreamError(Torrent torrent, Exception e) { - Log.v(Helper.TAG,"onStreamError: " + e.getMessage()); - e.printStackTrace(); - } - - @Override - public void onStreamReady(Torrent torrent) { - Log.v(Helper.TAG,"onStreamReady: " + torrent); - if (torrent.getVideoFile() != null) { - for (int i = 0; i < torrent.getFileNames().length; i++) { - torrent.getTorrentHandle().renameFile(i, torrent.getFileNames()[0].replaceAll("[^a-zA-Z0-9/.-]", "_")); - } - startStream(peertube, torrent.getVideoFile().getAbsolutePath().replaceAll("[^a-zA-Z0-9/.-]", "_"), null, autoPlay, -1, null, null, true); - PlayerControlView controlView = binding.doubleTapPlayerView.findViewById(R.id.exo_controller); - ConstraintLayout torrent_info = controlView.findViewById(R.id.torrent_info); - TextView dowload_rate = controlView.findViewById(R.id.dowload_rate); - TextView upload_rate = controlView.findViewById(R.id.upload_rate); - torrent_info.setVisibility(View.VISIBLE); - - new Timer().scheduleAtFixedRate(new TimerTask() { - @Override - public void run() { - SessionManager sessionManager = torrentStream.getSessionManager(); - if (sessionManager != null) { - long upload = sessionManager.uploadRate(); - long download = sessionManager.downloadRate(); - runOnUiThread(() -> { - dowload_rate.setText(String.format("▼ %s", Helper.rateSize(PeertubeActivity.this, download))); - upload_rate.setText(String.format("▲ %s", Helper.rateSize(PeertubeActivity.this, upload))); - }); - } - } - }, 0, 1000); - } else { - Toasty.error(PeertubeActivity.this, getString(R.string.toast_error), Toast.LENGTH_LONG).show(); - } - - } - - - @Override - public void onStreamProgress(Torrent torrent, StreamStatus status) { - Log.v(Helper.TAG,"onStreamProgress: " + torrent); - if (binding != null) { - PlayerControlView controlView = binding.doubleTapPlayerView.findViewById(R.id.exo_controller); - TextView peers_number = controlView.findViewById(R.id.peers_number); - peers_number.setText(getString(R.string.peers, status.peers)); - } - } - - @Override - public void onStreamStopped() { - Log.v(Helper.TAG,"onStreamStopped: "); - } - @Override protected void onCreate(Bundle savedInstanceState) { @@ -315,16 +236,9 @@ public class PeertubeActivity extends BasePeertubeActivity implements CommentLis Helper.loadAvatar(PeertubeActivity.this, account, binding.myPp); } isRemote = false; - TorrentOptions torrentOptions = new TorrentOptions.Builder() - .saveLocation(getCacheDir() + "/torrent/") - .autoDownload(true) - .removeFilesAfterStop(true) - .build(); fullScreenMode = false; - torrentStream = TorrentStream.init(torrentOptions); - torrentStream.addListener(PeertubeActivity.this); initialOrientation = getResources().getConfiguration().orientation; if (Helper.isTablet(PeertubeActivity.this)) { @@ -1180,7 +1094,6 @@ public class PeertubeActivity extends BasePeertubeActivity implements CommentLis startStream( apiResponse.getPeertubes().get(0), null, - null, autoPlay, position, null, null, true); player.prepare(); player.setPlayWhenReady(autoPlay); @@ -1273,83 +1186,65 @@ public class PeertubeActivity extends BasePeertubeActivity implements CommentLis * Manage video to play with different factors * * @param video VideoData.Video - * @param localTorrentUrl String if not null that will be used * @param resolution String the current resolution asked * @param autoPlay boolean * @param position int current position * @param subtitles Uri uri for subtitles * @param lang String ("en","fr", etc.) */ - private void stream(VideoData.Video video, String localTorrentUrl, String resolution, boolean autoPlay, long position, Uri subtitles, String lang) { - videoURL = localTorrentUrl == null ? video.getFileUrl(resolution, PeertubeActivity.this) : localTorrentUrl; + private void stream(VideoData.Video video, String resolution, boolean autoPlay, long position, Uri subtitles, String lang) { + videoURL = video.getFileUrl(resolution, PeertubeActivity.this); Log.v(Helper.TAG,">>>>>>>>videoURL: " + videoURL ); if (subtitles != null) { subtitlesStr = subtitles.toString(); } SharedPreferences sharedpreferences = getSharedPreferences(Helper.APP_PREFS, MODE_PRIVATE); int video_cache = sharedpreferences.getInt(Helper.SET_VIDEO_CACHE, Helper.DEFAULT_VIDEO_CACHE_MB); - if (videoURL != null && (videoURL.endsWith(".torrent") || videoURL.startsWith("magnet"))) { - torrentStream.startStream(videoURL); - return; - } else { - ProgressiveMediaSource videoSource = null; - HlsMediaSource hlsMediaSource = null; - SingleSampleMediaSource subtitleSource = null; - DataSource.Factory dataSourceFactory = null; - if (localTorrentUrl != null) { - DataSpec dataSpec = new DataSpec(Uri.fromFile(new java.io.File(localTorrentUrl))); - FileDataSource fileDataSource = new FileDataSource(); - try { - fileDataSource.open(dataSpec); - dataSourceFactory = () -> fileDataSource; - } catch (FileDataSource.FileDataSourceException e) { - e.printStackTrace(); - } - } - if (video_cache == 0 || dataSourceFactory != null || video.isLive()) { - if (dataSourceFactory == null) { - dataSourceFactory = new DefaultDataSourceFactory(PeertubeActivity.this, - Util.getUserAgent(PeertubeActivity.this, null), null); - } + ProgressiveMediaSource videoSource = null; + HlsMediaSource hlsMediaSource = null; + SingleSampleMediaSource subtitleSource = null; + DataSource.Factory dataSourceFactory = null; + if (video_cache == 0 || video.isLive()) { + dataSourceFactory = new DefaultDataSourceFactory(PeertubeActivity.this, + Util.getUserAgent(PeertubeActivity.this, null), null); - if (subtitles != null) { - MediaItem.Subtitle mediaSubtitle = new MediaItem.Subtitle(subtitles, MimeTypes.TEXT_VTT, lang); - subtitleSource = new SingleSampleMediaSource.Factory(dataSourceFactory).createMediaSource(mediaSubtitle, C.TIME_UNSET); - } - MediaItem mediaItem = new MediaItem.Builder().setUri(Uri.parse(videoURL)).build(); - if (videoURL != null && !videoURL.endsWith("m3u8")) { - videoSource = new ProgressiveMediaSource.Factory(dataSourceFactory).createMediaSource(mediaItem); - } else { - hlsMediaSource = new HlsMediaSource.Factory(dataSourceFactory) - .createMediaSource(mediaItem); - } - } else { - CacheDataSourceFactory cacheDataSourceFactory = new CacheDataSourceFactory(PeertubeActivity.this); - MediaItem mediaItem = new MediaItem.Builder().setUri(videoURL).build(); - if (subtitles != null) { - MediaItem.Subtitle mediaSubtitle = new MediaItem.Subtitle(subtitles, MimeTypes.TEXT_VTT, lang, Format.NO_VALUE); - subtitleSource = new SingleSampleMediaSource.Factory(cacheDataSourceFactory).createMediaSource(mediaSubtitle, C.TIME_UNSET); - } - if (videoURL != null && !videoURL.endsWith("m3u8")) { - videoSource = new ProgressiveMediaSource.Factory(cacheDataSourceFactory).createMediaSource(mediaItem); - } else { - hlsMediaSource = new HlsMediaSource.Factory(cacheDataSourceFactory) - .createMediaSource(mediaItem); - } + if (subtitles != null) { + MediaItem.Subtitle mediaSubtitle = new MediaItem.Subtitle(subtitles, MimeTypes.TEXT_VTT, lang); + subtitleSource = new SingleSampleMediaSource.Factory(dataSourceFactory).createMediaSource(mediaSubtitle, C.TIME_UNSET); } - if (lang != null && subtitleSource != null && videoSource != null) { - MergingMediaSource mergedSource = - new MergingMediaSource(videoSource, subtitleSource); - player.setMediaSource(mergedSource); - } else if (lang != null && subtitleSource != null) { - MergingMediaSource mergedSource = - new MergingMediaSource(hlsMediaSource, subtitleSource); - player.setMediaSource(mergedSource); - } else if (videoSource != null) { - player.setMediaSource(videoSource); + MediaItem mediaItem = new MediaItem.Builder().setUri(Uri.parse(videoURL)).build(); + if (videoURL != null && !videoURL.endsWith("m3u8")) { + videoSource = new ProgressiveMediaSource.Factory(dataSourceFactory).createMediaSource(mediaItem); } else { - player.setMediaSource(hlsMediaSource); + hlsMediaSource = new HlsMediaSource.Factory(dataSourceFactory) + .createMediaSource(mediaItem); } + } else { + CacheDataSourceFactory cacheDataSourceFactory = new CacheDataSourceFactory(PeertubeActivity.this); + MediaItem mediaItem = new MediaItem.Builder().setUri(videoURL).build(); + if (subtitles != null) { + MediaItem.Subtitle mediaSubtitle = new MediaItem.Subtitle(subtitles, MimeTypes.TEXT_VTT, lang, Format.NO_VALUE); + subtitleSource = new SingleSampleMediaSource.Factory(cacheDataSourceFactory).createMediaSource(mediaSubtitle, C.TIME_UNSET); + } + if (videoURL != null && !videoURL.endsWith("m3u8")) { + videoSource = new ProgressiveMediaSource.Factory(cacheDataSourceFactory).createMediaSource(mediaItem); + } else { + hlsMediaSource = new HlsMediaSource.Factory(cacheDataSourceFactory) + .createMediaSource(mediaItem); + } + } + if (lang != null && subtitleSource != null && videoSource != null) { + MergingMediaSource mergedSource = + new MergingMediaSource(videoSource, subtitleSource); + player.setMediaSource(mergedSource); + } else if (lang != null && subtitleSource != null) { + MergingMediaSource mergedSource = + new MergingMediaSource(hlsMediaSource, subtitleSource); + player.setMediaSource(mergedSource); + } else if (videoSource != null) { + player.setMediaSource(videoSource); + } else { + player.setMediaSource(hlsMediaSource); } player.prepare(); if (position > 0) { @@ -1386,14 +1281,9 @@ public class PeertubeActivity extends BasePeertubeActivity implements CommentLis } } - private void startStream(VideoData.Video video, String torrentLocal, String resolution, boolean autoPlay, long position, Uri subtitles, String lang, boolean promptNSFW) { + private void startStream(VideoData.Video video, String resolution, boolean autoPlay, long position, Uri subtitles, String lang, boolean promptNSFW) { - String videoURL; - if (torrentLocal != null) { - videoURL = torrentLocal; - } else { - videoURL = peertube.getFileUrl(resolution, PeertubeActivity.this); - } + String videoURL = peertube.getFileUrl(resolution, PeertubeActivity.this); if (peertube != null && peertube.isLive() && videoURL == null) { View parentLayout = findViewById(android.R.id.content); Snackbar snackbar = Snackbar.make(parentLayout, R.string.live_not_started, Snackbar.LENGTH_INDEFINITE); @@ -1416,13 +1306,13 @@ public class PeertubeActivity extends BasePeertubeActivity implements CommentLis finish(); }); dialogBuilder.setPositiveButton(R.string.play, (dialog, id) -> { - stream(video, null, resolution, autoPlay, position, subtitles, lang); + stream(video, resolution, autoPlay, position, subtitles, lang); dialog.dismiss(); }); alertDialog = dialogBuilder.create(); alertDialog.show(); } else { - stream(video, torrentLocal, resolution, autoPlay, position, subtitles, lang); + stream(video, resolution, autoPlay, position, subtitles, lang); } @@ -1468,9 +1358,6 @@ public class PeertubeActivity extends BasePeertubeActivity implements CommentLis if (player != null) { player.release(); } - if (torrentStream != null && torrentStream.isStreaming()) { - torrentStream.stopStream(); - } unregisterReceiver(); } @@ -1805,7 +1692,6 @@ public class PeertubeActivity extends BasePeertubeActivity implements CommentLis startStream( peertube, - null, res, true, position, captionURI, captionLang, false); } @@ -1849,7 +1735,6 @@ public class PeertubeActivity extends BasePeertubeActivity implements CommentLis startStream( peertube, null, - null, true, newPosition, captionURI, diff --git a/app/src/main/java/app/fedilab/fedilabtube/fragment/SettingsFragment.java b/app/src/main/java/app/fedilab/fedilabtube/fragment/SettingsFragment.java index dcd4954..83ff092 100644 --- a/app/src/main/java/app/fedilab/fedilabtube/fragment/SettingsFragment.java +++ b/app/src/main/java/app/fedilab/fedilabtube/fragment/SettingsFragment.java @@ -348,15 +348,16 @@ public class SettingsFragment extends PreferenceFragmentCompat implements Shared ListPreference set_video_mode_choice = findPreference(getString(R.string.set_video_mode_choice)); List array = Arrays.asList(getResources().getStringArray(R.array.settings_video_mode)); CharSequence[] entries = array.toArray(new CharSequence[0]); - CharSequence[] entryValues = new CharSequence[4]; + CharSequence[] entryValues = new CharSequence[2]; int video_mode = sharedpref.getInt(Helper.SET_VIDEO_MODE, Helper.VIDEO_MODE_NORMAL); entryValues[0] = String.valueOf(Helper.VIDEO_MODE_NORMAL); - entryValues[1] = String.valueOf(Helper.VIDEO_MODE_MAGNET); - entryValues[2] = String.valueOf(Helper.VIDEO_MODE_WEBVIEW); - entryValues[3] = String.valueOf(Helper.VIDEO_MODE_TORRENT); + entryValues[1] = String.valueOf(Helper.VIDEO_MODE_WEBVIEW); if (set_video_mode_choice != null) { set_video_mode_choice.setEntries(entries); set_video_mode_choice.setEntryValues(entryValues); + if(video_mode > Helper.VIDEO_MODE_WEBVIEW) { + video_mode = Helper.VIDEO_MODE_NORMAL; + } set_video_mode_choice.setValueIndex(video_mode); } diff --git a/app/src/main/java/app/fedilab/fedilabtube/helper/Helper.java b/app/src/main/java/app/fedilab/fedilabtube/helper/Helper.java index 257fba3..74ec992 100644 --- a/app/src/main/java/app/fedilab/fedilabtube/helper/Helper.java +++ b/app/src/main/java/app/fedilab/fedilabtube/helper/Helper.java @@ -96,8 +96,8 @@ public class Helper { public static final String DISPLAY = "display"; public static final String TIMELINE_TYPE = "timeline_type"; public static final int VIDEO_MODE_NORMAL = 0; - public static final int VIDEO_MODE_MAGNET = 2; - public static final int VIDEO_MODE_TORRENT = 3; + public static final int VIDEO_MODE_MAGNET = 0; + public static final int VIDEO_MODE_TORRENT = 0; public static final int VIDEO_MODE_WEBVIEW = 1; public static final int QUALITY_HIGH = 0; public static final int QUALITY_MEDIUM = 1; diff --git a/app/src/main/res/values-ar/strings.xml b/app/src/main/res/values-ar/strings.xml index 6ba3aaf..cd59e3b 100644 --- a/app/src/main/res/values-ar/strings.xml +++ b/app/src/main/res/values-ar/strings.xml @@ -284,8 +284,6 @@ عادي Webview - Magnet - تورنت فاتحة diff --git a/app/src/main/res/values-de/strings.xml b/app/src/main/res/values-de/strings.xml index f63affb..a85332b 100644 --- a/app/src/main/res/values-de/strings.xml +++ b/app/src/main/res/values-de/strings.xml @@ -280,8 +280,6 @@ Normal WebView - Magnet - Torrent Hell diff --git a/app/src/main/res/values-el/strings.xml b/app/src/main/res/values-el/strings.xml index 708bcc8..3877161 100644 --- a/app/src/main/res/values-el/strings.xml +++ b/app/src/main/res/values-el/strings.xml @@ -279,8 +279,6 @@ Κανονική Webview - Magnet - Torrent Φωτεινό diff --git a/app/src/main/res/values-es/strings.xml b/app/src/main/res/values-es/strings.xml index e3859bb..4949cea 100644 --- a/app/src/main/res/values-es/strings.xml +++ b/app/src/main/res/values-es/strings.xml @@ -280,8 +280,6 @@ Normal Webview - Magnet - Torrent Claro diff --git a/app/src/main/res/values-fr/strings.xml b/app/src/main/res/values-fr/strings.xml index 85b24f1..ad48257 100644 --- a/app/src/main/res/values-fr/strings.xml +++ b/app/src/main/res/values-fr/strings.xml @@ -280,8 +280,6 @@ Normal Navigateur - Magnet - Torrent Clair diff --git a/app/src/main/res/values-it/strings.xml b/app/src/main/res/values-it/strings.xml index 39c3faa..d4dad00 100644 --- a/app/src/main/res/values-it/strings.xml +++ b/app/src/main/res/values-it/strings.xml @@ -280,8 +280,6 @@ Normale Webview - Magnet - Torrent Chiaro diff --git a/app/src/main/res/values-ja/strings.xml b/app/src/main/res/values-ja/strings.xml index 607f32d..5ed940e 100644 --- a/app/src/main/res/values-ja/strings.xml +++ b/app/src/main/res/values-ja/strings.xml @@ -279,8 +279,6 @@ 標準 WebView - Magnet - Torrent ライト diff --git a/app/src/main/res/values-ko/strings.xml b/app/src/main/res/values-ko/strings.xml index 9c90d66..db79033 100644 --- a/app/src/main/res/values-ko/strings.xml +++ b/app/src/main/res/values-ko/strings.xml @@ -279,8 +279,6 @@ 보통 Webview - Magnet - Torrent 밝음 diff --git a/app/src/main/res/values-nl/strings.xml b/app/src/main/res/values-nl/strings.xml index 7a57da6..884451e 100644 --- a/app/src/main/res/values-nl/strings.xml +++ b/app/src/main/res/values-nl/strings.xml @@ -280,8 +280,6 @@ Normaal Webview - Magneetlink - Torrent Licht diff --git a/app/src/main/res/values-pl/strings.xml b/app/src/main/res/values-pl/strings.xml index 96f7200..555c85d 100644 --- a/app/src/main/res/values-pl/strings.xml +++ b/app/src/main/res/values-pl/strings.xml @@ -282,8 +282,6 @@ Normalny Webview - Magnes - Torrent Jasny diff --git a/app/src/main/res/values-pt/strings.xml b/app/src/main/res/values-pt/strings.xml index 2a3cec9..cb3d5db 100644 --- a/app/src/main/res/values-pt/strings.xml +++ b/app/src/main/res/values-pt/strings.xml @@ -280,8 +280,6 @@ Normal Webview - Magnet - Torrent Diurno diff --git a/app/src/main/res/values-ro/strings.xml b/app/src/main/res/values-ro/strings.xml index f6df5c9..ad3eea5 100644 --- a/app/src/main/res/values-ro/strings.xml +++ b/app/src/main/res/values-ro/strings.xml @@ -281,8 +281,6 @@ Normal Webview - Magnet - Torrent Light diff --git a/app/src/main/res/values-ru/strings.xml b/app/src/main/res/values-ru/strings.xml index 74fd42d..1cfd72f 100644 --- a/app/src/main/res/values-ru/strings.xml +++ b/app/src/main/res/values-ru/strings.xml @@ -282,8 +282,6 @@ По умолчанию Веб-просмотр - Magnet-ссылка - Торрент Светлая diff --git a/app/src/main/res/values-sv/strings.xml b/app/src/main/res/values-sv/strings.xml index f08d413..686ee66 100644 --- a/app/src/main/res/values-sv/strings.xml +++ b/app/src/main/res/values-sv/strings.xml @@ -280,8 +280,6 @@ Nomal Webbvy - Magnet - Torrent Ljust diff --git a/app/src/main/res/values-zh-rCN/strings.xml b/app/src/main/res/values-zh-rCN/strings.xml index 5033ee6..24ae8e9 100644 --- a/app/src/main/res/values-zh-rCN/strings.xml +++ b/app/src/main/res/values-zh-rCN/strings.xml @@ -278,8 +278,6 @@ 标准 网页播放器 - Magnet - 种子 亮色 diff --git a/app/src/main/res/values-zh-rTW/strings.xml b/app/src/main/res/values-zh-rTW/strings.xml index 5cdcd53..00d5830 100644 --- a/app/src/main/res/values-zh-rTW/strings.xml +++ b/app/src/main/res/values-zh-rTW/strings.xml @@ -279,8 +279,6 @@ 正常 Torrent - Magnet - Torrent diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml index 99cae20..162a5f6 100644 --- a/app/src/main/res/values/strings.xml +++ b/app/src/main/res/values/strings.xml @@ -350,8 +350,6 @@ Normal Webview - Magnet - Torrent diff --git a/settings.gradle b/settings.gradle index 885f00f..0c49066 100644 --- a/settings.gradle +++ b/settings.gradle @@ -1,3 +1,2 @@ -include ':torrentStream' include ':app' rootProject.name = "Fedilab Tube" diff --git a/torrentStream/.gitignore b/torrentStream/.gitignore deleted file mode 100644 index 796b96d..0000000 --- a/torrentStream/.gitignore +++ /dev/null @@ -1 +0,0 @@ -/build diff --git a/torrentStream/build.gradle b/torrentStream/build.gradle deleted file mode 100644 index 7cecec5..0000000 --- a/torrentStream/build.gradle +++ /dev/null @@ -1,75 +0,0 @@ -/* - * Copyright (C) 2015-2018 Sébastiaan (github.com/se-bastiaan) - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -apply plugin: 'com.android.library' -apply plugin: 'com.github.dcendents.android-maven' -apply plugin: 'de.undercouch.download' - -group='com.github.TorrentStream' - - -android { - compileSdkVersion 30 - - defaultConfig { - minSdkVersion 15 - targetSdkVersion 30 - } - - buildTypes { - release { - minifyEnabled false - proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro' - } - } - - lintOptions { - abortOnError true - } -} - -ext { - libtorrentVersion = '1.2.11.0' -} - -// Custom task which downloads the appropriate version of JAR files for jlibtorrent -task downloadDependencies(type: Download) { - def baseUrl = "https://github.com/frostwire/frostwire-jlibtorrent" + - "/releases/download/release%2F$libtorrentVersion" - - def platforms = ['arm', 'arm64', 'x86', 'x86_64'] - def urls = platforms.collect { "$baseUrl/jlibtorrent-android-$it-${libtorrentVersion}.jar" } - urls.add("$baseUrl/jlibtorrent-${libtorrentVersion}.jar") - - src urls - dest 'libs' - overwrite false -} - -// Add our custom task as a dependency to the build -// You may need to run gradle sync for IDE warnings to disappear -preBuild.dependsOn(downloadDependencies) - -// Add deletion of libs folder to clean task -clean { - delete 'libs' -} - -dependencies { - api fileTree(dir: 'libs', include: ['*.jar']) - implementation fileTree(dir: "libs", include: ["*.jar"]) - implementation files('libs/jlibtorrent-1.2.11.0.jar') -} \ No newline at end of file diff --git a/torrentStream/proguard-rules.pro b/torrentStream/proguard-rules.pro deleted file mode 100644 index 43926b7..0000000 --- a/torrentStream/proguard-rules.pro +++ /dev/null @@ -1,17 +0,0 @@ -# Add project specific ProGuard rules here. -# By default, the flags in this file are appended to flags specified -# in /Users/Sebastiaan/Development/Android/SDK/tools/proguard/proguard-android.txt -# You can edit the include path and order by changing the proguardFiles -# directive in build.gradle. -# -# For more details, see -# http://developer.android.com/guide/developing/tools/proguard.html - -# Add any project specific keep options here: - -# If your project uses WebView with JS, uncomment the following -# and specify the fully qualified class name to the JavaScript interface -# class: -#-keepclassmembers class fqcn.of.javascript.interface.for.webview { -# public *; -#} diff --git a/torrentStream/src/main/AndroidManifest.xml b/torrentStream/src/main/AndroidManifest.xml deleted file mode 100644 index 72d1c51..0000000 --- a/torrentStream/src/main/AndroidManifest.xml +++ /dev/null @@ -1,3 +0,0 @@ - - - diff --git a/torrentStream/src/main/java/com/github/se_bastiaan/torrentstream/StreamStatus.java b/torrentStream/src/main/java/com/github/se_bastiaan/torrentstream/StreamStatus.java deleted file mode 100644 index f9d6760..0000000 --- a/torrentStream/src/main/java/com/github/se_bastiaan/torrentstream/StreamStatus.java +++ /dev/null @@ -1,33 +0,0 @@ -/* - * Copyright (C) 2015-2018 Sébastiaan (github.com/se-bastiaan) - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.github.se_bastiaan.torrentstream; - -public class StreamStatus { - public final float progress; - public final int bufferProgress; - public final int seeds; - public final int peers; - public final int downloadSpeed; - - StreamStatus(float progress, int bufferProgress, int seeds, int peers, int downloadSpeed) { - this.progress = progress; - this.bufferProgress = bufferProgress; - this.seeds = seeds; - this.peers = peers; - this.downloadSpeed = downloadSpeed; - } -} diff --git a/torrentStream/src/main/java/com/github/se_bastiaan/torrentstream/Torrent.java b/torrentStream/src/main/java/com/github/se_bastiaan/torrentstream/Torrent.java deleted file mode 100644 index eec5529..0000000 --- a/torrentStream/src/main/java/com/github/se_bastiaan/torrentstream/Torrent.java +++ /dev/null @@ -1,530 +0,0 @@ -/* - * Copyright (C) 2015-2018 Sébastiaan (github.com/se-bastiaan) - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.github.se_bastiaan.torrentstream; - -import android.util.Log; - -import com.frostwire.jlibtorrent.AlertListener; -import com.frostwire.jlibtorrent.FileStorage; -import com.frostwire.jlibtorrent.Priority; -import com.frostwire.jlibtorrent.TorrentFlags; -import com.frostwire.jlibtorrent.TorrentHandle; -import com.frostwire.jlibtorrent.TorrentInfo; -import com.frostwire.jlibtorrent.TorrentStatus; -import com.frostwire.jlibtorrent.alerts.Alert; -import com.frostwire.jlibtorrent.alerts.AlertType; -import com.frostwire.jlibtorrent.alerts.BlockFinishedAlert; -import com.frostwire.jlibtorrent.alerts.PieceFinishedAlert; -import com.github.se_bastiaan.torrentstream.listeners.TorrentListener; - -import java.io.File; -import java.io.FileInputStream; -import java.io.FileNotFoundException; -import java.io.InputStream; -import java.lang.ref.WeakReference; -import java.util.ArrayList; -import java.util.Arrays; -import java.util.Iterator; -import java.util.List; - -public class Torrent implements AlertListener { - - private final static Integer MAX_PREPARE_COUNT = 20; - private final static Integer MIN_PREPARE_COUNT = 2; - private final static Integer DEFAULT_PREPARE_COUNT = 5; - private final static Integer SEQUENTIAL_CONCURRENT_PIECES_COUNT = 5; - private final List> torrentStreamReferences; - private final TorrentHandle torrentHandle; - private final TorrentListener listener; - private final Long prepareSize; - private Integer piecesToPrepare; - private Integer lastPieceIndex; - private Integer firstPieceIndex; - private Integer selectedFileIndex = -1; - private Integer interestedPieceIndex = 0; - private Double prepareProgress = 0d; - private Double progressStep = 0d; - private List preparePieces; - private Boolean[] hasPieces; - private State state = State.RETRIEVING_META; - - /** - * The constructor for a new Torrent - *

- * First the largest file in the download is selected as the file for playback - *

- * After setting this priority, the first and last index of the pieces that make up this file are determined. - * And last: amount of pieces that are needed for playback are calculated (needed for playback means: make up 10 megabyte of the file) - * - * @param torrentHandle jlibtorrent TorrentHandle - */ - public Torrent(TorrentHandle torrentHandle, TorrentListener listener, Long prepareSize) { - this.torrentHandle = torrentHandle; - this.listener = listener; - - this.prepareSize = prepareSize; - - torrentStreamReferences = new ArrayList<>(); - - if (selectedFileIndex == -1) { - setLargestFile(); - } - - if (this.listener != null) { - this.listener.onStreamPrepared(this); - } - } - - /** - * Reset piece priorities of selected file to normal - */ - private void resetPriorities() { - Priority[] priorities = torrentHandle.piecePriorities(); - for (int i = 0; i < priorities.length; i++) { - if (i >= firstPieceIndex && i <= lastPieceIndex) { - torrentHandle.piecePriority(i, Priority.NORMAL); - } else { - torrentHandle.piecePriority(i, Priority.IGNORE); - } - } - } - - /** - * Get LibTorrent torrent handle of this torrent - * - * @return {@link TorrentHandle} - */ - public TorrentHandle getTorrentHandle() { - return torrentHandle; - } - - public File getVideoFile() { - - return new File(torrentHandle.savePath() + "/" + torrentHandle.torrentFile().files().filePath(selectedFileIndex)); - } - - /** - * Get an InputStream for the video file. - * Read is be blocked until the requested piece(s) is downloaded. - * - * @return {@link InputStream} - */ - public InputStream getVideoStream() throws FileNotFoundException { - File file = getVideoFile(); - TorrentInputStream inputStream = new TorrentInputStream(this, new FileInputStream(file)); - torrentStreamReferences.add(new WeakReference<>(inputStream)); - - return inputStream; - } - - /** - * Get the location of the file that is being downloaded - * - * @return {@link File} The file location - */ - public File getSaveLocation() { - return new File(torrentHandle.savePath() + "/" + torrentHandle.name()); - } - - /** - * Resume the torrent download - */ - public void resume() { - torrentHandle.resume(); - } - - /** - * Pause the torrent download - */ - public void pause() { - torrentHandle.pause(); - } - - /** - * Set the selected file index to the largest file in the torrent - */ - public void setLargestFile() { - setSelectedFileIndex(-1); - } - - /** - * Set the index of the file that should be downloaded - * If the given index is -1, then the largest file is chosen - * - * @param selectedFileIndex {@link Integer} Index of the file - */ - public void setSelectedFileIndex(Integer selectedFileIndex) { - TorrentInfo torrentInfo = torrentHandle.torrentFile(); - FileStorage fileStorage = torrentInfo.files(); - - if (selectedFileIndex == -1) { - long highestFileSize = 0; - int selectedFile = -1; - for (int i = 0; i < fileStorage.numFiles(); i++) { - long fileSize = fileStorage.fileSize(i); - if (highestFileSize < fileSize) { - highestFileSize = fileSize; - torrentHandle.filePriority(selectedFile, Priority.IGNORE); - selectedFile = i; - torrentHandle.filePriority(i, Priority.NORMAL); - } else { - torrentHandle.filePriority(i, Priority.IGNORE); - } - } - selectedFileIndex = selectedFile; - } else { - for (int i = 0; i < fileStorage.numFiles(); i++) { - if (i == selectedFileIndex) { - torrentHandle.filePriority(i, Priority.NORMAL); - } else { - torrentHandle.filePriority(i, Priority.IGNORE); - } - } - } - this.selectedFileIndex = selectedFileIndex; - - Priority[] piecePriorities = torrentHandle.piecePriorities(); - int firstPieceIndexLocal = -1; - int lastPieceIndexLocal = -1; - for (int i = 0; i < piecePriorities.length; i++) { - if (piecePriorities[i] != Priority.IGNORE) { - if (firstPieceIndexLocal == -1) { - firstPieceIndexLocal = i; - } - piecePriorities[i] = Priority.IGNORE; - } else { - if (firstPieceIndexLocal != -1 && lastPieceIndexLocal == -1) { - lastPieceIndexLocal = i - 1; - } - } - } - - if (lastPieceIndexLocal == -1) { - lastPieceIndexLocal = piecePriorities.length - 1; - } - int pieceCount = lastPieceIndexLocal - firstPieceIndexLocal + 1; - int pieceLength = torrentHandle.torrentFile().pieceLength(); - int activePieceCount; - if (pieceLength > 0) { - activePieceCount = (int) (prepareSize / pieceLength); - if (activePieceCount < MIN_PREPARE_COUNT) { - activePieceCount = MIN_PREPARE_COUNT; - } else if (activePieceCount > MAX_PREPARE_COUNT) { - activePieceCount = MAX_PREPARE_COUNT; - } - } else { - activePieceCount = DEFAULT_PREPARE_COUNT; - } - - if (pieceCount < activePieceCount) { - activePieceCount = pieceCount / 2; - } - - this.firstPieceIndex = firstPieceIndexLocal; - this.interestedPieceIndex = this.firstPieceIndex; - this.lastPieceIndex = lastPieceIndexLocal; - piecesToPrepare = activePieceCount; - } - - /** - * Get the filenames of the files in the torrent - * - * @return {@link String[]} - */ - public String[] getFileNames() { - FileStorage fileStorage = torrentHandle.torrentFile().files(); - String[] fileNames = new String[fileStorage.numFiles()]; - for (int i = 0; i < fileStorage.numFiles(); i++) { - fileNames[i] = fileStorage.fileName(i); - } - return fileNames; - } - - /** - * Prepare torrent for playback. Prioritize the first {@code piecesToPrepare} pieces and the last {@code piecesToPrepare} pieces - * from {@code firstPieceIndex} and {@code lastPieceIndex}. Ignore all other pieces. - */ - public void startDownload() { - Log.v("TubeLab","startDownload: " + state); - if (state == State.STREAMING || state == State.STARTING) return; - state = State.STARTING; - - List indices = new ArrayList<>(); - - Priority[] priorities = torrentHandle.piecePriorities(); - for (int i = 0; i < priorities.length; i++) { - if (priorities[i] != Priority.IGNORE) { - torrentHandle.piecePriority(i, Priority.NORMAL); - } - } - - for (int i = 0; i < piecesToPrepare; i++) { - indices.add(lastPieceIndex - i); - torrentHandle.piecePriority(lastPieceIndex - i, Priority.SEVEN); - torrentHandle.setPieceDeadline(lastPieceIndex - i, 1000); - } - - for (int i = 0; i < piecesToPrepare; i++) { - indices.add(firstPieceIndex + i); - torrentHandle.piecePriority(firstPieceIndex + i, Priority.SEVEN); - torrentHandle.setPieceDeadline(firstPieceIndex + i, 1000); - } - - preparePieces = indices; - - hasPieces = new Boolean[lastPieceIndex - firstPieceIndex + 1]; - Arrays.fill(hasPieces, false); - - TorrentInfo torrentInfo = torrentHandle.torrentFile(); - TorrentStatus status = torrentHandle.status(); - - double blockCount = indices.size() * torrentInfo.pieceLength() / status.blockSize(); - - progressStep = 100 / blockCount; - - torrentStreamReferences.clear(); - - torrentHandle.resume(); - Log.v("TubeLab","onStreamStarted: " ); - listener.onStreamStarted(this); - } - - /** - * Check if the piece that contains the specified bytes were downloaded already - * - * @param bytes The bytes you're interested in - * @return {@code true} if downloaded, {@code false} if not - */ - public boolean hasBytes(long bytes) { - if (hasPieces == null) { - return false; - } - - int pieceIndex = (int) (bytes / torrentHandle.torrentFile().pieceLength()); - return hasPieces[pieceIndex]; - } - - /** - * Set the bytes of the selected file that you're interested in - * The piece of that specific offset is selected and that piece plus the 1 preceding and the 3 after it. - * These pieces will then be prioritised, which results in continuing the sequential download after that piece - * - * @param bytes The bytes you're interested in - */ - public void setInterestedBytes(long bytes) { - if (hasPieces == null && bytes >= 0) { - return; - } - - int pieceIndex = (int) (bytes / torrentHandle.torrentFile().pieceLength()); - interestedPieceIndex = pieceIndex; - if (!hasPieces[pieceIndex] && torrentHandle.piecePriority(pieceIndex + firstPieceIndex) != Priority.SEVEN) { - interestedPieceIndex = pieceIndex; - int pieces = 5; - for (int i = pieceIndex; i < hasPieces.length; i++) { - // Set full priority to first found piece that is not confirmed finished - if (!hasPieces[i]) { - torrentHandle.piecePriority(i + firstPieceIndex, Priority.SEVEN); - torrentHandle.setPieceDeadline(i + firstPieceIndex, 1000); - pieces--; - if (pieces == 0) { - break; - } - } - } - } - } - - /** - * Checks if the interesting pieces are downloaded already - * - * @return {@code true} if the 5 pieces that were selected using `setInterestedBytes` are all reported complete including the `nextPieces`, {@code false} if not - */ - public boolean hasInterestedBytes(int nextPieces) { - for (int i = 0; i < 5 + nextPieces; i++) { - int index = interestedPieceIndex + i; - if (hasPieces.length <= index || index < 0) { - continue; - } - - if (!hasPieces[interestedPieceIndex + i]) { - return false; - } - } - return true; - } - - /** - * Checks if the interesting pieces are downloaded already - * - * @return {@code true} if the 5 pieces that were selected using `setInterestedBytes` are all reported complete, {@code false} if not - */ - public boolean hasInterestedBytes() { - return hasInterestedBytes(5); - } - - /** - * Get the index of the piece we're currently interested in - * - * @return Interested piece index - */ - public int getInterestedPieceIndex() { - return interestedPieceIndex; - } - - /** - * Get amount of pieces to prepare - * - * @return Amount of pieces to prepare - */ - public Integer getPiecesToPrepare() { - return piecesToPrepare; - } - - /** - * Start sequential mode downloading - */ - private void startSequentialMode() { - resetPriorities(); - - if (hasPieces == null) { - torrentHandle.setFlags(torrentHandle.flags().and_(TorrentFlags.SEQUENTIAL_DOWNLOAD)); - } else { - for (int i = firstPieceIndex + piecesToPrepare; i < firstPieceIndex + piecesToPrepare + SEQUENTIAL_CONCURRENT_PIECES_COUNT; i++) { - torrentHandle.piecePriority(i, Priority.SEVEN); - torrentHandle.setPieceDeadline(i, 1000); - } - } - } - - /** - * Get current torrent state - * - * @return {@link State} - */ - public State getState() { - return state; - } - - /** - * Piece finished - * - * @param alert - */ - private void pieceFinished(PieceFinishedAlert alert) { - if (state == State.STREAMING && hasPieces != null) { - int pieceIndex = alert.pieceIndex() - firstPieceIndex; - hasPieces[pieceIndex] = true; - - if (pieceIndex >= interestedPieceIndex) { - for (int i = pieceIndex; i < hasPieces.length; i++) { - // Set full priority to first found piece that is not confirmed finished - if (!hasPieces[i]) { - torrentHandle.piecePriority(i + firstPieceIndex, Priority.SEVEN); - torrentHandle.setPieceDeadline(i + firstPieceIndex, 1000); - break; - } - } - } - } else { - Iterator piecesIterator = preparePieces.iterator(); - while (piecesIterator.hasNext()) { - int index = piecesIterator.next(); - if (index == alert.pieceIndex()) { - piecesIterator.remove(); - } - } - - if (hasPieces != null) { - hasPieces[alert.pieceIndex() - firstPieceIndex] = true; - } - - if (preparePieces.size() == 0) { - startSequentialMode(); - - prepareProgress = 100d; - sendStreamProgress(); - state = State.STREAMING; - - if (listener != null) { - listener.onStreamReady(this); - } - } - } - } - - private void blockFinished(BlockFinishedAlert alert) { - for (Integer index : preparePieces) { - if (index == alert.pieceIndex()) { - prepareProgress += progressStep; - break; - } - } - - sendStreamProgress(); - } - - private void sendStreamProgress() { - TorrentStatus status = torrentHandle.status(); - float progress = status.progress() * 100; - int seeds = status.numSeeds(); - int peers = status.numPeers(); - int downloadSpeed = status.downloadPayloadRate(); - - if (listener != null && prepareProgress >= 1) { - listener.onStreamProgress(this, new StreamStatus(progress, prepareProgress.intValue(), seeds, peers, downloadSpeed)); - } - } - - @Override - public int[] types() { - return new int[]{ - AlertType.PIECE_FINISHED.swig(), - AlertType.BLOCK_FINISHED.swig() - }; - } - - @Override - public void alert(Alert alert) { - switch (alert.type()) { - case PIECE_FINISHED: - pieceFinished((PieceFinishedAlert) alert); - break; - case BLOCK_FINISHED: - blockFinished((BlockFinishedAlert) alert); - break; - default: - break; - } - - Iterator> i = torrentStreamReferences.iterator(); - - while (i.hasNext()) { - WeakReference reference = i.next(); - TorrentInputStream inputStream = reference.get(); - - if (inputStream == null) { - i.remove(); - continue; - } - - inputStream.alert(alert); - } - } - - public enum State {UNKNOWN, RETRIEVING_META, STARTING, STREAMING} -} diff --git a/torrentStream/src/main/java/com/github/se_bastiaan/torrentstream/TorrentInputStream.java b/torrentStream/src/main/java/com/github/se_bastiaan/torrentstream/TorrentInputStream.java deleted file mode 100644 index 6ce04ed..0000000 --- a/torrentStream/src/main/java/com/github/se_bastiaan/torrentstream/TorrentInputStream.java +++ /dev/null @@ -1,116 +0,0 @@ -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; - } - } -} \ No newline at end of file diff --git a/torrentStream/src/main/java/com/github/se_bastiaan/torrentstream/TorrentOptions.java b/torrentStream/src/main/java/com/github/se_bastiaan/torrentstream/TorrentOptions.java deleted file mode 100644 index adf9c16..0000000 --- a/torrentStream/src/main/java/com/github/se_bastiaan/torrentstream/TorrentOptions.java +++ /dev/null @@ -1,151 +0,0 @@ -/* - * Copyright (C) 2015-2018 Sébastiaan (github.com/se-bastiaan) - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.github.se_bastiaan.torrentstream; - -import java.io.File; - -public final class TorrentOptions { - - String saveLocation = "/"; - String proxyHost; - String proxyUsername; - String proxyPassword; - String peerFingerprint; - Integer maxDownloadSpeed = 0; - Integer maxUploadSpeed = 0; - Integer maxConnections = 200; - Integer maxDht = 88; - Integer listeningPort = -1; - Boolean removeFiles = false; - Boolean anonymousMode = false; - Boolean autoDownload = true; - Long prepareSize = 15 * 1024L * 1024L; - - private TorrentOptions() { - // Unused - } - - private TorrentOptions(TorrentOptions torrentOptions) { - this.saveLocation = torrentOptions.saveLocation; - this.proxyHost = torrentOptions.proxyHost; - this.proxyUsername = torrentOptions.proxyUsername; - this.proxyPassword = torrentOptions.proxyPassword; - this.peerFingerprint = torrentOptions.peerFingerprint; - this.maxDownloadSpeed = torrentOptions.maxDownloadSpeed; - this.maxUploadSpeed = torrentOptions.maxUploadSpeed; - this.maxConnections = torrentOptions.maxConnections; - this.maxDht = torrentOptions.maxDht; - this.listeningPort = torrentOptions.listeningPort; - this.removeFiles = torrentOptions.removeFiles; - this.anonymousMode = torrentOptions.anonymousMode; - this.autoDownload = torrentOptions.autoDownload; - this.prepareSize = torrentOptions.prepareSize; - } - - public Builder toBuilder() { - return new Builder(this); - } - - public static class Builder { - - private TorrentOptions torrentOptions; - - public Builder() { - torrentOptions = new TorrentOptions(); - } - - private Builder(TorrentOptions torrentOptions) { - torrentOptions = new TorrentOptions(torrentOptions); - } - - public Builder saveLocation(String saveLocation) { - torrentOptions.saveLocation = saveLocation; - return this; - } - - public Builder saveLocation(File saveLocation) { - torrentOptions.saveLocation = saveLocation.getAbsolutePath(); - return this; - } - - public Builder maxUploadSpeed(Integer maxUploadSpeed) { - torrentOptions.maxUploadSpeed = maxUploadSpeed; - return this; - } - - public Builder maxDownloadSpeed(Integer maxDownloadSpeed) { - torrentOptions.maxDownloadSpeed = maxDownloadSpeed; - return this; - } - - public Builder maxConnections(Integer maxConnections) { - torrentOptions.maxConnections = maxConnections; - return this; - } - - public Builder maxActiveDHT(Integer maxActiveDHT) { - torrentOptions.maxDht = maxActiveDHT; - return this; - } - - public Builder removeFilesAfterStop(Boolean b) { - torrentOptions.removeFiles = b; - return this; - } - - public Builder prepareSize(Long prepareSize) { - torrentOptions.prepareSize = prepareSize; - return this; - } - - public Builder listeningPort(Integer port) { - torrentOptions.listeningPort = port; - return this; - } - - public Builder proxy(String host, String username, String password) { - torrentOptions.proxyHost = host; - torrentOptions.proxyUsername = username; - torrentOptions.proxyPassword = password; - return this; - } - - public Builder peerFingerprint(String peerId) { - torrentOptions.peerFingerprint = peerId; - torrentOptions.anonymousMode = false; - return this; - } - - public Builder anonymousMode(Boolean enable) { - torrentOptions.anonymousMode = enable; - if (torrentOptions.anonymousMode) - torrentOptions.peerFingerprint = null; - return this; - } - - public Builder autoDownload(Boolean enable) { - torrentOptions.autoDownload = enable; - return this; - } - - public TorrentOptions build() { - return torrentOptions; - } - - } - -} diff --git a/torrentStream/src/main/java/com/github/se_bastiaan/torrentstream/TorrentStream.java b/torrentStream/src/main/java/com/github/se_bastiaan/torrentstream/TorrentStream.java deleted file mode 100644 index 03bbef5..0000000 --- a/torrentStream/src/main/java/com/github/se_bastiaan/torrentstream/TorrentStream.java +++ /dev/null @@ -1,542 +0,0 @@ -/* - * Copyright (C) 2015-2018 Sébastiaan (github.com/se-bastiaan) - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.github.se_bastiaan.torrentstream; - -import android.net.Uri; -import android.os.Handler; -import android.os.HandlerThread; - -import com.frostwire.jlibtorrent.Priority; -import com.frostwire.jlibtorrent.SessionManager; -import com.frostwire.jlibtorrent.SessionParams; -import com.frostwire.jlibtorrent.SettingsPack; -import com.frostwire.jlibtorrent.TorrentHandle; -import com.frostwire.jlibtorrent.TorrentInfo; -import com.frostwire.jlibtorrent.alerts.AddTorrentAlert; -import com.frostwire.jlibtorrent.swig.settings_pack; -import com.github.se_bastiaan.torrentstream.exceptions.DirectoryModifyException; -import com.github.se_bastiaan.torrentstream.exceptions.NotInitializedException; -import com.github.se_bastiaan.torrentstream.exceptions.TorrentInfoException; -import com.github.se_bastiaan.torrentstream.listeners.DHTStatsAlertListener; -import com.github.se_bastiaan.torrentstream.listeners.TorrentAddedAlertListener; -import com.github.se_bastiaan.torrentstream.listeners.TorrentListener; -import com.github.se_bastiaan.torrentstream.utils.FileUtils; -import com.github.se_bastiaan.torrentstream.utils.ThreadUtils; - -import java.io.ByteArrayOutputStream; -import java.io.File; -import java.io.FileInputStream; -import java.io.IOException; -import java.io.InputStream; -import java.net.HttpURLConnection; -import java.net.URL; -import java.util.ArrayList; -import java.util.List; -import java.util.Locale; -import java.util.concurrent.CountDownLatch; - -public final class TorrentStream { - - private static final String LIBTORRENT_THREAD_NAME = "TORRENTSTREAM_LIBTORRENT", STREAMING_THREAD_NAME = "TORRENTSTREAMER_STREAMING"; - private static TorrentStream sThis; - private final List listeners = new ArrayList<>(); - private CountDownLatch initialisingLatch; - private SessionManager torrentSession; - private Boolean initialising = false, initialised = false, isStreaming = false, isCanceled = false; - private TorrentOptions torrentOptions; - private Torrent currentTorrent; - private final TorrentAddedAlertListener torrentAddedAlertListener = new TorrentAddedAlertListener() { - @Override - public void torrentAdded(AddTorrentAlert alert) { - InternalTorrentListener listener = new InternalTorrentListener(); - TorrentHandle th = torrentSession.find(alert.handle().infoHash()); - currentTorrent = new Torrent(th, listener, torrentOptions.prepareSize); - - torrentSession.addListener(currentTorrent); - } - }; - private String currentTorrentUrl; - private Integer dhtNodes = 0; - private final DHTStatsAlertListener dhtStatsAlertListener = new DHTStatsAlertListener() { - @Override - public void stats(int totalDhtNodes) { - dhtNodes = totalDhtNodes; - } - }; - private HandlerThread libTorrentThread, streamingThread; - private Handler libTorrentHandler, streamingHandler; - - private TorrentStream(TorrentOptions options) { - torrentOptions = options; - initialise(); - } - - public static TorrentStream init(TorrentOptions options) { - sThis = new TorrentStream(options); - return sThis; - } - - public static TorrentStream getInstance() throws NotInitializedException { - if (sThis == null) - throw new NotInitializedException(); - - return sThis; - } - - /** - * Obtain internal session manager - * - * @return {@link SessionManager} - */ - public SessionManager getSessionManager() { - return torrentSession; - } - - private void initialise() { - if (libTorrentThread != null && torrentSession != null) { - resumeSession(); - } else { - if ((initialising || initialised) && libTorrentThread != null) { - libTorrentThread.interrupt(); - } - - initialising = true; - initialised = false; - initialisingLatch = new CountDownLatch(1); - - libTorrentThread = new HandlerThread(LIBTORRENT_THREAD_NAME); - libTorrentThread.start(); - libTorrentHandler = new Handler(libTorrentThread.getLooper()); - libTorrentHandler.post(new Runnable() { - @Override - public void run() { - torrentSession = new SessionManager(); - setOptions(torrentOptions); - - torrentSession.addListener(dhtStatsAlertListener); - torrentSession.startDht(); - - initialising = false; - initialised = true; - initialisingLatch.countDown(); - } - }); - } - } - - /** - * Resume TorrentSession - */ - public void resumeSession() { - if (libTorrentThread != null && torrentSession != null) { - libTorrentHandler.removeCallbacksAndMessages(null); - - //resume torrent session if needed - if (torrentSession.isPaused()) { - libTorrentHandler.post(new Runnable() { - @Override - public void run() { - torrentSession.resume(); - } - }); - } - - if (!torrentSession.isDhtRunning()) { - libTorrentHandler.post(new Runnable() { - @Override - public void run() { - torrentSession.startDht(); - } - }); - } - } - } - - /** - * Pause TorrentSession - */ - public void pauseSession() { - if (!isStreaming) - libTorrentHandler.post(new Runnable() { - @Override - public void run() { - torrentSession.pause(); - } - }); - } - - /** - * Get torrent metadata, either by downloading the .torrent or fetching the magnet - * - * @param torrentUrl {@link String} URL to .torrent or magnet link - * @return {@link TorrentInfo} - */ - private TorrentInfo getTorrentInfo(String torrentUrl) throws TorrentInfoException { - if (torrentUrl.startsWith("magnet")) { - byte[] data = torrentSession.fetchMagnet(torrentUrl, 30); - if (data != null) - try { - return TorrentInfo.bdecode(data); - } catch (IllegalArgumentException e) { - throw new TorrentInfoException(e); - } - - } else if (torrentUrl.startsWith("http") || torrentUrl.startsWith("https")) { - try { - URL url = new URL(torrentUrl); - HttpURLConnection connection = (HttpURLConnection) url.openConnection(); - - connection.setRequestMethod("GET"); - connection.setInstanceFollowRedirects(true); - connection.connect(); - - InputStream inputStream = connection.getInputStream(); - - byte[] responseByteArray = new byte[0]; - - if (connection.getResponseCode() == 200) { - responseByteArray = getBytesFromInputStream(inputStream); - } - - inputStream.close(); - connection.disconnect(); - - if (responseByteArray.length > 0) { - return TorrentInfo.bdecode(responseByteArray); - } - } catch (IOException | IllegalArgumentException e) { - throw new TorrentInfoException(e); - } - } else if (torrentUrl.startsWith("file")) { - Uri path = Uri.parse(torrentUrl); - File file = new File(path.getPath()); - - try { - FileInputStream fileInputStream = new FileInputStream(file); - byte[] responseByteArray = getBytesFromInputStream(fileInputStream); - fileInputStream.close(); - - if (responseByteArray.length > 0) { - return TorrentInfo.bdecode(responseByteArray); - } - } catch (IOException | IllegalArgumentException e) { - throw new TorrentInfoException(e); - } - } - - return null; - } - - private byte[] getBytesFromInputStream(InputStream inputStream) throws IOException { - ByteArrayOutputStream byteBuffer = new ByteArrayOutputStream(); - - int bufferSize = 1024; - byte[] buffer = new byte[bufferSize]; - - int len = 0; - while ((len = inputStream.read(buffer)) != -1) { - byteBuffer.write(buffer, 0, len); - } - - return byteBuffer.toByteArray(); - } - - /** - * Start stream download for specified torrent - * - * @param torrentUrl {@link String} .torrent or magnet link - */ - public void startStream(final String torrentUrl) { - if (!initialising && !initialised) - initialise(); - - if (libTorrentHandler == null || isStreaming) return; - - isCanceled = false; - - streamingThread = new HandlerThread(STREAMING_THREAD_NAME); - streamingThread.start(); - streamingHandler = new Handler(streamingThread.getLooper()); - - streamingHandler.post(new Runnable() { - @Override - public void run() { - isStreaming = true; - - if (initialisingLatch != null) { - try { - initialisingLatch.await(); - initialisingLatch = null; - } catch (InterruptedException e) { - isStreaming = false; - return; - } - } - - currentTorrentUrl = torrentUrl; - - File saveDirectory = new File(torrentOptions.saveLocation); - if (!saveDirectory.isDirectory() && !saveDirectory.mkdirs()) { - for (final TorrentListener listener : listeners) { - ThreadUtils.runOnUiThread(new Runnable() { - @Override - public void run() { - listener.onStreamError(null, new DirectoryModifyException()); - } - }); - } - isStreaming = false; - return; - } - - torrentSession.removeListener(torrentAddedAlertListener); - TorrentInfo torrentInfo = null; - try { - torrentInfo = getTorrentInfo(torrentUrl); - } catch (final TorrentInfoException e) { - for (final TorrentListener listener : listeners) { - ThreadUtils.runOnUiThread(new Runnable() { - @Override - public void run() { - listener.onStreamError(null, e); - } - }); - } - } - torrentSession.addListener(torrentAddedAlertListener); - - if (torrentInfo == null) { - for (final TorrentListener listener : listeners) { - ThreadUtils.runOnUiThread(new Runnable() { - @Override - public void run() { - listener.onStreamError(null, new TorrentInfoException(null)); - } - }); - } - isStreaming = false; - return; - } - - Priority[] priorities = new Priority[torrentInfo.numFiles()]; - for (int i = 0; i < priorities.length; i++) { - priorities[i] = Priority.IGNORE; - } - - if (!currentTorrentUrl.equals(torrentUrl) || isCanceled) { - return; - } - - torrentSession.download(torrentInfo, saveDirectory, null, priorities, null); - } - }); - } - - /** - * Stop current torrent stream - */ - public void stopStream() { - //remove all callbacks from handler - if (libTorrentHandler != null) - libTorrentHandler.removeCallbacksAndMessages(null); - if (streamingHandler != null) - streamingHandler.removeCallbacksAndMessages(null); - - isCanceled = true; - isStreaming = false; - if (currentTorrent != null) { - final File saveLocation = currentTorrent.getSaveLocation(); - - currentTorrent.pause(); - torrentSession.removeListener(currentTorrent); - torrentSession.remove(currentTorrent.getTorrentHandle()); - currentTorrent = null; - - if (torrentOptions.removeFiles) { - new Thread(new Runnable() { - @Override - public void run() { - int tries = 0; - while (!FileUtils.recursiveDelete(saveLocation) && tries < 5) { - tries++; - try { - Thread.sleep(1000); // If deleted failed then something is still using the file, wait and then retry - } catch (InterruptedException e) { - for (final TorrentListener listener : listeners) { - ThreadUtils.runOnUiThread(new Runnable() { - @Override - public void run() { - listener.onStreamError(currentTorrent, new DirectoryModifyException()); - } - }); - } - } - } - } - }).start(); - } - } - - if (streamingThread != null) - streamingThread.interrupt(); - - for (final TorrentListener listener : listeners) { - ThreadUtils.runOnUiThread(new Runnable() { - @Override - public void run() { - listener.onStreamStopped(); - } - }); - } - } - - public TorrentOptions getOptions() { - return torrentOptions; - } - - public void setOptions(TorrentOptions options) { - torrentOptions = options; - - SettingsPack settingsPack = new SettingsPack() - .anonymousMode(torrentOptions.anonymousMode) - .connectionsLimit(torrentOptions.maxConnections) - .downloadRateLimit(torrentOptions.maxDownloadSpeed) - .uploadRateLimit(torrentOptions.maxUploadSpeed) - .activeDhtLimit(torrentOptions.maxDht); - - if (torrentOptions.listeningPort != -1) { - String ifStr = String.format(Locale.ENGLISH, "%s:%d", "0.0.0.0", torrentOptions.listeningPort); - settingsPack.setString(settings_pack.string_types.listen_interfaces.swigValue(), ifStr); - } - - if (torrentOptions.proxyHost != null) { - settingsPack.setString(settings_pack.string_types.proxy_hostname.swigValue(), torrentOptions.proxyHost); - if (torrentOptions.proxyUsername != null) { - settingsPack.setString(settings_pack.string_types.proxy_username.swigValue(), torrentOptions.proxyUsername); - if (torrentOptions.proxyPassword != null) { - settingsPack.setString(settings_pack.string_types.proxy_password.swigValue(), torrentOptions.proxyPassword); - } - } - } - - if (torrentOptions.peerFingerprint != null) { - settingsPack.setString(settings_pack.string_types.peer_fingerprint.swigValue(), torrentOptions.peerFingerprint); - } - - if (!torrentSession.isRunning()) { - SessionParams sessionParams = new SessionParams(settingsPack); - torrentSession.start(sessionParams); - } else { - torrentSession.applySettings(settingsPack); - } - } - - public boolean isStreaming() { - return isStreaming; - } - - public String getCurrentTorrentUrl() { - return currentTorrentUrl; - } - - public Integer getTotalDhtNodes() { - return dhtNodes; - } - - public Torrent getCurrentTorrent() { - return currentTorrent; - } - - public void addListener(TorrentListener listener) { - if (listener != null) - listeners.add(listener); - } - - public void removeListener(TorrentListener listener) { - if (listener != null) - listeners.remove(listener); - } - - protected class InternalTorrentListener implements TorrentListener { - - public void onStreamStarted(final Torrent torrent) { - for (final TorrentListener listener : listeners) { - ThreadUtils.runOnUiThread(new Runnable() { - @Override - public void run() { - listener.onStreamStarted(torrent); - } - }); - } - } - - public void onStreamError(final Torrent torrent, final Exception e) { - for (final TorrentListener listener : listeners) { - ThreadUtils.runOnUiThread(new Runnable() { - @Override - public void run() { - listener.onStreamError(torrent, e); - } - }); - } - } - - public void onStreamReady(final Torrent torrent) { - for (final TorrentListener listener : listeners) { - ThreadUtils.runOnUiThread(new Runnable() { - @Override - public void run() { - listener.onStreamReady(torrent); - } - }); - } - } - - public void onStreamProgress(final Torrent torrent, final StreamStatus status) { - for (final TorrentListener listener : listeners) { - ThreadUtils.runOnUiThread(new Runnable() { - @Override - public void run() { - listener.onStreamProgress(torrent, status); - } - }); - } - } - - @Override - public void onStreamStopped() { - // Not used - } - - @Override - public void onStreamPrepared(final Torrent torrent) { - if (torrentOptions.autoDownload) { - torrent.startDownload(); - } - - for (final TorrentListener listener : listeners) { - ThreadUtils.runOnUiThread(new Runnable() { - @Override - public void run() { - listener.onStreamPrepared(torrent); - } - }); - } - } - } - -} diff --git a/torrentStream/src/main/java/com/github/se_bastiaan/torrentstream/exceptions/DirectoryModifyException.java b/torrentStream/src/main/java/com/github/se_bastiaan/torrentstream/exceptions/DirectoryModifyException.java deleted file mode 100644 index 00803f8..0000000 --- a/torrentStream/src/main/java/com/github/se_bastiaan/torrentstream/exceptions/DirectoryModifyException.java +++ /dev/null @@ -1,25 +0,0 @@ -/* - * Copyright (C) 2015-2018 Sébastiaan (github.com/se-bastiaan) - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.github.se_bastiaan.torrentstream.exceptions; - -public class DirectoryModifyException extends Exception { - - public DirectoryModifyException() { - super("Could not create or delete save directory"); - } - -} diff --git a/torrentStream/src/main/java/com/github/se_bastiaan/torrentstream/exceptions/NotInitializedException.java b/torrentStream/src/main/java/com/github/se_bastiaan/torrentstream/exceptions/NotInitializedException.java deleted file mode 100644 index da3c5e3..0000000 --- a/torrentStream/src/main/java/com/github/se_bastiaan/torrentstream/exceptions/NotInitializedException.java +++ /dev/null @@ -1,25 +0,0 @@ -/* - * Copyright (C) 2015-2018 Sébastiaan (github.com/se-bastiaan) - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.github.se_bastiaan.torrentstream.exceptions; - -public class NotInitializedException extends Exception { - - public NotInitializedException() { - super("TorrentStreamer is not initialized. Call init() first before getting an instance."); - } - -} diff --git a/torrentStream/src/main/java/com/github/se_bastiaan/torrentstream/exceptions/TorrentInfoException.java b/torrentStream/src/main/java/com/github/se_bastiaan/torrentstream/exceptions/TorrentInfoException.java deleted file mode 100644 index 4d9431d..0000000 --- a/torrentStream/src/main/java/com/github/se_bastiaan/torrentstream/exceptions/TorrentInfoException.java +++ /dev/null @@ -1,25 +0,0 @@ -/* - * Copyright (C) 2015-2018 Sébastiaan (github.com/se-bastiaan) - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.github.se_bastiaan.torrentstream.exceptions; - -public class TorrentInfoException extends Exception { - - public TorrentInfoException(Throwable cause) { - super("No torrent info could be found or read", cause); - } - -} diff --git a/torrentStream/src/main/java/com/github/se_bastiaan/torrentstream/listeners/DHTStatsAlertListener.java b/torrentStream/src/main/java/com/github/se_bastiaan/torrentstream/listeners/DHTStatsAlertListener.java deleted file mode 100644 index 4e0e04a..0000000 --- a/torrentStream/src/main/java/com/github/se_bastiaan/torrentstream/listeners/DHTStatsAlertListener.java +++ /dev/null @@ -1,57 +0,0 @@ -/* - * - * * This file is part of TorrentStreamer-Android. - * * - * * TorrentStreamer-Android is free software: you can redistribute it and/or modify - * * it under the terms of the GNU Lesser General Public License as published by - * * the Free Software Foundation, either version 3 of the License, or - * * (at your option) any later version. - * * - * * TorrentStreamer-Android 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 Lesser General Public License for more details. - * * - * * You should have received a copy of the GNU Lesser General Public License - * * along with TorrentStreamer-Android. If not, see . - * - */ - -package com.github.se_bastiaan.torrentstream.listeners; - -import com.frostwire.jlibtorrent.AlertListener; -import com.frostwire.jlibtorrent.DhtRoutingBucket; -import com.frostwire.jlibtorrent.alerts.Alert; -import com.frostwire.jlibtorrent.alerts.AlertType; -import com.frostwire.jlibtorrent.alerts.DhtStatsAlert; - -import java.util.ArrayList; - -public abstract class DHTStatsAlertListener implements AlertListener { - @Override - public int[] types() { - return new int[]{AlertType.DHT_STATS.swig()}; - } - - public void alert(Alert alert) { - if (alert instanceof DhtStatsAlert) { - DhtStatsAlert dhtAlert = (DhtStatsAlert) alert; - stats(countTotalDHTNodes(dhtAlert)); - } - } - - public abstract void stats(int totalDhtNodes); - - private int countTotalDHTNodes(DhtStatsAlert alert) { - final ArrayList routingTable = alert.routingTable(); - - int totalNodes = 0; - if (routingTable != null) { - for (DhtRoutingBucket bucket : routingTable) { - totalNodes += bucket.numNodes(); - } - } - - return totalNodes; - } -} \ No newline at end of file diff --git a/torrentStream/src/main/java/com/github/se_bastiaan/torrentstream/listeners/TorrentAddedAlertListener.java b/torrentStream/src/main/java/com/github/se_bastiaan/torrentstream/listeners/TorrentAddedAlertListener.java deleted file mode 100644 index 19e0773..0000000 --- a/torrentStream/src/main/java/com/github/se_bastiaan/torrentstream/listeners/TorrentAddedAlertListener.java +++ /dev/null @@ -1,42 +0,0 @@ -/* - * Copyright (C) 2015-2018 Sébastiaan (github.com/se-bastiaan) - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.github.se_bastiaan.torrentstream.listeners; - -import com.frostwire.jlibtorrent.AlertListener; -import com.frostwire.jlibtorrent.alerts.AddTorrentAlert; -import com.frostwire.jlibtorrent.alerts.Alert; -import com.frostwire.jlibtorrent.alerts.AlertType; - -public abstract class TorrentAddedAlertListener implements AlertListener { - @Override - public int[] types() { - return new int[]{AlertType.ADD_TORRENT.swig()}; - } - - @Override - public void alert(Alert alert) { - switch (alert.type()) { - case ADD_TORRENT: - torrentAdded((AddTorrentAlert) alert); - break; - default: - break; - } - } - - public abstract void torrentAdded(AddTorrentAlert alert); -} diff --git a/torrentStream/src/main/java/com/github/se_bastiaan/torrentstream/listeners/TorrentListener.java b/torrentStream/src/main/java/com/github/se_bastiaan/torrentstream/listeners/TorrentListener.java deleted file mode 100644 index e099daa..0000000 --- a/torrentStream/src/main/java/com/github/se_bastiaan/torrentstream/listeners/TorrentListener.java +++ /dev/null @@ -1,34 +0,0 @@ -/* - * Copyright (C) 2015-2018 Sébastiaan (github.com/se-bastiaan) - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.github.se_bastiaan.torrentstream.listeners; - -import com.github.se_bastiaan.torrentstream.StreamStatus; -import com.github.se_bastiaan.torrentstream.Torrent; - -public interface TorrentListener { - void onStreamPrepared(Torrent torrent); - - void onStreamStarted(Torrent torrent); - - void onStreamError(Torrent torrent, Exception e); - - void onStreamReady(Torrent torrent); - - void onStreamProgress(Torrent torrent, StreamStatus status); - - void onStreamStopped(); -} diff --git a/torrentStream/src/main/java/com/github/se_bastiaan/torrentstream/utils/FileUtils.java b/torrentStream/src/main/java/com/github/se_bastiaan/torrentstream/utils/FileUtils.java deleted file mode 100644 index 7158239..0000000 --- a/torrentStream/src/main/java/com/github/se_bastiaan/torrentstream/utils/FileUtils.java +++ /dev/null @@ -1,48 +0,0 @@ -/* - * - * * This file is part of TorrentStreamer-Android. - * * - * * TorrentStreamer-Android is free software: you can redistribute it and/or modify - * * it under the terms of the GNU Lesser General Public License as published by - * * the Free Software Foundation, either version 3 of the License, or - * * (at your option) any later version. - * * - * * TorrentStreamer-Android 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 Lesser General Public License for more details. - * * - * * You should have received a copy of the GNU Lesser General Public License - * * along with TorrentStreamer-Android. If not, see . - * - */ - -package com.github.se_bastiaan.torrentstream.utils; - -import java.io.File; - -public final class FileUtils { - - private FileUtils() throws InstantiationException { - throw new InstantiationException("This class is not created for instantiation"); - } - - /** - * Delete every item below the File location - * - * @param file Location - * @return {@code true} when successful delete - */ - public static boolean recursiveDelete(File file) { - if (file.isDirectory()) { - String[] children = file.list(); - if (children == null) return false; - for (String child : children) { - recursiveDelete(new File(file, child)); - } - } - - return file.delete(); - } - -} diff --git a/torrentStream/src/main/java/com/github/se_bastiaan/torrentstream/utils/ThreadUtils.java b/torrentStream/src/main/java/com/github/se_bastiaan/torrentstream/utils/ThreadUtils.java deleted file mode 100644 index 6c27bb1..0000000 --- a/torrentStream/src/main/java/com/github/se_bastiaan/torrentstream/utils/ThreadUtils.java +++ /dev/null @@ -1,42 +0,0 @@ -/* - * - * * This file is part of TorrentStreamer-Android. - * * - * * TorrentStreamer-Android is free software: you can redistribute it and/or modify - * * it under the terms of the GNU Lesser General Public License as published by - * * the Free Software Foundation, either version 3 of the License, or - * * (at your option) any later version. - * * - * * TorrentStreamer-Android 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 Lesser General Public License for more details. - * * - * * You should have received a copy of the GNU Lesser General Public License - * * along with TorrentStreamer-Android. If not, see . - * - */ - -package com.github.se_bastiaan.torrentstream.utils; - -import android.os.Handler; -import android.os.Looper; - -public final class ThreadUtils { - - private ThreadUtils() throws InstantiationException { - throw new InstantiationException("This class is not created for instantiation"); - } - - /** - * Execute the given {@link Runnable} on the ui thread. - * - * @param runnable The runnable to execute. - */ - public static void runOnUiThread(Runnable runnable) { - Thread uiThread = Looper.getMainLooper().getThread(); - if (Thread.currentThread() != uiThread) new Handler(Looper.getMainLooper()).post(runnable); - else runnable.run(); - } - -} \ No newline at end of file