#include "web.h" #include #include #include #include #define HTTP_PORT 9966 #define WS_PORT 9967 static struct lws *client_wsi = NULL; synth_t * synthx; struct MHD_Daemon *server; pthread_t server_thread; #define BUFFER_SIZE 1024 * 4 char message_buffer[BUFFER_SIZE]; // Function to handle slider changes void handle_slider_change(void *cls, int value) { synth_t *synth = (synth_t*)cls; printf("Slider changed: %d\n", 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" "Content-Length: %d\r\n" "\r\n" "\r\n"; // HTML page with a slider const char *html_content = "\n" "\n" "\n" "C SYNTH WEB!\n" "\n" "\n" "\n" "\n" "\n" "\n" "\n" "\n"; // 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; 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); } 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; } 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; } // Callback to handle WebSocket events static int callback_ws(struct lws *wsi, enum lws_callback_reasons reason, void *user, void *in, size_t len) { (void)user; char buf[10000] = ""; char tmp[10000] = ""; switch (reason) { case LWS_CALLBACK_ESTABLISHED: { // When a connection is established client_wsi = wsi; // Store the WebSocket connection for later use printf("WebSocket connection established with client: %p\n", wsi); /* const char *msg = "Hello, Client!"; */ /* printf("Sending message: %s\n", msg); */ /* int n = lws_write(wsi, (unsigned char *)msg, strlen(msg), LWS_WRITE_TEXT); */ /* if (n < 0) { */ /* printf("Error sending message, error code: %d\n", n); */ /* } */ break; } 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); //lws_write(wsi, (unsigned char *)in, len, LWS_WRITE_TEXT); int value = atoi(buffer); handle_slider_change(synthx, value); break; } case LWS_CALLBACK_SERVER_WRITEABLE: { printf("\nLWS_CALLBACK_SERVER_WRITEABLE\n\n"); /* size_t msg_len = strlen(message_buffer); */ /* unsigned char buffer[LWS_PRE + BUFFER_SIZE]; */ /* memcpy(&buffer[LWS_PRE], message_buffer, msg_len); */ /* lws_write(wsi, (unsigned char *)buffer, strlen(buffer), LWS_WRITE_TEXT); */ break; } 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: { printf("WebSocket connection closed with client: %p\n", wsi); } default: break; } return 0; } // Thread function to run the WebSocket server void *websocket_server_thread(void *arg) { (void)arg; struct lws_context_creation_info info; struct lws_context *context; struct lws_protocols protocols[] = { //{ "http-only", callback_http, 0, 0 }, { "ws", callback_ws, 0, 128, 0, 0, 0 }, { NULL, NULL, 0, 0, 0, 0, 0 } // Terminator }; memset(&info, 0, sizeof(info)); info.port = WS_PORT; //info.user = arg; info.protocols = protocols; info.pt_serv_buf_size = 32 * 1024; info.options = LWS_SERVER_OPTION_VALIDATE_UTF8; context = lws_create_context(&info); if (!context) { fprintf(stderr, "lws_create_context failed\n"); return NULL; } printf("WebSocket server running on ws://localhost:%d\n", WS_PORT); while (1) { lws_service(context, 1000); // Service WebSocket events } lws_context_destroy(context); return NULL; } void init_web(synth_t * synth) { 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) { fprintf(stderr, "Failed to create server thread\n"); return; } } void free_web() { MHD_stop_daemon(server); } void ws_send_message(const char *message) { if (client_wsi != NULL) { /* strcpy(message_buffer, message); */ /* lws_callback_on_writable(client_wsi); */ size_t msg_len = strlen(message); unsigned char buffer[LWS_PRE + BUFFER_SIZE]; memcpy(&buffer[LWS_PRE], message, msg_len); lws_write(client_wsi, &buffer[LWS_PRE], msg_len, LWS_WRITE_TEXT); printf("[WS]: Sent <<%s>>\n", message); //lws_write(client_wsi, (unsigned char *)message, strlen(message), LWS_WRITE_TEXT); } }