package app.fedilab.android.activities; /* Copyright 2023 Thomas Schneider * * This file is a part of Fedilab * * 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. * * Fedilab 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 Fedilab; if not, * see . */ import android.content.BroadcastReceiver; import android.content.Context; import android.content.Intent; import android.content.IntentFilter; import android.os.Build; import android.os.Bundle; import android.os.Handler; import android.os.Looper; import android.view.View; import androidx.core.content.ContextCompat; 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.android.R; import app.fedilab.android.databinding.ActivityMainPeertubeBinding; import app.fedilab.android.mastodon.activities.BaseActivity; import app.fedilab.android.peertube.client.data.VideoData; import app.fedilab.android.peertube.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 PeertubeBaseMainActivity extends BaseActivity implements ChromeCastsListener { public static List chromeCasts; public static ChromeCast chromeCast; public static boolean chromecastActivated = false; protected ActivityMainPeertubeBinding binding; private BroadcastReceiver manage_chromecast; private VideoData.Video castedTube; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); binding = ActivityMainPeertubeBinding.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(PeertubeBaseMainActivity.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 = (VideoData.Video) b.getSerializable("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(PeertubeBaseMainActivity.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(); } } }; ContextCompat.registerReceiver(PeertubeBaseMainActivity.this, manage_chromecast, new IntentFilter(Helper.RECEIVE_CAST_SETTINGS), ContextCompat.RECEIVER_NOT_EXPORTED); } @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) { 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(); } }