mirror of
https://gitlab.futo.org/videostreaming/grayjay.git
synced 2026-05-16 04:52:39 +02:00
Merge branch 'master' of gitlab.futo.org:videostreaming/grayjay
This commit is contained in:
+1
-1
@@ -232,7 +232,7 @@ dependencies {
|
|||||||
androidTestImplementation 'androidx.test.espresso:espresso-core:3.7.0'
|
androidTestImplementation 'androidx.test.espresso:espresso-core:3.7.0'
|
||||||
|
|
||||||
//Rust casting SDK
|
//Rust casting SDK
|
||||||
implementation('org.futo.gitlab.videostreaming.fcast-sdk-jitpack:sender-sdk-minimal:0.3.1') {
|
implementation('org.futo.gitlab.videostreaming.fcast-sdk-jitpack:sender-sdk-minimal:0.4.0') {
|
||||||
// Polycentricandroid includes this
|
// Polycentricandroid includes this
|
||||||
exclude group: 'net.java.dev.jna'
|
exclude group: 'net.java.dev.jna'
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,5 +1,6 @@
|
|||||||
package com.futo.platformplayer.casting
|
package com.futo.platformplayer.casting
|
||||||
|
|
||||||
|
import com.futo.platformplayer.constructs.Event0
|
||||||
import com.futo.platformplayer.constructs.Event1
|
import com.futo.platformplayer.constructs.Event1
|
||||||
import com.futo.platformplayer.models.CastingDeviceInfo
|
import com.futo.platformplayer.models.CastingDeviceInfo
|
||||||
import org.fcast.sender_sdk.Metadata
|
import org.fcast.sender_sdk.Metadata
|
||||||
@@ -16,6 +17,7 @@ abstract class CastingDevice {
|
|||||||
abstract val onDurationChanged: Event1<Double>
|
abstract val onDurationChanged: Event1<Double>
|
||||||
abstract val onVolumeChanged: Event1<Double>
|
abstract val onVolumeChanged: Event1<Double>
|
||||||
abstract val onSpeedChanged: Event1<Double>
|
abstract val onSpeedChanged: Event1<Double>
|
||||||
|
abstract val onMediaItemEnd: Event0
|
||||||
abstract var connectionState: CastConnectionState
|
abstract var connectionState: CastConnectionState
|
||||||
abstract val protocolType: CastProtocolType
|
abstract val protocolType: CastProtocolType
|
||||||
abstract var isPlaying: Boolean
|
abstract var isPlaying: Boolean
|
||||||
|
|||||||
@@ -2,12 +2,14 @@ package com.futo.platformplayer.casting
|
|||||||
|
|
||||||
import android.os.Build
|
import android.os.Build
|
||||||
import com.futo.platformplayer.BuildConfig
|
import com.futo.platformplayer.BuildConfig
|
||||||
|
import com.futo.platformplayer.constructs.Event0
|
||||||
import com.futo.platformplayer.constructs.Event1
|
import com.futo.platformplayer.constructs.Event1
|
||||||
import com.futo.platformplayer.logging.Logger
|
import com.futo.platformplayer.logging.Logger
|
||||||
import com.futo.platformplayer.models.CastingDeviceInfo
|
import com.futo.platformplayer.models.CastingDeviceInfo
|
||||||
|
import com.futo.polycentric.core.Event
|
||||||
import org.fcast.sender_sdk.ApplicationInfo
|
import org.fcast.sender_sdk.ApplicationInfo
|
||||||
import org.fcast.sender_sdk.GenericKeyEvent
|
import org.fcast.sender_sdk.KeyEvent
|
||||||
import org.fcast.sender_sdk.GenericMediaEvent
|
import org.fcast.sender_sdk.MediaEvent
|
||||||
import org.fcast.sender_sdk.PlaybackState
|
import org.fcast.sender_sdk.PlaybackState
|
||||||
import org.fcast.sender_sdk.Source
|
import org.fcast.sender_sdk.Source
|
||||||
import java.net.InetAddress
|
import java.net.InetAddress
|
||||||
@@ -15,8 +17,10 @@ import org.fcast.sender_sdk.CastingDevice as RsCastingDevice;
|
|||||||
import org.fcast.sender_sdk.DeviceEventHandler as RsDeviceEventHandler;
|
import org.fcast.sender_sdk.DeviceEventHandler as RsDeviceEventHandler;
|
||||||
import org.fcast.sender_sdk.DeviceConnectionState
|
import org.fcast.sender_sdk.DeviceConnectionState
|
||||||
import org.fcast.sender_sdk.DeviceFeature
|
import org.fcast.sender_sdk.DeviceFeature
|
||||||
|
import org.fcast.sender_sdk.EventSubscription
|
||||||
import org.fcast.sender_sdk.IpAddr
|
import org.fcast.sender_sdk.IpAddr
|
||||||
import org.fcast.sender_sdk.LoadRequest
|
import org.fcast.sender_sdk.LoadRequest
|
||||||
|
import org.fcast.sender_sdk.MediaItemEventType
|
||||||
import org.fcast.sender_sdk.Metadata
|
import org.fcast.sender_sdk.Metadata
|
||||||
import org.fcast.sender_sdk.ProtocolType
|
import org.fcast.sender_sdk.ProtocolType
|
||||||
import org.fcast.sender_sdk.urlFormatIpAddr
|
import org.fcast.sender_sdk.urlFormatIpAddr
|
||||||
@@ -63,6 +67,7 @@ class CastingDeviceExp(val device: RsCastingDevice) : CastingDevice() {
|
|||||||
var onDurationChanged = Event1<Double>()
|
var onDurationChanged = Event1<Double>()
|
||||||
var onVolumeChanged = Event1<Double>()
|
var onVolumeChanged = Event1<Double>()
|
||||||
var onSpeedChanged = Event1<Double>()
|
var onSpeedChanged = Event1<Double>()
|
||||||
|
var onMediaItemEnd = Event0()
|
||||||
|
|
||||||
override fun connectionStateChanged(state: DeviceConnectionState) {
|
override fun connectionStateChanged(state: DeviceConnectionState) {
|
||||||
onConnectionStateChanged.emit(state)
|
onConnectionStateChanged.emit(state)
|
||||||
@@ -92,12 +97,14 @@ class CastingDeviceExp(val device: RsCastingDevice) : CastingDevice() {
|
|||||||
// TODO
|
// TODO
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun keyEvent(event: GenericKeyEvent) {
|
override fun keyEvent(event: KeyEvent) {
|
||||||
// Unreachable
|
// Unreachable
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun mediaEvent(event: GenericMediaEvent) {
|
override fun mediaEvent(event: MediaEvent) {
|
||||||
// Unreachable
|
if (event.type == MediaItemEventType.END) {
|
||||||
|
onMediaItemEnd.emit()
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun playbackError(message: String) {
|
override fun playbackError(message: String) {
|
||||||
@@ -127,6 +134,8 @@ class CastingDeviceExp(val device: RsCastingDevice) : CastingDevice() {
|
|||||||
get() = eventHandler.onVolumeChanged
|
get() = eventHandler.onVolumeChanged
|
||||||
override val onSpeedChanged: Event1<Double>
|
override val onSpeedChanged: Event1<Double>
|
||||||
get() = eventHandler.onSpeedChanged
|
get() = eventHandler.onSpeedChanged
|
||||||
|
override val onMediaItemEnd: Event0
|
||||||
|
get() = eventHandler.onMediaItemEnd
|
||||||
|
|
||||||
override fun resumePlayback() = device.resumePlayback()
|
override fun resumePlayback() = device.resumePlayback()
|
||||||
override fun pausePlayback() = device.pausePlayback()
|
override fun pausePlayback() = device.pausePlayback()
|
||||||
@@ -181,7 +190,8 @@ class CastingDeviceExp(val device: RsCastingDevice) : CastingDevice() {
|
|||||||
resumePosition = resumePosition,
|
resumePosition = resumePosition,
|
||||||
speed = speed,
|
speed = speed,
|
||||||
volume = volume,
|
volume = volume,
|
||||||
metadata = metadata
|
metadata = metadata,
|
||||||
|
requestHeaders = null,
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
|
|
||||||
@@ -200,6 +210,7 @@ class CastingDeviceExp(val device: RsCastingDevice) : CastingDevice() {
|
|||||||
speed = speed,
|
speed = speed,
|
||||||
volume = volume,
|
volume = volume,
|
||||||
metadata = metadata,
|
metadata = metadata,
|
||||||
|
requestHeaders = null,
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
|
|
||||||
@@ -227,6 +238,13 @@ class CastingDeviceExp(val device: RsCastingDevice) : CastingDevice() {
|
|||||||
eventHandler.onConnectionStateChanged.subscribe { newState ->
|
eventHandler.onConnectionStateChanged.subscribe { newState ->
|
||||||
when (newState) {
|
when (newState) {
|
||||||
is DeviceConnectionState.Connected -> {
|
is DeviceConnectionState.Connected -> {
|
||||||
|
if (device.supportsFeature(DeviceFeature.MEDIA_EVENT_SUBSCRIPTION)) {
|
||||||
|
try {
|
||||||
|
device.subscribeEvent(EventSubscription.MediaItemEnd)
|
||||||
|
} catch (e: Exception) {
|
||||||
|
Logger.e(TAG, "Failed to subscribe to MediaItemEnd events: $e")
|
||||||
|
}
|
||||||
|
}
|
||||||
usedRemoteAddress = ipAddrToInetAddress(newState.usedRemoteAddr)
|
usedRemoteAddress = ipAddrToInetAddress(newState.usedRemoteAddr)
|
||||||
localAddress = ipAddrToInetAddress(newState.localAddr)
|
localAddress = ipAddrToInetAddress(newState.localAddr)
|
||||||
connectionState = CastConnectionState.CONNECTED
|
connectionState = CastConnectionState.CONNECTED
|
||||||
|
|||||||
@@ -1,5 +1,6 @@
|
|||||||
package com.futo.platformplayer.casting
|
package com.futo.platformplayer.casting
|
||||||
|
|
||||||
|
import com.futo.platformplayer.constructs.Event0
|
||||||
import com.futo.platformplayer.constructs.Event1
|
import com.futo.platformplayer.constructs.Event1
|
||||||
import com.futo.platformplayer.models.CastingDeviceInfo
|
import com.futo.platformplayer.models.CastingDeviceInfo
|
||||||
import kotlinx.serialization.KSerializer
|
import kotlinx.serialization.KSerializer
|
||||||
@@ -181,6 +182,7 @@ class CastingDeviceLegacyWrapper(val inner: CastingDeviceLegacy) : CastingDevice
|
|||||||
override val onDurationChanged: Event1<Double> get() = inner.onDurationChanged
|
override val onDurationChanged: Event1<Double> get() = inner.onDurationChanged
|
||||||
override val onVolumeChanged: Event1<Double> get() = inner.onVolumeChanged
|
override val onVolumeChanged: Event1<Double> get() = inner.onVolumeChanged
|
||||||
override val onSpeedChanged: Event1<Double> get() = inner.onSpeedChanged
|
override val onSpeedChanged: Event1<Double> get() = inner.onSpeedChanged
|
||||||
|
override val onMediaItemEnd: Event0 = Event0()
|
||||||
override var connectionState: CastConnectionState
|
override var connectionState: CastConnectionState
|
||||||
get() = inner.connectionState
|
get() = inner.connectionState
|
||||||
set(_) = Unit
|
set(_) = Unit
|
||||||
|
|||||||
@@ -40,6 +40,7 @@ import com.futo.platformplayer.api.media.platforms.local.models.sources.LocalAud
|
|||||||
import com.futo.platformplayer.api.media.platforms.local.models.sources.LocalVideoContentSource
|
import com.futo.platformplayer.api.media.platforms.local.models.sources.LocalVideoContentSource
|
||||||
import com.futo.platformplayer.awaitCancelConverted
|
import com.futo.platformplayer.awaitCancelConverted
|
||||||
import com.futo.platformplayer.builders.DashBuilder
|
import com.futo.platformplayer.builders.DashBuilder
|
||||||
|
import com.futo.platformplayer.constructs.Event0
|
||||||
import com.futo.platformplayer.models.CastingDeviceInfo
|
import com.futo.platformplayer.models.CastingDeviceInfo
|
||||||
import com.futo.platformplayer.constructs.Event1
|
import com.futo.platformplayer.constructs.Event1
|
||||||
import com.futo.platformplayer.constructs.Event2
|
import com.futo.platformplayer.constructs.Event2
|
||||||
@@ -82,6 +83,7 @@ abstract class StateCasting {
|
|||||||
val onActiveDeviceTimeChanged = Event1<Double>();
|
val onActiveDeviceTimeChanged = Event1<Double>();
|
||||||
val onActiveDeviceDurationChanged = Event1<Double>();
|
val onActiveDeviceDurationChanged = Event1<Double>();
|
||||||
val onActiveDeviceVolumeChanged = Event1<Double>();
|
val onActiveDeviceVolumeChanged = Event1<Double>();
|
||||||
|
val onActiveDeviceMediaItemEnd = Event0()
|
||||||
var activeDevice: CastingDevice? = null;
|
var activeDevice: CastingDevice? = null;
|
||||||
private var _videoExecutor: JSRequestExecutor? = null
|
private var _videoExecutor: JSRequestExecutor? = null
|
||||||
private var _audioExecutor: JSRequestExecutor? = null
|
private var _audioExecutor: JSRequestExecutor? = null
|
||||||
@@ -145,6 +147,7 @@ abstract class StateCasting {
|
|||||||
device.onTimeChanged.clear();
|
device.onTimeChanged.clear();
|
||||||
device.onVolumeChanged.clear();
|
device.onVolumeChanged.clear();
|
||||||
device.onDurationChanged.clear();
|
device.onDurationChanged.clear();
|
||||||
|
device.onMediaItemEnd.clear();
|
||||||
ad.disconnect()
|
ad.disconnect()
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -159,6 +162,7 @@ abstract class StateCasting {
|
|||||||
device.onTimeChanged.clear();
|
device.onTimeChanged.clear();
|
||||||
device.onVolumeChanged.clear();
|
device.onVolumeChanged.clear();
|
||||||
device.onDurationChanged.clear();
|
device.onDurationChanged.clear();
|
||||||
|
device.onMediaItemEnd.clear();
|
||||||
activeDevice = null;
|
activeDevice = null;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -222,6 +226,9 @@ abstract class StateCasting {
|
|||||||
device.onTimeChanged.subscribe {
|
device.onTimeChanged.subscribe {
|
||||||
invokeInMainScopeIfRequired { onActiveDeviceTimeChanged.emit(it) };
|
invokeInMainScopeIfRequired { onActiveDeviceTimeChanged.emit(it) };
|
||||||
};
|
};
|
||||||
|
device.onMediaItemEnd.subscribe {
|
||||||
|
invokeInMainScopeIfRequired { onActiveDeviceMediaItemEnd.emit() }
|
||||||
|
}
|
||||||
|
|
||||||
try {
|
try {
|
||||||
device.connect();
|
device.connect();
|
||||||
@@ -232,6 +239,7 @@ abstract class StateCasting {
|
|||||||
device.onTimeChanged.clear();
|
device.onTimeChanged.clear();
|
||||||
device.onVolumeChanged.clear();
|
device.onVolumeChanged.clear();
|
||||||
device.onDurationChanged.clear();
|
device.onDurationChanged.clear();
|
||||||
|
device.onMediaItemEnd.clear();
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
+9
-6
@@ -723,15 +723,17 @@ class VideoDetailView : ConstraintLayout {
|
|||||||
val activeDevice = StateCasting.instance.activeDevice;
|
val activeDevice = StateCasting.instance.activeDevice;
|
||||||
if (activeDevice != null) {
|
if (activeDevice != null) {
|
||||||
handlePlayChanged(it);
|
handlePlayChanged(it);
|
||||||
|
|
||||||
val v = video;
|
|
||||||
if (!it && v != null && v.duration - activeDevice.time.toLong() < 2L) {
|
|
||||||
Log.i(TAG, "Next video (loop?)")
|
|
||||||
nextVideo();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
StateCasting.instance.onActiveDeviceMediaItemEnd.subscribe(this) {
|
||||||
|
val activeDevice = StateCasting.instance.activeDevice;
|
||||||
|
if (activeDevice != null) {
|
||||||
|
Log.i(TAG, "Next video (loop?)")
|
||||||
|
nextVideo();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
StateCasting.instance.onActiveDeviceTimeChanged.subscribe(this) {
|
StateCasting.instance.onActiveDeviceTimeChanged.subscribe(this) {
|
||||||
if (_isCasting) {
|
if (_isCasting) {
|
||||||
setLastPositionMilliseconds((it * 1000.0).toLong(), true);
|
setLastPositionMilliseconds((it * 1000.0).toLong(), true);
|
||||||
@@ -1273,6 +1275,7 @@ class VideoDetailView : ConstraintLayout {
|
|||||||
StateCasting.instance.onActiveDevicePlayChanged.remove(this);
|
StateCasting.instance.onActiveDevicePlayChanged.remove(this);
|
||||||
StateCasting.instance.onActiveDeviceTimeChanged.remove(this);
|
StateCasting.instance.onActiveDeviceTimeChanged.remove(this);
|
||||||
StateCasting.instance.onActiveDeviceConnectionStateChanged.remove(this);
|
StateCasting.instance.onActiveDeviceConnectionStateChanged.remove(this);
|
||||||
|
StateCasting.instance.onActiveDeviceMediaItemEnd.remove(this)
|
||||||
StateApp.instance.preventPictureInPicture.remove(this);
|
StateApp.instance.preventPictureInPicture.remove(this);
|
||||||
StatePlayer.instance.onQueueChanged.remove(this);
|
StatePlayer.instance.onQueueChanged.remove(this);
|
||||||
StatePlayer.instance.onVideoChanging.remove(this);
|
StatePlayer.instance.onVideoChanging.remove(this);
|
||||||
|
|||||||
Reference in New Issue
Block a user