Skip to content

Commit

Permalink
add: full queue support
Browse files Browse the repository at this point in the history
This commit adds support for internal queueing.
  • Loading branch information
ThePedroo committed Apr 9, 2024
1 parent 621acbe commit 93633df
Show file tree
Hide file tree
Showing 8 changed files with 117 additions and 60 deletions.
2 changes: 2 additions & 0 deletions include/codecs.h
Original file line number Diff line number Diff line change
Expand Up @@ -199,6 +199,8 @@ void *coglink_parse_websocket_data(int *type, const char *json, size_t length);

void *coglink_parse_load_tracks_response(struct coglink_load_tracks_response *response, const char *json, size_t length);

void coglink_free_load_tracks_response(struct coglink_load_tracks_response *response);

struct coglink_voice_state *coglink_parse_voice_state(const char *json, size_t length);

struct coglink_voice_server_update *coglink_parse_voice_server_update(const char *json, size_t length);
Expand Down
12 changes: 6 additions & 6 deletions include/events.h
Original file line number Diff line number Diff line change
Expand Up @@ -6,17 +6,17 @@
#include "codecs.h"

struct coglink_events {
int (*onRaw)(struct coglink_client *c_client, const char *data, size_t length);
void (*onReady)(struct coglink_ready_payload *ready);
void (*onClose)(enum ws_close_reason wscode, const char *reason);
int (*on_raw)(struct coglink_client *c_client, const char *data, size_t length);
void (*on_ready)(struct coglink_ready_payload *ready);
void (*on_close)(enum ws_close_reason wscode, const char *reason);
// void (*onTrackStart)(char *guild_id, struct coglink_partial_track *track);
// void (*onTrackEnd)(char *guild_id, struct coglink_partial_track *track, char *reason);
void (*on_track_end)(struct coglink_track_end_payload *trackEnd);
// void (*onTrackException)(char *guild_id, struct coglink_partial_track *track, char *message, char *severity, char *cause);
// void (*onTrackStuck)(char *guild_id, char *thresholdMs, struct coglink_track *track);
// void (*onWebSocketClosed)(char *guild_id, char *code, char *reason, int byRemote);
// void (*onUnknownEvent)(char *guild_id, char *type, const char *text);
void (*onPlayerUpdate)(struct coglink_player_update_payload *playerUpdate);
void (*onStats)(struct coglink_stats_payload *stats);
void (*on_player_update)(struct coglink_player_update_payload *playerUpdate);
void (*on_stats)(struct coglink_stats_payload *stats);
// void (*onUnknownOp)(char *op, const char *text);
};

