mirror of
https://github.com/vgmstream/vgmstream.git
synced 2024-11-12 01:30:49 +01:00
cleanup: replace jansson
This commit is contained in:
parent
e6a2bec8c2
commit
3edb6e71d6
@ -39,6 +39,8 @@ CFLAGS += $(LIBS_CFLAGS)
|
||||
LDFLAGS += $(LIBS_LDFLAGS)
|
||||
TARGET_EXT_LIBS += $(LIBS_TARGET_EXT_LIBS)
|
||||
|
||||
CLI_SRCS = vgmstream_cli.c vgmstream_cli_utils.c wav_utils.c
|
||||
V123_SRCS = vgmstream123.c wav_utils.c
|
||||
|
||||
export CFLAGS LDFLAGS
|
||||
|
||||
@ -47,11 +49,11 @@ export CFLAGS LDFLAGS
|
||||
### targets
|
||||
|
||||
vgmstream_cli: libvgmstream.a $(TARGET_EXT_LIBS)
|
||||
$(CC) $(CFLAGS) vgmstream_cli.c vgmstream_cli_utils.c wav_utils.c $(LDFLAGS) -o $(OUTPUT_CLI)
|
||||
$(CC) $(CFLAGS) $(CLI_SRCS) $(LDFLAGS) -o $(OUTPUT_CLI)
|
||||
$(STRIP) $(OUTPUT_CLI)
|
||||
|
||||
vgmstream123: libvgmstream.a $(TARGET_EXT_LIBS)
|
||||
$(CC) $(CFLAGS) $(LIBAO_INC) vgmstream123.c wav_utils.c $(LDFLAGS) $(LIBAO_LIB) -o $(OUTPUT_123)
|
||||
$(CC) $(CFLAGS) $(LIBAO_INC) $(V123_SRCS) $(LDFLAGS) $(LIBAO_LIB) -o $(OUTPUT_123)
|
||||
$(STRIP) $(OUTPUT_123)
|
||||
|
||||
api_example: libvgmstream.a $(TARGET_EXT_LIBS)
|
||||
|
@ -66,10 +66,8 @@ static void print_usage(const char* progname, bool is_help) {
|
||||
" -c: loop forever (continuously) to stdout\n"
|
||||
" -L: append a smpl chunk and create a looping wav\n"
|
||||
//" -w: allow .wav in original sample format rather than downmixing to PCM16\n"
|
||||
#ifdef HAVE_JSON
|
||||
" -V: print version info and supported extensions as JSON\n"
|
||||
" -I: print requested file info as JSON\n"
|
||||
#endif
|
||||
" -h: print all commands\n"
|
||||
, progname);
|
||||
|
||||
@ -110,11 +108,7 @@ static bool parse_config(cli_config_t* cfg, int argc, char** argv) {
|
||||
optind = 1; /* reset getopt's ugly globals (needed in wasm that may call same main() multiple times) */
|
||||
|
||||
/* read config */
|
||||
while ((opt = getopt(argc, argv, "o:l:f:d:ipPcmxeLEFrgb2:s:tTk:K:hOvD:S:B:"
|
||||
#ifdef HAVE_JSON
|
||||
"VI"
|
||||
#endif
|
||||
)) != -1) {
|
||||
while ((opt = getopt(argc, argv, "o:l:f:d:ipPcmxeLEFrgb2:s:tTk:K:hOvD:S:B:VI")) != -1) {
|
||||
switch (opt) {
|
||||
case 'o':
|
||||
cfg->outfilename = optarg;
|
||||
@ -229,14 +223,12 @@ static bool parse_config(cli_config_t* cfg, int argc, char** argv) {
|
||||
case 'h':
|
||||
print_usage(argv[0], true);
|
||||
goto fail;
|
||||
#ifdef HAVE_JSON
|
||||
case 'V':
|
||||
print_json_version(VGMSTREAM_VERSION);
|
||||
goto fail;
|
||||
case 'I':
|
||||
cfg->print_metajson = true;
|
||||
break;
|
||||
#endif
|
||||
case '?':
|
||||
fprintf(stderr, "missing argument or unknown option -%c\n", optopt);
|
||||
goto fail;
|
||||
@ -580,18 +572,14 @@ static bool convert_file(cli_config_t* cfg) {
|
||||
|
||||
|
||||
/* prints */
|
||||
#ifdef HAVE_JSON
|
||||
if (!cfg->print_metajson) {
|
||||
#endif
|
||||
print_info(vgmstream, cfg);
|
||||
print_tags(cfg);
|
||||
print_title(vgmstream, cfg);
|
||||
#ifdef HAVE_JSON
|
||||
}
|
||||
else {
|
||||
print_json_info(vgmstream, cfg, VGMSTREAM_VERSION);
|
||||
}
|
||||
#endif
|
||||
|
||||
/* prints done */
|
||||
if (cfg->print_metaonly) {
|
||||
|
@ -1,5 +1,5 @@
|
||||
#ifndef _VGMSTREAM_CLI_H
|
||||
#define _VGMSTREAM_CLI_H
|
||||
#ifndef _VGMSTREAM_CLI_H_
|
||||
#define _VGMSTREAM_CLI_H_
|
||||
|
||||
#include "../src/api.h"
|
||||
#include "../src/vgmstream.h"
|
||||
@ -43,9 +43,7 @@ typedef struct {
|
||||
bool print_oggenc;
|
||||
bool print_batchvar;
|
||||
bool print_title;
|
||||
#ifdef HAVE_JSON
|
||||
bool print_metajson;
|
||||
#endif
|
||||
const char* tag_filename;
|
||||
|
||||
// debug stuff
|
||||
@ -69,10 +67,8 @@ void print_info(VGMSTREAM* vgmstream, cli_config_t* cfg);
|
||||
void print_tags(cli_config_t* cfg);
|
||||
void print_title(VGMSTREAM* vgmstream, cli_config_t* cfg);
|
||||
|
||||
#ifdef HAVE_JSON
|
||||
void print_json_version(const char* vgmstream_version);
|
||||
void print_json_info(VGMSTREAM* vgm, cli_config_t* cfg, const char* vgmstream_version);
|
||||
#endif
|
||||
|
||||
|
||||
#endif
|
||||
|
@ -105,6 +105,7 @@
|
||||
</ItemDefinitionGroup>
|
||||
<ItemGroup>
|
||||
<ClInclude Include="vgmstream_cli.h" />
|
||||
<ClInclude Include="vjson.h" />
|
||||
<ClInclude Include="wav_utils.h" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
|
@ -22,6 +22,9 @@
|
||||
<ClCompile Include="vgmstream_cli.h">
|
||||
<Filter>Header Files</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="vjson.h">
|
||||
<Filter>Header Files</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="wav_utils.h">
|
||||
<Filter>Header Files</Filter>
|
||||
</ClCompile>
|
||||
|
@ -6,10 +6,7 @@
|
||||
#include "../src/api.h"
|
||||
#include "../src/vgmstream.h"
|
||||
|
||||
//todo use <>?
|
||||
#ifdef HAVE_JSON
|
||||
#include "jansson/jansson.h"
|
||||
#endif
|
||||
#include "vjson.h"
|
||||
|
||||
|
||||
static void clean_filename(char* dst, int clean_paths) {
|
||||
@ -191,114 +188,106 @@ void print_title(VGMSTREAM* vgmstream, cli_config_t* cfg) {
|
||||
printf("title: %s\n", title);
|
||||
}
|
||||
|
||||
#ifdef HAVE_JSON
|
||||
void print_json_version(const char* vgmstream_version) {
|
||||
size_t extension_list_len;
|
||||
size_t common_extension_list_len;
|
||||
size_t extension_list_len = 0;
|
||||
const char** extension_list;
|
||||
const char** common_extension_list;
|
||||
extension_list = vgmstream_get_formats(&extension_list_len);
|
||||
common_extension_list = vgmstream_get_common_formats(&common_extension_list_len);
|
||||
|
||||
json_t* ext_list = json_array();
|
||||
json_t* cext_list = json_array();
|
||||
vjson_t j = {0};
|
||||
|
||||
for (size_t i = 0; i < extension_list_len; ++i) {
|
||||
json_t* ext = json_string(extension_list[i]);
|
||||
json_array_append(ext_list, ext);
|
||||
}
|
||||
char buf[0x4000]; // exts need ~0x1400
|
||||
vjson_init(&j, buf, sizeof(buf));
|
||||
|
||||
for (size_t i = 0; i < common_extension_list_len; ++i) {
|
||||
json_t* cext = json_string(common_extension_list[i]);
|
||||
json_array_append(cext_list, cext);
|
||||
}
|
||||
vjson_obj_open(&j);
|
||||
vjson_keystr(&j, "version", vgmstream_version);
|
||||
|
||||
json_t* version_string = json_string(vgmstream_version);
|
||||
vjson_key(&j, "extensions");
|
||||
vjson_obj_open(&j);
|
||||
|
||||
json_t* final_object = json_object();
|
||||
json_object_set(final_object, "version", version_string);
|
||||
json_decref(version_string);
|
||||
vjson_key(&j, "vgm");
|
||||
vjson_arr_open(&j);
|
||||
extension_list = vgmstream_get_formats(&extension_list_len);
|
||||
for (int i = 0; i < extension_list_len; i++) {
|
||||
vjson_str(&j, extension_list[i]);
|
||||
}
|
||||
vjson_arr_close(&j);
|
||||
|
||||
json_object_set(final_object, "extensions",
|
||||
json_pack("{soso}",
|
||||
"vgm", ext_list,
|
||||
"common", cext_list));
|
||||
vjson_key(&j, "common");
|
||||
vjson_arr_open(&j);
|
||||
extension_list = vgmstream_get_common_formats(&extension_list_len);
|
||||
for (int i = 0; i < extension_list_len; i++) {
|
||||
vjson_str(&j, extension_list[i]);
|
||||
}
|
||||
vjson_arr_close(&j);
|
||||
|
||||
json_dumpf(final_object, stdout, JSON_COMPACT);
|
||||
vjson_obj_close(&j);
|
||||
vjson_obj_close(&j);
|
||||
|
||||
printf("%s\n", buf);
|
||||
}
|
||||
|
||||
void print_json_info(VGMSTREAM* vgm, cli_config_t* cfg, const char* vgmstream_version) {
|
||||
json_t* version_string = json_string(vgmstream_version);
|
||||
char buf[0x1000]; // probably fine with ~0x400
|
||||
vjson_t j = {0};
|
||||
vjson_init(&j, buf, sizeof(buf));
|
||||
|
||||
vgmstream_info info;
|
||||
describe_vgmstream_info(vgm, &info);
|
||||
|
||||
vjson_obj_open(&j);
|
||||
vjson_keystr(&j, "version", vgmstream_version);
|
||||
vjson_keyint(&j, "sampleRate", info.sample_rate);
|
||||
vjson_keyint(&j, "channels", info.channels);
|
||||
|
||||
json_t* mixing_info = NULL;
|
||||
vjson_key(&j, "mixingInfo");
|
||||
if (info.mixing_info.input_channels > 0) {
|
||||
vjson_obj_open(&j);
|
||||
vjson_keyint(&j, "inputChannels", info.mixing_info.input_channels);
|
||||
vjson_keyint(&j, "outputChannels", info.mixing_info.output_channels);
|
||||
vjson_obj_close(&j);
|
||||
}
|
||||
else {
|
||||
vjson_null(&j);
|
||||
}
|
||||
|
||||
// The JSON pack format string is defined here: https://jansson.readthedocs.io/en/latest/apiref.html#building-values
|
||||
vjson_keyintnull(&j, "channelLayout", info.channel_layout);
|
||||
|
||||
if (info.mixing_info.input_channels > 0) {
|
||||
mixing_info = json_pack("{sisi}",
|
||||
"inputChannels", info.mixing_info.input_channels,
|
||||
"outputChannels", info.mixing_info.output_channels);
|
||||
}
|
||||
vjson_key(&j, "loopingInfo");
|
||||
if (info.loop_info.end > info.loop_info.start) {
|
||||
vjson_obj_open(&j);
|
||||
vjson_keyint(&j, "start", info.loop_info.start);
|
||||
vjson_keyint(&j, "end", info.loop_info.start);
|
||||
vjson_obj_close(&j);
|
||||
}
|
||||
else {
|
||||
vjson_null(&j);
|
||||
}
|
||||
|
||||
json_t* loop_info = NULL;
|
||||
vjson_key(&j, "interleaveInfo");
|
||||
if (info.interleave_info.last_block > info.interleave_info.first_block) {
|
||||
vjson_obj_open(&j);
|
||||
vjson_keyint(&j, "firstBlock", info.interleave_info.last_block);
|
||||
vjson_keyint(&j, "lastBlock", info.interleave_info.first_block);
|
||||
vjson_obj_close(&j);
|
||||
}
|
||||
else {
|
||||
vjson_null(&j);
|
||||
}
|
||||
|
||||
if (info.loop_info.end > info.loop_info.start) {
|
||||
loop_info = json_pack("{sisi}",
|
||||
"start", info.loop_info.start,
|
||||
"end", info.loop_info.end);
|
||||
}
|
||||
vjson_keyint(&j, "numberOfSamples", info.num_samples);
|
||||
vjson_keystr(&j, "encoding", info.encoding);
|
||||
vjson_keystr(&j, "layout", info.layout);
|
||||
vjson_keyintnull(&j, "frameSize", info.frame_size);
|
||||
vjson_keystr(&j, "metadataSource", info.metadata);
|
||||
vjson_keyint(&j, "bitrate", info.bitrate);
|
||||
|
||||
json_t* interleave_info = NULL;
|
||||
vjson_key(&j, "streamInfo");
|
||||
vjson_obj_open(&j);
|
||||
vjson_keyint(&j, "index", info.stream_info.current);
|
||||
vjson_keystr(&j, "name", info.stream_info.name);
|
||||
vjson_keyint(&j, "total", info.stream_info.total);
|
||||
vjson_obj_close(&j);
|
||||
|
||||
if (info.interleave_info.last_block > info.interleave_info.first_block) {
|
||||
interleave_info = json_pack("{sisi}",
|
||||
"firstBlock", info.interleave_info.first_block,
|
||||
"lastBlock", info.interleave_info.last_block
|
||||
);
|
||||
}
|
||||
vjson_obj_close(&j);
|
||||
|
||||
json_t* stream_info = json_pack("{sisssi}",
|
||||
"index", info.stream_info.current,
|
||||
"name", info.stream_info.name,
|
||||
"total", info.stream_info.total
|
||||
);
|
||||
|
||||
if (info.stream_info.name[0] == '\0') {
|
||||
json_object_set(stream_info, "name", json_null());
|
||||
}
|
||||
|
||||
json_t* final_object = json_pack(
|
||||
"{sssisiso?siso?so?sisssssisssiso?}",
|
||||
"version", version_string,
|
||||
"sampleRate", info.sample_rate,
|
||||
"channels", info.channels,
|
||||
"mixingInfo", mixing_info,
|
||||
"channelLayout", info.channel_layout,
|
||||
"loopingInfo", loop_info,
|
||||
"interleaveInfo", interleave_info,
|
||||
"numberOfSamples", info.num_samples,
|
||||
"encoding", info.encoding,
|
||||
"layout", info.layout,
|
||||
"frameSize", info.frame_size,
|
||||
"metadataSource", info.metadata,
|
||||
"bitrate", info.bitrate,
|
||||
"streamInfo", stream_info
|
||||
);
|
||||
|
||||
if (info.frame_size == 0) {
|
||||
json_object_set(final_object, "frameSize", json_null());
|
||||
}
|
||||
|
||||
if (info.channel_layout == 0) {
|
||||
json_object_set(final_object, "channelLayout", json_null());
|
||||
}
|
||||
|
||||
json_dumpf(final_object, stdout, JSON_COMPACT);
|
||||
|
||||
json_decref(final_object);
|
||||
|
||||
printf("\n");
|
||||
printf("%s\n", buf);
|
||||
}
|
||||
#endif
|
||||
|
154
cli/vjson.h
Normal file
154
cli/vjson.h
Normal file
@ -0,0 +1,154 @@
|
||||
#ifndef _VJSON_H_
|
||||
#define _VJSON_H_
|
||||
|
||||
/* What is this crap, you may wonder? For probably non-existant use cases Jansson was added to write JSON info,
|
||||
* but external libs are a pain to maintain. For now this glorified string joiner replaces it.
|
||||
*
|
||||
* On incorrect usage or small buf it'll create invalid JSON because who cares, try-parse-catch as usual.
|
||||
*/
|
||||
|
||||
#include <stdio.h>
|
||||
#include <inttypes.h>
|
||||
#include <stdint.h>
|
||||
#include <stdbool.h>
|
||||
|
||||
#define VJSON_STACK_MAX 16
|
||||
typedef struct {
|
||||
char* buf;
|
||||
int buf_len;
|
||||
char* bufp;
|
||||
int buf_left;
|
||||
|
||||
bool stack[VJSON_STACK_MAX];
|
||||
int stack_pos;
|
||||
bool is_last_key;
|
||||
} vjson_t;
|
||||
|
||||
static void vjson_init(vjson_t* j, char* buf, int buf_len) {
|
||||
j->buf = buf;
|
||||
j->buf_len = buf_len;
|
||||
j->bufp = buf;
|
||||
j->buf_left = buf_len;
|
||||
}
|
||||
|
||||
static void vjson_raw(vjson_t* j, const char* str) {
|
||||
if (!str)
|
||||
str = "null";
|
||||
int done = snprintf(j->bufp, j->buf_left, "%s", str);
|
||||
|
||||
j->bufp += done;
|
||||
j->buf_left -= done;
|
||||
}
|
||||
|
||||
static void vjson_comma_(vjson_t* j) {
|
||||
if (j->stack[j->stack_pos] && !j->is_last_key) {
|
||||
vjson_raw(j, ",");
|
||||
}
|
||||
j->stack[j->stack_pos] = true;
|
||||
j->is_last_key = false;
|
||||
}
|
||||
|
||||
static void vjson_open_(vjson_t* j, const char* str) {
|
||||
vjson_comma_(j);
|
||||
vjson_raw(j, str);
|
||||
|
||||
if (j->stack_pos + 1 >= VJSON_STACK_MAX)
|
||||
return;
|
||||
j->stack_pos++;
|
||||
j->stack[j->stack_pos] = false;
|
||||
}
|
||||
|
||||
static void vjson_close_(vjson_t* j, const char* str) {
|
||||
//vjson_comma_(j);
|
||||
vjson_raw(j, str);
|
||||
|
||||
if (j->stack_pos - 1 <= 0)
|
||||
return;
|
||||
j->stack[j->stack_pos] = false;
|
||||
j->stack_pos--;
|
||||
}
|
||||
|
||||
static void vjson_arr_open(vjson_t* j) {
|
||||
vjson_open_(j, "[");
|
||||
}
|
||||
|
||||
static void vjson_arr_close(vjson_t* j) {
|
||||
vjson_close_(j, "]");
|
||||
}
|
||||
|
||||
static void vjson_obj_open(vjson_t* j) {
|
||||
vjson_open_(j, "{");
|
||||
}
|
||||
|
||||
static void vjson_obj_close(vjson_t* j) {
|
||||
vjson_close_(j, "}");
|
||||
}
|
||||
|
||||
static void vjson_key(vjson_t* j, const char* key) {
|
||||
vjson_comma_(j);
|
||||
vjson_raw(j, "\"");
|
||||
vjson_raw(j, key);
|
||||
vjson_raw(j, "\":");
|
||||
j->is_last_key = true;
|
||||
}
|
||||
|
||||
static void vjson_str(vjson_t* j, const char* str) {
|
||||
vjson_comma_(j);
|
||||
if (!str || str[0] == '\0') {
|
||||
vjson_raw(j, NULL);
|
||||
}
|
||||
else {
|
||||
vjson_raw(j, "\"");
|
||||
vjson_raw(j, str);
|
||||
vjson_raw(j, "\"");
|
||||
}
|
||||
}
|
||||
|
||||
static void vjson_int(vjson_t* j, int64_t num) {
|
||||
vjson_comma_(j);
|
||||
|
||||
char tmp[32] = {0};
|
||||
snprintf(tmp, sizeof(tmp), "%" PRId64, num);
|
||||
vjson_raw(j, tmp);
|
||||
}
|
||||
|
||||
#if 0
|
||||
static void vjson_dbl(vjson_t* j, double num) {
|
||||
vjson_comma_(j);
|
||||
|
||||
char tmp[32] = {0};
|
||||
snprintf(tmp, sizeof(tmp), "%f", num);
|
||||
vjson_raw(j, tmp);
|
||||
}
|
||||
#endif
|
||||
|
||||
void vjson_null(vjson_t* j){
|
||||
vjson_comma_(j);
|
||||
vjson_raw(j, "null");
|
||||
}
|
||||
|
||||
static void vjson_intnull(vjson_t* j, int64_t num) {
|
||||
if (num == 0) {
|
||||
vjson_str(j, NULL);
|
||||
}
|
||||
else {
|
||||
vjson_int(j, num);
|
||||
}
|
||||
}
|
||||
|
||||
static void vjson_keystr(vjson_t* j, const char* key, const char* val) {
|
||||
vjson_key(j, key);
|
||||
vjson_str(j, val);
|
||||
}
|
||||
|
||||
static void vjson_keyint(vjson_t* j, const char* key, int64_t val) {
|
||||
vjson_key(j, key);
|
||||
vjson_int(j, val);
|
||||
}
|
||||
|
||||
static void vjson_keyintnull(vjson_t* j, const char* key, int64_t val) {
|
||||
vjson_key(j, key);
|
||||
vjson_intnull(j, val);
|
||||
}
|
||||
|
||||
#endif
|
Loading…
Reference in New Issue
Block a user