diff options
Diffstat (limited to 'src')
| -rw-r--r-- | src/b.h | 35 | ||||
| -rw-r--r-- | src/gui.h | 16 | ||||
| -rw-r--r-- | src/midi.c | 20 | ||||
| -rw-r--r-- | src/sound.c | 3 | ||||
| -rw-r--r-- | src/synth_engine.h | 7 | ||||
| -rw-r--r-- | src/synth_engine_v2.c | 2 | ||||
| -rw-r--r-- | src/synth_gui.c | 40 | ||||
| -rw-r--r-- | src/tt.c | 124 | ||||
| -rw-r--r-- | src/web.c | 248 | 
9 files changed, 332 insertions, 163 deletions
@@ -50,7 +50,8 @@  typedef enum {      B_INFO,      B_CMD, -    B_BUILDING, +    B_COMPILE, +    B_TEMPLATE,      B_CHANGE,      B_WARNING,      B_ERROR, @@ -195,8 +196,8 @@ void b_temp_rewind(size_t checkpoint);  int is_path1_modified_after_path2(const char *path1, const char *path2);  bool b_rename(const char *old_path, const char *new_path); -int b_needs_rebuild(const char *output_path, const char **input_paths, size_t input_paths_count); -int b_needs_rebuild1(const char *output_path, const char *input_path); +int b_needs_rebuild(B_Log_Level log, const char *output_path, const char **input_paths, size_t input_paths_count); +int b_needs_rebuild1(B_Log_Level log, const char *output_path, const char *input_path);  int b_file_exists(const char *file_path);  // TODO: add MinGW support for Go Rebuild Urself™ Technology @@ -246,7 +247,7 @@ int b_file_exists(const char *file_path);          assert(argc >= 1);                                                      \          const char *binary_path = argv[0];                                      \                                                                                  \ -        int rebuild_is_needed = b_needs_rebuild(binary_path, &source_path, 1);  \ +        int rebuild_is_needed = b_needs_rebuild(B_COMPILE, binary_path, &source_path, 1); \          if (rebuild_is_needed < 0) exit(1);                                     \          if (rebuild_is_needed) {                                                \              B_String_Builder sb = {0};                                          \ @@ -506,22 +507,25 @@ void b_log(B_Log_Level level, const char *fmt, ...)  {      switch (level) {      case B_INFO: -        fprintf(stderr, "[INFO] "); +        fprintf(stderr, "    [INFO] ");          break;      case B_CMD: -        fprintf(stderr, "[CMD] "); +        fprintf(stderr, "     [CMD] ");          break; -    case B_BUILDING: -        fprintf(stderr, "[BUILDING] "); +    case B_COMPILE: +        fprintf(stderr, " [COMPILE] "); +        break; +    case B_TEMPLATE: +        fprintf(stderr, "[TEMPLATE] ");          break;      case B_CHANGE: -        fprintf(stderr, "[CHANGE] "); +        fprintf(stderr, "  [CHANGE] ");          break;      case B_WARNING: -        fprintf(stderr, "[WARNING] "); +        fprintf(stderr, " [WARNING] ");          break;      case B_ERROR: -        fprintf(stderr, "[ERROR] "); +        fprintf(stderr, "   [ERROR] ");          break;      default:          B_ASSERT(0 && "unreachable"); @@ -734,14 +738,14 @@ const char *b_temp_sv_to_cstr(B_String_View sv)      return result;  } -int b_needs_rebuild(const char *output_path, const char **input_paths, size_t input_paths_count) +int b_needs_rebuild(B_Log_Level log, const char *output_path, const char **input_paths, size_t input_paths_count)  {      struct stat statbuf = {0};      if (stat(output_path, &statbuf) < 0) {          // NOTE: if output does not exist it 100% must be rebuilt          if (errno == ENOENT) { -          b_log(B_BUILDING, "%s", output_path); +          b_log(log, "%s", output_path);            return 1;          }          b_log(B_ERROR, "could not stat %s: %s", output_path, strerror(errno)); @@ -760,6 +764,7 @@ int b_needs_rebuild(const char *output_path, const char **input_paths, size_t in          // NOTE: if even a single input_path is fresher than output_path that's 100% rebuild          if (input_path_time > output_path_time) {            b_log(B_CHANGE, "%s", input_path); +          b_log(log, "%s", output_path);            return 1;          }      } @@ -767,9 +772,9 @@ int b_needs_rebuild(const char *output_path, const char **input_paths, size_t in      return 0;  } -int b_needs_rebuild1(const char *output_path, const char *input_path) +int b_needs_rebuild1(B_Log_Level log, const char *output_path, const char *input_path)  { -    return b_needs_rebuild(output_path, &input_path, 1); +  return b_needs_rebuild(log, output_path, &input_path, 1);  }  bool b_rename(const char *old_path, const char *new_path) diff --git a/src/gui.h b/src/gui.h new file mode 100644 index 0000000..f151e35 --- /dev/null +++ b/src/gui.h @@ -0,0 +1,16 @@ +#ifndef GUI_H +#define GUI_H + +typedef enum screen_e { +  SCREEN_MAIN = 0, +  SCREEN_AUDIOMIDISETUP, +  SCREEN_ERR +} screen_e; + +typedef struct synth_gui { +  screen_e screen; +  int audiomidi_initialized; +} synth_gui; + + +#endif /* GUI_H */ @@ -161,22 +161,14 @@ init_midi(midi_t *m, synth_t *synth)    printf("midi devs: %d\n", Pm_CountDevices());    const PmDeviceInfo *info; -  int i, c=0; +  int i=0;    for (i = 0; i < Pm_CountDevices(); i++) {      info = Pm_GetDeviceInfo(i);      if (!info->input) {        continue;      }      printf("%d: %s [input: %d output: %d opened: %d is_virt:%d] (interf: %s) -- %d\n", i, info->name, info->input, info->output, info->opened, info->is_virtual, info->interf, Pm_GetDefaultInputDeviceID()); -    if (synth->midi_device_id == c) { -      break; -    } -    c++; -    //if (!strcmp("MPK225 MIDI", info->name) && !info->input) break; -    //if (!strcmp("MPK225 Port A", info->name) && info->input == 1) break; -    //if (!strcmp("CH345 MIDI 1", info->name) && info->input == 1) break; -    //if (!strcmp("Midi Through Port-0", info->name) && info->input == 1) break; -    //if (!strcmp("DigitalKBD MIDI 1", info->name) && info->input == 1) break; +    if (!strcmp(synth->midi_device.name, info->name) && !info->input) break;    }    Pt_Start(1, midiCallback, m); @@ -190,6 +182,7 @@ init_midi(midi_t *m, synth_t *synth)    enable = 1;  } +// unused  int  get_midi_device_id(const char * name)  { @@ -211,23 +204,20 @@ get_midi_device_id(const char * name)  char *  get_midi_devices()  { -  //Pm_Initialize();    int i;    char *ret = (char *)malloc(sizeof(char) * 4096); -  strcpy(ret, ""); +  strcpy(ret, "Select Midi Device;");    const PmDeviceInfo *info;    for (i = 0; i < Pm_CountDevices(); i++) {      info = Pm_GetDeviceInfo(i);      if (!info->input) {        continue;      } -    printf("!!!!!!!!!!!!!!!!!!!!!!!!! ==> %s ========\n", info->name);      strcat(ret, info->name);      strcat(ret, ";");    }    ret[strlen(ret) - 1] = '\0'; -  //Pm_Terminate(); - +     return ret;  } diff --git a/src/sound.c b/src/sound.c index 2b2ca12..d4b0242 100644 --- a/src/sound.c +++ b/src/sound.c @@ -101,7 +101,8 @@ init_sound(synth_t * synth, PaStreamCallback *streamCallback, const char* device             deviceInfo->name);      if (strcmp(device_name, "default")) {        printf("Trying to use default device\n"); -      init_sound(synth, streamCallback, "default"); +      strcpy(synth->soundcard.name, "default"); +      init_sound(synth, streamCallback, synth->soundcard.name);      }      return;    } diff --git a/src/synth_engine.h b/src/synth_engine.h index 21e427c..f771073 100644 --- a/src/synth_engine.h +++ b/src/synth_engine.h @@ -22,6 +22,11 @@ typedef struct soundcard_t {    int id;  } soundcard_t; +typedef struct midi_device_t { +  char name[2048]; +  int id; +} midi_device_t; +  typedef struct lfo_t {    float freq;    float amp; @@ -136,7 +141,7 @@ typedef struct {    int sound_active;    soundcard_t soundcard; -  int midi_device_id; +  midi_device_t midi_device;    synth_viz viz; diff --git a/src/synth_engine_v2.c b/src/synth_engine_v2.c index d4b7509..4d9721c 100644 --- a/src/synth_engine_v2.c +++ b/src/synth_engine_v2.c @@ -569,8 +569,8 @@ init_synth(void)    strcpy(synth->soundcard.name, "default");    init_sound(synth, sound_gen, synth->soundcard.name); +  strcpy(synth->midi_device.name, "Midi Through Port-0");    synth->midi = (midi_t *)malloc(sizeof(midi_t)); -  synth->midi_device_id = get_midi_device_id("Midi Through Port-0");    init_midi(synth->midi, synth);    synth->gui.screen = SCREEN_MAIN; diff --git a/src/synth_gui.c b/src/synth_gui.c index 43cfda1..d1dc78e 100644 --- a/src/synth_gui.c +++ b/src/synth_gui.c @@ -708,17 +708,21 @@ void get_nth_entry(const char *str, int n, char *result) {  }  char *soundcards = NULL; +char *midi_devices = NULL;  void  draw_audiomidisetup(synth_t *synth, const char *midi_devices)  {    static int edit_midi = 0;    static int edit_sound = 0; -  static int pick = 0; +  static int midi_pick = 0; +  static int soundcard_pick = 0;    if (synth->gui.audiomidi_initialized == 0) {      soundcards = get_soundcards(); -    pick = 0; +    midi_devices = get_midi_devices(); +    soundcard_pick = 0; +    midi_pick = 0;      synth->gui.audiomidi_initialized = 1;      printf("================ AUDIOMIDISETUP GUI INITIALIZED!\n");    } @@ -734,38 +738,38 @@ draw_audiomidisetup(synth_t *synth, const char *midi_devices)    if (GuiButton((Rectangle){WIDTH - 100 - 50,                              50 + 24 + 6 + 24 + 6 + 24 + 6 + 24 + 6, 100, 24},                  "apply")) { -    if (pick != 0) { -      get_nth_entry(soundcards, pick, synth->soundcard.name); -      printf("CHANGING TO %s\n", synth->soundcard.name); +    if (soundcard_pick != 0) { +      get_nth_entry(soundcards, soundcard_pick, synth->soundcard.name); +      printf("[AUDIO] CHANGING TO %s\n", synth->soundcard.name);        change_soundcard(synth);      } +    if (midi_pick != 0) { +      get_nth_entry(midi_devices, midi_pick, synth->midi_device.name); +      printf("[MIDI] CHANGING TO %s\n", synth->midi_device.name); +      change_midi_device(synth); +    }      synth->gui.screen = SCREEN_MAIN;    } -  // audio dev +  // midi dev    if (GuiDropdownBox((Rectangle){WIDTH - 300 - 50,                                   12 + 24 + 6, 300,                                   24}, -      soundcards, &pick, edit_sound)) { -    edit_sound = !edit_sound; +      midi_devices, &midi_pick, edit_midi)) { +    edit_midi = !edit_midi;    } -  /* if (old_soundcard_id != synth->soundcard_id) { */ -  /*   old_soundcard_id = synth->soundcard_id; */ -  /*   get_nth_entry(soundcards, pick, synth->soundcard_name); */ -  /* } */ -  // midi dev +  // audio dev    if (GuiDropdownBox((Rectangle){WIDTH - 300 - 50, -                                 12, 200, +                                 12, 300,                                   24}, -      midi_devices, &synth->midi_device_id, edit_midi)) { -    edit_midi = !edit_midi; +      soundcards, &soundcard_pick, edit_sound)) { +    edit_sound = !edit_sound;    }    /* if (old_midi_device_id != synth->midi_device_id) { */    /*   old_midi_device_id = synth->midi_device_id; */ -  /*   change_midi_device(synth); */    /* } */ @@ -778,6 +782,7 @@ draw_main(synth_t *synth)  {    if (synth->gui.audiomidi_initialized != 0) {      if (soundcards) free(soundcards); +    if (midi_devices) free(midi_devices);      synth->gui.audiomidi_initialized = 0;    }    BeginDrawing(); @@ -891,7 +896,6 @@ rayrun(synth_t *synth){        draw_audiomidisetup(synth, midi_devices);      //---------------------------------------------------------------------------------- -      current_time = Pa_GetStreamTime(synth->stream);      //printf("%f :: %ld\n", current_time - prev_time, phase); diff --git a/src/tt.c b/src/tt.c new file mode 100644 index 0000000..01c9614 --- /dev/null +++ b/src/tt.c @@ -0,0 +1,124 @@ +#include <stdio.h> +#include <stdlib.h> +#include <assert.h> +#include <stdint.h> +#include <string.h> +#include <unistd.h> + +#define DEFAULT_DELIMITER "$" + +void compile_c_code(char * s) { +  printf("%.*s\n", (int) strlen(s), s); +} + +void compile_byte_array(char * s) { +  printf("write(OUT, \""); +  uint64_t slen = strlen(s); +  for (uint64_t i = 0; i < slen; ++i) { +    printf("\\x%02x", s[i]); +  } +  printf("\", %lu);\n", strlen(s)); +} + +char *read_file_to_string(const char *filename) { +  FILE *file = fopen(filename, "rb"); +  if (!file) { +    perror("Error opening file"); +    return NULL; +  } + +  fseek(file, 0, SEEK_END); +  long file_size = ftell(file); +  rewind(file); + +  char *buffer = (char *)malloc(file_size + 1); +  if (!buffer) { +    perror("Memory allocation failed"); +    fclose(file); +    return NULL; +  } + +  fread(buffer, 1, file_size, file); +  buffer[file_size] = '\0'; + +  fclose(file); +  return buffer; +} + +#define CHARSET_SIZE 128  // Covering standard ASCII characters + +int print_good_delimiters(const char * s) { +    int seen[CHARSET_SIZE] = {0};  // Array to track seen characters + +    size_t len = strlen(s); +    for (size_t i = 0; i < len; i++) { +      if (s[i] >= 0 && (int)s[i] < CHARSET_SIZE) { +        seen[(int)s[i]] = 1; +      } +    } + +    // Define the characters to check: A-Za-z0-9 and common symbols +    char *valid_chars = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789!@#$%^&*()-_=+[{]}\\|;:'\",<.>/?`~"; + +    int flag = 0; +    printf("Good options for delimiters:\n"); +    for (int i = 0; valid_chars[i] != '\0'; i++) { +        if (!seen[(unsigned char)valid_chars[i]]) { +          putchar(valid_chars[i]); +          flag++; +        } +    } +    if (!flag) { +      printf(" :( none found, compromises shall be made"); +    } +    putchar('\n'); + +    return 0; +} + + +int main(int argc, char *argv[]) +{ +  if (argc < 2) { +    fprintf(stderr, "Usage: %s <template> [delim|-d] [> OUTPUT]\n", argv[0]); +    return 1; +  } + +  const char *filepath = argv[1]; +  char *template = read_file_to_string(filepath); +  if (!template) return 1; + +  if (argc > 2 && 0 == strcmp(argv[2], "-d")) { +    print_good_delimiters(template); +    exit(0); +  } + +  char delim[1024] = DEFAULT_DELIMITER; +  if (argc > 2) { +    strcpy(delim, argv[2]); +  } + + +  int c_code_mode = 1; +  for (int i = 0; delim[i] != '\0'; i++) { +    if (template[i] != delim[i]) { +      c_code_mode = 0; +      break; +    } +  } + +  char *token = strtok(template, delim); +  while (token) { +    if (c_code_mode) { +      compile_c_code(token); +    } else { +      compile_byte_array(token); +    } +    c_code_mode = !c_code_mode; + +    token = strtok(NULL, delim); +  } + +  free(template); +  return 0; +} @@ -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) {  | 
