Add log functions to show errors to users

This commit is contained in:
bnnm 2021-08-26 18:41:03 +02:00
parent 2ade940989
commit f799aec0ca
12 changed files with 205 additions and 55 deletions

View File

@ -16,10 +16,12 @@ list(REMOVE_ITEM MAIN_HEADERS ${CMAKE_CURRENT_SOURCE_DIR}/stack_alloc.h)
source_group("Header Files\\coding" FILES ${CODING_HEADERS})
source_group("Header Files\\layout" FILES ${LAYOUT_HEADERS})
source_group("Header Files\\meta" FILES ${META_HEADERS})
source_group("Header Files\\util" FILES ${UTIL_HEADERS})
source_group("Header Files\\ext" FILES ${EXT_HEADERS})
source_group("Source Files\\coding" FILES ${CODING_SOURCES})
source_group("Source Files\\layout" FILES ${LAYOUT_SOURCES})
source_group("Source Files\\meta" FILES ${META_SOURCES})
source_group("Source Files\\util" FILES ${UTIL_SOURCES})
add_library(libvgmstream STATIC
${CODING_HEADERS}
@ -28,6 +30,8 @@ add_library(libvgmstream STATIC
${LAYOUT_SOURCES}
${META_HEADERS}
${META_SOURCES}
${UTIL_HEADERS}
${UTIL_SOURCES}
${EXT_HEADERS}
${MAIN_HEADERS}
${MAIN_SOURCES})
@ -39,4 +43,5 @@ target_include_directories(libvgmstream PRIVATE
${VGM_SOURCE_DIR}/ext_includes
coding
layout
meta)
meta
util)

View File

