summaryrefslogtreecommitdiffstats
path: root/src/web.c
diff options
context:
space:
mode:
authorgrm <grm@eyesin.space>2025-03-02 13:53:54 +0200
committergrm <grm@eyesin.space>2025-03-02 13:53:54 +0200
commit9847614871e861c216425b95a8300dba37b0f6e6 (patch)
treef319cc5ebd58d2247d546a3c2149ce85559be6d8 /src/web.c
parentd5e9beaf5cc38c0e57bbc555a6e3054f3bf000d8 (diff)
downloadsynth-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.c248
1 files changed, 136 insertions, 112 deletions
diff --git a/src/web.c b/src/web.c
index 3a65850..3108545 100644
--- a/src/web.c
+++ b/src/web.c
@@ -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) {