Expand Down
2 changes: 1 addition & 1 deletion include/rest.h
Original file line number Diff line number Diff line change
Expand Up @@ -43,7 +43,7 @@ struct coglink_player_queue *coglink_get_player_queue(struct coglink_client *c_c

int coglink_add_track_to_queue(struct coglink_client *c_client, struct coglink_player *player, char *track);

int coglink_remove_track_from_queue(struct coglink_client *c_client, struct coglink_player *player, char *track);
int coglink_remove_track_from_queue(struct coglink_client *c_client, struct coglink_player *player, size_t position);

int coglink_remove_player(struct coglink_client *c_client, struct coglink_player *player);

Expand Down
9 changes: 4 additions & 5 deletions include/utils.h
Original file line number Diff line number Diff line change
Expand Up @@ -7,21 +7,20 @@
jsmnf_pair *field = jsmnf_find(pairs, json, fieldName, sizeof(fieldName) - 1); \
\
if (field == NULL) { \
ERROR("[coglink] Failed to find field: %s", fieldName); \
\
return NULL; \
}

#define FIND_FIELD_PATH(pairs, field, fieldName, pathSize) \
jsmnf_pair *field = jsmnf_find_path(pairs, json, path, pathSize); \
\
if (field == NULL) { \
ERROR("[coglink] Failed to find field: %s", fieldName); \
\
return NULL; \
}

#define FIND_FIELD_PATH_INT(pairs, field, fieldName, pathSize) \
jsmnf_pair *field = jsmnf_find_path(pairs, json, path, pathSize); \
\
if (field == NULL) return -1;

#define PAIR_TO_SIZET(pair, fieldName, outputName, size) \
char fieldName[size]; \
memcpy(fieldName, json + pair->v.pos, pair->v.len); \
Expand Down
68 changes: 46 additions & 22 deletions lib/codecs.c
Original file line number Diff line number Diff line change
Expand Up @@ -65,6 +65,8 @@
snprintf(track_info->info->sourceName, sizeof(track_info->info->sourceName), "%.*s", (int)sourceName->v.len, json + sourceName->v.pos);

void *coglink_parse_websocket_data(int *event_type, const char *json, size_t length) {
*event_type = COGLINK_PARSE_ERROR;

jsmn_parser parser;
jsmntok_t tokens[64];

Expand All @@ -74,8 +76,6 @@ void *coglink_parse_websocket_data(int *event_type, const char *json, size_t len
if (r < 0) {
ERROR("[coglink:jsmn-find] Failed to parse JSON.");

*event_type = COGLINK_PARSE_ERROR;

return NULL;
}

Expand All @@ -88,25 +88,23 @@ void *coglink_parse_websocket_data(int *event_type, const char *json, size_t len
if (r < 0) {
FATAL("[coglink:jsmn-find] Failed to load jsmn-find.");

*event_type = COGLINK_PARSE_ERROR;

return NULL;
}

jsmnf_pair *op = jsmnf_find(pairs, json, "op", sizeof("op") - 1);
if (!op) {
*event_type = COGLINK_PARSE_ERROR;
ERROR("[coglink:jsmn-find] No op field found.");

return NULL;
}

const char *Op = json + op->v.pos;

switch(Op[0]) {
case 'r': { /* ready */
case 'r': { /* Ready */
jsmnf_pair *sessionId = jsmnf_find(pairs, json, "sessionId", sizeof("sessionId") - 1);
if (!sessionId) {
*event_type = COGLINK_PARSE_ERROR;
ERROR("[coglink:jsmn-find] No sessionId field found.");

return NULL;
}
Expand All @@ -125,7 +123,7 @@ void *coglink_parse_websocket_data(int *event_type, const char *json, size_t len

return ready;
}
case 'e': {
case 'e': { /* Event */
FIND_FIELD(type, "type");
FIND_FIELD(guildId, "guildId");

Expand All @@ -135,7 +133,8 @@ void *coglink_parse_websocket_data(int *event_type, const char *json, size_t len

PAIR_TO_SIZET(guildId, guildIdStr, parsedTrack->guildId, 18);

_coglink_parse_track(pairs, json); /* Defines track_info */
jsmnf_pair *event_track_info = jsmnf_find(pairs, json, "track", sizeof("track") - 1);
_coglink_parse_track(event_track_info, json); /* Defines track_info */

parsedTrack->track = track_info;

Expand All @@ -150,7 +149,8 @@ void *coglink_parse_websocket_data(int *event_type, const char *json, size_t len

PAIR_TO_SIZET(guildId, guildIdStr, parsedTrack->guildId, 18);

_coglink_parse_track(pairs, json); /* Defines track_info */
jsmnf_pair *event_track_info = jsmnf_find(pairs, json, "track", sizeof("track") - 1);
_coglink_parse_track(event_track_info, json); /* Defines track_info */

parsedTrack->track = track_info;

Expand All @@ -169,7 +169,8 @@ void *coglink_parse_websocket_data(int *event_type, const char *json, size_t len

PAIR_TO_SIZET(guildId, guildIdStr, parsedTrack->guildId, 18);

_coglink_parse_track(pairs, json); /* Defines track_info */
jsmnf_pair *event_track_info = jsmnf_find(pairs, json, "track", sizeof("track") - 1);
_coglink_parse_track(event_track_info, json); /* Defines track_info */

parsedTrack->track = track_info;
parsedTrack->exception = malloc(sizeof(struct coglink_exception_payload));
Expand All @@ -191,7 +192,8 @@ void *coglink_parse_websocket_data(int *event_type, const char *json, size_t len

PAIR_TO_SIZET(guildId, guildIdStr, parsedTrack->guildId, 18);

_coglink_parse_track(pairs, json); /* Defines track_info */
jsmnf_pair *event_track_info = jsmnf_find(pairs, json, "track", sizeof("track") - 1);
_coglink_parse_track(event_track_info, json); /* Defines track_info */

parsedTrack->track = track_info;

Expand Down Expand Up @@ -335,25 +337,25 @@ void *coglink_parse_websocket_data(int *event_type, const char *json, size_t len
/* todo: move to int */
void *coglink_parse_load_tracks_response(struct coglink_load_tracks_response *response, const char *json, size_t length) {
jsmn_parser parser;
jsmntok_t tokens[256];
jsmntok_t *toks = NULL;
unsigned num_tokens = 0;

jsmn_init(&parser);
int r = jsmn_parse(&parser, json, length, tokens, sizeof(tokens));

if (r < 0) {
int r = jsmn_parse_auto(&parser, json, length, &toks, &num_tokens);
if (r <= 0) {
ERROR("[coglink:jsmn-find] Failed to parse JSON.");

return NULL;
}

jsmnf_loader loader;
jsmnf_pair pairs[256];
jsmnf_pair *pairs = NULL;
unsigned num_pairs = 0;

jsmnf_init(&loader);
r = jsmnf_load(&loader, json, tokens, parser.toknext, pairs, sizeof(pairs) / sizeof(*pairs));

if (r < 0) {
FATAL("[coglink:jsmn-find] Failed to load jsmn-find.");
r = jsmnf_load_auto(&loader, json, toks, num_tokens, &pairs, &num_pairs);
if (r <= 0) {
ERROR("[coglink:jsmn-find] Failed to load jsmn-find.");

return NULL;
}
Expand Down Expand Up @@ -414,7 +416,7 @@ void *coglink_parse_load_tracks_response(struct coglink_load_tracks_response *re
response->type = COGLINK_LOAD_TYPE_SEARCH;
response->data = data;

return NULL;
goto cleanup;
}
// case 'm': { /* eMpty */
// struct coglink_load_tracks_response *response = malloc(sizeof(struct coglink_load_tracks_response));
Expand All @@ -432,9 +434,31 @@ void *coglink_parse_load_tracks_response(struct coglink_load_tracks_response *re
// }
}

cleanup: {
free(toks);
free(pairs);
}

return NULL;
}

void coglink_free_load_tracks_response(struct coglink_load_tracks_response *response) {
switch (response->type) {
case COGLINK_LOAD_TYPE_SEARCH: {
struct coglink_load_tracks_search_response *data = response->data;

for (size_t i = 0; i < data->size; i++) {
free(data->array[i].info);
}

free(data->array);
free(data);

break;
}
}
}

struct coglink_voice_state *coglink_parse_voice_state(const char *json, size_t length) {
jsmn_parser parser;
jsmntok_t tokens[128];
Expand Down
39 changes: 21 additions & 18 deletions lib/rest.c
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ int _coglink_select_node(struct coglink_client *c_client) {

do {
if (!c_client->nodes->array[i].stats) {
if (bestStatsNode == -1) bestStatsNode = i;
if (bestStatsNode == -1 && c_client->nodes->array[i].session_id) bestStatsNode = i;

continue;
}
Expand Down Expand Up @@ -140,29 +140,31 @@ int coglink_add_track_to_queue(struct coglink_client *c_client, struct coglink_p
queue->array = realloc(queue->array, sizeof(char *) * (queue->size + 1));
queue->size++;

queue->array[queue->size - 1] = track;
/* copy */
queue->array[queue->size - 1] = malloc(strlen(track) + 1);
strcpy(queue->array[queue->size - 1], track);

return COGLINK_SUCCESS;
}

int coglink_remove_track_from_queue(struct coglink_client *c_client, struct coglink_player *player, char *track) {
int coglink_remove_track_from_queue(struct coglink_client *c_client, struct coglink_player *player, size_t position) {
struct coglink_player_queue *queue = coglink_get_player_queue(c_client, player);

for (size_t i = 0; i < queue->size; i++) {
if (strcmp(queue->array[i], track) == 0) {
queue->array[i] = '\0';

for (size_t j = i; j < queue->size - 1; j++) {
queue->array[j] = queue->array[j + 1];
}
if (position >= queue->size) {
FATAL("[coglink] Attempted to remove a track from an invalid position.");
}

queue->array = realloc(queue->array, sizeof(char *) * (queue->size - 1));
free(queue->array[position]);
queue->array[position] = '\0';

return COGLINK_SUCCESS;
}
for (size_t j = position; j < queue->size - 1; j++) {
queue->array[j] = queue->array[j + 1];
}

return COGLINK_NOT_FOUND;
queue->array = realloc(queue->array, sizeof(char *) * (queue->size - 1));
queue->size--;

return COGLINK_SUCCESS;
}

int coglink_remove_player(struct coglink_client *c_client, struct coglink_player *player) {
Expand Down Expand Up @@ -204,6 +206,7 @@ int coglink_load_tracks(struct coglink_client *c_client, struct coglink_player *
return COGLINK_SUCCESS;
}

/* todo: methods for creating payloads instead */
int coglink_play_track(struct coglink_client *c_client, struct coglink_player *player, char *track) {
struct coglink_node *node = &c_client->nodes->array[player->node];

Expand All @@ -213,15 +216,15 @@ int coglink_play_track(struct coglink_client *c_client, struct coglink_player *p
char *payload = malloc(payload_size);
snprintf(payload, payload_size, "{\"track\":{\"encoded\":\"%s\"}}", track);

size_t endpoint_size = (sizeof("/sessions//guilds/") - 1) + COGLINK_SESSION_ID_LENGTH + 19 + 1;
size_t endpoint_size = (sizeof("/sessions//players/") - 1) + COGLINK_SESSION_ID_LENGTH + 19 + 1;
char *endpoint = malloc(endpoint_size);
snprintf(endpoint, endpoint_size, "/sessions/%s/guilds/%" PRIu64 "", node->session_id, player->guild_id);
snprintf(endpoint, endpoint_size, "/sessions/%s/players/%" PRIu64 "", node->session_id, player->guild_id);

_coglink_perform_request(node, &(struct coglink_request_params) {
.endpoint = endpoint,
.method = "POST",
.method = "PATCH",
.body = payload,
.body_length = payload_size,
.body_length = payload_size - 1,
.get_response = false
}, NULL);

Expand Down
10 changes: 8 additions & 2 deletions lib/utils.c
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,12 @@ size_t _coglink_write_cb(void *data, size_t size, size_t nmemb, void *userp) {
return write_size;
}

size_t _coglink_fake_write_cb(void *data, size_t size, size_t nmemb, void *userp) {
(void)data; (void)size; (void)nmemb; (void)userp;

return size * nmemb;
}

int _coglink_perform_request(struct coglink_node *nodeInfo, struct coglink_request_params *req, struct coglink_response *res) {
CURL *curl = curl_easy_init();

Expand Down Expand Up @@ -66,8 +72,8 @@ int _coglink_perform_request(struct coglink_node *nodeInfo, struct coglink_reque
c_res = curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, _coglink_write_cb);
c_res = curl_easy_setopt(curl, CURLOPT_WRITEDATA, (void *)res);
} else {
/* todo: Is it necessary? */
// c_res = curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, __coglink_WriteMemoryCallbackNoSave);
/* avoids libcurl to write to stdout */
c_res = curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, _coglink_fake_write_cb);
}

c_res = curl_easy_perform(curl);
Expand Down
Loading

0 comments on commit 93633df

Please sign in to comment.