@ -21,9 +21,9 @@ META_SRCS = $(wildcard meta/*.c)
META_OBJS = $(patsubst %.c,%.o,$(META_SRCS))
OBJECTS += $(META_OBJS)
EXT_LIBS_SRCS = $(wildcard ../ext_libs/*.c)
EXT_LIBS_OBJS = $(patsubst %.c,%.o,$(EXT_LIBS_SRCS))
OBJECTS += $(EXT_LIBS_OBJS)
UTIL_SRCS = $(wildcard util/*.c)
UTIL_OBJS = $(patsubst %.c,%.o,$(UTIL_SRCS))
OBJECTS += $(UTIL_OBJS)
libvgmstream.a: $(OBJECTS)

View File

@ -59,7 +59,7 @@
<ClCompile>
<Optimization>Disabled</Optimization>
<AdditionalIncludeDirectories>../ext_includes;../ext_includes/ffmpeg;$(DependenciesDir)/qaac/mp4v2/include;$(DependenciesDir)/fdk-aac/libSYS/include;$(DependenciesDir)/fdk-aac/libAACdec/include;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
<PreprocessorDefinitions>WIN32;VGMSTREAM_VERSION_AUTO;VGM_USE_VORBIS;VGM_USE_MPEG;VGM_USE_FFMPEG;VGM_USE_G7221;VGM_USE_G719;VGM_USE_ATRAC9;VGM_USE_CELT;VGM_USE_SPEEX;USE_ALLOCA;_DEBUG;_LIB;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<PreprocessorDefinitions>WIN32;VGMSTREAM_VERSION_AUTO;VGM_LOG_OUTPUT;VGM_USE_VORBIS;VGM_USE_MPEG;VGM_USE_FFMPEG;VGM_USE_G7221;VGM_USE_G719;VGM_USE_ATRAC9;VGM_USE_CELT;VGM_USE_SPEEX;USE_ALLOCA;_DEBUG;_LIB;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<BasicRuntimeChecks>EnableFastChecks</BasicRuntimeChecks>
<RuntimeLibrary>MultiThreadedDebug</RuntimeLibrary>
<PrecompiledHeader>
@ -72,7 +72,7 @@
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
<ClCompile>
<AdditionalIncludeDirectories>../ext_includes;../ext_includes/ffmpeg;$(DependenciesDir)/qaac/mp4v2/include;$(DependenciesDir)/fdk-aac/libSYS/include;$(DependenciesDir)/fdk-aac/libAACdec/include;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
<PreprocessorDefinitions>_WIN32_WINNT=0x501;WIN32;VGMSTREAM_VERSION_AUTO;VGM_USE_VORBIS;VGM_USE_MPEG;VGM_USE_FFMPEG;VGM_USE_G7221;VGM_USE_G719;VGM_USE_ATRAC9;VGM_USE_CELT;VGM_USE_SPEEX;USE_ALLOCA;NDEBUG;_LIB;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<PreprocessorDefinitions>_WIN32_WINNT=0x501;WIN32;VGMSTREAM_VERSION_AUTO;VGM_LOG_OUTPUT;VGM_USE_VORBIS;VGM_USE_MPEG;VGM_USE_FFMPEG;VGM_USE_G7221;VGM_USE_G719;VGM_USE_ATRAC9;VGM_USE_CELT;VGM_USE_SPEEX;USE_ALLOCA;NDEBUG;_LIB;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<RuntimeLibrary>MultiThreaded</RuntimeLibrary>
<PrecompiledHeader>
</PrecompiledHeader>
@ -708,6 +708,7 @@
<ClCompile Include="layout\blocked_xa.c" />
<ClCompile Include="layout\blocked_xa_aiff.c" />
<ClCompile Include="layout\blocked_xvas.c" />
<ClCompile Include="util\log.c" />
</ItemGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
<ImportGroup Label="ExtensionTargets">

View File

@ -1918,5 +1918,8 @@
<ClCompile Include="meta\sbk.c">
<Filter>meta\Source Files</Filter>
</ClCompile>
<ClCompile Include="util\log.c">
<Filter>util\Source Files</Filter>
</ClCompile>
</ItemGroup>
</Project>

View File

@ -1,4 +1,5 @@
#include "cri_utf.h"
#include "../util/log.h"
#define COLUMN_BITMASK_FLAG 0xf0
#define COLUMN_BITMASK_TYPE 0x0f
@ -113,7 +114,7 @@ utf_context* utf_open(STREAMFILE* sf, uint32_t table_offset, int* p_rows, const
/* 00: early (32b rows_offset?), 01: +2017 (no apparent differences) */
if (utf->version != 0x00 && utf->version != 0x01) {
VGM_LOG("@UTF: unknown version\n");
vgm_logi("@UTF: unknown version\n");
}
if (utf->table_offset + utf->table_size > get_streamfile_size(sf))
goto fail;
@ -169,7 +170,7 @@ utf_context* utf_open(STREAMFILE* sf, uint32_t table_offset, int* p_rows, const
!(utf->schema[i].flag & COLUMN_FLAG_NAME) ||
((utf->schema[i].flag & COLUMN_FLAG_DEFAULT) && (utf->schema[i].flag & COLUMN_FLAG_ROW)) ||
(utf->schema[i].flag & COLUMN_FLAG_UNDEFINED) ) {
VGM_LOG("@UTF: unknown column flag combo found\n");
vgm_logi("@UTF: unknown column flag combo found\n");
goto fail;
}
@ -197,7 +198,7 @@ utf_context* utf_open(STREAMFILE* sf, uint32_t table_offset, int* p_rows, const
//case COLUMN_TYPE_UINT128:
// value_size = 0x16;
default:
VGM_LOG("@UTF: unknown column type\n");
vgm_logi("@UTF: unknown column type\n");
goto fail;
}
@ -228,7 +229,7 @@ utf_context* utf_open(STREAMFILE* sf, uint32_t table_offset, int* p_rows, const
return utf;
fail:
utf_close(utf);
VGM_LOG("@UTF: fail\n");
vgm_logi("@UTF: init failure\n");
return NULL;
}

View File

@ -1,4 +1,5 @@
#include "deblock_streamfile.h"
#include "../util/log.h"
//todo move to utils or something

View File

@ -1,6 +1,7 @@
#include "vgmstream.h"
#include "plugins.h"
#include "mixing.h"
#include "util/log.h"
/* ****************************************** */
@ -546,3 +547,16 @@ void vgmstream_mixing_stereo_only(VGMSTREAM *vgmstream, int start) {
/* remove channels after stereo */
mixing_push_killmix(vgmstream, start + 2);
}
/* ****************************************** */
/* LOG: log */
/* ****************************************** */
void vgmstream_set_log_callback(int level, void* callback) {
vgm_log_set_callback(NULL, level, 0, callback);
}
void vgmstream_set_log_stdout(int level) {
vgm_log_set_callback(NULL, level, 1, NULL);
}

View File

@ -77,6 +77,14 @@ typedef struct {
/* get a simple title for plugins */
void vgmstream_get_title(char* buf, int buf_len, const char* filename, VGMSTREAM* vgmstream, vgmstream_title_t* cfg);
enum {
VGM_LOG_LEVEL_INFO = 1,
VGM_LOG_LEVEL_DEBUG = 2,
VGM_LOG_LEVEL_ALL = 100,
};
// CB: void (*callback)(int level, const char* str)
void vgmstream_set_log_callback(int level, void* callback);
void vgmstream_set_log_stdout(int level);
#if 0

View File

@ -136,49 +136,4 @@ void swap_samples_le(sample_t *buf, int count);
void concatn(int length, char * dst, const char * src);
/* Simple stdout logging for debugging and regression testing purposes.
* Needs C99 variadic macros, uses do..while to force ";" as statement */
#ifdef VGM_DEBUG_OUTPUT
/* equivalent to printf when condition is true */
#define VGM_ASSERT(condition, ...) \
do { if (condition) {printf(__VA_ARGS__);} } while (0)
#define VGM_ASSERT_ONCE(condition, ...) \
do { static int written; if (!written) { if (condition) {printf(__VA_ARGS__); written = 1;} } } while (0)
/* equivalent to printf */
#define VGM_LOG(...) \
do { printf(__VA_ARGS__); } while (0)
#define VGM_LOG_ONCE(...) \
do { static int written; if (!written) { printf(__VA_ARGS__); written = 1; } } while (0)
/* prints file/line/func */
#define VGM_LOGF() \
do { printf("%s:%i '%s'\n", __FILE__, __LINE__, __func__); } while (0)
/* prints to a file */
#define VGM_LOGT(txt, ...) \
do { FILE *fl = fopen(txt,"a+"); if(fl){fprintf(fl,__VA_ARGS__); fflush(fl);} fclose(fl); } while(0)
/* prints a buffer/array */
#define VGM_LOGB(buf, buf_size, bytes_per_line) \
do { \
int i; \
for (i=0; i < buf_size; i++) { \
printf("%02x",buf[i]); \
if (bytes_per_line && (i+1) % bytes_per_line == 0) printf("\n"); \
} \
printf("\n"); \
} while (0)
#else/*VGM_DEBUG_OUTPUT*/
#define VGM_ASSERT(condition, ...) /* nothing */
#define VGM_ASSERT_ONCE(condition, ...) /* nothing */
#define VGM_LOG(...) /* nothing */
#define VGM_LOG_ONCE(...) /* nothing */
#define VGM_LOGF() /* nothing */
#define VGM_LOGT() /* nothing */
#define VGM_LOGB(buf, buf_size, bytes_per_line) /* nothing */
#endif/*VGM_DEBUG_OUTPUT*/
#endif

77
src/util/log.c Normal file
View File

@ -0,0 +1,77 @@
#include <stdarg.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
/* log context; should probably make a unique instance and pass to metas/decoders/etc, but for the time being use global */
//extern ...* log;
typedef struct {
int level;
void (*callback)(int level, const char* str);
} logger_t;
logger_t log_impl = {0};
//void* log = &log_impl;
enum {
LOG_LEVEL_INFO = 1,
LOG_LEVEL_DEBUG = 2,
LOG_LEVEL_ALL = 100,
};
static void vgm_log_callback_printf(int level, const char* str) {
printf("%s", str);
}
void vgm_log_set_callback(void* ctx_p, int level, int type, void* callback) {
logger_t* ctx = ctx_p;
if (!ctx) ctx = &log_impl;
ctx->level = level;
switch(type) {
case 0:
ctx->callback = callback;
break;
case 1:
ctx->callback = vgm_log_callback_printf;
break;
default:
break;
}
}
static void log_internal(void* ctx_p, int level, const char* fmt, va_list args) {
char line[255];
int out;
logger_t* ctx = ctx_p;
if (!ctx) ctx = &log_impl;
if (!ctx->callback)
return;
if (level > ctx->level)
return;
out = vsnprintf(line, sizeof(line), fmt, args);
if (out < 0 || out > sizeof(line))
strcpy(line, "(ignored log)"); //to-do something better, meh
ctx->callback(level, line);
}
void vgm_logd(const char* fmt, ...) {
va_list args;
va_start(args, fmt);
log_internal(NULL, LOG_LEVEL_DEBUG, fmt, args);
va_end(args);
}
void vgm_logi(const char* fmt, ...) {
va_list args;
va_start(args, fmt);
log_internal(NULL, LOG_LEVEL_INFO, fmt, args);
va_end(args);
}

84
src/util/log.h Normal file
View File

@ -0,0 +1,84 @@
#ifndef _UTIL_LOG_H
#define _UTIL_LOG_H
/* Dumb logger utils (tuned for simplicity). Notes:
* - must set callback/defaults to print anything
* - mainly used to print info for users, like format detected but wrong size
* (don't clutter by logging code that happens most of the time, since log may be shared with other plugins)
* - callbacks receive formed string for simplicity (to be adjusted)
* - DO NOT put logs in tight loops (like decoders), slow fn calls and clutter
* (metas are usually fine but also consider cluttering)
* - as compiler must support variable args, needs to pass VGM_LOG_OUTPUT flag to enable
* - debug logs are removed unless VGM_DEBUG_OUTPUT is passed to compiler args
* (passing either of them works)
* - callback should be thread-safe (no internal checks and only one log ATM)
* - still WIP, some stuff not working ATM or may change
*/
// void (*callback)(int level, const char* str);
void vgm_log_set_callback(void* ctx_p, int level, int type, void* callback);
#if defined(VGM_LOG_OUTPUT) || defined(VGM_DEBUG_OUTPUT)
void vgm_logi(/*void* ctx,*/ const char* fmt, ...);
//void vgm_logi_once(/*void* ctx, int* once_flag, */ const char* fmt, ...);
#else
#define vgm_logi(...) /* nothing */
#endif
#ifdef VGM_DEBUG_OUTPUT
void vgm_logd(/*void* ctx,*/ const char* fmt, ...);
#define VGM_LOG(...) do { vgm_logd(__VA_ARGS__); } while (0)
#else
#define vgm_logd(...) /* nothing */
#define VGM_LOG(...) /* nothing */
#endif
/* original stdout logging for debugging and regression testing purposes, may be removed later.
* Needs C99 variadic macros, uses do..while to force ";" as statement */
#ifdef VGM_DEBUG_OUTPUT
/* equivalent to printf when condition is true */
#define VGM_ASSERT(condition, ...) \
do { if (condition) {printf(__VA_ARGS__);} } while (0)
#define VGM_ASSERT_ONCE(condition, ...) \
do { static int written; if (!written) { if (condition) {printf(__VA_ARGS__); written = 1;} } } while (0)
/* equivalent to printf */
//#define VGM_LOG(...) do { printf(__VA_ARGS__); } while (0)
#define VGM_LOG_ONCE(...) \
do { static int written; if (!written) { printf(__VA_ARGS__); written = 1; } } while (0)
/* prints file/line/func */
//#define VGM_LOGF() do { printf("%s:%i '%s'\n", __FILE__, __LINE__, __func__); } while (0)
/* prints to a file */
#define VGM_LOGT(txt, ...) \
do { FILE *fl = fopen(txt,"a+"); if(fl){fprintf(fl,__VA_ARGS__); fflush(fl);} fclose(fl); } while(0)
/* prints a buffer/array */
#define VGM_LOGB(buf, buf_size, bytes_per_line) \
do { \
int i; \
for (i=0; i < buf_size; i++) { \
printf("%02x",buf[i]); \
if (bytes_per_line && (i+1) % bytes_per_line == 0) printf("\n"); \
} \
printf("\n"); \
} while (0)
#else/*VGM_DEBUG_OUTPUT*/
#define VGM_ASSERT(condition, ...) /* nothing */
#define VGM_ASSERT_ONCE(condition, ...) /* nothing */
//#define VGM_LOG(...) /* nothing */
#define VGM_LOG_ONCE(...) /* nothing */
//#define VGM_LOGF() /* nothing */
#define VGM_LOGT() /* nothing */
#define VGM_LOGB(buf, buf_size, bytes_per_line) /* nothing */
#endif/*VGM_DEBUG_OUTPUT*/
#endif

View File

@ -17,6 +17,7 @@ enum {
};
#include "streamfile.h"
#include "util/log.h"
/* Due mostly to licensing issues, Vorbis, MPEG, G.722.1, etc decoding is done by external libraries.
* Libs are disabled by default, defined on compile-time for builds that support it */