From 71ac5ccff54b86cc756133d55b2d75a85c06767d Mon Sep 17 00:00:00 2001 From: Aino Spring Date: Sun, 17 Mar 2024 00:38:49 +0100 Subject: [PATCH] Implemented json-output --- src/CMakeLists.txt | 2 + src/main.c | 135 +++++++++++++++++++++++++++++++++++++++------ src/output.c | 63 +++++++++++++++++++++ src/output.h | 21 +++++++ 4 files changed, 203 insertions(+), 18 deletions(-) create mode 100644 src/output.c create mode 100644 src/output.h diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index 0054167..7b6a434 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -8,6 +8,8 @@ set(SOURCE_FILES ${SOURCE_FILES} ${CMAKE_CURRENT_SOURCE_DIR}/device_registry.h ${CMAKE_CURRENT_SOURCE_DIR}/hid_utility.c ${CMAKE_CURRENT_SOURCE_DIR}/hid_utility.h + ${CMAKE_CURRENT_SOURCE_DIR}/output.c + ${CMAKE_CURRENT_SOURCE_DIR}/output.h ${CMAKE_CURRENT_SOURCE_DIR}/utility.c ${CMAKE_CURRENT_SOURCE_DIR}/utility.h PARENT_SCOPE) diff --git a/src/main.c b/src/main.c index d8897d1..b2c86d1 100644 --- a/src/main.c +++ b/src/main.c @@ -21,6 +21,7 @@ #include "device.h" #include "device_registry.h" #include "hid_utility.h" +#include "output.h" #include "utility.h" #include @@ -35,13 +36,15 @@ int hsc_device_timeout = 5000; -// 0=false; 1=true -static int short_output = 0; +// 0=text; 1=short; 2=json +static int output = 0; + +static t_output json_output; /// printf only when short output not specified #define PRINT_INFO(...) \ { \ - if (!short_output) { \ + if (output == 0) { \ printf(__VA_ARGS__); \ } \ } @@ -63,6 +66,14 @@ static int find_device(struct device* device_found) if (found == 0) { PRINT_INFO("Found %s!\n", device_found->device_name); + if (output == 2) { + char* device_name = malloc(strlen(device_found->device_name) + 2); + strcpy(device_name, "\""); + strcat(device_name, device_found->device_name); + strcat(device_name, "\""); + output_add(&json_output, new_entry("device", device_name)); + free(device_name); + } break; } @@ -185,14 +196,52 @@ static int handle_feature(struct device* device_found, hid_device** device_handl case CAP_BATTERY_STATUS: ret = device_found->request_battery(*device_handle); - if (ret < 0) + if (ret < 0) { break; - else if (ret == BATTERY_CHARGING) - short_output ? printf("-1") : printf("Battery: Charging\n"); - else if (ret == BATTERY_UNAVAILABLE) - short_output ? printf("-2") : printf("Battery: Unavailable\n"); - else - short_output ? printf("%d", ret) : printf("Battery: %d%%\n", ret); + } + + else if (ret == BATTERY_CHARGING) { + switch (output) { + case 0: + printf("Battery: Charging\n"); + break; + case 1: + printf("-1"); + break; + case 2: + output_add(&json_output, new_entry("battery", "charging")); + break; + } + } else if (ret == BATTERY_UNAVAILABLE) { + switch (output) { + case 0: + printf("Battery: Unavailable\n"); + break; + case 1: + printf("-2"); + break; + case 2: + output_add(&json_output, new_entry("battery", "unavailable")); + break; + } + } else { + switch (output) { + case 0: { + printf("Battery: %d%%\n", ret); + break; + } + case 1: { + printf("%d", ret); + break; + } + case 2: { + char buffer[16]; + sprintf(buffer, "%d", ret); + output_add(&json_output, new_entry("battery", buffer)); + break; + } + } + } break; @@ -216,10 +265,26 @@ static int handle_feature(struct device* device_found, hid_device** device_handl case CAP_CHATMIX_STATUS: ret = device_found->request_chatmix(*device_handle); - if (ret < 0) + if (ret < 0) { break; + } - short_output ? printf("%d", ret) : printf("Chat-Mix: %d\n", ret); + switch (output) { + case 0: { + printf("Chat-Mix: %d\n", ret); + break; + } + case 1: { + printf("%d", ret); + break; + } + case 2: { + char buffer[16]; + sprintf(buffer, "%d", ret); + output_add(&json_output, new_entry("chatmix", buffer)); + break; + } + } break; case CAP_VOICE_PROMPTS: @@ -325,6 +390,7 @@ int main(int argc, char* argv[]) { "microphone-mute-led-brightness", required_argument, NULL, 0 }, { "microphone-volume", required_argument, NULL, 0 }, { "inactive-time", required_argument, NULL, 'i' }, + { "json-output", no_argument, NULL, 'j' }, { "light", required_argument, NULL, 'l' }, { "follow", optional_argument, NULL, 'f' }, { "notificate", required_argument, NULL, 'n' }, @@ -344,7 +410,7 @@ int main(int argc, char* argv[]) // describes the headsetcontrol device, when a headset was found static struct device device_found; - while ((c = getopt_long(argc, argv, "bchi:l:f::mn:r:s:uv:p:e:?", opts, &option_index)) != -1) { + while ((c = getopt_long(argc, argv, "bchi:jl:f::mn:r:s:uv:p:e:?", opts, &option_index)) != -1) { char* endptr = NULL; // for strtol switch (c) { @@ -352,7 +418,7 @@ int main(int argc, char* argv[]) request_battery = 1; break; case 'c': - short_output = 1; + output = 1; break; case 'e': { int size = get_float_data_from_parameter(optarg, read_buffer, BUFFERLENGTH); @@ -392,6 +458,9 @@ int main(int argc, char* argv[]) return 1; } break; + case 'j': + output = 2; + break; case 'l': lights = strtol(optarg, &endptr, 10); if (*endptr != '\0' || endptr == optarg || lights < 0 || lights > 1) { @@ -455,6 +524,7 @@ int main(int argc, char* argv[]) printf(" -n, --notificate soundid\tMakes the headset play a notifiation\n"); printf(" -l, --light 0|1\t\tSwitch lights (0 = off, 1 = on)\n"); printf(" -c, --short-output\t\tUse more machine-friendly output \n"); + printf(" -j, --json-output\t\tUse json-format output \n"); printf(" -i, --inactive-time time\tSets inactive time in minutes, time must be between 0 and 90, 0 disables the feature.\n"); printf(" -m, --chatmix\t\t\tRetrieves the current chat-mix-dial level setting between 0 and 128. Below 64 is the game side and above is the chat side.\n"); printf(" -v, --voice-prompt 0|1\tTurn voice prompts on or off (0 = off, 1 = on)\n"); @@ -502,7 +572,8 @@ int main(int argc, char* argv[]) } break; } else if (strcmp(opts[option_index].name, "connected") == 0) { - short_output = 1; + if (output == 0) + output = 1; if (find_device(&device_found) != 0) { return 1; } @@ -526,6 +597,10 @@ int main(int argc, char* argv[]) fprintf(stderr, "Non-option argument %s\n", argv[index]); } + if (output == 2) { + json_output = new_output(); + } + // Look for a supported device int headset_available = find_device(&device_found); if (headset_available != 0) { @@ -607,17 +682,41 @@ int main(int argc, char* argv[]) if (print_capabilities != -1) { PRINT_INFO("Supported capabilities:\n\n"); + char json_string[256]; + strcpy(json_string, "["); + // go through all enum capabilities for (int i = 0; i < NUM_CAPABILITIES; i++) { // When the capability i is included in .capabilities if ((device_found.capabilities & B(i)) == B(i)) { - if (short_output) { - printf("%c", capabilities_str_short[i]); - } else { + switch (output) { + case 0: { printf("* %s\n", capabilities_str[i]); + break; + } + case 1: { + printf("%c", capabilities_str_short[i]); + break; + } + case 2: { + char buffer[64]; + sprintf(buffer, "\"%s\",", capabilities_str[i]); + strcat(json_string, buffer); + break; + } } } } + if (output == 2) { + json_string[strlen(json_string) - 1] = ']'; + output_add(&json_output, new_entry("capabilities", json_string)); + } + } + + if (output == 2) { + char* json = gen_output(&json_output); + printf("%s\n", json); + output_free(&json_output); } if (request_connected) { diff --git a/src/output.c b/src/output.c new file mode 100644 index 0000000..3455f88 --- /dev/null +++ b/src/output.c @@ -0,0 +1,63 @@ +#include "output.h" +#include +#include +#include + +t_entry* new_entry(char* key, char* value) +{ + t_entry* entry = malloc(sizeof(t_entry)); + entry->key = strdup(key); + entry->value = strdup(value); + return entry; +} + +t_output new_output() +{ + t_output output; + output.entries = malloc(0); + output.length = 0; + return output; +} + +void output_add(t_output* output, t_entry* entry) +{ + output->length++; + output->entries = realloc(output->entries, output->length * sizeof(t_entry)); + output->entries[output->length - 1] = *entry; +} + +void output_free(t_output* output) +{ + free(output->entries); + output->length = 0; +} + +char* gen_output(t_output* output) +{ + if (output->length == 0) { + return strdup("{}"); + } + + size_t max_length = 2; // For '{' and '}' + for (size_t i = 0; i < output->length; i++) { + max_length += strlen(output->entries[i].key) + strlen(output->entries[i].value) + 5; // 5 for quotes, colon, and comma + } + + char* result = (char*)malloc(max_length + 1); // Allocate memory for the result string + if (result == NULL) { + // Handle memory allocation failure + return NULL; + } + + strcpy(result, "{"); + for (size_t i = 0; i < output->length; i++) { + char entry[64]; + sprintf(entry, "\"%s\":%s,", output->entries[i].key, output->entries[i].value); + strcat(result, entry); + } + + result[strlen(result) - 1] = '}'; // Replace the last comma with '}' + char* dup_result = strdup(result); + free(result); + return dup_result; +} diff --git a/src/output.h b/src/output.h new file mode 100644 index 0000000..53ffb9e --- /dev/null +++ b/src/output.h @@ -0,0 +1,21 @@ +#pragma once + +typedef struct { + char* key; + char* value; +} t_entry; + +t_entry* new_entry(char* key, char* value); + +typedef struct { + t_entry* entries; + int length; +} t_output; + +t_output new_output(); + +void output_add(t_output* output, t_entry* entry); + +void output_free(t_output* output); + +char* gen_output(t_output* output);