Skip to content

Commit

Permalink
Well Koe finally works!
Browse files Browse the repository at this point in the history
  • Loading branch information
alula committed Sep 30, 2019
1 parent 2d4ef99 commit 4dfd78a
Show file tree
Hide file tree
Showing 74 changed files with 1,169 additions and 379 deletions.
4 changes: 4 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
target/
.gradle/
pom.xml.tag
pom.xml.releaseBackup
pom.xml.versionsBackup
Expand Down Expand Up @@ -48,6 +49,9 @@ buildNumber.properties
*.iml
*.ipr

*/build/
*/out/

# CMake
cmake-build-*/

Expand Down
18 changes: 18 additions & 0 deletions build.gradle
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
allprojects {
apply plugin: 'maven'
apply plugin: 'java'

group = 'moe.kyokobot'
version = '1.0.0-SNAPSHOT'

sourceCompatibility = 11
targetCompatibility = 11

repositories {
mavenLocal()

maven { url "https://jcenter.bintray.com/" }
maven { url "http://repo.maven.apache.org/maven2" }
maven { url "https://jitpack.io/" }
}
}
5 changes: 5 additions & 0 deletions core/build.gradle
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
dependencies {
compile group: 'io.netty', name: 'netty-all', version: '4.1.36.Final'
compile group: 'org.slf4j', name: 'slf4j-api', version: '1.8.0-beta4'
compileOnly group: 'org.jetbrains', name: 'annotations', version: '13.0'
}
File renamed without changes.
34 changes: 34 additions & 0 deletions core/src/main/java/moe/kyokobot/koe/KoeClient.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
package moe.kyokobot.koe;

import moe.kyokobot.koe.gateway.GatewayVersion;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;

import java.io.Closeable;
import java.util.Map;

public interface KoeClient extends Closeable {
@NotNull
VoiceConnection createConnection(long guildId);

@Nullable
VoiceConnection getConnection(long guildId);

void destroyConnection(long guildId);

@NotNull
Map<Long, VoiceConnection> getConnections();

@Override
void close();

VoiceConnection createVoiceConnection(long id);

long getClientId();

@NotNull
KoeOptions getOptions();

@NotNull
GatewayVersion getGatewayVersion();
}
47 changes: 47 additions & 0 deletions core/src/main/java/moe/kyokobot/koe/VoiceConnection.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
package moe.kyokobot.koe;

import moe.kyokobot.koe.audio.AudioFrameProvider;
import moe.kyokobot.koe.codec.Codec;
import moe.kyokobot.koe.gateway.VoiceGatewayConnection;
import moe.kyokobot.koe.handler.ConnectionHandler;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;

import java.io.Closeable;
import java.util.concurrent.CompletionStage;

