Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Implement Media Sink Wants in Voice #898

Open
wants to merge 5 commits into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from 2 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
40 changes: 36 additions & 4 deletions voice/api/voice.api
Original file line number Diff line number Diff line change
Expand Up @@ -526,21 +526,24 @@ public final class dev/kord/voice/gateway/DefaultVoiceGatewayBuilder {
public final fun getReconnectRetry ()Ldev/kord/gateway/retry/Retry;
public final fun getSelfId ()Ldev/kord/common/entity/Snowflake;
public final fun getSessionId ()Ljava/lang/String;
public final fun isDeaf ()Z
public final fun setClient (Lio/ktor/client/HttpClient;)V
public final fun setDeaf (Z)V
public final fun setEventFlow (Lkotlinx/coroutines/flow/MutableSharedFlow;)V
public final fun setReconnectRetry (Ldev/kord/gateway/retry/Retry;)V
}

public final class dev/kord/voice/gateway/DefaultVoiceGatewayData {
public fun <init> (Ldev/kord/common/entity/Snowflake;Ldev/kord/common/entity/Snowflake;Ljava/lang/String;Lio/ktor/client/HttpClient;Ldev/kord/gateway/retry/Retry;Lkotlinx/coroutines/flow/MutableSharedFlow;)V
public fun <init> (Ldev/kord/common/entity/Snowflake;Ldev/kord/common/entity/Snowflake;Ljava/lang/String;Lio/ktor/client/HttpClient;Ldev/kord/gateway/retry/Retry;ZLkotlinx/coroutines/flow/MutableSharedFlow;)V
public final fun component1 ()Ldev/kord/common/entity/Snowflake;
public final fun component2 ()Ldev/kord/common/entity/Snowflake;
public final fun component3 ()Ljava/lang/String;
public final fun component4 ()Lio/ktor/client/HttpClient;
public final fun component5 ()Ldev/kord/gateway/retry/Retry;
public final fun component6 ()Lkotlinx/coroutines/flow/MutableSharedFlow;
public final fun copy (Ldev/kord/common/entity/Snowflake;Ldev/kord/common/entity/Snowflake;Ljava/lang/String;Lio/ktor/client/HttpClient;Ldev/kord/gateway/retry/Retry;Lkotlinx/coroutines/flow/MutableSharedFlow;)Ldev/kord/voice/gateway/DefaultVoiceGatewayData;
public static synthetic fun copy$default (Ldev/kord/voice/gateway/DefaultVoiceGatewayData;Ldev/kord/common/entity/Snowflake;Ldev/kord/common/entity/Snowflake;Ljava/lang/String;Lio/ktor/client/HttpClient;Ldev/kord/gateway/retry/Retry;Lkotlinx/coroutines/flow/MutableSharedFlow;ILjava/lang/Object;)Ldev/kord/voice/gateway/DefaultVoiceGatewayData;
public final fun component6 ()Z
public final fun component7 ()Lkotlinx/coroutines/flow/MutableSharedFlow;
public final fun copy (Ldev/kord/common/entity/Snowflake;Ldev/kord/common/entity/Snowflake;Ljava/lang/String;Lio/ktor/client/HttpClient;Ldev/kord/gateway/retry/Retry;ZLkotlinx/coroutines/flow/MutableSharedFlow;)Ldev/kord/voice/gateway/DefaultVoiceGatewayData;
public static synthetic fun copy$default (Ldev/kord/voice/gateway/DefaultVoiceGatewayData;Ldev/kord/common/entity/Snowflake;Ldev/kord/common/entity/Snowflake;Ljava/lang/String;Lio/ktor/client/HttpClient;Ldev/kord/gateway/retry/Retry;ZLkotlinx/coroutines/flow/MutableSharedFlow;ILjava/lang/Object;)Ldev/kord/voice/gateway/DefaultVoiceGatewayData;
public fun equals (Ljava/lang/Object;)Z
public final fun getClient ()Lio/ktor/client/HttpClient;
public final fun getEventFlow ()Lkotlinx/coroutines/flow/MutableSharedFlow;
Expand All @@ -549,6 +552,7 @@ public final class dev/kord/voice/gateway/DefaultVoiceGatewayData {
public final fun getSelfId ()Ldev/kord/common/entity/Snowflake;
public final fun getSessionId ()Ljava/lang/String;
public fun hashCode ()I
public final fun isDeaf ()Z
public fun toString ()Ljava/lang/String;
}

Expand Down Expand Up @@ -668,12 +672,40 @@ public final class dev/kord/voice/gateway/Identify$Companion {
public final fun serializer ()Lkotlinx/serialization/KSerializer;
}

public final class dev/kord/voice/gateway/MediaSinkWants : dev/kord/voice/gateway/Command {
public static final field Companion Ldev/kord/voice/gateway/MediaSinkWants$Companion;
public fun <init> (I)V
public final fun component1 ()I
public final fun copy (I)Ldev/kord/voice/gateway/MediaSinkWants;
public static synthetic fun copy$default (Ldev/kord/voice/gateway/MediaSinkWants;IILjava/lang/Object;)Ldev/kord/voice/gateway/MediaSinkWants;
public fun equals (Ljava/lang/Object;)Z
public final fun getAny ()I
public fun hashCode ()I
public fun toString ()Ljava/lang/String;
}

public final class dev/kord/voice/gateway/MediaSinkWants$$serializer : kotlinx/serialization/internal/GeneratedSerializer {
public static final field INSTANCE Ldev/kord/voice/gateway/MediaSinkWants$$serializer;
public fun childSerializers ()[Lkotlinx/serialization/KSerializer;
public fun deserialize (Lkotlinx/serialization/encoding/Decoder;)Ldev/kord/voice/gateway/MediaSinkWants;
public synthetic fun deserialize (Lkotlinx/serialization/encoding/Decoder;)Ljava/lang/Object;
public fun getDescriptor ()Lkotlinx/serialization/descriptors/SerialDescriptor;
public fun serialize (Lkotlinx/serialization/encoding/Encoder;Ldev/kord/voice/gateway/MediaSinkWants;)V
public synthetic fun serialize (Lkotlinx/serialization/encoding/Encoder;Ljava/lang/Object;)V
public fun typeParametersSerializers ()[Lkotlinx/serialization/KSerializer;
}

public final class dev/kord/voice/gateway/MediaSinkWants$Companion {
public final fun serializer ()Lkotlinx/serialization/KSerializer;
}

public final class dev/kord/voice/gateway/OpCode : java/lang/Enum {
public static final field ClientDisconnect Ldev/kord/voice/gateway/OpCode;
public static final field Heartbeat Ldev/kord/voice/gateway/OpCode;
public static final field HeartbeatAck Ldev/kord/voice/gateway/OpCode;
public static final field Hello Ldev/kord/voice/gateway/OpCode;
public static final field Identify Ldev/kord/voice/gateway/OpCode;
public static final field MediaSinkWants Ldev/kord/voice/gateway/OpCode;
public static final field Ready Ldev/kord/voice/gateway/OpCode;
public static final field Resume Ldev/kord/voice/gateway/OpCode;
public static final field Resumed Ldev/kord/voice/gateway/OpCode;
Expand Down
10 changes: 10 additions & 0 deletions voice/src/main/kotlin/gateway/Command.kt
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,10 @@ public sealed class Command {
composite.encodeSerializableElement(descriptor, 0, OpCode.Serializer, OpCode.Heartbeat)
composite.encodeLongElement(descriptor, 1, value.nonce)
}
is MediaSinkWants -> {
composite.encodeSerializableElement(descriptor, 0, OpCode.Serializer, OpCode.MediaSinkWants)
composite.encodeSerializableElement(descriptor, 1, MediaSinkWants.serializer(), value)
}
is SendSpeaking -> {
composite.encodeSerializableElement(descriptor, 0, OpCode.Serializer, OpCode.Speaking)
composite.encodeSerializableElement(descriptor, 1, SendSpeaking.serializer(), value)
Expand Down Expand Up @@ -72,6 +76,12 @@ public data class SendSpeaking(
val ssrc: UInt
) : Command()

@KordVoice
@Serializable
public data class MediaSinkWants(
val any: Int
viztea marked this conversation as resolved.
Show resolved Hide resolved
) : Command()

@KordVoice
@Serializable
public data class SelectProtocol(
Expand Down
3 changes: 2 additions & 1 deletion voice/src/main/kotlin/gateway/DefaultVoiceGateway.kt
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,7 @@ public data class DefaultVoiceGatewayData(
val sessionId: String,
val client: HttpClient,
val reconnectRetry: Retry,
val isDeaf: Boolean,
val eventFlow: MutableSharedFlow<VoiceEvent>
)

Expand Down Expand Up @@ -196,7 +197,7 @@ public class DefaultVoiceGateway(
val copy = command.copy(data = command.data.copy(address = "ip"))
"Voice Gateway >>> ${Json.encodeToString(Command.SerializationStrategy, copy)}"
}
is Heartbeat, is Resume, is SendSpeaking -> "Voice Gateway >>> $json"
else -> "Voice Gateway >>> $json"
viztea marked this conversation as resolved.
Show resolved Hide resolved
}
}
socket.send(Frame.Text(json))
Expand Down
2 changes: 2 additions & 0 deletions voice/src/main/kotlin/gateway/DefaultVoiceGatewayBuilder.kt
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@ public class DefaultVoiceGatewayBuilder(
public var client: HttpClient? = null
public var reconnectRetry: Retry? = null
public var eventFlow: MutableSharedFlow<VoiceEvent> = MutableSharedFlow(extraBufferCapacity = Int.MAX_VALUE)
public var isDeaf: Boolean = false
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

VoiceConnectionBuilder already has the selfDeaf option, can't this be used instead?

Copy link
Contributor Author

@viztea viztea Dec 21, 2023

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I suppose. I think the VoiceConnectionBuilder could get cleaned up quite a bit though.

Like I state in the PR description, you can set selfDeaf and a streams implementation.

Since selfDeaf is just a UI update right now it's not that much of an issue but if it gets updated to actually prevent voice receive it might be a good idea to set it depending on the streams implementation so that there isn't any confusion.

And maybe add some more functionality to it as well:

interface Streams {
	suspend fun setDeafen(value: Boolean)
	
	suspend fun setMute(ssrc: UInt, value: Boolean)
}

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think this is a fair solution. Makes the deafening much behavior much more consistent, especially with this addition. Streams#setDeafen might not be needed, as it isn't provided for the UI deafen either. I could see the use for a VoiceConnection#(set)Deafen which would UI deafen and media sink deafen (if streams are open).


public fun build(): DefaultVoiceGateway {
val client = client ?: HttpClient(CIO) {
Expand All @@ -37,6 +38,7 @@ public class DefaultVoiceGatewayBuilder(
sessionId,
client,
retry,
isDeaf,
eventFlow
)

Expand Down
3 changes: 2 additions & 1 deletion voice/src/main/kotlin/gateway/OpCode.kt
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,8 @@ public enum class OpCode(public val code: Int) {
Resume(7),
Hello(8),
Resumed(9),
ClientDisconnect(13);
ClientDisconnect(13),
MediaSinkWants(15);

internal object Serializer : KSerializer<OpCode> {
override val descriptor: SerialDescriptor
Expand Down
1 change: 1 addition & 0 deletions voice/src/main/kotlin/gateway/handler/HandshakeHandler.kt
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@ internal class HandshakeHandler(
on<Hello> {
data.reconnectRetry.reset()
send(identify)
send(MediaSinkWants(if (data.isDeaf) 0 else 100))
}
}
}