1
0
Fork 0
mirror of https://gitlab.com/futo-org/fcast.git synced 2025-06-24 21:25:23 +00:00

Fixed issue causing FCast Receiver to freeze. Added support to request headers on Android implementation.

This commit is contained in:
Koen 2024-01-04 09:37:14 +01:00
parent bc84f7b767
commit 9b14e665b5
3 changed files with 37 additions and 9 deletions

View file

@ -8,7 +8,8 @@ data class PlayMessage(
val url: String? = null, val url: String? = null,
val content: String? = null, val content: String? = null,
val time: Double? = null, val time: Double? = null,
val speed: Double? = null val speed: Double? = null,
val headers: Map<String, String>? = null
) )
@Serializable @Serializable

View file

@ -2,7 +2,11 @@ package com.futo.fcast.receiver
import android.content.Context import android.content.Context
import android.graphics.drawable.Animatable import android.graphics.drawable.Animatable
import android.net.* import android.net.ConnectivityManager
import android.net.Network
import android.net.NetworkCapabilities
import android.net.NetworkRequest
import android.net.Uri
import android.os.Build import android.os.Build
import android.os.Bundle import android.os.Bundle
import android.util.Log import android.util.Log
@ -14,19 +18,29 @@ import android.widget.ImageView
import android.widget.TextView import android.widget.TextView
import androidx.appcompat.app.AppCompatActivity import androidx.appcompat.app.AppCompatActivity
import androidx.constraintlayout.widget.ConstraintLayout import androidx.constraintlayout.widget.ConstraintLayout
import com.google.android.exoplayer2.* import com.google.android.exoplayer2.ExoPlayer
import com.google.android.exoplayer2.MediaItem
import com.google.android.exoplayer2.PlaybackException
import com.google.android.exoplayer2.PlaybackParameters
import com.google.android.exoplayer2.Player
import com.google.android.exoplayer2.source.DefaultMediaSourceFactory import com.google.android.exoplayer2.source.DefaultMediaSourceFactory
import com.google.android.exoplayer2.source.dash.DashMediaSource import com.google.android.exoplayer2.source.dash.DashMediaSource
import com.google.android.exoplayer2.source.hls.HlsMediaSource import com.google.android.exoplayer2.source.hls.HlsMediaSource
import com.google.android.exoplayer2.trackselection.DefaultTrackSelector import com.google.android.exoplayer2.trackselection.DefaultTrackSelector
import com.google.android.exoplayer2.ui.StyledPlayerView import com.google.android.exoplayer2.ui.StyledPlayerView
import com.google.android.exoplayer2.upstream.DefaultDataSource import com.google.android.exoplayer2.upstream.DefaultDataSource
import kotlinx.coroutines.* import com.google.android.exoplayer2.upstream.DefaultHttpDataSource
import com.google.android.exoplayer2.upstream.HttpDataSource
import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.cancel
import kotlinx.coroutines.launch
import java.io.File import java.io.File
import java.io.FileOutputStream import java.io.FileOutputStream
import kotlin.math.abs import kotlin.math.abs
import kotlin.math.max import kotlin.math.max
class PlayerActivity : AppCompatActivity() { class PlayerActivity : AppCompatActivity() {
private lateinit var _playerControlView: StyledPlayerView private lateinit var _playerControlView: StyledPlayerView
private lateinit var _imageSpinner: ImageView private lateinit var _imageSpinner: ImageView
@ -320,7 +334,15 @@ class PlayerActivity : AppCompatActivity() {
throw IllegalArgumentException("Either URL or content must be provided.") throw IllegalArgumentException("Either URL or content must be provided.")
} }
val dataSourceFactory = DefaultDataSource.Factory(this) val dataSourceFactory = if (playMessage.headers != null) {
val httpDataSourceFactory: HttpDataSource.Factory = DefaultHttpDataSource.Factory()
httpDataSourceFactory.setDefaultRequestProperties(playMessage.headers)
DefaultDataSource.Factory(this, httpDataSourceFactory)
} else {
DefaultDataSource.Factory(this)
}
val mediaItem = mediaItemBuilder.build() val mediaItem = mediaItemBuilder.build()
val mediaSource = when (playMessage.container) { val mediaSource = when (playMessage.container) {
"application/dash+xml" -> DashMediaSource.Factory(dataSourceFactory).createMediaSource(mediaItem) "application/dash+xml" -> DashMediaSource.Factory(dataSourceFactory).createMediaSource(mediaItem)

View file

@ -12,6 +12,7 @@ class TcpListenerService(private val _networkService: NetworkService, private va
private var _listenThread: Thread? = null private var _listenThread: Thread? = null
private var _clientThreads: ArrayList<Thread> = arrayListOf() private var _clientThreads: ArrayList<Thread> = arrayListOf()
private var _sessions: ArrayList<FCastSession> = arrayListOf() private var _sessions: ArrayList<FCastSession> = arrayListOf()
private var _serverSocket: ServerSocket? = null
fun start() { fun start() {
Log.i(TAG, "Starting TcpListenerService") Log.i(TAG, "Starting TcpListenerService")
@ -36,6 +37,9 @@ class TcpListenerService(private val _networkService: NetworkService, private va
_stopped = true _stopped = true
_serverSocket?.close()
_serverSocket = null
_listenThread?.join() _listenThread?.join()
_listenThread = null _listenThread = null
@ -59,13 +63,13 @@ class TcpListenerService(private val _networkService: NetworkService, private va
while (!_stopped) { while (!_stopped) {
try { try {
val serverSocket = ServerSocket() _serverSocket = ServerSocket()
try { try {
serverSocket.bind(InetSocketAddress(PORT)) _serverSocket!!.bind(InetSocketAddress(PORT))
while (!_stopped) { while (!_stopped) {
val clientSocket = serverSocket.accept() ?: break val clientSocket = _serverSocket!!.accept() ?: break
val clientThread = Thread { val clientThread = Thread {
try { try {
Log.i(TAG, "New connection received from ${clientSocket.remoteSocketAddress}") Log.i(TAG, "New connection received from ${clientSocket.remoteSocketAddress}")
@ -97,7 +101,8 @@ class TcpListenerService(private val _networkService: NetworkService, private va
Log.e(TAG, "Failed to accept client connection due to an error, sleeping 1 second then restarting", e) Log.e(TAG, "Failed to accept client connection due to an error, sleeping 1 second then restarting", e)
Thread.sleep(1000) Thread.sleep(1000)
} finally { } finally {
serverSocket.close() _serverSocket?.close()
_serverSocket = null
} }
} catch (e: Throwable) { } catch (e: Throwable) {
Log.e(TAG, "Failed to create server socket, sleeping 1 second then restarting", e) Log.e(TAG, "Failed to create server socket, sleeping 1 second then restarting", e)