Lumenarium/src_v2/user_space/incenter_interface_connecti...

240 lines
7.0 KiB
C

internal void incenter_handle_interface_msg(Incenter_State* ins, Data msg);
void
incenter_interface_connection_cleanup(Incenter_State* ins)
{
if (ins->interface_socket.value == 0) return;
if (!os_socket_close(ins->interface_socket)) {
printf("Error closing interface connection socket\n");
}
ins->interface_socket = (Socket_Handle){0};
printf("Incenter Interface Socket Connection Closed.\n");
}
Thread_Result
incenter_interface_connection_thread_proc(u8* user_data)
{
Incenter_State* ins = (Incenter_State*)user_data;
// Open Socket Connection To Server
ins->interface_socket = os_socket_create(
AF_INET, // IPv4
SOCK_DGRAM,
0
);
// Bind the socket to the correct address
if (!os_socket_bind(ins->interface_socket, 1337)) {
printf("ERROR: Unable to bind incenter interface socket\n");
return (Thread_Result){ 0 };
}
// Message Recv Loop
while (ins->running)
{
u32 next_msg_i = ins->interface_messages_write_next;
Data* next_msg = ins->interface_messages + next_msg_i;
next_msg->size = INTERFACE_MESSAGE_SIZE; // reset buffer of known size
Socket_Error err = SocketError_NOERROR;
*next_msg = os_socket_recvfrom(ins->interface_socket, next_msg->base, next_msg->size, &err);
if (err == SocketError_EBADF && ins->running) {
if (!os_socket_close(ins->interface_socket)) {
printf("Trying to close interface socket before reopening. Socket was already closed.\n");
}
ins->interface_socket = os_socket_create(AF_INET, SOCK_DGRAM, 0);
}
if (err == SocketError_EINTR) {
printf("Recvfrom returned EINTR, trying again\n");
continue; // retry the same operation, as it was interrupted
}
if (err == SocketError_NOERROR) {
next_msg->base[next_msg->size] = 0;
// write_next isn't incremented until here because the message
// is not ready to be read until this point
ins->interface_messages_write_next = (ins->interface_messages_write_next + 1) % INTERFACE_MESSAGES_CAP;
} else {
char* errstr = (char*)"Invalid";
if (err > SocketError_Invalid && err < SocketError_Count) {
errstr = socket_error_strings[err];
}
// TODO: if you hit an EFAULT, go check how big the buffer
// recvfrom was trying to write into
printf("Socket Error: %s - code: %d\n", errstr, (s32)err);
}
}
// Close Down once Incenter indicates it's time to stop running
incenter_interface_connection_cleanup(ins);
return (Thread_Result){ 0 };
}
internal void
incenter_interface_connection_init(App_State* state, Incenter_State* ins)
{
// Start Thread to handle blocking socket calls
ins->interface_thread = os_thread_begin(incenter_interface_connection_thread_proc, (u8*)ins);
for (u32 msg_i = 0; msg_i < INTERFACE_MESSAGES_CAP; msg_i++)
{
ins->interface_messages[msg_i] = (Data){
.base = allocator_alloc(permanent, INTERFACE_MESSAGE_SIZE),
.size = INTERFACE_MESSAGE_SIZE,
};
}
}
internal void
incenter_interface_connection_frame(App_State* state, Incenter_State* ins)
{
while (ins->interface_messages_write_next != ins->interface_messages_read_next)
{
u32 read_next = ins->interface_messages_read_next;
ins->interface_messages_read_next = (read_next + 1) % INTERFACE_MESSAGES_CAP;
Data msg_read = ins->interface_messages[read_next];
printf("Handling message on the main thread\n");
printf(" %s\n", (char*)msg_read.base);
incenter_handle_interface_msg(ins, msg_read);
}
}
#define INCENTER_CMP3(base, str) ((base[0] == str[0]) && (base[1] == str[1]) && (base[2] == str[2]))
internal void
incenter_handle_sliding_scale_msg(Incenter_State* ins, Incenter_Scene scene, char msg)
{
assert(scene.kind == Incenter_SceneKind_SlidingScale);
if (msg != 'M' && msg != 'L' && msg != 'C') {
printf("Invalid input sent to sliding scale scene: %c\n", msg);
printf(" Scene: %s\n", scene.name);
return;
}
switch (msg) {
case 'M': {
ins->input_pct += 0.1f;
} break;
case 'L': {
ins->input_pct -= 0.1f;
} break;
case 'C': {
live_answers_input_r32(ins, scene, ins->input_pct);
ins->scene_mode = Incenter_SceneMode_Passive;
ins->scene_time = 0;
} break;
}
ins->input_pct = clamp(0, ins->input_pct, 1);
}
internal void
incenter_handle_yes_no_msg(Incenter_State* ins, Incenter_Scene scene, char msg)
{
assert(scene.kind == Incenter_SceneKind_YesOrNo);
if (msg != 'Y' && msg != 'N') {
printf("Invalid input sent to yes no scene: %c\n", msg);
printf(" Scene: %s\n", scene.name);
return;
}
switch (msg) {
case 'Y': {
ins->input_option = 1;
} break;
case 'N': {
ins->input_option = 0;
} break;
}
live_answers_input_u32(ins, scene, ins->input_option);
ins->scene_mode = Incenter_SceneMode_Passive;
ins->scene_time = 0;
}
internal void
incenter_handle_three_option_msg(Incenter_State* ins, Incenter_Scene scene, char msg)
{
assert(scene.kind == Incenter_SceneKind_ThreeOption);
if (msg != '1' && msg != '2' && msg != '3') {
printf("Invalid input sent to 3 option scene: %c\n", msg);
printf(" Scene: %s\n", scene.name);
return;
}
ins->input_option = (msg - '0') - 1;
live_answers_input_u32(ins, scene, ins->input_option);
ins->scene_mode = Incenter_SceneMode_Passive;
ins->scene_time = 0;
}
internal void
incenter_handle_interface_msg(Incenter_State* ins, Data msg)
{
u32 msg_kind = Incenter_InterfaceMessage_Invalid;
u32 scene_id = 0;
if (INCENTER_CMP3(msg.base, "UIN")) {
msg_kind = Incenter_InterfaceMessage_UserInput;
} else if (INCENTER_CMP3(msg.base, "GTS")){
msg_kind = Incenter_InterfaceMessage_GoToScene;
char* scene_id_start = (char*)(msg.base + 3);
scene_id = scene_id_start[0] - '0';
if (scene_id_start[1] != 0) {
scene_id *= 10;
scene_id += scene_id_start[1] - '0';
}
}
switch (msg_kind)
{
case Incenter_InterfaceMessage_GoToScene:
{
if (scene_id > Incenter_Scene_Invalid &&
scene_id < Incenter_Scene_Count)
{
if (scene_id != ins->scene_at) {
incenter_scene_go_to(ins, scene_id);
}
}
else
{
printf("Unknown Scene ID Requested: %d\n", scene_id);
}
} break;
case Incenter_InterfaceMessage_UserInput:
{
Incenter_Scene scene = ins->scenes[ins->scene_at];
char input_kind = msg.base[3];
switch (scene.kind) {
case Incenter_SceneKind_SlidingScale: {
incenter_handle_sliding_scale_msg(ins, scene, input_kind);
} break;
case Incenter_SceneKind_YesOrNo: {
incenter_handle_yes_no_msg(ins, scene, input_kind);
} break;
case Incenter_SceneKind_ThreeOption: {
incenter_handle_three_option_msg(ins, scene, input_kind);
} break;
}
} break;
default:
{
printf("Unknown message kind: %d\n", msg_kind);
// TODO: Print the actual message received
} break;
}
}