public interface VoiceConnection extends Closeable {
CompletionStage<Void> connect(VoiceServerInfo info);

void disconnect();

@NotNull
KoeClient getClient();

@NotNull
KoeOptions getOptions();

@Nullable
AudioFrameProvider getSender();

long getGuildId();

@Nullable
VoiceGatewayConnection getGatewayConnection();

@Nullable
VoiceServerInfo getVoiceServerInfo();

ConnectionHandler getConnectionHandler();

void setAudioSender(@Nullable AudioFrameProvider sender);

void setAudioCodec(@NotNull Codec audioCodec);

void startFramePolling();

void stopFramePolling();

@Override
void close();
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
package moe.kyokobot.koe.audio;

public interface AudioFrameHandler {
}
Original file line number Diff line number Diff line change
@@ -1,23 +1,25 @@
package moe.kyokobot.koe.audio;

import io.netty.buffer.ByteBuf;
import moe.kyokobot.koe.codec.Codec;

public interface AudioSender {
public interface AudioFrameProvider {
/**
* @return If true, Koe will request audio data by calling {@link #retrieve(ByteBuf)} method.
*/
boolean canSendFrame();

/**
* If {@link #canSendFrame()} returns true, Koe will attempt to retrieve raw 20ms Opus frame, by calling this method
* with target {@link ByteBuf} where the data should be written to. Do not call {@link ByteBuf#release()} - memory
* management is already handled by Koe itself. Also in case if no data gets written to the buffer, audio packet
* won't be sent.
* If {@link #canSendFrame()} returns true, Koe will attempt to retrieve an audio frame encoded with specified
* {@link Codec} type, by calling this method with target {@link ByteBuf} where the data should be written to.
* Do not call {@link ByteBuf#release()} - memory management is already handled by Koe itself. In case if no
* data gets written to the buffer, audio packet won't be sent.
* <p>
* Do not let this method block - all data should be queued on another thread or pre-loaded in
* memory - otherwise it will very likely have significant impact of application performance.
*
* @param codec {@link Codec} type this handler was registered with.
* @param buf {@link ByteBuf} the buffer where the audio data should be written to.
*/
void retrieve(ByteBuf buf);
void retrieve(Codec codec, ByteBuf buf);
}
49 changes: 49 additions & 0 deletions core/src/main/java/moe/kyokobot/koe/codec/AbstractCodec.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
package moe.kyokobot.koe.codec;

import moe.kyokobot.koe.internal.json.JsonObject;

public abstract class AbstractCodec implements Codec {
private final String name;
private final byte payloadType;
private final int priority;
private final CodecType type;
private final JsonObject jsonDescription;

protected AbstractCodec(String name, byte payloadType, int priority, CodecType type) {
this.name = name;
this.payloadType = payloadType;
this.priority = priority;
this.type = type;

this.jsonDescription = new JsonObject()
.add("name", name)
.add("payload_type", payloadType)
.add("priority", priority)
.add("type", type.name().toLowerCase());
}

@Override
public String getName() {
return name;
}

@Override
public byte getPayloadType() {
return payloadType;
}

@Override
public int getPriority() {
return priority;
}

@Override
public CodecType getType() {
return type;
}

@Override
public JsonObject getJsonDescription() {
return jsonDescription;
}
}
23 changes: 23 additions & 0 deletions core/src/main/java/moe/kyokobot/koe/codec/AbstractFramePoller.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
package moe.kyokobot.koe.codec;

import io.netty.buffer.ByteBufAllocator;
import io.netty.channel.EventLoopGroup;
import moe.kyokobot.koe.VoiceConnection;

public abstract class AbstractFramePoller implements FramePoller {
protected final VoiceConnection connection;
protected final ByteBufAllocator allocator;
protected final EventLoopGroup eventLoop;
protected volatile boolean polling = false;

public AbstractFramePoller(VoiceConnection connection) {
this.connection = connection;
this.allocator = connection.getOptions().getByteBufAllocator();
this.eventLoop = connection.getOptions().getEventLoopGroup();
}

@Override
public boolean isPolling() {
return polling;
}
}
61 changes: 61 additions & 0 deletions core/src/main/java/moe/kyokobot/koe/codec/Codec.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,61 @@
package moe.kyokobot.koe.codec;

import moe.kyokobot.koe.VoiceConnection;
import moe.kyokobot.koe.internal.json.JsonObject;
import org.jetbrains.annotations.Nullable;

public interface Codec {
String getName();

byte getPayloadType();

int getPriority();

CodecType getType();

JsonObject getJsonDescription();

FramePoller createFramePoller(VoiceConnection connection);

/**
* Gets audio codec description by name.
* @param name the codec name
* @return Codec instance or null if the codec is not found/supported by Koe.
*/
@Nullable
static Codec getAudio(String name) {
return DefaultCodecs.audioCodecs.get(name);
}

/**
* Gets video codec description by name.
* @param name the codec name
* @return Codec instance or null if the codec is not found/supported by Koe.
*/
@Nullable
static Codec getVideo(String name) {
return DefaultCodecs.audioCodecs.get(name);
}

/**
* Gets audio or video codec by payload type.
* @param payloadType the payload type
* @return Codec instance or null if the codec is not found/supported by Koe.
*/
@Nullable
static Codec getByPayload(byte payloadType) {
for (var codec : DefaultCodecs.audioCodecs.values()) {
if (codec.getPayloadType() == payloadType) {
return codec;
}
}

for (var codec : DefaultCodecs.videoCodecs.values()) {
if (codec.getPayloadType() == payloadType) {
return codec;
}
}

return null;
}
}
5 changes: 5 additions & 0 deletions core/src/main/java/moe/kyokobot/koe/codec/CodecType.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
package moe.kyokobot.koe.codec;

public enum CodecType {
AUDIO, VIDEO;
}
18 changes: 18 additions & 0 deletions core/src/main/java/moe/kyokobot/koe/codec/DefaultCodecs.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
package moe.kyokobot.koe.codec;

import java.util.Map;

class DefaultCodecs {
private DefaultCodecs() {
//
}

static final Map<String, Codec> audioCodecs;
static final Map<String, Codec> videoCodecs;

static {
audioCodecs = Map.of("opus", new OpusCodec());

videoCodecs = Map.of();
}
}
9 changes: 9 additions & 0 deletions core/src/main/java/moe/kyokobot/koe/codec/FramePoller.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
package moe.kyokobot.koe.codec;

public interface FramePoller {
boolean isPolling();

void start();

void stop();
}
Loading

0 comments on commit 4dfd78a

Please sign in to comment.