mirror of
https://gitlab.futo.org/videostreaming/grayjay.git
synced 2025-08-04 15:19:48 +00:00
Default language fixes.
This commit is contained in:
parent
5fffaf2f4e
commit
280feea06e
7 changed files with 128 additions and 48 deletions
|
@ -146,7 +146,7 @@ class DashBuilder : XMLBuilder {
|
||||||
dashBuilder.withAdaptationSet(
|
dashBuilder.withAdaptationSet(
|
||||||
mapOf(
|
mapOf(
|
||||||
Pair("mimeType", subtitleSource.format ?: "text/vtt"),
|
Pair("mimeType", subtitleSource.format ?: "text/vtt"),
|
||||||
Pair("lang", "en"),
|
Pair("lang", "df"),
|
||||||
Pair("default", "true")
|
Pair("default", "true")
|
||||||
)
|
)
|
||||||
) {
|
) {
|
||||||
|
|
|
@ -18,6 +18,7 @@ class AirPlayCastingDevice : CastingDevice {
|
||||||
override var usedRemoteAddress: InetAddress? = null;
|
override var usedRemoteAddress: InetAddress? = null;
|
||||||
override var localAddress: InetAddress? = null;
|
override var localAddress: InetAddress? = null;
|
||||||
override val canSetVolume: Boolean get() = false;
|
override val canSetVolume: Boolean get() = false;
|
||||||
|
override val canSetSpeed: Boolean get() = false; //TODO: Implement playback speed for AirPlay
|
||||||
|
|
||||||
var addresses: Array<InetAddress>? = null;
|
var addresses: Array<InetAddress>? = null;
|
||||||
var port: Int = 0;
|
var port: Int = 0;
|
||||||
|
@ -43,12 +44,12 @@ class AirPlayCastingDevice : CastingDevice {
|
||||||
return addresses?.toList() ?: listOf();
|
return addresses?.toList() ?: listOf();
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun loadVideo(streamType: String, contentType: String, contentId: String, resumePosition: Double, duration: Double) {
|
override fun loadVideo(streamType: String, contentType: String, contentId: String, resumePosition: Double, duration: Double, speed: Double?) {
|
||||||
if (invokeInIOScopeIfRequired({ loadVideo(streamType, contentType, contentId, resumePosition, duration) })) {
|
if (invokeInIOScopeIfRequired({ loadVideo(streamType, contentType, contentId, resumePosition, duration, speed) })) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
Logger.i(FCastCastingDevice.TAG, "Start streaming (streamType: $streamType, contentType: $contentType, contentId: $contentId, resumePosition: $resumePosition, duration: $duration)");
|
Logger.i(FCastCastingDevice.TAG, "Start streaming (streamType: $streamType, contentType: $contentType, contentId: $contentId, resumePosition: $resumePosition, duration: $duration, speed: $speed)");
|
||||||
|
|
||||||
time = resumePosition;
|
time = resumePosition;
|
||||||
if (resumePosition > 0.0) {
|
if (resumePosition > 0.0) {
|
||||||
|
@ -60,7 +61,7 @@ class AirPlayCastingDevice : CastingDevice {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun loadContent(contentType: String, content: String, resumePosition: Double, duration: Double) {
|
override fun loadContent(contentType: String, content: String, resumePosition: Double, duration: Double, speed: Double?) {
|
||||||
throw NotImplementedError();
|
throw NotImplementedError();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -48,6 +48,7 @@ abstract class CastingDevice {
|
||||||
abstract var usedRemoteAddress: InetAddress?;
|
abstract var usedRemoteAddress: InetAddress?;
|
||||||
abstract var localAddress: InetAddress?;
|
abstract var localAddress: InetAddress?;
|
||||||
abstract val canSetVolume: Boolean;
|
abstract val canSetVolume: Boolean;
|
||||||
|
abstract val canSetSpeed: Boolean;
|
||||||
|
|
||||||
var name: String? = null;
|
var name: String? = null;
|
||||||
var isPlaying: Boolean = false
|
var isPlaying: Boolean = false
|
||||||
|
@ -77,6 +78,14 @@ abstract class CastingDevice {
|
||||||
onVolumeChanged.emit(value);
|
onVolumeChanged.emit(value);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
var speed: Double = 1.0
|
||||||
|
set(value) {
|
||||||
|
val changed = value != field;
|
||||||
|
speed = value;
|
||||||
|
if (changed) {
|
||||||
|
onSpeedChanged.emit(value);
|
||||||
|
}
|
||||||
|
};
|
||||||
val expectedCurrentTime: Double
|
val expectedCurrentTime: Double
|
||||||
get() {
|
get() {
|
||||||
val diff = timeReceivedAt.getNowDiffMiliseconds().toDouble() / 1000.0;
|
val diff = timeReceivedAt.getNowDiffMiliseconds().toDouble() / 1000.0;
|
||||||
|
@ -96,6 +105,7 @@ abstract class CastingDevice {
|
||||||
var onPlayChanged = Event1<Boolean>();
|
var onPlayChanged = Event1<Boolean>();
|
||||||
var onTimeChanged = Event1<Double>();
|
var onTimeChanged = Event1<Double>();
|
||||||
var onVolumeChanged = Event1<Double>();
|
var onVolumeChanged = Event1<Double>();
|
||||||
|
var onSpeedChanged = Event1<Double>();
|
||||||
|
|
||||||
abstract fun stopCasting();
|
abstract fun stopCasting();
|
||||||
|
|
||||||
|
@ -103,9 +113,10 @@ abstract class CastingDevice {
|
||||||
abstract fun stopVideo();
|
abstract fun stopVideo();
|
||||||
abstract fun pauseVideo();
|
abstract fun pauseVideo();
|
||||||
abstract fun resumeVideo();
|
abstract fun resumeVideo();
|
||||||
abstract fun loadVideo(streamType: String, contentType: String, contentId: String, resumePosition: Double, duration: Double);
|
abstract fun loadVideo(streamType: String, contentType: String, contentId: String, resumePosition: Double, duration: Double, speed: Double?);
|
||||||
abstract fun loadContent(contentType: String, content: String, resumePosition: Double, duration: Double);
|
abstract fun loadContent(contentType: String, content: String, resumePosition: Double, duration: Double, speed: Double?);
|
||||||
open fun changeVolume(volume: Double) { throw NotImplementedError() }
|
open fun changeVolume(volume: Double) { throw NotImplementedError() }
|
||||||
|
open fun changeSpeed(speed: Double) { throw NotImplementedError() }
|
||||||
|
|
||||||
abstract fun start();
|
abstract fun start();
|
||||||
abstract fun stop();
|
abstract fun stop();
|
||||||
|
|
|
@ -27,6 +27,7 @@ class ChromecastCastingDevice : CastingDevice {
|
||||||
override var usedRemoteAddress: InetAddress? = null;
|
override var usedRemoteAddress: InetAddress? = null;
|
||||||
override var localAddress: InetAddress? = null;
|
override var localAddress: InetAddress? = null;
|
||||||
override val canSetVolume: Boolean get() = true;
|
override val canSetVolume: Boolean get() = true;
|
||||||
|
override val canSetSpeed: Boolean get() = false; //TODO: Implement
|
||||||
|
|
||||||
var addresses: Array<InetAddress>? = null;
|
var addresses: Array<InetAddress>? = null;
|
||||||
var port: Int = 0;
|
var port: Int = 0;
|
||||||
|
@ -62,12 +63,12 @@ class ChromecastCastingDevice : CastingDevice {
|
||||||
return addresses?.toList() ?: listOf();
|
return addresses?.toList() ?: listOf();
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun loadVideo(streamType: String, contentType: String, contentId: String, resumePosition: Double, duration: Double) {
|
override fun loadVideo(streamType: String, contentType: String, contentId: String, resumePosition: Double, duration: Double, speed: Double?) {
|
||||||
if (invokeInIOScopeIfRequired({ loadVideo(streamType, contentType, contentId, resumePosition, duration) })) {
|
if (invokeInIOScopeIfRequired({ loadVideo(streamType, contentType, contentId, resumePosition, duration, speed) })) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
Logger.i(TAG, "Start streaming (streamType: $streamType, contentType: $contentType, contentId: $contentId, resumePosition: $resumePosition, duration: $duration)");
|
Logger.i(TAG, "Start streaming (streamType: $streamType, contentType: $contentType, contentId: $contentId, resumePosition: $resumePosition, duration: $duration, speed: $speed)");
|
||||||
|
|
||||||
time = resumePosition;
|
time = resumePosition;
|
||||||
_streamType = streamType;
|
_streamType = streamType;
|
||||||
|
@ -77,7 +78,7 @@ class ChromecastCastingDevice : CastingDevice {
|
||||||
playVideo();
|
playVideo();
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun loadContent(contentType: String, content: String, resumePosition: Double, duration: Double) {
|
override fun loadContent(contentType: String, content: String, resumePosition: Double, duration: Double, speed: Double?) {
|
||||||
//TODO: Can maybe be implemented by sending data:contentType,base64...
|
//TODO: Can maybe be implemented by sending data:contentType,base64...
|
||||||
throw NotImplementedError();
|
throw NotImplementedError();
|
||||||
}
|
}
|
||||||
|
|
|
@ -2,6 +2,7 @@ package com.futo.platformplayer.casting
|
||||||
|
|
||||||
import android.os.Looper
|
import android.os.Looper
|
||||||
import android.util.Log
|
import android.util.Log
|
||||||
|
import com.futo.platformplayer.UIDialogs
|
||||||
import com.futo.platformplayer.casting.models.*
|
import com.futo.platformplayer.casting.models.*
|
||||||
import com.futo.platformplayer.logging.Logger
|
import com.futo.platformplayer.logging.Logger
|
||||||
import com.futo.platformplayer.getConnectedSocket
|
import com.futo.platformplayer.getConnectedSocket
|
||||||
|
@ -27,7 +28,10 @@ enum class Opcode(val value: Byte) {
|
||||||
SEEK(5),
|
SEEK(5),
|
||||||
PLAYBACK_UPDATE(6),
|
PLAYBACK_UPDATE(6),
|
||||||
VOLUME_UPDATE(7),
|
VOLUME_UPDATE(7),
|
||||||
SET_VOLUME(8)
|
SET_VOLUME(8),
|
||||||
|
PLAYBACK_ERROR(9),
|
||||||
|
SET_SPEED(10),
|
||||||
|
VERSION(11)
|
||||||
}
|
}
|
||||||
|
|
||||||
class FCastCastingDevice : CastingDevice {
|
class FCastCastingDevice : CastingDevice {
|
||||||
|
@ -38,6 +42,7 @@ class FCastCastingDevice : CastingDevice {
|
||||||
override var usedRemoteAddress: InetAddress? = null;
|
override var usedRemoteAddress: InetAddress? = null;
|
||||||
override var localAddress: InetAddress? = null;
|
override var localAddress: InetAddress? = null;
|
||||||
override val canSetVolume: Boolean get() = true;
|
override val canSetVolume: Boolean get() = true;
|
||||||
|
override val canSetSpeed: Boolean get() = true;
|
||||||
|
|
||||||
var addresses: Array<InetAddress>? = null;
|
var addresses: Array<InetAddress>? = null;
|
||||||
var port: Int = 0;
|
var port: Int = 0;
|
||||||
|
@ -47,6 +52,7 @@ class FCastCastingDevice : CastingDevice {
|
||||||
private var _inputStream: DataInputStream? = null;
|
private var _inputStream: DataInputStream? = null;
|
||||||
private var _scopeIO: CoroutineScope? = null;
|
private var _scopeIO: CoroutineScope? = null;
|
||||||
private var _started: Boolean = false;
|
private var _started: Boolean = false;
|
||||||
|
private var _version: Long = 1;
|
||||||
|
|
||||||
constructor(name: String, addresses: Array<InetAddress>, port: Int) : super() {
|
constructor(name: String, addresses: Array<InetAddress>, port: Int) : super() {
|
||||||
this.name = name;
|
this.name = name;
|
||||||
|
@ -64,33 +70,45 @@ class FCastCastingDevice : CastingDevice {
|
||||||
return addresses?.toList() ?: listOf();
|
return addresses?.toList() ?: listOf();
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun loadVideo(streamType: String, contentType: String, contentId: String, resumePosition: Double, duration: Double) {
|
override fun loadVideo(streamType: String, contentType: String, contentId: String, resumePosition: Double, duration: Double, speed: Double?) {
|
||||||
if (invokeInIOScopeIfRequired({ loadVideo(streamType, contentType, contentId, resumePosition, duration) })) {
|
if (invokeInIOScopeIfRequired({ loadVideo(streamType, contentType, contentId, resumePosition, duration, speed) })) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
Logger.i(TAG, "Start streaming (streamType: $streamType, contentType: $contentType, contentId: $contentId, resumePosition: $resumePosition, duration: $duration)");
|
//TODO: Remove this later, temporary for the transition
|
||||||
|
if (_version <= 1L) {
|
||||||
|
UIDialogs.toast("Version not received, if you are experiencing issues, try updating FCast")
|
||||||
|
}
|
||||||
|
|
||||||
|
Logger.i(TAG, "Start streaming (streamType: $streamType, contentType: $contentType, contentId: $contentId, resumePosition: $resumePosition, duration: $duration, speed: $speed)");
|
||||||
|
|
||||||
time = resumePosition;
|
time = resumePosition;
|
||||||
sendMessage(Opcode.PLAY, FCastPlayMessage(
|
sendMessage(Opcode.PLAY, FCastPlayMessage(
|
||||||
container = contentType,
|
container = contentType,
|
||||||
url = contentId,
|
url = contentId,
|
||||||
time = resumePosition.toInt()
|
time = resumePosition,
|
||||||
|
speed = speed
|
||||||
));
|
));
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun loadContent(contentType: String, content: String, resumePosition: Double, duration: Double) {
|
override fun loadContent(contentType: String, content: String, resumePosition: Double, duration: Double, speed: Double?) {
|
||||||
if (invokeInIOScopeIfRequired({ loadContent(contentType, content, resumePosition, duration) })) {
|
if (invokeInIOScopeIfRequired({ loadContent(contentType, content, resumePosition, duration, speed) })) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
Logger.i(TAG, "Start streaming content (contentType: $contentType, resumePosition: $resumePosition, duration: $duration)");
|
//TODO: Remove this later, temporary for the transition
|
||||||
|
if (_version <= 1L) {
|
||||||
|
UIDialogs.toast("Version not received, if you are experiencing issues, try updating FCast")
|
||||||
|
}
|
||||||
|
|
||||||
|
Logger.i(TAG, "Start streaming content (contentType: $contentType, resumePosition: $resumePosition, duration: $duration, speed: $speed)");
|
||||||
|
|
||||||
time = resumePosition;
|
time = resumePosition;
|
||||||
sendMessage(Opcode.PLAY, FCastPlayMessage(
|
sendMessage(Opcode.PLAY, FCastPlayMessage(
|
||||||
container = contentType,
|
container = contentType,
|
||||||
content = content,
|
content = content,
|
||||||
time = resumePosition.toInt()
|
time = resumePosition,
|
||||||
|
speed = speed
|
||||||
));
|
));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -103,13 +121,22 @@ class FCastCastingDevice : CastingDevice {
|
||||||
sendMessage(Opcode.SET_VOLUME, FCastSetVolumeMessage(volume))
|
sendMessage(Opcode.SET_VOLUME, FCastSetVolumeMessage(volume))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
override fun changeSpeed(speed: Double) {
|
||||||
|
if (invokeInIOScopeIfRequired({ changeSpeed(volume) })) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
this.speed = speed
|
||||||
|
sendMessage(Opcode.SET_SPEED, FCastSetSpeedMessage(volume))
|
||||||
|
}
|
||||||
|
|
||||||
override fun seekVideo(timeSeconds: Double) {
|
override fun seekVideo(timeSeconds: Double) {
|
||||||
if (invokeInIOScopeIfRequired({ seekVideo(timeSeconds) })) {
|
if (invokeInIOScopeIfRequired({ seekVideo(timeSeconds) })) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
sendMessage(Opcode.SEEK, FCastSeekMessage(
|
sendMessage(Opcode.SEEK, FCastSeekMessage(
|
||||||
time = timeSeconds.toInt()
|
time = timeSeconds
|
||||||
));
|
));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -282,8 +309,8 @@ class FCastCastingDevice : CastingDevice {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
val playbackUpdate = Json.decodeFromString<FCastPlaybackUpdateMessage>(json);
|
val playbackUpdate = FCastCastingDevice.json.decodeFromString<FCastPlaybackUpdateMessage>(json);
|
||||||
time = playbackUpdate.time.toDouble();
|
time = playbackUpdate.time;
|
||||||
isPlaying = when (playbackUpdate.state) {
|
isPlaying = when (playbackUpdate.state) {
|
||||||
1 -> true
|
1 -> true
|
||||||
else -> false
|
else -> false
|
||||||
|
@ -295,9 +322,28 @@ class FCastCastingDevice : CastingDevice {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
val volumeUpdate = Json.decodeFromString<FCastVolumeUpdateMessage>(json);
|
val volumeUpdate = FCastCastingDevice.json.decodeFromString<FCastVolumeUpdateMessage>(json);
|
||||||
volume = volumeUpdate.volume;
|
volume = volumeUpdate.volume;
|
||||||
}
|
}
|
||||||
|
Opcode.PLAYBACK_ERROR -> {
|
||||||
|
if (json == null) {
|
||||||
|
Logger.w(TAG, "Got playback error without JSON, ignoring.");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
val playbackError = FCastCastingDevice.json.decodeFromString<FCastPlaybackErrorMessage>(json);
|
||||||
|
Logger.e(TAG, "Remote casting playback error received: $playbackError")
|
||||||
|
}
|
||||||
|
Opcode.VERSION -> {
|
||||||
|
if (json == null) {
|
||||||
|
Logger.w(TAG, "Got version without JSON, ignoring.");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
val version = FCastCastingDevice.json.decodeFromString<FCastVersionMessage>(json);
|
||||||
|
_version = version.version;
|
||||||
|
Logger.i(TAG, "Remote version received: $version")
|
||||||
|
}
|
||||||
else -> { }
|
else -> { }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -333,7 +379,7 @@ class FCastCastingDevice : CastingDevice {
|
||||||
val data: ByteArray;
|
val data: ByteArray;
|
||||||
var jsonString: String? = null;
|
var jsonString: String? = null;
|
||||||
if (message != null) {
|
if (message != null) {
|
||||||
jsonString = Json.encodeToString(message);
|
jsonString = json.encodeToString(message);
|
||||||
data = jsonString.encodeToByteArray();
|
data = jsonString.encodeToByteArray();
|
||||||
} else {
|
} else {
|
||||||
data = ByteArray(0);
|
data = ByteArray(0);
|
||||||
|
@ -403,5 +449,6 @@ class FCastCastingDevice : CastingDevice {
|
||||||
|
|
||||||
companion object {
|
companion object {
|
||||||
val TAG = "FastCastCastingDevice";
|
val TAG = "FastCastCastingDevice";
|
||||||
|
private val json = Json { ignoreUnknownKeys = true }
|
||||||
}
|
}
|
||||||
}
|
}
|
|
@ -395,17 +395,17 @@ class StateCasting {
|
||||||
} else {
|
} else {
|
||||||
if (videoSource is IVideoUrlSource) {
|
if (videoSource is IVideoUrlSource) {
|
||||||
Logger.i(TAG, "Casting as singular video");
|
Logger.i(TAG, "Casting as singular video");
|
||||||
ad.loadVideo(if (video.isLive) "LIVE" else "BUFFERED", videoSource.container, videoSource.getVideoUrl(), resumePosition, video.duration.toDouble());
|
ad.loadVideo(if (video.isLive) "LIVE" else "BUFFERED", videoSource.container, videoSource.getVideoUrl(), resumePosition, video.duration.toDouble(), null);
|
||||||
} else if (audioSource is IAudioUrlSource) {
|
} else if (audioSource is IAudioUrlSource) {
|
||||||
Logger.i(TAG, "Casting as singular audio");
|
Logger.i(TAG, "Casting as singular audio");
|
||||||
ad.loadVideo(if (video.isLive) "LIVE" else "BUFFERED", audioSource.container, audioSource.getAudioUrl(), resumePosition, video.duration.toDouble());
|
ad.loadVideo(if (video.isLive) "LIVE" else "BUFFERED", audioSource.container, audioSource.getAudioUrl(), resumePosition, video.duration.toDouble(), null);
|
||||||
} else if(videoSource is IHLSManifestSource) {
|
} else if(videoSource is IHLSManifestSource) {
|
||||||
if (ad is ChromecastCastingDevice) {
|
if (ad is ChromecastCastingDevice) {
|
||||||
Logger.i(TAG, "Casting as proxied HLS");
|
Logger.i(TAG, "Casting as proxied HLS");
|
||||||
castProxiedHls(video, videoSource.url, videoSource.codec, resumePosition);
|
castProxiedHls(video, videoSource.url, videoSource.codec, resumePosition);
|
||||||
} else {
|
} else {
|
||||||
Logger.i(TAG, "Casting as non-proxied HLS");
|
Logger.i(TAG, "Casting as non-proxied HLS");
|
||||||
ad.loadVideo(if (video.isLive) "LIVE" else "BUFFERED", videoSource.container, videoSource.url, resumePosition, video.duration.toDouble());
|
ad.loadVideo(if (video.isLive) "LIVE" else "BUFFERED", videoSource.container, videoSource.url, resumePosition, video.duration.toDouble(), null);
|
||||||
}
|
}
|
||||||
} else if(audioSource is IHLSManifestAudioSource) {
|
} else if(audioSource is IHLSManifestAudioSource) {
|
||||||
if (ad is ChromecastCastingDevice) {
|
if (ad is ChromecastCastingDevice) {
|
||||||
|
@ -413,7 +413,7 @@ class StateCasting {
|
||||||
castProxiedHls(video, audioSource.url, audioSource.codec, resumePosition);
|
castProxiedHls(video, audioSource.url, audioSource.codec, resumePosition);
|
||||||
} else {
|
} else {
|
||||||
Logger.i(TAG, "Casting as non-proxied audio HLS");
|
Logger.i(TAG, "Casting as non-proxied audio HLS");
|
||||||
ad.loadVideo(if (video.isLive) "LIVE" else "BUFFERED", audioSource.container, audioSource.url, resumePosition, video.duration.toDouble());
|
ad.loadVideo(if (video.isLive) "LIVE" else "BUFFERED", audioSource.container, audioSource.url, resumePosition, video.duration.toDouble(), null);
|
||||||
}
|
}
|
||||||
} else if (videoSource is LocalVideoSource) {
|
} else if (videoSource is LocalVideoSource) {
|
||||||
Logger.i(TAG, "Casting as local video");
|
Logger.i(TAG, "Casting as local video");
|
||||||
|
@ -480,7 +480,7 @@ class StateCasting {
|
||||||
).withTag("cast");
|
).withTag("cast");
|
||||||
|
|
||||||
Logger.i(TAG, "Casting local video (videoUrl: $videoUrl).");
|
Logger.i(TAG, "Casting local video (videoUrl: $videoUrl).");
|
||||||
ad.loadVideo("BUFFERED", videoSource.container, videoUrl, resumePosition, video.duration.toDouble());
|
ad.loadVideo("BUFFERED", videoSource.container, videoUrl, resumePosition, video.duration.toDouble(), null);
|
||||||
|
|
||||||
return listOf(videoUrl);
|
return listOf(videoUrl);
|
||||||
}
|
}
|
||||||
|
@ -499,7 +499,7 @@ class StateCasting {
|
||||||
).withTag("cast");
|
).withTag("cast");
|
||||||
|
|
||||||
Logger.i(TAG, "Casting local audio (audioUrl: $audioUrl).");
|
Logger.i(TAG, "Casting local audio (audioUrl: $audioUrl).");
|
||||||
ad.loadVideo("BUFFERED", audioSource.container, audioUrl, resumePosition, video.duration.toDouble());
|
ad.loadVideo("BUFFERED", audioSource.container, audioUrl, resumePosition, video.duration.toDouble(), null);
|
||||||
|
|
||||||
return listOf(audioUrl);
|
return listOf(audioUrl);
|
||||||
}
|
}
|
||||||
|
@ -563,7 +563,7 @@ class StateCasting {
|
||||||
.withHeader("Access-Control-Allow-Origin", "*"), true
|
.withHeader("Access-Control-Allow-Origin", "*"), true
|
||||||
).withTag("castLocalHls")
|
).withTag("castLocalHls")
|
||||||
|
|
||||||
mediaRenditions.add(HLS.MediaRendition("AUDIO", audioVariantPlaylistUrl, "audio", "en", "english", true, true, true))
|
mediaRenditions.add(HLS.MediaRendition("AUDIO", audioVariantPlaylistUrl, "audio", "df", "default", true, true, true))
|
||||||
}
|
}
|
||||||
|
|
||||||
if (subtitleSource != null) {
|
if (subtitleSource != null) {
|
||||||
|
@ -584,7 +584,7 @@ class StateCasting {
|
||||||
.withHeader("Access-Control-Allow-Origin", "*"), true
|
.withHeader("Access-Control-Allow-Origin", "*"), true
|
||||||
).withTag("castLocalHls")
|
).withTag("castLocalHls")
|
||||||
|
|
||||||
mediaRenditions.add(HLS.MediaRendition("SUBTITLES", subtitleVariantPlaylistUrl, "subtitles", "en", "english", true, true, true))
|
mediaRenditions.add(HLS.MediaRendition("SUBTITLES", subtitleVariantPlaylistUrl, "subtitles", "df", "default", true, true, true))
|
||||||
}
|
}
|
||||||
|
|
||||||
val masterPlaylist = HLS.MasterPlaylist(variantPlaylistReferences, mediaRenditions, listOf(), true)
|
val masterPlaylist = HLS.MasterPlaylist(variantPlaylistReferences, mediaRenditions, listOf(), true)
|
||||||
|
@ -595,7 +595,7 @@ class StateCasting {
|
||||||
).withTag("castLocalHls")
|
).withTag("castLocalHls")
|
||||||
|
|
||||||
Logger.i(TAG, "added new castLocalHls handlers (hlsPath: $hlsPath, videoPath: $videoPath, audioPath: $audioPath, subtitlePath: $subtitlePath).")
|
Logger.i(TAG, "added new castLocalHls handlers (hlsPath: $hlsPath, videoPath: $videoPath, audioPath: $audioPath, subtitlePath: $subtitlePath).")
|
||||||
ad.loadVideo("BUFFERED", "application/vnd.apple.mpegurl", hlsUrl, resumePosition, video.duration.toDouble())
|
ad.loadVideo("BUFFERED", "application/vnd.apple.mpegurl", hlsUrl, resumePosition, video.duration.toDouble(), null)
|
||||||
|
|
||||||
return listOf(hlsUrl, videoUrl, audioUrl, subtitleUrl)
|
return listOf(hlsUrl, videoUrl, audioUrl, subtitleUrl)
|
||||||
}
|
}
|
||||||
|
@ -641,7 +641,7 @@ class StateCasting {
|
||||||
}
|
}
|
||||||
|
|
||||||
Logger.i(TAG, "added new castLocalDash handlers (dashPath: $dashPath, videoPath: $videoPath, audioPath: $audioPath, subtitlePath: $subtitlePath).");
|
Logger.i(TAG, "added new castLocalDash handlers (dashPath: $dashPath, videoPath: $videoPath, audioPath: $audioPath, subtitlePath: $subtitlePath).");
|
||||||
ad.loadVideo("BUFFERED", "application/dash+xml", dashUrl, resumePosition, video.duration.toDouble());
|
ad.loadVideo("BUFFERED", "application/dash+xml", dashUrl, resumePosition, video.duration.toDouble(), null);
|
||||||
|
|
||||||
return listOf(dashUrl, videoUrl, audioUrl, subtitleUrl);
|
return listOf(dashUrl, videoUrl, audioUrl, subtitleUrl);
|
||||||
}
|
}
|
||||||
|
@ -686,7 +686,7 @@ class StateCasting {
|
||||||
val content = DashBuilder.generateOnDemandDash(videoSource, videoUrl, audioSource, audioUrl, subtitleSource, subtitlesUrl);
|
val content = DashBuilder.generateOnDemandDash(videoSource, videoUrl, audioSource, audioUrl, subtitleSource, subtitlesUrl);
|
||||||
|
|
||||||
Logger.i(TAG, "Direct dash cast to casting device (videoUrl: $videoUrl, audioUrl: $audioUrl).");
|
Logger.i(TAG, "Direct dash cast to casting device (videoUrl: $videoUrl, audioUrl: $audioUrl).");
|
||||||
ad.loadContent("application/dash+xml", content, resumePosition, video.duration.toDouble());
|
ad.loadContent("application/dash+xml", content, resumePosition, video.duration.toDouble(), null);
|
||||||
|
|
||||||
return listOf(videoSource?.getVideoUrl() ?: "", audioSource?.getAudioUrl() ?: "");
|
return listOf(videoSource?.getVideoUrl() ?: "", audioSource?.getAudioUrl() ?: "");
|
||||||
}
|
}
|
||||||
|
@ -812,7 +812,7 @@ class StateCasting {
|
||||||
|
|
||||||
//ChromeCast is sometimes funky with resume position 0
|
//ChromeCast is sometimes funky with resume position 0
|
||||||
val hackfixResumePosition = if (ad is ChromecastCastingDevice && !video.isLive && resumePosition == 0.0) 0.1 else resumePosition;
|
val hackfixResumePosition = if (ad is ChromecastCastingDevice && !video.isLive && resumePosition == 0.0) 0.1 else resumePosition;
|
||||||
ad.loadVideo(if (video.isLive) "LIVE" else "BUFFERED", "application/vnd.apple.mpegurl", hlsUrl, hackfixResumePosition, video.duration.toDouble());
|
ad.loadVideo(if (video.isLive) "LIVE" else "BUFFERED", "application/vnd.apple.mpegurl", hlsUrl, hackfixResumePosition, video.duration.toDouble(), null);
|
||||||
|
|
||||||
return listOf(hlsUrl);
|
return listOf(hlsUrl);
|
||||||
}
|
}
|
||||||
|
@ -892,7 +892,7 @@ class StateCasting {
|
||||||
.withHeader("Access-Control-Allow-Origin", "*"), true
|
.withHeader("Access-Control-Allow-Origin", "*"), true
|
||||||
).withTag("castHlsIndirectVariant");
|
).withTag("castHlsIndirectVariant");
|
||||||
|
|
||||||
mediaRenditions.add(HLS.MediaRendition("AUDIO", audioVariantPlaylistUrl, "audio", "en", "english", true, true, true))
|
mediaRenditions.add(HLS.MediaRendition("AUDIO", audioVariantPlaylistUrl, "audio", "df", "default", true, true, true))
|
||||||
|
|
||||||
_castServer.addHandlerWithAllowAllOptions(
|
_castServer.addHandlerWithAllowAllOptions(
|
||||||
HttpProxyHandler("GET", audioPath, audioSource.getAudioUrl(), true)
|
HttpProxyHandler("GET", audioPath, audioSource.getAudioUrl(), true)
|
||||||
|
@ -942,7 +942,7 @@ class StateCasting {
|
||||||
.withHeader("Access-Control-Allow-Origin", "*"), true
|
.withHeader("Access-Control-Allow-Origin", "*"), true
|
||||||
).withTag("castHlsIndirectVariant");
|
).withTag("castHlsIndirectVariant");
|
||||||
|
|
||||||
mediaRenditions.add(HLS.MediaRendition("SUBTITLES", subtitleVariantPlaylistUrl, "subtitles", "en", "english", true, true, true))
|
mediaRenditions.add(HLS.MediaRendition("SUBTITLES", subtitleVariantPlaylistUrl, "subtitles", "df", "default", true, true, true))
|
||||||
}
|
}
|
||||||
|
|
||||||
if (videoSource != null) {
|
if (videoSource != null) {
|
||||||
|
@ -986,7 +986,7 @@ class StateCasting {
|
||||||
).withTag("castHlsIndirectMaster")
|
).withTag("castHlsIndirectMaster")
|
||||||
|
|
||||||
Logger.i(TAG, "added new castHls handlers (hlsPath: $hlsPath).");
|
Logger.i(TAG, "added new castHls handlers (hlsPath: $hlsPath).");
|
||||||
ad.loadVideo(if (video.isLive) "LIVE" else "BUFFERED", "application/vnd.apple.mpegurl", hlsUrl, resumePosition, video.duration.toDouble());
|
ad.loadVideo(if (video.isLive) "LIVE" else "BUFFERED", "application/vnd.apple.mpegurl", hlsUrl, resumePosition, video.duration.toDouble(), null);
|
||||||
|
|
||||||
return listOf(hlsUrl, videoSource?.getVideoUrl() ?: "", audioSource?.getAudioUrl() ?: "", subtitlesUri.toString());
|
return listOf(hlsUrl, videoSource?.getVideoUrl() ?: "", audioSource?.getAudioUrl() ?: "", subtitlesUri.toString());
|
||||||
}
|
}
|
||||||
|
@ -1061,7 +1061,7 @@ class StateCasting {
|
||||||
}
|
}
|
||||||
|
|
||||||
Logger.i(TAG, "added new castDash handlers (dashPath: $dashPath, videoPath: $videoPath, audioPath: $audioPath).");
|
Logger.i(TAG, "added new castDash handlers (dashPath: $dashPath, videoPath: $videoPath, audioPath: $audioPath).");
|
||||||
ad.loadVideo(if (video.isLive) "LIVE" else "BUFFERED", "application/dash+xml", dashUrl, resumePosition, video.duration.toDouble());
|
ad.loadVideo(if (video.isLive) "LIVE" else "BUFFERED", "application/dash+xml", dashUrl, resumePosition, video.duration.toDouble(), null);
|
||||||
|
|
||||||
return listOf(dashUrl, videoUrl ?: "", audioUrl ?: "", subtitlesUrl ?: "", videoSource?.getVideoUrl() ?: "", audioSource?.getAudioUrl() ?: "", subtitlesUri.toString());
|
return listOf(dashUrl, videoUrl ?: "", audioUrl ?: "", subtitlesUrl ?: "", videoSource?.getVideoUrl() ?: "", audioSource?.getAudioUrl() ?: "", subtitlesUri.toString());
|
||||||
}
|
}
|
||||||
|
|
|
@ -2,28 +2,33 @@ package com.futo.platformplayer.casting.models
|
||||||
|
|
||||||
import kotlinx.serialization.Serializable
|
import kotlinx.serialization.Serializable
|
||||||
|
|
||||||
@kotlinx.serialization.Serializable
|
@Serializable
|
||||||
data class FCastPlayMessage(
|
data class FCastPlayMessage(
|
||||||
val container: String,
|
val container: String,
|
||||||
val url: String? = null,
|
val url: String? = null,
|
||||||
val content: String? = null,
|
val content: String? = null,
|
||||||
val time: Int? = null
|
val time: Double? = null,
|
||||||
|
val speed: Double? = null
|
||||||
) { }
|
) { }
|
||||||
|
|
||||||
@kotlinx.serialization.Serializable
|
@Serializable
|
||||||
data class FCastSeekMessage(
|
data class FCastSeekMessage(
|
||||||
val time: Int
|
val time: Double
|
||||||
) { }
|
) { }
|
||||||
|
|
||||||
@kotlinx.serialization.Serializable
|
@Serializable
|
||||||
data class FCastPlaybackUpdateMessage(
|
data class FCastPlaybackUpdateMessage(
|
||||||
val time: Int,
|
val generationTime: Long,
|
||||||
val state: Int
|
val time: Double,
|
||||||
|
val duration: Double,
|
||||||
|
val state: Int,
|
||||||
|
val speed: Double
|
||||||
) { }
|
) { }
|
||||||
|
|
||||||
|
|
||||||
@Serializable
|
@Serializable
|
||||||
data class FCastVolumeUpdateMessage(
|
data class FCastVolumeUpdateMessage(
|
||||||
|
val generationTime: Long,
|
||||||
val volume: Double
|
val volume: Double
|
||||||
)
|
)
|
||||||
|
|
||||||
|
@ -31,3 +36,18 @@ data class FCastVolumeUpdateMessage(
|
||||||
data class FCastSetVolumeMessage(
|
data class FCastSetVolumeMessage(
|
||||||
val volume: Double
|
val volume: Double
|
||||||
)
|
)
|
||||||
|
|
||||||
|
@Serializable
|
||||||
|
data class FCastSetSpeedMessage(
|
||||||
|
val speed: Double
|
||||||
|
)
|
||||||
|
|
||||||
|
@Serializable
|
||||||
|
data class FCastPlaybackErrorMessage(
|
||||||
|
val message: String
|
||||||
|
)
|
||||||
|
|
||||||
|
@Serializable
|
||||||
|
data class FCastVersionMessage(
|
||||||
|
val version: Long
|
||||||
|
)
|
Loading…
Add table
Add a link
Reference in a new issue