Skip to content

Commit

Permalink
Implemented json-output
Browse files Browse the repository at this point in the history
  • Loading branch information
theaino committed Mar 16, 2024
1 parent a95a015 commit b3dcb06
Show file tree
Hide file tree
Showing 4 changed files with 194 additions and 18 deletions.
2 changes: 2 additions & 0 deletions src/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -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)
126 changes: 108 additions & 18 deletions src/main.c
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@
#include "device.h"
#include "device_registry.h"
#include "hid_utility.h"
#include "output.h"
#include "utility.h"

#include <hidapi.h>
Expand All @@ -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__); \
} \
}
Expand All @@ -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;
}

Expand Down Expand Up @@ -185,14 +196,49 @@ 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];

Check failure on line 236 in src/main.c

View workflow job for this annotation

GitHub Actions / macos-latest-compile

expected expression
sprintf(buffer, "%d", ret);

Check failure on line 237 in src/main.c

View workflow job for this annotation

GitHub Actions / macos-latest-compile

use of undeclared identifier 'buffer'

Check failure on line 237 in src/main.c

View workflow job for this annotation

GitHub Actions / macos-latest-compile

use of undeclared identifier 'buffer'
output_add(&json_output, new_entry("battery", buffer));

Check failure on line 238 in src/main.c

View workflow job for this annotation

GitHub Actions / macos-latest-compile

use of undeclared identifier 'buffer'
break;
}
}

break;

Expand All @@ -216,10 +262,23 @@ 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];

Check failure on line 277 in src/main.c

View workflow job for this annotation

GitHub Actions / macos-latest-compile

expected expression
sprintf(buffer, "%d", ret);

Check failure on line 278 in src/main.c

View workflow job for this annotation

GitHub Actions / macos-latest-compile

use of undeclared identifier 'buffer'

Check failure on line 278 in src/main.c

View workflow job for this annotation

GitHub Actions / macos-latest-compile

use of undeclared identifier 'buffer'
output_add(&json_output, new_entry("chatmix", buffer));

Check failure on line 279 in src/main.c

View workflow job for this annotation

GitHub Actions / macos-latest-compile

use of undeclared identifier 'buffer'
break;
}
break;

case CAP_VOICE_PROMPTS:
Expand Down Expand Up @@ -325,6 +384,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' },
Expand All @@ -344,15 +404,15 @@ 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) {
case 'b':
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);
Expand Down Expand Up @@ -392,6 +452,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) {
Expand Down Expand Up @@ -455,6 +518,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");
Expand Down Expand Up @@ -502,7 +566,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;
}
Expand All @@ -526,6 +591,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) {
Expand Down Expand Up @@ -607,17 +676,38 @@ 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];

Check failure on line 694 in src/main.c

View workflow job for this annotation

GitHub Actions / macos-latest-compile

expected expression
sprintf(buffer, "\"%s\",", capabilities_str[i]);

Check failure on line 695 in src/main.c

View workflow job for this annotation

GitHub Actions / macos-latest-compile

use of undeclared identifier 'buffer'
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) {
Expand Down
63 changes: 63 additions & 0 deletions src/output.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,63 @@
#include "output.h"
#include <stdio.h>
#include <stdlib.h>
#include <string.h>

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;
}
21 changes: 21 additions & 0 deletions src/output.h
Original file line number Diff line number Diff line change
@@ -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);

0 comments on commit b3dcb06

Please sign in to comment.