diff options
author | grm <grm@eyesin.space> | 2025-03-02 13:53:54 +0200 |
---|---|---|
committer | grm <grm@eyesin.space> | 2025-03-02 13:53:54 +0200 |
commit | 9847614871e861c216425b95a8300dba37b0f6e6 (patch) | |
tree | f319cc5ebd58d2247d546a3c2149ce85559be6d8 /src/web.c | |
parent | d5e9beaf5cc38c0e57bbc555a6e3054f3bf000d8 (diff) | |
download | synth-project-9847614871e861c216425b95a8300dba37b0f6e6.tar.gz synth-project-9847614871e861c216425b95a8300dba37b0f6e6.tar.bz2 synth-project-9847614871e861c216425b95a8300dba37b0f6e6.zip |
Also improve midi and add tt for templating
Diffstat (limited to 'src/web.c')
-rw-r--r-- | src/web.c | 248 |
1 files changed, 136 insertions, 112 deletions
@@ -1,11 +1,10 @@ #include "web.h" +#define _GNU_SOURCE #include <libwebsockets.h> #include <pthread.h> -#include <microhttpd.h> #include <unistd.h> - #define HTTP_PORT 9966 #define WS_PORT 9967 @@ -15,6 +14,7 @@ struct MHD_Daemon *server; pthread_t server_thread; #define BUFFER_SIZE 1024 * 4 char message_buffer[BUFFER_SIZE]; +static char *html_content; // Function to handle slider changes void handle_slider_change(void *cls, int value) { @@ -23,41 +23,6 @@ void handle_slider_change(void *cls, int value) { cc_set(&synth->cc_cutoff, value); } -void handle_button_click(void *cls) { - printf("Button clicked!!!"); - synth_t *synth = (synth_t*)cls; - - int i = 5; - //printf("Note On : %s[%d] %fHz\n", int_to_note(i % 12), (synth->octave + (i / 12)) % 8, note); - synth->midi_note[i].freq = 16.35160 * pow(2, (synth->octave + i / 12.0)); - //synth->midi_note[i].freq = notes[i % 12][(synth->octave + (i / 12)) % 8]; - synth->midi_note[i].channel = -1; - synth->midi_note[i].noteOn = Pa_GetStreamTime(synth->stream); - synth->midi_note[i].noteOff = 0; - synth->midi_note[i].velocity = 1.0; - synth->midi_note[i].elapsed = 0; - synth->midi_note[i].active = 1; - int flag = 1; - for (int j = 0; j < synth->midi_active_n; j++) { - if (synth->midi_active[j] == &synth->midi_note[i]) { - flag = 0; - } - } - if (flag) { - synth->midi_active[synth->midi_active_n++] = &synth->midi_note[i]; - } - - //synth->adsr.elapsed = 0; - synth->active = 1; - - usleep(500000); - - synth->midi_note[i].noteOff = Pa_GetStreamTime(synth->stream); - synth->midi_note[i].noteOffSample = synth->midi_note[i].elapsed; - -} - - const char *html_header = "HTTP/1.1 200 OK\r\n" "Connection: close\r\n" @@ -65,76 +30,75 @@ const char *html_header = "\r\n" "\r\n"; -// HTML page with a slider -const char *html_content = - "<!DOCTYPE html>\n" - "<html>\n" - "<head>\n" - "<title>C SYNTH WEB!</title>\n" - "</head>\n" - "<body>\n" - "<input id='slider' style='width: 100%; height: 200px;' type='range' min='1' max='22000' />\n" - "<button onclick='onButtonClick()'>Trigger</button>\n" - "<button id='but'>ws</button>\n" - "<script>\n" - "const ws = new WebSocket('ws://10.0.0.10:9967');\n" - "const slider = document.getElementById('slider');\n" - "const but = document.getElementById('but');\n" - "\n" - "slider.oninput = function() { ws.send(slider.value); };\n" - "\n" - "but.onclick = function() { ws.send('THIS IS A TEST DONT KILL ME'); };\n" - "\n" - "ws.onmessage = function(event) {\n" - " console.log('Message from server: ' + event.data);\n" - " slider.value = parseInt(event.data);" - "};\n" - "ws.onopen = function() {\n" - " console.log('Connected to WebSocket server');\n" - "};\n" - "ws.onerror = function(error) {\n" - " console.error('WebSocket error: ' + error);\n" - "};\n" - "</script>\n" - "</body>\n" - "</html>\n"; +char *read_file_to_string(const char *filename) { + FILE *file = fopen(filename, "rb"); // Open file in binary mode + if (!file) { + perror("Error opening file"); + return NULL; + } -// HTTP request handler -enum MHD_Result handle_request(void *cls, struct MHD_Connection *connection, - const char *url, const char *method, - const char *version, const char *upload_data, - size_t *upload_data_size, void **con_cls) { - (void)version; - (void)upload_data; - (void)upload_data_size; - (void)con_cls; - struct MHD_Response *response; - enum MHD_Result ret; + // Seek to the end to determine file size + fseek(file, 0, SEEK_END); + long file_size = ftell(file); + rewind(file); // Go back to the beginning - if (strcmp(url, "/slider") == 0 && strcmp(method, "GET") == 0) { - const char *value_str = MHD_lookup_connection_value(connection, MHD_GET_ARGUMENT_KIND, "value"); - if (value_str) { - int value = atoi(value_str); - handle_slider_change(cls, value); + // Allocate memory for the file content (+1 for null terminator) + char *buffer = (char *)malloc(file_size + 1); + if (!buffer) { + perror("Memory allocation failed"); + fclose(file); + return NULL; } - response = MHD_create_response_from_buffer(0, "", MHD_RESPMEM_PERSISTENT); - ret = MHD_queue_response(connection, MHD_HTTP_OK, response); - MHD_destroy_response(response); - return ret; - } - if (strcmp(url, "/button") == 0 && strcmp(method, "GET") == 0) { - handle_button_click(cls); - response = MHD_create_response_from_buffer(0, "", MHD_RESPMEM_PERSISTENT); - ret = MHD_queue_response(connection, MHD_HTTP_OK, response); - MHD_destroy_response(response); - return ret; - } + // Read file into buffer + fread(buffer, 1, file_size, file); + buffer[file_size] = '\0'; // Null-terminate the string - response = MHD_create_response_from_buffer(strlen(html_content), (void *)html_content, MHD_RESPMEM_PERSISTENT); - ret = MHD_queue_response(connection, MHD_HTTP_OK, response); - MHD_destroy_response(response); - return ret; + fclose(file); + return buffer; +} + + + +int +key_to_number(char key) { + switch (key) { + case 'q': + return 0; + case '2': + return 1; + case 'w': + return 2; + case '3': + return 3; + case 'e': + return 4; + case 'r': + return 5; + case '5': + return 6; + case 't': + return 7; + case '6': + return 8; + case 'y': + return 9; + case '7': + return 10; + case 'u': + return 11; + case 'i': + return 12; + case '9': + return 13; + case 'o': + return 14; + case '0': + return 15; + case 'p': + return 16; + } + return 0; } // Callback to handle WebSocket events @@ -158,7 +122,44 @@ static int callback_ws(struct lws *wsi, enum lws_callback_reasons reason, case LWS_CALLBACK_RECEIVE: { // When a message is received char buffer[128]; snprintf(buffer, sizeof(buffer), "%.*s", (int)len, (char *)in); - printf("Received slider value: %s\n", buffer); + printf("Got ws message: [%s]\n", buffer); + if (!strcmp("note_on", buffer)) { + break; + } + if (!strcmp("note_off", buffer)) { + break; + } + if (buffer[0] == '+') { + char key = buffer[1]; + int i = key_to_number(key); + synthx->midi_note[i].freq = 16.35160 * pow(2, (synthx->octave + i / 12.0)); + synthx->midi_note[i].channel = -1; + synthx->midi_note[i].noteOn = Pa_GetStreamTime(synthx->stream); + synthx->midi_note[i].noteOff = 0; + synthx->midi_note[i].velocity = 1.0; + synthx->midi_note[i].elapsed = 0; + synthx->midi_note[i].active = 1; + int flag = 1; + for (int j = 0; j < synthx->midi_active_n; j++) { + if (synthx->midi_active[j] == &synthx->midi_note[i]) { + flag = 0; + } + } + if (flag) { + synthx->midi_active[synthx->midi_active_n++] = &synthx->midi_note[i]; + } + + //synth->adsr.elapsed = 0; + synthx->active = 1; + break; + } + if (buffer[0] == '-') { + char key = buffer[1]; + int i = key_to_number(key); + synthx->midi_note[i].noteOff = Pa_GetStreamTime(synthx->stream); + synthx->midi_note[i].noteOffSample = synthx->midi_note[i].elapsed; + break; + } //lws_write(wsi, (unsigned char *)in, len, LWS_WRITE_TEXT); int value = atoi(buffer); handle_slider_change(synthx, value); @@ -175,10 +176,8 @@ static int callback_ws(struct lws *wsi, enum lws_callback_reasons reason, case LWS_CALLBACK_HTTP: { snprintf(tmp, sizeof(tmp), html_header, strlen(html_content)); strcpy(buf, tmp); - printf("\nHTTP?!\n\n%s\n", tmp); strcat(buf, html_content); lws_write(wsi, (unsigned char *)buf, strlen(buf), LWS_WRITE_HTTP); - return -1; break; } case LWS_CALLBACK_CLOSED: { @@ -224,16 +223,41 @@ void *websocket_server_thread(void *arg) { return NULL; } +char *get_from_template() { + int size = 1024^3 * 1000; + char * ret = (char *)malloc(sizeof(char) * size); + + int pipefd[2]; + if (pipe(pipefd) == -1) { + perror("pipe"); + return NULL; + } + + #define OUT pipefd[1] + #define INT(x) dprintf(OUT, "%d", x); + #define PERCENT dprintf(OUT, "%s", "%"); + #include "index.html.h" + close(pipefd[1]); + + // Read from the pipe into a buffer + ssize_t bytes_read = read(pipefd[0], ret, size - 1); + if (bytes_read == -1) { + perror("read"); + return NULL; + } + + // Null-terminate the ret + ret[bytes_read] = '\0'; + close(pipefd[0]); + return ret; +} + void init_web(synth_t * synth) { + //html_content = read_file_to_string("src/index.html"); + html_content = get_from_template(); synthx = synth; - // Start the HTTP server - server = MHD_start_daemon(MHD_USE_THREAD_PER_CONNECTION, HTTP_PORT, NULL, NULL, &handle_request, (void *)synth, MHD_OPTION_END); - if (server == NULL) { - fprintf(stderr, "Failed to start server\n"); - return; - } // Create a new thread for the WebSocket server if (pthread_create(&server_thread, NULL, websocket_server_thread, NULL) != 0) { @@ -245,7 +269,7 @@ init_web(synth_t * synth) void free_web() { - MHD_stop_daemon(server); + free(html_content); } void ws_send_message(const char *message) { |