Skip to content

Commit

Permalink
added own casting implementation
Browse files Browse the repository at this point in the history
  • Loading branch information
DatL4g committed Jul 21, 2024
1 parent aa63afc commit 79f1854
Show file tree
Hide file tree
Showing 33 changed files with 665 additions and 601 deletions.
1 change: 0 additions & 1 deletion composeApp/build.gradle.kts
Original file line number Diff line number Diff line change
Expand Up @@ -132,7 +132,6 @@ kotlin {
implementation(project(":firebase"))
implementation(project(":database"))
implementation(project(":github"))
// implementation(project(":k2k"))
}

val androidMain by getting {
Expand Down
6 changes: 2 additions & 4 deletions composeApp/src/androidMain/AndroidManifest.xml
Original file line number Diff line number Diff line change
Expand Up @@ -2,14 +2,12 @@
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools">

<uses-permission android:name="android.permission.ACCESS_WIFI_STATE"/>
<uses-permission android:name="android.permission.CHANGE_WIFI_STATE"/>
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
<uses-permission android:name="android.permission.INTERNET" />
<uses-permission android:name="android.permission.REQUEST_INSTALL_PACKAGES" />

<uses-permission
android:name="android.permission.PERMISSION_TO_REMOVE"
tools:node="remove" />

<permission android:name="dev.datlag.burningseries.READ_DATABASE" />

<queries>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,7 @@ import dev.datlag.burningseries.common.icon
import dev.datlag.burningseries.common.rememberIsTv
import dev.datlag.burningseries.composeapp.generated.resources.Res
import dev.datlag.burningseries.composeapp.generated.resources.cast
import dev.datlag.burningseries.other.K2Kast
import dev.datlag.kast.ConnectionState
import dev.datlag.kast.DeviceType
import dev.datlag.kast.Kast
Expand Down Expand Up @@ -148,6 +149,7 @@ fun TopControls(
Kast.unselect(UnselectReason.disconnected)
Kast.Android.passiveDiscovery()
} else {
K2Kast.disconnect()
Kast.select(device)
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -74,4 +74,9 @@
<string name="pip_unsupported">Bild in Bild ist hier nicht verfügbar.</string>
<string name="open_source_licenses">Open-Source Lizenzen</string>
<string name="open_source_licenses_text">Das ist eine Liste von (allen) Bibliotheken, die in diesem Projekt verwendet werden und deren Lizenzen</string>
<string name="k2kast_loading">Stream wird geladen, bitte warten</string>
<string name="k2kast_connection_code">Verbindungscode</string>
<string name="k2kast_experimental">Diese Funktion ist experimentell und funktioniert möglicherweise nicht wie erwartet, bitte verwende Chromecasting wenn verfügbar.</string>
<string name="k2kast_support">Beachte dass einige Geräte diese Funktion nicht unterstützen.</string>
<string name="k2kast_default_home">Normale Ansicht</string>
</resources>
5 changes: 5 additions & 0 deletions composeApp/src/commonMain/composeResources/values/strings.xml
Original file line number Diff line number Diff line change
Expand Up @@ -74,4 +74,9 @@
<string name="pip_unsupported">Picture in Picture is not available in this screen.</string>
<string name="open_source_licenses">Open-Source Licenses</string>
<string name="open_source_licenses_text">This is a list of (all) libraries used in this project and it's licenses</string>
<string name="k2kast_loading">Loading Stream, please wait</string>
<string name="k2kast_connection_code">Connection Code</string>
<string name="k2kast_experimental">This feature is experimental and may not work as expected, please use Chromecasting if possible.</string>
<string name="k2kast_support">Please note that some devices do not support this feature.</string>
<string name="k2kast_default_home">Default View</string>
</resources>
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,8 @@ import dev.datlag.burningseries.ui.theme.dynamicDark
import dev.datlag.burningseries.ui.theme.dynamicLight
import dev.datlag.tooling.Platform
import dev.datlag.tooling.compose.platform.CombinedPlatformMaterialTheme
import dev.datlag.tooling.compose.platform.PlatformSurface
import dev.datlag.tooling.compose.platform.colorScheme
import dev.datlag.tooling.compose.platform.rememberIsTv
import dev.datlag.tooling.compose.toTypography
import kotlinx.coroutines.flow.MutableStateFlow
Expand All @@ -57,10 +59,10 @@ internal fun App(
colorScheme = if (systemDarkTheme) Colors.dynamicDark() else Colors.dynamicLight(),
typography = ManropeFontFamily().toTypography()
) {
Surface(
PlatformSurface(
modifier = Modifier.fillMaxSize(),
color = MaterialTheme.colorScheme.background,
contentColor = MaterialTheme.colorScheme.onBackground
containerColor = Platform.colorScheme().background,
contentColor = Platform.colorScheme().onBackground
) {
content()
}
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,212 @@
package dev.datlag.burningseries.other

import dev.datlag.burningseries.model.Series
import dev.datlag.burningseries.model.SeriesData
import dev.datlag.burningseries.model.serializer.SerializableImmutableSet
import dev.datlag.k2k.Host
import dev.datlag.k2k.connect.Connection
import dev.datlag.k2k.connect.connection
import dev.datlag.k2k.discover.Discovery
import dev.datlag.k2k.discover.discovery
import dev.datlag.nanoid.NanoIdUtils
import dev.datlag.skeo.DirectLink
import dev.datlag.tooling.async.suspendCatching
import dev.datlag.tooling.compose.ioDispatcher
import io.github.aakira.napier.Napier
import kotlinx.collections.immutable.ImmutableCollection
import kotlinx.collections.immutable.ImmutableSet
import kotlinx.collections.immutable.persistentSetOf
import kotlinx.collections.immutable.toImmutableSet
import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.DelicateCoroutinesApi
import kotlinx.coroutines.GlobalScope
import kotlinx.coroutines.cancel
import kotlinx.coroutines.delay
import kotlinx.coroutines.flow.MutableStateFlow
import kotlinx.coroutines.flow.SharingStarted
import kotlinx.coroutines.flow.StateFlow
import kotlinx.coroutines.flow.combine
import kotlinx.coroutines.flow.stateIn
import kotlinx.coroutines.flow.update
import kotlinx.coroutines.plus
import kotlinx.serialization.ExperimentalSerializationApi
import kotlinx.serialization.Serializable
import kotlinx.serialization.encodeToByteArray
import kotlinx.serialization.protobuf.ProtoBuf

data object K2Kast : AutoCloseable {

private lateinit var showClient: Discovery
private lateinit var searchClient: Discovery

private lateinit var connection: Connection

private var scope: CoroutineScope? = null
private val connectedHost = MutableStateFlow<Host?>(null)

val code: String by lazy {
NanoIdUtils.randomNanoId(
alphabet = "0123456789".toCharArray(),
size = 6
)
}

@OptIn(DelicateCoroutinesApi::class)
val devices: StateFlow<ImmutableSet<Device>>
get() = if (::searchClient.isInitialized) {
combine(
connectedHost,
searchClient.peers
) { selected, all ->
all.map {
Device(
host = it,
selected = selected == it
)
}.toImmutableSet()
}.stateIn(
scope = scope ?: (GlobalScope + ioDispatcher()),
started = SharingStarted.WhileSubscribed(),
initialValue = searchClient.peers.value.map(::Device).toImmutableSet()
)
} else {
MutableStateFlow(persistentSetOf())
}

val connectedDevice: Device?
get() = devices.value.firstOrNull { it.selected }

fun initialize(scope: CoroutineScope) {
this.scope = scope

initializeShow(scope)
initializeSearch(scope)
initializeConnection(scope)
}

private fun initializeShow(scope: CoroutineScope) {
if (::showClient.isInitialized) {
return
}

showClient = scope.discovery {
setShowTimeout(0L)
setPort(7330)
}
}

private fun initializeSearch(scope: CoroutineScope) {
if (::searchClient.isInitialized) {
return
}

searchClient = scope.discovery {
setSearchTimeout(0L)
setPort(7330)
}
}

private fun initializeConnection(scope: CoroutineScope) {
if (::connection.isInitialized) {
return
}

connection = scope.connection {
setPort(7332)
noDelay()
}
}

fun show(name: String) {
showClient.show(name = name, filterMatch = code)
}

fun hide() {
showClient.hide()
}

fun search(code: String?) {
if (code.isNullOrBlank() || code.length != 6) {
searchClient.lose()
return
}

searchClient.search(
filter = "^$code$".toRegex()
)
}

fun lose() {
searchClient.lose()
}

fun connect(host: Host) {
connectedHost.update { host }
}

fun connect(device: Device) = connect(device.host)

fun disconnect() {
connectedHost.update { null }
}

fun receive(listener: suspend (ByteArray) -> Unit) = connection.receive(listener)

suspend fun send(byteArray: ByteArray, host: Host? = connectedDevice?.host) {
if (host == null) {
return
}

suspendCatching {
connection.sendNow(byteArray, host)
}
}
suspend fun send(byteArray: ByteArray, device: Device? = connectedDevice) = send(byteArray, device?.host)

suspend fun watch(
episode: Series.Episode,
host: Host? = connectedDevice?.host
) = send(
byteArray = episode.href.encodeToByteArray(),
host = host
)

suspend fun watch(
episode: Series.Episode,
device: Device? = connectedDevice
) = watch(
episode = episode,
host = device?.host
)

override fun close() {
this.scope?.cancel()
this.scope = null

closeShow()
closeSearch()
}

private fun closeShow() {
if (!::showClient.isInitialized) {
return
}

showClient.close()
}

private fun closeSearch() {
if (!::searchClient.isInitialized) {
return
}

searchClient.close()
}

@Serializable
data class Device(
val host: Host,
val name: String = host.name,
val selected: Boolean = connectedHost.value == host
)
}
Original file line number Diff line number Diff line change
@@ -1,5 +1,8 @@
package dev.datlag.burningseries.other

import kotlinx.coroutines.flow.MutableStateFlow

data object StateSaver {
var sekretLibraryLoaded: Boolean = false
val defaultHome = MutableStateFlow(false)
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
package dev.datlag.burningseries.ui.navigation

interface K2KastComponent : Component {

suspend fun k2kastLoad(href: String?)
}
Loading

0 comments on commit 79f1854

Please sign in to comment.