diff --git a/app/build.gradle b/app/build.gradle
index 70af9de..6fc471d 100644
--- a/app/build.gradle
+++ b/app/build.gradle
@@ -53,6 +53,9 @@ android {
buildConfigField "boolean", "sepia_search", "false"
buildConfigField "boolean", "instance_switcher", "true"
buildConfigField "boolean", "allow_remote_connections", "false"
+ buildConfigField "boolean", "google_cast_lib", "false"
+ buildConfigField "int", "cast_enabled", "0"
+ buildConfigField "int", "default_theme", "2"
}
google_peertube_apps_educ {
applicationId "app.fedilab.fedilabtube"
@@ -65,6 +68,9 @@ android {
buildConfigField "boolean", "sepia_search", "false"
buildConfigField "boolean", "instance_switcher", "true"
buildConfigField "boolean", "allow_remote_connections", "false"
+ buildConfigField "boolean", "google_cast_lib", "false"
+ buildConfigField "int", "cast_enabled", "0"
+ buildConfigField "int", "default_theme", "2"
}
fdroid_full {
applicationId "app.fedilab.tubelab"
@@ -77,6 +83,9 @@ android {
buildConfigField "boolean", "sepia_search", "true"
buildConfigField "boolean", "instance_switcher", "true"
buildConfigField "boolean", "allow_remote_connections", "true"
+ buildConfigField "boolean", "google_cast_lib", "false"
+ buildConfigField "int", "cast_enabled", "0"
+ buildConfigField "int", "default_theme", "2"
}
google_full {
applicationId "app.fedilab.tubelab"
@@ -89,6 +98,9 @@ android {
buildConfigField "boolean", "sepia_search", "true"
buildConfigField "boolean", "instance_switcher", "true"
buildConfigField "boolean", "allow_remote_connections", "true"
+ buildConfigField "boolean", "google_cast_lib", "true"
+ buildConfigField "int", "cast_enabled", "1"
+ buildConfigField "int", "default_theme", "2"
}
queermotion {
applicationId "org.queermotion.peertube"
@@ -101,6 +113,9 @@ android {
buildConfigField "boolean", "sepia_search", "false"
buildConfigField "boolean", "instance_switcher", "false"
buildConfigField "boolean", "allow_remote_connections", "false"
+ buildConfigField "boolean", "google_cast_lib", "false"
+ buildConfigField "int", "cast_enabled", "0"
+ buildConfigField "int", "default_theme", "2"
}
bittube {
applicationId "app.fedilab.bittube"
@@ -113,33 +128,38 @@ android {
buildConfigField "boolean", "sepia_search", "false"
buildConfigField "boolean", "instance_switcher", "true"
buildConfigField "boolean", "allow_remote_connections", "false"
+ buildConfigField "boolean", "google_cast_lib", "true"
+ buildConfigField "int", "cast_enabled", "1"
+ buildConfigField "int", "default_theme", "1"
}
}
sourceSets {
fdroid_peertube_apps_educ {
- res.srcDirs = ['src/main/res', 'src/acad/res']
- java.srcDirs = ['src/main/java', 'src/acad/java', 'src/no_google_donation/java']
+ res.srcDirs = ['src/main/res', 'src/acad/res', 'src/no_google_cast_lib/res']
+ java.srcDirs = ['src/main/java', 'src/acad/java', 'src/no_google_donation/java', 'src/no_google_cast_lib/java']
}
google_peertube_apps_educ {
- res.srcDirs = ['src/main/res', 'src/acad/res']
- java.srcDirs = ['src/main/java', 'src/acad/java', 'src/no_google_donation/java']
+ res.srcDirs = ['src/main/res', 'src/acad/res', 'src/no_google_cast_lib/res']
+ java.srcDirs = ['src/main/java', 'src/acad/java', 'src/no_google_donation/java', 'src/no_google_cast_lib/java']
}
fdroid_full {
- res.srcDirs = ['src/main/res', 'src/full/res']
- java.srcDirs = ['src/main/java', 'src/full/java', 'src/no_google_donation/java']
+ res.srcDirs = ['src/main/res', 'src/full/res', 'src/no_google_cast_lib/res']
+ java.srcDirs = ['src/main/java', 'src/full/java', 'src/no_google_donation/java', 'src/no_google_cast_lib/java']
}
google_full {
- res.srcDirs = ['src/main/res', 'src/full/res', 'src/google_donation/res']
- java.srcDirs = ['src/main/java', 'src/full/java', 'src/google_donation/java']
+ res.srcDirs = ['src/main/res', 'src/full/res', 'src/google_donation/res', 'src/google_cast_lib/res']
+ java.srcDirs = ['src/main/java', 'src/full/java', 'src/google_donation/java', 'src/google_cast_lib/java']
+ manifest.srcFile "src/google_cast_lib/AndroidManifest.xml"
}
queermotion {
- res.srcDirs = ['src/main/res', 'src/queermotion/res']
- java.srcDirs = ['src/main/java', 'src/full/java', 'src/no_google_donation/java']
+ res.srcDirs = ['src/main/res', 'src/queermotion/res', 'src/no_google_cast_lib/res']
+ java.srcDirs = ['src/main/java', 'src/full/java', 'src/no_google_donation/java', 'src/no_google_cast_lib/java']
}
bittube {
- res.srcDirs = ['src/main/res', 'src/bittube/res']
- java.srcDirs = ['src/main/java', 'src/full/java', 'src/no_google_donation/java']
+ res.srcDirs = ['src/main/res', 'src/bittube/res', 'src/google_cast_lib/res']
+ java.srcDirs = ['src/main/java', 'src/full/java', 'src/no_google_donation/java', 'src/google_cast_lib/java']
+ manifest.srcFile "src/google_cast_lib/AndroidManifest.xml"
}
}
}
@@ -179,6 +199,7 @@ dependencies {
implementation "com.github.mabbas007:TagsEditText:1.0.5"
implementation "com.github.bumptech.glide:glide:4.11.0"
annotationProcessor "com.github.bumptech.glide:compiler:4.11.0"
+ implementation 'jp.wasabeef:glide-transformations:4.0.0'
implementation "androidx.swiperefreshlayout:swiperefreshlayout:1.1.0"
implementation "net.gotev:uploadservice:4.5.1"
implementation "net.gotev:uploadservice-okhttp:4.5.1"
@@ -196,17 +217,34 @@ dependencies {
implementation "androidx.work:work-runtime:2.4.0"
implementation "androidx.work:work-runtime-ktx:2.4.0"
- //custom cast feature
- implementation 'jp.wasabeef:glide-transformations:4.0.0'
- implementation 'su.litvak.chromecast:api-v2:0.11.3'
- implementation 'com.fasterxml.jackson.core:jackson-core:2.12.0'
- implementation 'org.slf4j:slf4j-simple:1.7.30'
-
+ //************ DONATION GOOGLE ONLY **************//
google_fullImplementation "com.android.billingclient:billing:3.0.2"
+ //************ MATOMO --> acad instances only **************//
+
fdroid_peertube_apps_educImplementation 'org.matomo.sdk:tracker:4.1.2'
google_peertube_apps_educImplementation 'org.matomo.sdk:tracker:4.1.2'
+ //************ CAST **************///
+
+ //---> Google libs (google_full + bittube)
+ google_fullImplementation "androidx.mediarouter:mediarouter:1.2.1"
+ google_fullImplementation 'com.google.android.gms:play-services-cast-framework:19.0.0'
+ bittubeImplementation "androidx.mediarouter:mediarouter:1.2.1"
+ bittubeImplementation 'com.google.android.gms:play-services-cast-framework:19.0.0'
+ //----> Other flavors
+ fdroid_peertube_apps_educImplementation 'su.litvak.chromecast:api-v2:0.11.3'
+ fdroid_peertube_apps_educImplementation 'com.fasterxml.jackson.core:jackson-core:2.12.0'
+ fdroid_peertube_apps_educImplementation 'org.slf4j:slf4j-simple:1.7.30'
+ google_peertube_apps_educImplementation 'su.litvak.chromecast:api-v2:0.11.3'
+ google_peertube_apps_educImplementation 'com.fasterxml.jackson.core:jackson-core:2.12.0'
+ google_peertube_apps_educImplementation 'org.slf4j:slf4j-simple:1.7.30'
+ fdroid_fullImplementation 'su.litvak.chromecast:api-v2:0.11.3'
+ fdroid_fullImplementation 'com.fasterxml.jackson.core:jackson-core:2.12.0'
+ fdroid_fullImplementation 'org.slf4j:slf4j-simple:1.7.30'
+ queermotionImplementation 'su.litvak.chromecast:api-v2:0.11.3'
+ queermotionImplementation 'com.fasterxml.jackson.core:jackson-core:2.12.0'
+ queermotionImplementation 'org.slf4j:slf4j-simple:1.7.30'
}
\ No newline at end of file
diff --git a/app/src/google_cast_lib/AndroidManifest.xml b/app/src/google_cast_lib/AndroidManifest.xml
new file mode 100644
index 0000000..4e12e9a
--- /dev/null
+++ b/app/src/google_cast_lib/AndroidManifest.xml
@@ -0,0 +1,18 @@
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/app/src/google_cast_lib/java/app/fedilab/fedilabtube/BaseMainActivity.java b/app/src/google_cast_lib/java/app/fedilab/fedilabtube/BaseMainActivity.java
new file mode 100644
index 0000000..1f5b39a
--- /dev/null
+++ b/app/src/google_cast_lib/java/app/fedilab/fedilabtube/BaseMainActivity.java
@@ -0,0 +1,41 @@
+package app.fedilab.fedilabtube;
+/* Copyright 2021 Thomas Schneider
+ *
+ * This file is a part of TubeLab
+ *
+ * This program is free software; you can redistribute it and/or modify it under the terms of the
+ * GNU General Public License as published by the Free Software Foundation; either version 3 of the
+ * License, or (at your option) any later version.
+ *
+ * TubeLab 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 General
+ * Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along with TubeLab; if not,
+ * see . */
+
+import android.os.Bundle;
+import android.view.View;
+
+import androidx.appcompat.app.AppCompatActivity;
+
+import app.fedilab.fedilabtube.databinding.ActivityMainBinding;
+
+public class BaseMainActivity extends AppCompatActivity {
+
+ protected ActivityMainBinding binding;
+
+ @Override
+ protected void onCreate(Bundle savedInstanceState) {
+
+ super.onCreate(savedInstanceState);
+ binding = ActivityMainBinding.inflate(getLayoutInflater());
+ View view = binding.getRoot();
+ setContentView(view);
+ }
+
+ //Method for discovering cast devices
+ public void discoverCast() {
+ }
+
+}
diff --git a/app/src/google_cast_lib/java/app/fedilab/fedilabtube/BasePeertubeActivity.java b/app/src/google_cast_lib/java/app/fedilab/fedilabtube/BasePeertubeActivity.java
new file mode 100644
index 0000000..4afe379
--- /dev/null
+++ b/app/src/google_cast_lib/java/app/fedilab/fedilabtube/BasePeertubeActivity.java
@@ -0,0 +1,177 @@
+package app.fedilab.fedilabtube;
+
+import android.content.Context;
+import android.content.SharedPreferences;
+import android.net.Uri;
+import android.os.Bundle;
+import android.view.Menu;
+import android.view.View;
+
+import androidx.appcompat.app.AppCompatActivity;
+
+import com.google.android.exoplayer2.SimpleExoPlayer;
+import com.google.android.gms.cast.MediaInfo;
+import com.google.android.gms.cast.MediaMetadata;
+import com.google.android.gms.cast.framework.CastButtonFactory;
+import com.google.android.gms.cast.framework.CastContext;
+import com.google.android.gms.cast.framework.CastSession;
+import com.google.android.gms.cast.framework.SessionManagerListener;
+import com.google.android.gms.cast.framework.media.RemoteMediaClient;
+import com.google.android.gms.common.images.WebImage;
+
+import app.fedilab.fedilabtube.client.data.VideoData;
+import app.fedilab.fedilabtube.databinding.ActivityPeertubeBinding;
+import app.fedilab.fedilabtube.helper.Helper;
+
+/* Copyright 2021 Thomas Schneider
+ *
+ * This file is a part of TubeLab
+ *
+ * This program is free software; you can redistribute it and/or modify it under the terms of the
+ * GNU General Public License as published by the Free Software Foundation; either version 3 of the
+ * License, or (at your option) any later version.
+ *
+ * TubeLab 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 General
+ * Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along with TubeLab; if not,
+ * see . */
+
+public class BasePeertubeActivity extends AppCompatActivity {
+
+ protected ActivityPeertubeBinding binding;
+ protected VideoData.Video peertube;
+ protected SimpleExoPlayer player;
+ protected String videoURL;
+ protected String subtitlesStr;
+
+ private CastContext mCastContext;
+ private CastSession mCastSession;
+ private SessionManagerListener mSessionManagerListener;
+
+
+ @Override
+ protected void onCreate(Bundle savedInstanceState) {
+ super.onCreate(savedInstanceState);
+ binding = ActivityPeertubeBinding.inflate(getLayoutInflater());
+ View view = binding.getRoot();
+ setContentView(view);
+ final SharedPreferences sharedpreferences = getSharedPreferences(Helper.APP_PREFS, Context.MODE_PRIVATE);
+
+ int search_cast = sharedpreferences.getInt(getString(R.string.set_cast_choice), BuildConfig.cast_enabled);
+ if (search_cast == 1) {
+ setupCastListener();
+ mCastContext = CastContext.getSharedInstance(this);
+ mCastSession = mCastContext.getSessionManager().getCurrentCastSession();
+
+ }
+
+ }
+
+
+ protected void loadCast() {
+ MediaMetadata movieMetadata = new MediaMetadata(MediaMetadata.MEDIA_TYPE_MOVIE);
+
+ movieMetadata.putString(MediaMetadata.KEY_TITLE, peertube.getTitle());
+ if (subtitlesStr != null) {
+ movieMetadata.putString(MediaMetadata.KEY_SUBTITLE, subtitlesStr);
+ }
+ movieMetadata.addImage(new WebImage(Uri.parse(peertube.getPreviewPath())));
+ MediaInfo mediaInfo = new MediaInfo.Builder(videoURL)
+ .setStreamType(MediaInfo.STREAM_TYPE_BUFFERED)
+ .setMetadata(movieMetadata)
+ .setStreamDuration(peertube.getDuration() * 1000)
+ .build();
+ if (mCastSession != null) {
+ RemoteMediaClient remoteMediaClient = mCastSession.getRemoteMediaClient();
+ remoteMediaClient.load(mediaInfo);
+ }
+ }
+
+
+ private void setupCastListener() {
+ mSessionManagerListener = new SessionManagerListener() {
+ @Override
+ public void onSessionStarting(CastSession castSession) {
+ }
+
+ @Override
+ public void onSessionStarted(CastSession castSession, String s) {
+ onApplicationConnected(castSession);
+ }
+
+ @Override
+ public void onSessionStartFailed(CastSession castSession, int i) {
+ onApplicationDisconnected();
+ }
+
+ @Override
+ public void onSessionEnding(CastSession castSession) {
+ onApplicationDisconnected();
+ }
+
+ @Override
+ public void onSessionEnded(CastSession castSession, int i) {
+ onApplicationDisconnected();
+ }
+
+ @Override
+ public void onSessionResuming(CastSession castSession, String s) {
+ }
+
+ @Override
+ public void onSessionResumed(CastSession castSession, boolean b) {
+ onApplicationConnected(castSession);
+ }
+
+ @Override
+ public void onSessionResumeFailed(CastSession castSession, int i) {
+ onApplicationDisconnected();
+ }
+
+ @Override
+ public void onSessionSuspended(CastSession castSession, int i) {
+ onApplicationDisconnected();
+ }
+
+ private void onApplicationConnected(CastSession castSession) {
+ mCastSession = castSession;
+ supportInvalidateOptionsMenu();
+ player.setPlayWhenReady(false);
+ binding.doubleTapPlayerView.setVisibility(View.INVISIBLE);
+ loadCast();
+ }
+
+ private void onApplicationDisconnected() {
+ binding.doubleTapPlayerView.setVisibility(View.VISIBLE);
+ supportInvalidateOptionsMenu();
+ }
+ };
+ }
+
+ @Override
+ protected void onResume() {
+ mCastContext.getSessionManager().addSessionManagerListener(
+ mSessionManagerListener, CastSession.class);
+ super.onResume();
+ }
+
+ @Override
+ protected void onPause() {
+ mCastContext.getSessionManager().removeSessionManagerListener(
+ mSessionManagerListener, CastSession.class);
+ super.onPause();
+ }
+
+
+ @Override
+ public boolean onCreateOptionsMenu(Menu menu) {
+ super.onCreateOptionsMenu(menu);
+ getMenuInflater().inflate(R.menu.video_menu, menu);
+ CastButtonFactory.setUpMediaRouteButton(getApplicationContext(),
+ menu,
+ R.id.media_route_button);
+ return true;
+ }
+}
diff --git a/app/src/google_cast_lib/java/app/fedilab/fedilabtube/expandedcontrols/ExpandedControlsActivity.java b/app/src/google_cast_lib/java/app/fedilab/fedilabtube/expandedcontrols/ExpandedControlsActivity.java
new file mode 100755
index 0000000..6195e6a
--- /dev/null
+++ b/app/src/google_cast_lib/java/app/fedilab/fedilabtube/expandedcontrols/ExpandedControlsActivity.java
@@ -0,0 +1,36 @@
+/*
+ * Copyright (C) 2016 Google LLC. All Rights Reserved.
+ *
+ * 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 app.fedilab.fedilabtube.expandedcontrols;
+
+import android.view.Menu;
+
+import com.google.android.gms.cast.framework.CastButtonFactory;
+import com.google.android.gms.cast.framework.media.widget.ExpandedControllerActivity;
+
+import app.fedilab.fedilabtube.R;
+
+
+public class ExpandedControlsActivity extends ExpandedControllerActivity {
+
+ @Override
+ public boolean onCreateOptionsMenu(Menu menu) {
+ super.onCreateOptionsMenu(menu);
+ getMenuInflater().inflate(R.menu.video_menu, menu);
+ CastButtonFactory.setUpMediaRouteButton(this, menu, R.id.media_route_button);
+ return true;
+ }
+}
\ No newline at end of file
diff --git a/app/src/google_cast_lib/java/app/fedilab/fedilabtube/provider/CastOptionsProvider.java b/app/src/google_cast_lib/java/app/fedilab/fedilabtube/provider/CastOptionsProvider.java
new file mode 100644
index 0000000..922aa3f
--- /dev/null
+++ b/app/src/google_cast_lib/java/app/fedilab/fedilabtube/provider/CastOptionsProvider.java
@@ -0,0 +1,54 @@
+package app.fedilab.fedilabtube.provider;
+/* Copyright 2021 Thomas Schneider
+ *
+ * This file is a part of TubeLab
+ *
+ * This program is free software; you can redistribute it and/or modify it under the terms of the
+ * GNU General Public License as published by the Free Software Foundation; either version 3 of the
+ * License, or (at your option) any later version.
+ *
+ * TubeLab 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 General
+ * Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along with TubeLab; if not,
+ * see . */
+
+import android.content.Context;
+
+import com.google.android.gms.cast.framework.CastOptions;
+import com.google.android.gms.cast.framework.OptionsProvider;
+import com.google.android.gms.cast.framework.SessionProvider;
+import com.google.android.gms.cast.framework.media.CastMediaOptions;
+import com.google.android.gms.cast.framework.media.NotificationOptions;
+
+import java.util.List;
+
+import app.fedilab.fedilabtube.BuildConfig;
+import app.fedilab.fedilabtube.expandedcontrols.ExpandedControlsActivity;
+import app.fedilab.fedilabtube.helper.Helper;
+
+
+public class CastOptionsProvider implements OptionsProvider {
+
+
+ @Override
+ public CastOptions getCastOptions(Context context) {
+ NotificationOptions notificationOptions = new NotificationOptions.Builder()
+ .setTargetActivityClassName(ExpandedControlsActivity.class.getName())
+ .build();
+ CastMediaOptions mediaOptions = new CastMediaOptions.Builder()
+ .setNotificationOptions(notificationOptions)
+ .setExpandedControllerActivityClassName(ExpandedControlsActivity.class.getName())
+ .build();
+ return new CastOptions.Builder()
+ .setReceiverApplicationId(BuildConfig.FLAVOR.compareTo("bittube") == 0 ? Helper.CAST_ID_BITTUBE : Helper.CAST_ID)
+ .setCastMediaOptions(mediaOptions)
+ .build();
+ }
+
+ @Override
+ public List getAdditionalSessionProviders(Context context) {
+ return null;
+ }
+}
\ No newline at end of file
diff --git a/app/src/google_cast_lib/res/menu/video_menu.xml b/app/src/google_cast_lib/res/menu/video_menu.xml
new file mode 100644
index 0000000..1e36b9b
--- /dev/null
+++ b/app/src/google_cast_lib/res/menu/video_menu.xml
@@ -0,0 +1,9 @@
+
+
diff --git a/app/src/main/java/app/fedilab/fedilabtube/BaseFedilabTube.java b/app/src/main/java/app/fedilab/fedilabtube/BaseFedilabTube.java
index cd5bb4b..c075850 100644
--- a/app/src/main/java/app/fedilab/fedilabtube/BaseFedilabTube.java
+++ b/app/src/main/java/app/fedilab/fedilabtube/BaseFedilabTube.java
@@ -65,7 +65,7 @@ public class BaseFedilabTube extends MultiDexApplication {
MultiDex.install(BaseFedilabTube.this);
SharedPreferences sharedpreferences = getSharedPreferences(Helper.APP_PREFS, Context.MODE_PRIVATE);
- int themePref = sharedpreferences.getInt(Helper.SET_THEME, Helper.DEFAULT_MODE);
+ int themePref = sharedpreferences.getInt(Helper.SET_THEME, BuildConfig.default_theme);
ThemeHelper.switchTo(themePref);
diff --git a/app/src/main/java/app/fedilab/fedilabtube/MainActivity.java b/app/src/main/java/app/fedilab/fedilabtube/MainActivity.java
index 25e494f..8f122a1 100644
--- a/app/src/main/java/app/fedilab/fedilabtube/MainActivity.java
+++ b/app/src/main/java/app/fedilab/fedilabtube/MainActivity.java
@@ -16,17 +16,14 @@ package app.fedilab.fedilabtube;
import android.annotation.SuppressLint;
import android.app.Activity;
-import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
-import android.content.IntentFilter;
import android.content.SharedPreferences;
import android.database.sqlite.SQLiteDatabase;
import android.net.Uri;
import android.os.Build;
import android.os.Bundle;
import android.os.Handler;
-import android.os.Looper;
import android.view.Menu;
import android.view.MenuItem;
import android.view.View;
@@ -37,14 +34,12 @@ import android.widget.TextView;
import android.widget.Toast;
import androidx.appcompat.app.AlertDialog;
-import androidx.appcompat.app.AppCompatActivity;
import androidx.appcompat.widget.SearchView;
import androidx.appcompat.widget.Toolbar;
import androidx.appcompat.widget.TooltipCompat;
import androidx.fragment.app.Fragment;
import androidx.fragment.app.FragmentManager;
import androidx.fragment.app.FragmentStatePagerAdapter;
-import androidx.localbroadcastmanager.content.LocalBroadcastManager;
import androidx.viewpager.widget.PagerAdapter;
import androidx.viewpager.widget.ViewPager;
@@ -53,13 +48,7 @@ import com.kobakei.ratethisapp.RateThisApp;
import org.jetbrains.annotations.NotNull;
-import java.io.IOException;
-import java.net.InetAddress;
-import java.net.NetworkInterface;
import java.net.URL;
-import java.util.ArrayList;
-import java.util.Collections;
-import java.util.Enumeration;
import java.util.HashMap;
import java.util.Iterator;
import java.util.LinkedHashMap;
@@ -73,7 +62,6 @@ import java.util.regex.Pattern;
import app.fedilab.fedilabtube.client.RetrofitPeertubeAPI;
import app.fedilab.fedilabtube.client.data.AccountData.Account;
import app.fedilab.fedilabtube.client.data.InstanceData;
-import app.fedilab.fedilabtube.client.data.VideoData;
import app.fedilab.fedilabtube.client.entities.Error;
import app.fedilab.fedilabtube.client.entities.OauthParams;
import app.fedilab.fedilabtube.client.entities.PeertubeInformation;
@@ -95,17 +83,13 @@ import app.fedilab.fedilabtube.sqlite.Sqlite;
import app.fedilab.fedilabtube.sqlite.StoredInstanceDAO;
import app.fedilab.fedilabtube.viewmodel.TimelineVM;
import es.dmoral.toasty.Toasty;
-import su.litvak.chromecast.api.v2.ChromeCast;
-import su.litvak.chromecast.api.v2.ChromeCasts;
-import su.litvak.chromecast.api.v2.ChromeCastsListener;
-import su.litvak.chromecast.api.v2.MediaStatus;
import static app.fedilab.fedilabtube.MainActivity.TypeOfConnection.NORMAL;
import static app.fedilab.fedilabtube.MainActivity.TypeOfConnection.SURFING;
import static app.fedilab.fedilabtube.helper.Helper.peertubeInformation;
-public class MainActivity extends AppCompatActivity implements ChromeCastsListener {
+public class MainActivity extends BaseMainActivity {
public static int PICK_INSTANCE = 5641;
@@ -113,9 +97,8 @@ public class MainActivity extends AppCompatActivity implements ChromeCastsListen
public static UserMe userMe;
public static InstanceData.InstanceConfig instanceConfig;
public static TypeOfConnection typeOfConnection;
- public static List chromeCasts;
- public static ChromeCast chromeCast;
- public static boolean chromecastActivated = false;
+
+
private DisplayVideosFragment recentFragment, locaFragment, trendingFragment, subscriptionFragment, mostLikedFragment;
private DisplayOverviewFragment overviewFragment;
private ActivityMainBinding binding;
@@ -158,8 +141,7 @@ public class MainActivity extends AppCompatActivity implements ChromeCastsListen
}
return true;
};
- private BroadcastReceiver manage_chromecast;
- private VideoData.Video castedTube;
+
@SuppressLint("ApplySharedPref")
public static void showRadioButtonDialogFullInstances(Activity activity, boolean storeInDb) {
@@ -234,123 +216,20 @@ public class MainActivity extends AppCompatActivity implements ChromeCastsListen
}
}
- @Override
- public void newChromeCastDiscovered(ChromeCast chromeCast) {
- if (chromeCasts == null) {
- chromeCasts = new ArrayList<>();
- chromeCasts.add(chromeCast);
- } else {
- boolean canBeAdded = true;
- for (ChromeCast cast : chromeCasts) {
- if (cast.getName().compareTo(chromeCast.getName()) == 0) {
- canBeAdded = false;
- break;
- }
- }
- if (canBeAdded) {
- chromeCasts.add(chromeCast);
- }
- }
- try {
- if (chromeCast.isAppRunning(Helper.CAST_ID) && chromeCast.getMediaStatus() != null && chromeCast.getMediaStatus().playerState != null) {
- if (binding.castInfo.getVisibility() == View.GONE) {
- binding.castInfo.setVisibility(View.VISIBLE);
- }
- }
- } catch (IOException e) {
- e.printStackTrace();
- }
- }
-
- @Override
- public void chromeCastRemoved(ChromeCast chromeCast) {
-
- }
@Override
public void onDestroy() {
super.onDestroy();
binding = null;
- ChromeCasts.unregisterListener(this);
- if (manage_chromecast != null) {
- LocalBroadcastManager.getInstance(MainActivity.this).unregisterReceiver(manage_chromecast);
-
- new Thread(() -> {
- if (chromeCasts != null && chromeCasts.size() > 0) {
- for (ChromeCast cast : chromeCasts) {
- try {
- cast.stopApp();
- cast.disconnect();
- } catch (IOException e) {
- e.printStackTrace();
- }
- }
- }
- }).start();
- }
- if (chromeCasts != null) {
- chromeCasts = null;
- }
- if (chromeCast != null) {
- chromeCast = null;
- }
}
- //Method for discovering cast devices
- public void discoverCast() {
- new Thread(() -> {
- if (chromeCasts != null) {
- for (ChromeCast cast : chromeCasts) {
- try {
- cast.disconnect();
- } catch (IOException e) {
- e.printStackTrace();
- }
- }
- chromeCasts = null;
- }
- chromeCasts = new ArrayList<>();
- try {
- List interfaces;
- interfaces = Collections.list(NetworkInterface.getNetworkInterfaces());
- for (NetworkInterface ni : interfaces) {
- if ((!ni.isLoopback()) && ni.isUp() && (ni.getName().equals("wlan0"))) {
- Enumeration inetAddressEnumeration = ni.getInetAddresses();
- while (inetAddressEnumeration.hasMoreElements()) {
- InetAddress inetAddress = inetAddressEnumeration.nextElement();
- ChromeCasts.restartDiscovery(inetAddress);
- int tryFind = 0;
- while (ChromeCasts.get().isEmpty() && tryFind < 5) {
- try {
- //noinspection BusyWait
- Thread.sleep(1000);
- tryFind++;
- } catch (InterruptedException ignored) {
- }
- }
- }
- }
- }
- ChromeCasts.stopDiscovery();
- Handler mainHandler = new Handler(Looper.getMainLooper());
- Runnable myRunnable = this::invalidateOptionsMenu;
- mainHandler.post(myRunnable);
- } catch (IOException e) {
- e.printStackTrace();
- }
- }).start();
- }
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
- binding = ActivityMainBinding.inflate(getLayoutInflater());
- View view = binding.getRoot();
- setContentView(view);
- ChromeCastsListener chromeCastsListener = this;
- ChromeCasts.registerListener(chromeCastsListener);
+ binding = super.binding;
Toolbar toolbar = findViewById(R.id.toolbar);
setSupportActionBar(toolbar);
@@ -462,92 +341,10 @@ public class MainActivity extends AppCompatActivity implements ChromeCastsListen
}
- binding.castClose.setOnClickListener(v -> {
- Intent intentBC = new Intent(Helper.RECEIVE_CAST_SETTINGS);
- Bundle b = new Bundle();
- b.putInt("displayed", 0);
- intentBC.putExtras(b);
- LocalBroadcastManager.getInstance(MainActivity.this).sendBroadcast(intentBC);
- });
-
- binding.castTogglePlay.setOnClickListener(v -> {
- if (chromeCast != null) {
- new Thread(() -> {
- try {
- Handler mainHandler = new Handler(Looper.getMainLooper());
- Runnable myRunnable = () -> binding.castTogglePlay.setVisibility(View.GONE);
- mainHandler.post(myRunnable);
- int icon = -1;
- if (chromeCast.getMediaStatus().playerState == MediaStatus.PlayerState.PLAYING) {
- chromeCast.pause();
- icon = R.drawable.ic_baseline_play_arrow_32;
- } else if (chromeCast.getMediaStatus().playerState == MediaStatus.PlayerState.PAUSED) {
- chromeCast.play();
- icon = R.drawable.ic_baseline_pause_32;
- }
- if (icon != -1) {
- int finalIcon = icon;
- myRunnable = () -> binding.castTogglePlay.setImageResource(finalIcon);
- mainHandler.post(myRunnable);
- }
- myRunnable = () -> binding.castTogglePlay.setVisibility(View.VISIBLE);
- mainHandler.post(myRunnable);
- } catch (IOException e) {
- e.printStackTrace();
- }
- }).start();
- }
- });
- manage_chromecast = new BroadcastReceiver() {
- @Override
- public void onReceive(Context context, Intent intent) {
- Bundle b = intent.getExtras();
- assert b != null;
- int state = b.getInt("state_asked", -1);
- int displayed = b.getInt("displayed", -1);
- castedTube = b.getParcelable("castedTube");
-
- if (state == 1) {
- discoverCast();
- } else if (state == 0) {
- new Thread(() -> {
- try {
- if (chromeCast != null) {
- chromeCast.stopApp();
- chromeCast.disconnect();
- }
- } catch (IOException e) {
- e.printStackTrace();
- }
- }).start();
- }
- if (displayed == 1) {
- chromecastActivated = true;
- if (castedTube != null) {
- binding.castInfo.setVisibility(View.VISIBLE);
- Helper.loadGiF(MainActivity.this, castedTube.getThumbnailPath(), binding.castView);
- binding.castTitle.setText(castedTube.getTitle());
- binding.castDescription.setText(castedTube.getDescription());
- }
- } else if (displayed == 0) {
- chromecastActivated = false;
- binding.castInfo.setVisibility(View.GONE);
- new Thread(() -> {
- try {
- if (chromeCast != null) {
- chromeCast.stopApp();
- }
- } catch (IOException e) {
- e.printStackTrace();
- }
- }).start();
- }
- }
- };
final SharedPreferences sharedpreferences = getSharedPreferences(Helper.APP_PREFS, Context.MODE_PRIVATE);
- LocalBroadcastManager.getInstance(MainActivity.this).registerReceiver(manage_chromecast, new IntentFilter(Helper.RECEIVE_CAST_SETTINGS));
- int search_cast = sharedpreferences.getInt(getString(R.string.set_cast_choice), 0);
+
+ int search_cast = sharedpreferences.getInt(getString(R.string.set_cast_choice), BuildConfig.cast_enabled);
if (search_cast == 1) {
discoverCast();
}
diff --git a/app/src/main/java/app/fedilab/fedilabtube/PeertubeActivity.java b/app/src/main/java/app/fedilab/fedilabtube/PeertubeActivity.java
index f105b1b..b1cfba5 100644
--- a/app/src/main/java/app/fedilab/fedilabtube/PeertubeActivity.java
+++ b/app/src/main/java/app/fedilab/fedilabtube/PeertubeActivity.java
@@ -44,7 +44,6 @@ import android.text.method.LinkMovementMethod;
import android.text.style.ClickableSpan;
import android.util.DisplayMetrics;
import android.view.LayoutInflater;
-import android.view.Menu;
import android.view.MenuItem;
import android.view.MotionEvent;
import android.view.View;
@@ -52,7 +51,6 @@ import android.view.WindowManager;
import android.view.animation.Animation;
import android.view.animation.TranslateAnimation;
import android.view.inputmethod.InputMethodManager;
-import android.webkit.MimeTypeMap;
import android.widget.EditText;
import android.widget.ImageButton;
import android.widget.ImageView;
@@ -63,14 +61,12 @@ import android.widget.Toast;
import androidx.annotation.NonNull;
import androidx.annotation.RequiresApi;
import androidx.appcompat.app.AlertDialog;
-import androidx.appcompat.app.AppCompatActivity;
import androidx.appcompat.widget.PopupMenu;
import androidx.constraintlayout.widget.ConstraintLayout;
import androidx.core.app.ActivityCompat;
import androidx.core.content.ContextCompat;
import androidx.core.graphics.drawable.DrawableCompat;
import androidx.lifecycle.ViewModelProvider;
-import androidx.localbroadcastmanager.content.LocalBroadcastManager;
import androidx.recyclerview.widget.LinearLayoutManager;
import androidx.recyclerview.widget.RecyclerView;
@@ -111,8 +107,6 @@ import com.google.android.material.snackbar.Snackbar;
import org.jetbrains.annotations.NotNull;
-import java.io.IOException;
-import java.security.GeneralSecurityException;
import java.text.DateFormat;
import java.util.ArrayList;
import java.util.HashMap;
@@ -163,19 +157,12 @@ import app.fedilab.fedilabtube.webview.CustomWebview;
import app.fedilab.fedilabtube.webview.MastalabWebChromeClient;
import app.fedilab.fedilabtube.webview.MastalabWebViewClient;
import es.dmoral.toasty.Toasty;
-import su.litvak.chromecast.api.v2.ChromeCast;
-import su.litvak.chromecast.api.v2.MediaStatus;
-import su.litvak.chromecast.api.v2.Status;
-import static app.fedilab.fedilabtube.MainActivity.chromeCast;
-import static app.fedilab.fedilabtube.MainActivity.chromeCasts;
-import static app.fedilab.fedilabtube.MainActivity.chromecastActivated;
import static app.fedilab.fedilabtube.client.RetrofitPeertubeAPI.ActionType.ADD_COMMENT;
import static app.fedilab.fedilabtube.client.RetrofitPeertubeAPI.ActionType.RATEVIDEO;
import static app.fedilab.fedilabtube.client.RetrofitPeertubeAPI.ActionType.REPLY;
import static app.fedilab.fedilabtube.client.RetrofitPeertubeAPI.ActionType.REPORT_ACCOUNT;
import static app.fedilab.fedilabtube.client.RetrofitPeertubeAPI.ActionType.REPORT_VIDEO;
-import static app.fedilab.fedilabtube.helper.Helper.CAST_ID;
import static app.fedilab.fedilabtube.helper.Helper.canMakeAction;
import static app.fedilab.fedilabtube.helper.Helper.getAttColor;
import static app.fedilab.fedilabtube.helper.Helper.isLoggedIn;
@@ -184,15 +171,13 @@ import static app.fedilab.fedilabtube.helper.Helper.peertubeInformation;
import static com.google.android.exoplayer2.Player.MEDIA_ITEM_TRANSITION_REASON_AUTO;
-public class PeertubeActivity extends AppCompatActivity implements CommentListAdapter.AllCommentRemoved, Player.EventListener, VideoListener, TorrentListener, MenuAdapter.ItemClicked, MenuItemAdapter.ItemAction {
+public class PeertubeActivity extends BasePeertubeActivity implements CommentListAdapter.AllCommentRemoved, Player.EventListener, VideoListener, TorrentListener, MenuAdapter.ItemClicked, MenuItemAdapter.ItemAction {
public static String video_id;
public static List playedVideos = new ArrayList<>();
private String peertubeInstance, videoUuid;
private ImageView fullScreenIcon;
- private SimpleExoPlayer player;
private boolean fullScreenMode;
- private VideoData.Video peertube;
private int mode;
private Map> playlists;
private boolean playInMinimized, autoPlay, autoFullscreen;
@@ -218,7 +203,7 @@ public class PeertubeActivity extends AppCompatActivity implements CommentListAd
private String currentCaption;
private boolean isRemote;
private boolean willPlayFromIntent;
- private String chromeCastVideoURL;
+
private app.fedilab.fedilabtube.client.mastodon.Status status;
Uri captionURI;
String captionLang;
@@ -307,10 +292,7 @@ public class PeertubeActivity extends AppCompatActivity implements CommentListAd
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
-
- binding = ActivityPeertubeBinding.inflate(getLayoutInflater());
- View view = binding.getRoot();
- setContentView(view);
+ binding = super.binding;
videoOrientationType = videoOrientation.LANDSCAPE;
max_id = "0";
SQLiteDatabase db = Sqlite.getInstance(getApplicationContext(), Sqlite.DB_NAME, null, Sqlite.DB_VERSION).open();
@@ -512,34 +494,7 @@ public class PeertubeActivity extends AppCompatActivity implements CommentListAd
}
});
- binding.castPlay.setOnClickListener(v -> {
- binding.castLoader.setVisibility(View.VISIBLE);
- if (chromeCast != null) {
- new Thread(() -> {
- try {
- int icon = -1;
- if (chromeCast.getMediaStatus().playerState == MediaStatus.PlayerState.PLAYING) {
- chromeCast.pause();
- icon = R.drawable.ic_baseline_play_arrow_32;
- } else if (chromeCast.getMediaStatus().playerState == MediaStatus.PlayerState.PAUSED) {
- chromeCast.play();
- icon = R.drawable.ic_baseline_pause_32;
- }
- if (icon != -1) {
- Handler mainHandler = new Handler(Looper.getMainLooper());
- int finalIcon = icon;
- Runnable myRunnable = () -> binding.castPlay.setImageResource(finalIcon);
- mainHandler.post(myRunnable);
- }
- Handler mainHandler = new Handler(Looper.getMainLooper());
- Runnable myRunnable = () -> binding.castLoader.setVisibility(View.GONE);
- mainHandler.post(myRunnable);
- } catch (IOException e) {
- e.printStackTrace();
- }
- }).start();
- }
- });
+
}
@@ -798,20 +753,6 @@ public class PeertubeActivity extends AppCompatActivity implements CommentListAd
}).start();
}
- @Override
- public boolean onCreateOptionsMenu(@NotNull Menu menu) {
- getMenuInflater().inflate(R.menu.video_menu, menu);
- MenuItem castItem = menu.findItem(R.id.action_cast);
- if (chromeCasts != null && chromeCasts.size() > 0) {
- castItem.setVisible(true);
- if (chromeCast != null && chromeCast.isConnected()) {
- castItem.setIcon(R.drawable.ic_baseline_cast_connected_24);
- } else {
- castItem.setIcon(R.drawable.ic_baseline_cast_24);
- }
- }
- return true;
- }
@Override
public boolean onOptionsItemSelected(MenuItem item) {
@@ -821,101 +762,6 @@ public class PeertubeActivity extends AppCompatActivity implements CommentListAd
}
finish();
return true;
- } else if (item.getItemId() == R.id.action_cast) {
- if (chromeCasts != null && chromeCasts.size() > 0) {
- String[] chromecast_choice = new String[chromeCasts.size()];
- AlertDialog.Builder alt_bld = new AlertDialog.Builder(this);
- alt_bld.setTitle(R.string.chromecast_choice);
- int i = 0;
- for (ChromeCast cc : chromeCasts) {
- chromecast_choice[i] = cc.getTitle();
- i++;
- }
- i = 0;
- for (ChromeCast cc : chromeCasts) {
- if (chromecastActivated && cc.isConnected()) {
- break;
- }
- i++;
- }
-
- alt_bld.setSingleChoiceItems(chromecast_choice, i, (dialog, position) -> {
- chromeCast = chromeCasts.get(position);
- new Thread(() -> {
- if (chromeCast != null) {
- Intent intentBC = new Intent(Helper.RECEIVE_CAST_SETTINGS);
- Bundle b = new Bundle();
- if (chromecastActivated) {
- b.putInt("displayed", 0);
- intentBC.putExtras(b);
- LocalBroadcastManager.getInstance(PeertubeActivity.this).sendBroadcast(intentBC);
- Handler mainHandler = new Handler(Looper.getMainLooper());
- Runnable myRunnable = () -> {
- binding.doubleTapPlayerView.setVisibility(View.VISIBLE);
- binding.castController.setVisibility(View.GONE);
- };
- mainHandler.post(myRunnable);
-
- } else {
- b.putInt("displayed", 1);
- b.putParcelable("castedTube", peertube);
- intentBC.putExtras(b);
- LocalBroadcastManager.getInstance(PeertubeActivity.this).sendBroadcast(intentBC);
- try {
- Handler mainHandler = new Handler(Looper.getMainLooper());
- Runnable myRunnable = () -> {
- invalidateOptionsMenu();
- binding.castLoader.setVisibility(View.VISIBLE);
- player.setPlayWhenReady(false);
- binding.doubleTapPlayerView.setVisibility(View.GONE);
- binding.castController.setVisibility(View.VISIBLE);
- dialog.dismiss();
- if (chromeCastVideoURL != null) {
- if (player != null && player.getCurrentPosition() > 0) {
- chromeCastVideoURL += "?start=" + (player.getCurrentPosition() / 1000);
- }
- }
- };
- mainHandler.post(myRunnable);
- if (!chromeCast.isConnected()) {
- chromeCast.connect();
- }
- myRunnable = this::invalidateOptionsMenu;
- mainHandler.post(myRunnable);
- Status status = chromeCast.getStatus();
- if (chromeCast.isAppAvailable(CAST_ID) && !status.isAppRunning(CAST_ID)) {
- chromeCast.launchApp(CAST_ID);
- }
-
- if (chromeCastVideoURL != null) {
- String mime = MimeTypeMap.getFileExtensionFromUrl(chromeCastVideoURL);
- chromeCast.setRequestTimeout(60000);
- chromeCast.load(peertube.getTitle(), null, chromeCastVideoURL, mime);
- chromeCast.play();
- binding.castPlay.setImageResource(R.drawable.ic_baseline_pause_32);
- }
- myRunnable = () -> binding.castLoader.setVisibility(View.GONE);
- mainHandler.post(myRunnable);
- } catch (IOException | GeneralSecurityException e) {
- e.printStackTrace();
- }
- }
-
- Handler mainHandler = new Handler(Looper.getMainLooper());
- Runnable myRunnable = () -> {
- invalidateOptionsMenu();
- dialog.dismiss();
- };
- mainHandler.post(myRunnable);
-
- }
- }).start();
-
- });
- alt_bld.setPositiveButton(R.string.close, (dialog, id) -> dialog.dismiss());
- AlertDialog alert = alt_bld.create();
- alert.show();
- }
}
return super.onOptionsItemSelected(item);
}
@@ -1417,6 +1263,7 @@ public class PeertubeActivity extends AppCompatActivity implements CommentListAd
});
}
+
/**
* Manage video to play with different factors
*
@@ -1429,7 +1276,10 @@ public class PeertubeActivity extends AppCompatActivity implements CommentListAd
* @param lang String ("en","fr", etc.)
*/
private void stream(VideoData.Video video, String localTorrentUrl, String resolution, boolean autoPlay, long position, Uri subtitles, String lang) {
- String videoURL = localTorrentUrl == null ? video.getFileUrl(resolution, PeertubeActivity.this) : localTorrentUrl;
+ videoURL = localTorrentUrl == null ? video.getFileUrl(resolution, PeertubeActivity.this) : localTorrentUrl;
+ 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"))) {
@@ -1503,6 +1353,7 @@ public class PeertubeActivity extends AppCompatActivity implements CommentListAd
if (autoPlay) {
binding.doubleTapPlayerView.hideController();
}
+ // loadCast(video, videoURL, subtitles!=null?subtitles.toString():null);
}
private void fetchComments() {
@@ -1544,7 +1395,7 @@ public class PeertubeActivity extends AppCompatActivity implements CommentListAd
snackbar.show();
return;
}
- chromeCastVideoURL = videoURL;
+
SharedPreferences sharedpreferences = getSharedPreferences(Helper.APP_PREFS, MODE_PRIVATE);
String nsfwAction = sharedpreferences.getString(getString(R.string.set_video_sensitive_choice), Helper.BLUR);
if (promptNSFW && peertube != null && peertube.isNsfw() && (nsfwAction.compareTo(Helper.BLUR) == 0 || nsfwAction.compareTo(Helper.DO_NOT_LIST) == 0)) {
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 b61a599..5f4bd17 100644
--- a/app/src/main/java/app/fedilab/fedilabtube/fragment/SettingsFragment.java
+++ b/app/src/main/java/app/fedilab/fedilabtube/fragment/SettingsFragment.java
@@ -34,6 +34,7 @@ import java.util.List;
import java.util.Map;
import java.util.Set;
+import app.fedilab.fedilabtube.BuildConfig;
import app.fedilab.fedilabtube.MainActivity;
import app.fedilab.fedilabtube.R;
import app.fedilab.fedilabtube.client.RetrofitPeertubeAPI;
@@ -315,7 +316,7 @@ public class SettingsFragment extends PreferenceFragmentCompat implements Shared
CharSequence[] entriesTheme = arrayTheme.toArray(new CharSequence[0]);
CharSequence[] entryValuesTheme = new CharSequence[3];
final SharedPreferences sharedpref = context.getSharedPreferences(Helper.APP_PREFS, Context.MODE_PRIVATE);
- int currentTheme = sharedpref.getInt(Helper.SET_THEME, Helper.DEFAULT_MODE);
+ int currentTheme = sharedpref.getInt(Helper.SET_THEME, BuildConfig.default_theme);
entryValuesTheme[0] = String.valueOf(Helper.LIGHT_MODE);
entryValuesTheme[1] = String.valueOf(Helper.DARK_MODE);
entryValuesTheme[2] = String.valueOf(Helper.DEFAULT_MODE);
@@ -407,7 +408,7 @@ public class SettingsFragment extends PreferenceFragmentCompat implements Shared
set_video_in_list_choice.setChecked(videosInList);
//****** Allow Chromecast *******
- int cast = sharedpref.getInt(getString(R.string.set_cast_choice), 0);
+ int cast = sharedpref.getInt(getString(R.string.set_cast_choice), BuildConfig.cast_enabled);
SwitchPreference set_cast_choice = findPreference(getString(R.string.set_cast_choice));
assert set_cast_choice != null;
set_cast_choice.setChecked(cast == 1);
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 5f0846d..309be0a 100644
--- a/app/src/main/java/app/fedilab/fedilabtube/helper/Helper.java
+++ b/app/src/main/java/app/fedilab/fedilabtube/helper/Helper.java
@@ -135,6 +135,7 @@ public class Helper {
public static final String VIDEO_ID = "video_id_update";
public static final String APP_PREFS = "app_prefs";
public static final String CAST_ID = "D402501A";
+ public static final String CAST_ID_BITTUBE = "CBA4A31D";
public static final int VIDEOS_PER_PAGE = 10;
public static final String RECEIVE_ACTION = "receive_action";
public static final String SET_UNFOLLOW_VALIDATION = "set_unfollow_validation";
diff --git a/app/src/main/java/app/fedilab/fedilabtube/sqlite/AccountDAO.java b/app/src/main/java/app/fedilab/fedilabtube/sqlite/AccountDAO.java
index 38d498d..4cacb52 100644
--- a/app/src/main/java/app/fedilab/fedilabtube/sqlite/AccountDAO.java
+++ b/app/src/main/java/app/fedilab/fedilabtube/sqlite/AccountDAO.java
@@ -244,7 +244,7 @@ public class AccountDAO {
public List getAllPeertubeAccount() {
try {
- Cursor c = db.query(Sqlite.TABLE_USER_ACCOUNT, null, Sqlite.COL_SOFTWARE + "=? OR " + Sqlite.COL_SOFTWARE + "is null", new String[]{"PEERTUBE"}, null, null, Sqlite.COL_INSTANCE + " ASC", null);
+ Cursor c = db.query(Sqlite.TABLE_USER_ACCOUNT, null, Sqlite.COL_SOFTWARE + "=? OR " + Sqlite.COL_SOFTWARE + " is null", new String[]{"PEERTUBE"}, null, null, Sqlite.COL_INSTANCE + " ASC", null);
return cursorToListUser(c);
} catch (Exception e) {
e.printStackTrace();
diff --git a/app/src/main/res/layout/activity_peertube.xml b/app/src/main/res/layout/activity_peertube.xml
index e79789d..287458a 100644
--- a/app/src/main/res/layout/activity_peertube.xml
+++ b/app/src/main/res/layout/activity_peertube.xml
@@ -689,6 +689,5 @@
android:layout_gravity="center"
android:layout_margin="30dp" />
-
diff --git a/app/src/no_google_cast_lib/java/app/fedilab/fedilabtube/BaseMainActivity.java b/app/src/no_google_cast_lib/java/app/fedilab/fedilabtube/BaseMainActivity.java
new file mode 100644
index 0000000..46c3bb8
--- /dev/null
+++ b/app/src/no_google_cast_lib/java/app/fedilab/fedilabtube/BaseMainActivity.java
@@ -0,0 +1,261 @@
+package app.fedilab.fedilabtube;
+/* Copyright 2021 Thomas Schneider
+ *
+ * This file is a part of TubeLab
+ *
+ * This program is free software; you can redistribute it and/or modify it under the terms of the
+ * GNU General Public License as published by the Free Software Foundation; either version 3 of the
+ * License, or (at your option) any later version.
+ *
+ * TubeLab 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 General
+ * Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along with TubeLab; if not,
+ * see . */
+
+import android.content.BroadcastReceiver;
+import android.content.Context;
+import android.content.Intent;
+import android.content.IntentFilter;
+import android.os.Bundle;
+import android.os.Handler;
+import android.os.Looper;
+import android.view.View;
+
+import androidx.appcompat.app.AppCompatActivity;
+import androidx.localbroadcastmanager.content.LocalBroadcastManager;
+
+import java.io.IOException;
+import java.net.InetAddress;
+import java.net.NetworkInterface;
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.Enumeration;
+import java.util.List;
+
+import app.fedilab.fedilabtube.client.data.VideoData;
+import app.fedilab.fedilabtube.databinding.ActivityMainBinding;
+import app.fedilab.fedilabtube.helper.Helper;
+import su.litvak.chromecast.api.v2.ChromeCast;
+import su.litvak.chromecast.api.v2.ChromeCasts;
+import su.litvak.chromecast.api.v2.ChromeCastsListener;
+import su.litvak.chromecast.api.v2.MediaStatus;
+
+public abstract class BaseMainActivity extends AppCompatActivity implements ChromeCastsListener {
+
+ public static List chromeCasts;
+ public static ChromeCast chromeCast;
+ public static boolean chromecastActivated = false;
+ protected ActivityMainBinding binding;
+ private BroadcastReceiver manage_chromecast;
+ private VideoData.Video castedTube;
+
+ @Override
+ protected void onCreate(Bundle savedInstanceState) {
+ super.onCreate(savedInstanceState);
+ binding = ActivityMainBinding.inflate(getLayoutInflater());
+ View view = binding.getRoot();
+ setContentView(view);
+ ChromeCastsListener chromeCastsListener = this;
+ ChromeCasts.registerListener(chromeCastsListener);
+
+
+ binding.castClose.setOnClickListener(v -> {
+ Intent intentBC = new Intent(Helper.RECEIVE_CAST_SETTINGS);
+ Bundle b = new Bundle();
+ b.putInt("displayed", 0);
+ intentBC.putExtras(b);
+ LocalBroadcastManager.getInstance(BaseMainActivity.this).sendBroadcast(intentBC);
+ });
+
+ binding.castTogglePlay.setOnClickListener(v -> {
+ if (chromeCast != null) {
+ new Thread(() -> {
+ try {
+ Handler mainHandler = new Handler(Looper.getMainLooper());
+ Runnable myRunnable = () -> binding.castTogglePlay.setVisibility(View.GONE);
+ mainHandler.post(myRunnable);
+ int icon = -1;
+ if (chromeCast.getMediaStatus().playerState == MediaStatus.PlayerState.PLAYING) {
+ chromeCast.pause();
+ icon = R.drawable.ic_baseline_play_arrow_32;
+ } else if (chromeCast.getMediaStatus().playerState == MediaStatus.PlayerState.PAUSED) {
+ chromeCast.play();
+ icon = R.drawable.ic_baseline_pause_32;
+ }
+ if (icon != -1) {
+ int finalIcon = icon;
+ myRunnable = () -> binding.castTogglePlay.setImageResource(finalIcon);
+ mainHandler.post(myRunnable);
+ }
+ myRunnable = () -> binding.castTogglePlay.setVisibility(View.VISIBLE);
+ mainHandler.post(myRunnable);
+ } catch (IOException e) {
+ e.printStackTrace();
+ }
+ }).start();
+ }
+ });
+
+
+ manage_chromecast = new BroadcastReceiver() {
+ @Override
+ public void onReceive(Context context, Intent intent) {
+ Bundle b = intent.getExtras();
+ assert b != null;
+ int state = b.getInt("state_asked", -1);
+ int displayed = b.getInt("displayed", -1);
+ castedTube = b.getParcelable("castedTube");
+
+ if (state == 1) {
+ discoverCast();
+ } else if (state == 0) {
+ new Thread(() -> {
+ try {
+ if (chromeCast != null) {
+ chromeCast.stopApp();
+ chromeCast.disconnect();
+ }
+ } catch (IOException e) {
+ e.printStackTrace();
+ }
+ }).start();
+ }
+ if (displayed == 1) {
+ chromecastActivated = true;
+ if (castedTube != null) {
+ binding.castInfo.setVisibility(View.VISIBLE);
+ Helper.loadGiF(BaseMainActivity.this, castedTube.getThumbnailPath(), binding.castView);
+ binding.castTitle.setText(castedTube.getTitle());
+ binding.castDescription.setText(castedTube.getDescription());
+ }
+ } else if (displayed == 0) {
+ chromecastActivated = false;
+ binding.castInfo.setVisibility(View.GONE);
+ new Thread(() -> {
+ try {
+ if (chromeCast != null) {
+ chromeCast.stopApp();
+ }
+ } catch (IOException e) {
+ e.printStackTrace();
+ }
+ }).start();
+ }
+ }
+ };
+ LocalBroadcastManager.getInstance(BaseMainActivity.this).registerReceiver(manage_chromecast, new IntentFilter(Helper.RECEIVE_CAST_SETTINGS));
+ }
+
+ @Override
+ public void newChromeCastDiscovered(ChromeCast chromeCast) {
+ if (chromeCasts == null) {
+ chromeCasts = new ArrayList<>();
+ chromeCasts.add(chromeCast);
+ } else {
+ boolean canBeAdded = true;
+ for (ChromeCast cast : chromeCasts) {
+ if (cast.getName().compareTo(chromeCast.getName()) == 0) {
+ canBeAdded = false;
+ break;
+ }
+ }
+ if (canBeAdded) {
+ chromeCasts.add(chromeCast);
+ }
+ }
+ try {
+ if (chromeCast.isAppRunning(Helper.CAST_ID) && chromeCast.getMediaStatus() != null && chromeCast.getMediaStatus().playerState != null) {
+ if (binding.castInfo.getVisibility() == View.GONE) {
+ binding.castInfo.setVisibility(View.VISIBLE);
+ }
+ }
+ } catch (IOException e) {
+ e.printStackTrace();
+ }
+
+ }
+
+ @Override
+ public void chromeCastRemoved(ChromeCast chromeCast) {
+
+ }
+
+ @Override
+ public void onDestroy() {
+ super.onDestroy();
+ ChromeCasts.unregisterListener(this);
+ if (manage_chromecast != null) {
+ LocalBroadcastManager.getInstance(BaseMainActivity.this).unregisterReceiver(manage_chromecast);
+
+ new Thread(() -> {
+ if (chromeCasts != null && chromeCasts.size() > 0) {
+ for (ChromeCast cast : chromeCasts) {
+ try {
+ cast.stopApp();
+ cast.disconnect();
+ } catch (IOException e) {
+ e.printStackTrace();
+ }
+ }
+ }
+ }).start();
+ }
+ if (chromeCasts != null) {
+ chromeCasts = null;
+ }
+ if (chromeCast != null) {
+ chromeCast = null;
+ }
+ }
+
+
+ //Method for discovering cast devices
+ public void discoverCast() {
+
+ new Thread(() -> {
+ if (chromeCasts != null) {
+ for (ChromeCast cast : chromeCasts) {
+ try {
+ cast.disconnect();
+ } catch (IOException e) {
+ e.printStackTrace();
+ }
+ }
+ chromeCasts = null;
+ }
+ chromeCasts = new ArrayList<>();
+ try {
+ List interfaces;
+ interfaces = Collections.list(NetworkInterface.getNetworkInterfaces());
+ for (NetworkInterface ni : interfaces) {
+ if ((!ni.isLoopback()) && ni.isUp() && (ni.getName().equals("wlan0"))) {
+ Enumeration inetAddressEnumeration = ni.getInetAddresses();
+ while (inetAddressEnumeration.hasMoreElements()) {
+ InetAddress inetAddress = inetAddressEnumeration.nextElement();
+ ChromeCasts.restartDiscovery(inetAddress);
+ int tryFind = 0;
+ while (ChromeCasts.get().isEmpty() && tryFind < 5) {
+ try {
+ //noinspection BusyWait
+ Thread.sleep(1000);
+ tryFind++;
+ } catch (InterruptedException ignored) {
+ }
+ }
+ }
+ }
+ }
+ ChromeCasts.stopDiscovery();
+ Handler mainHandler = new Handler(Looper.getMainLooper());
+ Runnable myRunnable = this::invalidateOptionsMenu;
+ mainHandler.post(myRunnable);
+ } catch (IOException e) {
+ e.printStackTrace();
+ }
+ }).start();
+ }
+
+
+}
diff --git a/app/src/no_google_cast_lib/java/app/fedilab/fedilabtube/BasePeertubeActivity.java b/app/src/no_google_cast_lib/java/app/fedilab/fedilabtube/BasePeertubeActivity.java
new file mode 100644
index 0000000..dc695b7
--- /dev/null
+++ b/app/src/no_google_cast_lib/java/app/fedilab/fedilabtube/BasePeertubeActivity.java
@@ -0,0 +1,206 @@
+package app.fedilab.fedilabtube;
+
+import android.content.Intent;
+import android.os.Bundle;
+import android.os.Handler;
+import android.os.Looper;
+import android.view.Menu;
+import android.view.MenuItem;
+import android.view.View;
+import android.webkit.MimeTypeMap;
+
+import androidx.appcompat.app.AlertDialog;
+import androidx.appcompat.app.AppCompatActivity;
+import androidx.localbroadcastmanager.content.LocalBroadcastManager;
+
+import com.google.android.exoplayer2.SimpleExoPlayer;
+
+import org.jetbrains.annotations.NotNull;
+
+import java.io.IOException;
+import java.security.GeneralSecurityException;
+
+import app.fedilab.fedilabtube.client.data.VideoData;
+import app.fedilab.fedilabtube.databinding.ActivityPeertubeBinding;
+import app.fedilab.fedilabtube.helper.Helper;
+import su.litvak.chromecast.api.v2.ChromeCast;
+import su.litvak.chromecast.api.v2.MediaStatus;
+import su.litvak.chromecast.api.v2.Status;
+
+import static app.fedilab.fedilabtube.helper.Helper.CAST_ID;
+
+/* Copyright 2021 Thomas Schneider
+ *
+ * This file is a part of TubeLab
+ *
+ * This program is free software; you can redistribute it and/or modify it under the terms of the
+ * GNU General Public License as published by the Free Software Foundation; either version 3 of the
+ * License, or (at your option) any later version.
+ *
+ * TubeLab 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 General
+ * Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along with TubeLab; if not,
+ * see . */
+
+public class BasePeertubeActivity extends AppCompatActivity {
+
+ protected ActivityPeertubeBinding binding;
+ private String chromeCastVideoURL;
+ protected VideoData.Video peertube;
+ protected SimpleExoPlayer player;
+ protected String videoURL;
+ protected String subtitlesStr;
+
+
+ @Override
+ protected void onCreate(Bundle savedInstanceState) {
+ super.onCreate(savedInstanceState);
+ binding = ActivityPeertubeBinding.inflate(getLayoutInflater());
+ View view = binding.getRoot();
+ setContentView(view);
+ binding.castPlay.setOnClickListener(v -> {
+ binding.castLoader.setVisibility(View.VISIBLE);
+ if (BaseMainActivity.chromeCast != null) {
+ new Thread(() -> {
+ try {
+ int icon = -1;
+ if (BaseMainActivity.chromeCast.getMediaStatus().playerState == MediaStatus.PlayerState.PLAYING) {
+ BaseMainActivity.chromeCast.pause();
+ icon = R.drawable.ic_baseline_play_arrow_32;
+ } else if (BaseMainActivity.chromeCast.getMediaStatus().playerState == MediaStatus.PlayerState.PAUSED) {
+ BaseMainActivity.chromeCast.play();
+ icon = R.drawable.ic_baseline_pause_32;
+ }
+ if (icon != -1) {
+ Handler mainHandler = new Handler(Looper.getMainLooper());
+ int finalIcon = icon;
+ Runnable myRunnable = () -> binding.castPlay.setImageResource(finalIcon);
+ mainHandler.post(myRunnable);
+ }
+ Handler mainHandler = new Handler(Looper.getMainLooper());
+ Runnable myRunnable = () -> binding.castLoader.setVisibility(View.GONE);
+ mainHandler.post(myRunnable);
+ } catch (IOException e) {
+ e.printStackTrace();
+ }
+ }).start();
+ }
+ });
+ }
+
+ @Override
+ public boolean onOptionsItemSelected(MenuItem item) {
+ if (item.getItemId() == R.id.action_cast) {
+ if (BaseMainActivity.chromeCasts != null && BaseMainActivity.chromeCasts.size() > 0) {
+ String[] chromecast_choice = new String[BaseMainActivity.chromeCasts.size()];
+ AlertDialog.Builder alt_bld = new AlertDialog.Builder(this);
+ alt_bld.setTitle(R.string.chromecast_choice);
+ int i = 0;
+ for (ChromeCast cc : BaseMainActivity.chromeCasts) {
+ chromecast_choice[i] = cc.getTitle();
+ i++;
+ }
+ i = 0;
+ for (ChromeCast cc : BaseMainActivity.chromeCasts) {
+ if (BaseMainActivity.chromecastActivated && cc.isConnected()) {
+ break;
+ }
+ i++;
+ }
+
+ alt_bld.setSingleChoiceItems(chromecast_choice, i, (dialog, position) -> {
+ BaseMainActivity.chromeCast = BaseMainActivity.chromeCasts.get(position);
+ new Thread(() -> {
+ if (BaseMainActivity.chromeCast != null) {
+ Intent intentBC = new Intent(Helper.RECEIVE_CAST_SETTINGS);
+ Bundle b = new Bundle();
+ if (BaseMainActivity.chromecastActivated) {
+ b.putInt("displayed", 0);
+ intentBC.putExtras(b);
+ LocalBroadcastManager.getInstance(BasePeertubeActivity.this).sendBroadcast(intentBC);
+ Handler mainHandler = new Handler(Looper.getMainLooper());
+ Runnable myRunnable = () -> {
+ binding.doubleTapPlayerView.setVisibility(View.VISIBLE);
+ binding.castController.setVisibility(View.GONE);
+ };
+ mainHandler.post(myRunnable);
+
+ } else {
+ b.putInt("displayed", 1);
+ b.putParcelable("castedTube", peertube);
+ intentBC.putExtras(b);
+ LocalBroadcastManager.getInstance(BasePeertubeActivity.this).sendBroadcast(intentBC);
+ try {
+ Handler mainHandler = new Handler(Looper.getMainLooper());
+ Runnable myRunnable = () -> {
+ invalidateOptionsMenu();
+ binding.castLoader.setVisibility(View.VISIBLE);
+ player.setPlayWhenReady(false);
+ binding.doubleTapPlayerView.setVisibility(View.GONE);
+ binding.castController.setVisibility(View.VISIBLE);
+ dialog.dismiss();
+ if (chromeCastVideoURL != null) {
+ if (player != null && player.getCurrentPosition() > 0) {
+ chromeCastVideoURL += "?start=" + (player.getCurrentPosition() / 1000);
+ }
+ }
+ };
+ mainHandler.post(myRunnable);
+ if (!BaseMainActivity.chromeCast.isConnected()) {
+ BaseMainActivity.chromeCast.connect();
+ }
+ myRunnable = this::invalidateOptionsMenu;
+ mainHandler.post(myRunnable);
+ Status status = BaseMainActivity.chromeCast.getStatus();
+ if (BaseMainActivity.chromeCast.isAppAvailable(CAST_ID) && !status.isAppRunning(CAST_ID)) {
+ BaseMainActivity.chromeCast.launchApp(CAST_ID);
+ }
+ if (chromeCastVideoURL != null) {
+ String mime = MimeTypeMap.getFileExtensionFromUrl(chromeCastVideoURL);
+ BaseMainActivity.chromeCast.setRequestTimeout(60000);
+ BaseMainActivity.chromeCast.load(peertube.getTitle(), null, chromeCastVideoURL, mime);
+ BaseMainActivity.chromeCast.play();
+ binding.castPlay.setImageResource(R.drawable.ic_baseline_pause_32);
+ }
+ myRunnable = () -> binding.castLoader.setVisibility(View.GONE);
+ mainHandler.post(myRunnable);
+ } catch (IOException | GeneralSecurityException e) {
+ e.printStackTrace();
+ }
+ }
+ Handler mainHandler = new Handler(Looper.getMainLooper());
+ Runnable myRunnable = () -> {
+ invalidateOptionsMenu();
+ dialog.dismiss();
+ };
+ mainHandler.post(myRunnable);
+ }
+ }).start();
+ });
+ alt_bld.setPositiveButton(R.string.close, (dialog, id) -> dialog.dismiss());
+ AlertDialog alert = alt_bld.create();
+ alert.show();
+ }
+ }
+ return super.onOptionsItemSelected(item);
+ }
+
+
+ @Override
+ public boolean onCreateOptionsMenu(@NotNull Menu menu) {
+ getMenuInflater().inflate(R.menu.video_menu, menu);
+ MenuItem castItem = menu.findItem(R.id.action_cast);
+ if (BaseMainActivity.chromeCasts != null && BaseMainActivity.chromeCasts.size() > 0) {
+ castItem.setVisible(true);
+ if (BaseMainActivity.chromeCast != null && BaseMainActivity.chromeCast.isConnected()) {
+ castItem.setIcon(R.drawable.ic_baseline_cast_connected_24);
+ } else {
+ castItem.setIcon(R.drawable.ic_baseline_cast_24);
+ }
+ }
+ return true;
+ }
+
+}
diff --git a/app/src/main/java/app/fedilab/fedilabtube/helper/DashCastRequest.java b/app/src/no_google_cast_lib/java/app/fedilab/fedilabtube/DashCastRequest.java
similarity index 100%
rename from app/src/main/java/app/fedilab/fedilabtube/helper/DashCastRequest.java
rename to app/src/no_google_cast_lib/java/app/fedilab/fedilabtube/DashCastRequest.java
diff --git a/app/src/no_google_cast_lib/java/app/fedilab/fedilabtube/provider/CastOptionsProvider.java b/app/src/no_google_cast_lib/java/app/fedilab/fedilabtube/provider/CastOptionsProvider.java
new file mode 100644
index 0000000..70d5277
--- /dev/null
+++ b/app/src/no_google_cast_lib/java/app/fedilab/fedilabtube/provider/CastOptionsProvider.java
@@ -0,0 +1,18 @@
+package app.fedilab.fedilabtube.provider;
+/* Copyright 2021 Thomas Schneider
+ *
+ * This file is a part of TubeLab
+ *
+ * This program is free software; you can redistribute it and/or modify it under the terms of the
+ * GNU General Public License as published by the Free Software Foundation; either version 3 of the
+ * License, or (at your option) any later version.
+ *
+ * TubeLab 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 General
+ * Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along with TubeLab; if not,
+ * see . */
+
+public class CastOptionsProvider {
+}
\ No newline at end of file
diff --git a/app/src/main/res/menu/video_menu.xml b/app/src/no_google_cast_lib/res/menu/video_menu.xml
similarity index 100%
rename from app/src/main/res/menu/video_menu.xml
rename to app/src/no_google_cast_lib/res/menu/video_menu.xml