Refactor texture code + start splitting networking into threads.

This commit is contained in:
Sheldon Lee 2024-11-08 22:46:33 +08:00
parent 759a99edcf
commit 1d30dba681
3 changed files with 121 additions and 48 deletions

116
main.c
View File

@ -2,6 +2,9 @@
#include <SDL2/SDL_ttf.h> #include <SDL2/SDL_ttf.h>
#include <stdio.h> #include <stdio.h>
#include <semaphore.h>
#include <pthread.h>
#include "texture.h" #include "texture.h"
#include "audio.h" #include "audio.h"
#include "net.h" #include "net.h"
@ -9,15 +12,18 @@
#define SCREEN_WIDTH 640 #define SCREEN_WIDTH 640
#define SCREEN_HEIGHT 480 #define SCREEN_HEIGHT 480
#define TEXT_LINES 20
#define BODY_TEXT_LINES TEXT_LINES-2
#define FONT_SIZE SCREEN_HEIGHT/TEXT_LINES
#define PORT 55555 #define PORT 55555
typedef enum { typedef enum {
SOCKET_LISTEN,
SELECTING_DEVICE, SELECTING_DEVICE,
RECORDING, RECORDING,
RECORDED, RECORDED,
PLAYBACK, PLAYBACK,
SOCKET,
} application_state; } application_state;
typedef struct { typedef struct {
@ -25,6 +31,7 @@ typedef struct {
audio_state audio; audio_state audio;
int device_index; int device_index;
int update_ui; int update_ui;
sem_t sem;
} state; } state;
int init(); int init();
@ -32,6 +39,8 @@ void destroy();
int select_device(SDL_KeyboardEvent* key_event, int max_index); int select_device(SDL_KeyboardEvent* key_event, int max_index);
void application_state_to_string(application_state state, char* string); void application_state_to_string(application_state state, char* string);
void* peer_discovery_t(void* args);
SDL_Window* window = NULL; SDL_Window* window = NULL;
SDL_Renderer* renderer = NULL; SDL_Renderer* renderer = NULL;
@ -39,6 +48,7 @@ int num_devices = 0;
int handle_input(SDL_Event* event, state* state); int handle_input(SDL_Event* event, state* state);
void handle_task(state* state); void handle_task(state* state);
void render_body_text(text_texture* textures, int len);
int main(int argc, char* argv[]) int main(int argc, char* argv[])
{ {
if (!init()) return 1; if (!init()) return 1;
@ -46,33 +56,43 @@ int main(int argc, char* argv[])
num_devices = SDL_GetNumAudioDevices(1); num_devices = SDL_GetNumAudioDevices(1);
log_message(LOG_INFO, "Num audio devices: %i", num_devices); log_message(LOG_INFO, "Num audio devices: %i", num_devices);
char char_buffer[64]; char char_buffer[64];
char default_fmt[] = "Device selected: %i"; char device_selected_fmt[] = "Device selected: %i";
state state; state state;
state.application_state = SOCKET; //state.application_state = SOCKET_LISTEN;
state.application_state = SELECTING_DEVICE;
if (!audio_init(&state.audio)) return 1; if (!audio_init(&state.audio)) return 1;
state.device_index = -1; state.device_index = -1;
state.update_ui = 0; state.update_ui = 0;
sem_init(&state.sem, 0, 1);
text_texture display_text_texture; text_texture display_text_texture;
text_texture_init(&display_text_texture, renderer); text_texture_init(&display_text_texture, renderer, FONT_SIZE);
sprintf(char_buffer, default_fmt, state.device_index); sprintf(char_buffer, device_selected_fmt, state.device_index);
text_texture_load(&display_text_texture, char_buffer); text_texture_load(&display_text_texture, char_buffer);
text_texture device_textures[num_devices];
for (int i = 0; i < num_devices; i++) {
text_texture_init(&device_textures[i], renderer);
sprintf(char_buffer, "%i: %s", i, SDL_GetAudioDeviceName(i, 1));
text_texture_load(&device_textures[i], char_buffer);
}
text_texture state_text_texture; text_texture state_text_texture;
text_texture_init(&state_text_texture, renderer); text_texture_init(&state_text_texture, renderer, FONT_SIZE);
application_state_to_string(state.application_state, char_buffer); application_state_to_string(state.application_state, char_buffer);
text_texture_load(&state_text_texture, char_buffer); text_texture_load(&state_text_texture, char_buffer);
text_texture_frame socket_frame;
text_texture_frame_init(&socket_frame, BODY_TEXT_LINES, renderer, FONT_SIZE);
text_texture_frame select_device_frame;
text_texture_frame_init(&select_device_frame, num_devices, renderer, FONT_SIZE);
for (int i = 0; i < select_device_frame.len; i++) {
sprintf(char_buffer, "%i: %s", i, SDL_GetAudioDeviceName(i, 1));
text_texture_load(&select_device_frame.textures[i], char_buffer);
}
pthread_t peer_discovery_thread;
pthread_create(&peer_discovery_thread, NULL, peer_discovery_t, &state);
SDL_Event event; SDL_Event event;
while (1) { while (1) {
sem_wait(&state.sem);
while (SDL_PollEvent(&event)) { while (SDL_PollEvent(&event)) {
SDL_Keycode keysym = event.key.keysym.sym; SDL_Keycode keysym = event.key.keysym.sym;
switch (event.type) { switch (event.type) {
@ -91,7 +111,7 @@ int main(int argc, char* argv[])
handle_task(&state); handle_task(&state);
if (state.update_ui) { if (state.update_ui) {
sprintf(char_buffer, default_fmt, state.device_index); sprintf(char_buffer, device_selected_fmt, state.device_index);
text_texture_load(&display_text_texture, char_buffer); text_texture_load(&display_text_texture, char_buffer);
application_state_to_string(state.application_state, char_buffer); application_state_to_string(state.application_state, char_buffer);
text_texture_load(&state_text_texture, char_buffer); text_texture_load(&state_text_texture, char_buffer);
@ -106,29 +126,29 @@ int main(int argc, char* argv[])
// Render // Render
text_texture_render(&display_text_texture, 0, 0); text_texture_render(&display_text_texture, 0, 0);
if (state.application_state == SOCKET_LISTEN) {
text_texture_frame_render(&socket_frame, 0, FONT_SIZE);
}
if (state.application_state == SELECTING_DEVICE) { if (state.application_state == SELECTING_DEVICE) {
int text_y_offset_step = display_text_texture.height * 2; text_texture_frame_render(&select_device_frame, 0, FONT_SIZE);
int text_y_offset = text_y_offset_step;
for (int i = 0; i < num_devices; i++) {
text_texture_render(&device_textures[i], 0, text_y_offset);
text_y_offset += text_y_offset_step;
}
} }
text_texture_render(&state_text_texture, 0, SCREEN_HEIGHT - state_text_texture.height); text_texture_render(&state_text_texture, 0, SCREEN_HEIGHT - state_text_texture.height);
// Update the screen // Update the screen
SDL_RenderPresent(renderer); SDL_RenderPresent(renderer);
sem_post(&state.sem);
} }
cleanup: cleanup:
log_message(LOG_INFO, "Cleanup start"); log_message(LOG_INFO, "Cleanup start");
audio_destroy(&state.audio); audio_destroy(&state.audio);
log_message(LOG_INFO, "Audio done"); log_message(LOG_INFO, "Audio done");
text_texture_free(&display_text_texture); text_texture_destroy(&display_text_texture);
for (int i = 0; i < num_devices; i++) { text_texture_destroy(&state_text_texture);
text_texture_free(&device_textures[i]); text_texture_frame_destroy(&socket_frame);
} text_texture_frame_destroy(&select_device_frame);
log_message(LOG_INFO, "Texture done"); log_message(LOG_INFO, "Texture done");
destroy(); destroy();
log_message(LOG_INFO, "Done"); log_message(LOG_INFO, "Done");
@ -140,6 +160,18 @@ int handle_input(SDL_Event* event, state* state)
SDL_Keycode keysym = event->key.keysym.sym; SDL_Keycode keysym = event->key.keysym.sym;
switch (state->application_state) { switch (state->application_state) {
case SOCKET_LISTEN:
switch (keysym) {
case SDLK_1:
log_message(LOG_INFO, "Socket button 1 pressed");
net_broadcast();
break;
case SDLK_2:
log_message(LOG_INFO, "Socket button 2 pressed");
break;
}
break;
case SELECTING_DEVICE: case SELECTING_DEVICE:
switch (keysym) { switch (keysym) {
case SDLK_y: case SDLK_y:
@ -163,7 +195,6 @@ int handle_input(SDL_Event* event, state* state)
audio_device_close(&state->audio, 1); audio_device_close(&state->audio, 1);
audio_recording_init(&state->audio, state->device_index); audio_recording_init(&state->audio, state->device_index);
state->update_ui = 1; state->update_ui = 1;
break; break;
case RECORDING: case RECORDING:
@ -207,17 +238,6 @@ int handle_input(SDL_Event* event, state* state)
} }
break; break;
case SOCKET:
switch (keysym) {
case SDLK_1:
log_message(LOG_INFO, "Socket button 1 pressed");
net_broadcast();
break;
case SDLK_2:
log_message(LOG_INFO, "Socket button 2 pressed");
net_listen_clients();
break;
}
} }
return 1; return 1;
} }
@ -226,6 +246,9 @@ void handle_task(state* state)
{ {
switch (state->application_state) { switch (state->application_state) {
case SOCKET_LISTEN:
break;
case SELECTING_DEVICE: case SELECTING_DEVICE:
break; break;
@ -246,8 +269,6 @@ void handle_task(state* state)
} }
break; break;
case SOCKET:
break;
} }
} }
@ -318,8 +339,11 @@ int select_device(SDL_KeyboardEvent* key_event, int max_index)
void application_state_to_string(application_state state, char* string) void application_state_to_string(application_state state, char* string)
{ {
switch (state) { switch (state) {
case SOCKET_LISTEN:
sprintf(string, "Socket");
break;
case SELECTING_DEVICE: case SELECTING_DEVICE:
sprintf(string, "Selecting Device [0-9] -> [y/RET], "); sprintf(string, "Selecting Device [0-9] -> [y/RET]");
break; break;
case RECORDING: case RECORDING:
sprintf(string, "Recording [ESC]: CANCEL"); sprintf(string, "Recording [ESC]: CANCEL");
@ -330,8 +354,16 @@ void application_state_to_string(application_state state, char* string)
case PLAYBACK: case PLAYBACK:
sprintf(string, "Playing [ESC]: CANCEL"); sprintf(string, "Playing [ESC]: CANCEL");
break; break;
case SOCKET: }
sprintf(string, "Socket"); }
break;
void* peer_discovery_t(void* args)
{
state* state = args;
while (1) {
sem_wait(&state->sem);
net_listen_clients();
sem_post(&state->sem);
sleep(1);
} }
} }

View File

@ -1,11 +1,11 @@
#include "texture.h" #include "texture.h"
#include "log.h" #include "log.h"
int text_texture_init(text_texture* text_texture, SDL_Renderer* renderer) int text_texture_init(text_texture* text_texture, SDL_Renderer* renderer, int font_size)
{ {
text_texture->texture = NULL; text_texture->texture = NULL;
text_texture->renderer = renderer; text_texture->renderer = renderer;
text_texture->font = TTF_OpenFont("FiraCode-Regular.ttf", 24); text_texture->font = TTF_OpenFont("FiraCode-Regular.ttf", font_size);
if (!text_texture->font) { if (!text_texture->font) {
log_message(LOG_ERROR, "Failed to load font! TTF_Error: %s", TTF_GetError()); log_message(LOG_ERROR, "Failed to load font! TTF_Error: %s", TTF_GetError());
return 0; return 0;
@ -23,6 +23,7 @@ int text_texture_load(text_texture* text_texture, char* string)
} }
SDL_Color text_color = { 255, 255, 255 }; SDL_Color text_color = { 255, 255, 255 };
if (strlen(string) == 0) string = " ";
SDL_Surface* text_surface = TTF_RenderText_Solid(text_texture->font, string, text_color); SDL_Surface* text_surface = TTF_RenderText_Solid(text_texture->font, string, text_color);
if (!text_surface) { if (!text_surface) {
log_message(LOG_ERROR, "Unable to render text surface! TTF_Error: %s", TTF_GetError()); log_message(LOG_ERROR, "Unable to render text surface! TTF_Error: %s", TTF_GetError());
@ -35,7 +36,7 @@ int text_texture_load(text_texture* text_texture, char* string)
return 0; return 0;
} }
text_texture->texture = SDL_CreateTextureFromSurface(text_texture->renderer, text_surface); text_texture->texture = texture;
text_texture->width = text_surface->w; text_texture->width = text_surface->w;
text_texture->height = text_surface->h; text_texture->height = text_surface->h;
@ -62,11 +63,42 @@ int text_texture_render(text_texture* text_texture, int x, int y)
return 1; return 1;
} }
int text_texture_free(text_texture* text_texture) int text_texture_destroy(text_texture* text_texture)
{ {
if (!text_texture->texture) { if (!text_texture->texture) {
return 0; return 0;
} }
SDL_DestroyTexture(text_texture->texture); SDL_DestroyTexture(text_texture->texture);
TTF_CloseFont(text_texture->font);
return 1;
}
int text_texture_frame_init(text_texture_frame* text_texture_frame, int len, SDL_Renderer* renderer, int font_size)
{
text_texture_frame->textures = malloc(len*sizeof(text_texture));
for (int i = 0; i < len; i++) {
text_texture_init(&text_texture_frame->textures[i], renderer, font_size);
}
text_texture_frame->len = len;
return 1;
}
int text_texture_frame_render(text_texture_frame* text_texture_frame, int x, int y)
{
int text_y_offset_step = TTF_FontHeight(text_texture_frame->textures[0].font);
int text_y_offset = y;
for (int i = 0; i < text_texture_frame->len; i++) {
text_texture_render(&text_texture_frame->textures[i], x, text_y_offset);
text_y_offset += text_y_offset_step;
}
return 1;
}
int text_texture_frame_destroy(text_texture_frame* text_texture_frame)
{
for (int i = 0; i < text_texture_frame->len; i++) {
text_texture_destroy(&text_texture_frame->textures[i]);
}
free(text_texture_frame->textures);
return 1; return 1;
} }

View File

@ -12,9 +12,18 @@ typedef struct {
int height; int height;
} text_texture; } text_texture;
int text_texture_init(text_texture* text_texture, SDL_Renderer* renderer); typedef struct {
text_texture* textures;
int len;
} text_texture_frame;
int text_texture_init(text_texture* text_texture, SDL_Renderer* renderer, int font_size);
int text_texture_load(text_texture* text_texture, char* string); int text_texture_load(text_texture* text_texture, char* string);
int text_texture_render(text_texture* text_texture, int x, int y); int text_texture_render(text_texture* text_texture, int x, int y);
int text_texture_free(text_texture* text_texture); int text_texture_destroy(text_texture* text_texture);
int text_texture_frame_init(text_texture_frame* text_texture_frame, int len, SDL_Renderer* renderer, int font_size);
int text_texture_frame_render(text_texture_frame* text_texture_frame, int x, int y);
int text_texture_frame_destroy(text_texture_frame* text_texture_frame);
#endif #endif