diff options
author | pommicket <pommicket@gmail.com> | 2025-02-25 14:41:59 -0500 |
---|---|---|
committer | pommicket <pommicket@gmail.com> | 2025-02-25 15:16:09 -0500 |
commit | 5626363c05bd379047cbe102feaceb18a04a738c (patch) | |
tree | 5e9599171fc38a61f1f53988627013b289377f1e | |
parent | 9b90ceee792cb51917af474ddcbc47edaacff16b (diff) |
start logger
-rw-r--r-- | camera.c | 8 | ||||
-rw-r--r-- | camera.h | 5 | ||||
-rw-r--r-- | log.c | 67 | ||||
-rw-r--r-- | log.h | 16 | ||||
-rw-r--r-- | main.c | 66 | ||||
-rw-r--r-- | meson.build | 2 | ||||
-rw-r--r-- | util.h | 5 |
7 files changed, 148 insertions, 21 deletions
@@ -1067,12 +1067,16 @@ Hash camera_hash(Camera *camera) { return camera->hash; } -void camera_hash_str(Camera *camera, char str[HASH_SIZE * 2 + 1]) { +void hash_to_str(Hash h, char str[HASH_STR_SIZE]) { for (int i = 0; i < HASH_SIZE; i++) { - sprintf(&str[2*i], "%02x", camera->hash.hash[i]); + sprintf(&str[2*i], "%02x", h.hash[i]); } } +void camera_hash_str(Camera *camera, char str[HASH_STR_SIZE]) { + hash_to_str(camera->hash, str); +} + const char *camera_devnode(Camera *camera) { return camera->devnode; } @@ -100,6 +100,9 @@ static bool hash_eq(Hash h1, Hash h2) { return memcmp(h1.hash, h2.hash, sizeof h1.hash) == 0; } +#define HASH_STR_SIZE (2 * HASH_SIZE + 1) + +void hash_to_str(Hash h, char str[HASH_STR_SIZE]); void camera_init(const GlProcs *procs); bool pix_fmt_supported(uint32_t pixfmt); int picture_format_cmp_resolution(const PictureFormat *a, const PictureFormat *b); @@ -128,7 +131,7 @@ void camera_close(Camera *camera); void cameras_from_device(const char *dev_path, const char *serial, Camera ***cameras); bool camera_open(Camera *camera, PictureFormat desired_format, int desired_framerate); Hash camera_hash(Camera *camera); -void camera_hash_str(Camera *camera, char str[HASH_SIZE * 2 + 1]); +void camera_hash_str(Camera *camera, char str[HASH_STR_SIZE]); bool camera_set_format(Camera *camera, PictureFormat picfmt, int desired_framerate, CameraAccessMethod access, bool force); /// Copy current frame from camera to AVFrame. /// @@ -0,0 +1,67 @@ +#include "log.h" +#include <stdbool.h> +#include <unistd.h> + +static FILE *log_file = NULL; + +static void get_timestamp(char timestamp[24]) { + struct tm tm = {0}; + localtime_r((const time_t[1]) { time(NULL) }, &tm); + strftime(timestamp, 24, "[%Y-%m-%d %H:%M:%S]", &tm); +} + +void log_init(const char *out) { + assert(!log_file); + log_file = fopen(out, "a"); + if (log_file) { + char timestamp[24] = {0}; + get_timestamp(timestamp); + fprintf(log_file, "\n\n--- new session %s ---\n", timestamp); + } else { + perror("fopen"); + } +} + +void log_message(int severity, const char *fmt, va_list args) { + char *message = va_sprintf(fmt, args); + if (!message) return; + if (log_file) { + char timestamp[24] = {0}; + get_timestamp(timestamp); + fprintf(log_file, "%s ", timestamp); + } + const char *color_start = "", *severity_str = "???"; + switch (severity) { + case LOG_ERROR: + color_start = "\x1b[91m"; + severity_str = "error"; + break; + case LOG_WARNING: + color_start = "\x1b[93m"; + severity_str = "warning"; + break; + } + bool color = isatty(2) == 1; + if (color) + fprintf(stderr, "%s", color_start); + fprintf(stderr, "%s: ", severity_str); + if (color) + fprintf(stderr, "\x1b[0m"); + fprintf(stderr, "%s\n", message); + if (log_file) fprintf(log_file, "%s: %s\n", severity_str, message); + free(message); +} + +void log_error(const char *fmt, ...) { + va_list args; + va_start(args, fmt); + log_message(LOG_ERROR, fmt, args); + va_end(args); +} + +void log_warning(const char *fmt, ...) { + va_list args; + va_start(args, fmt); + log_message(LOG_WARNING, fmt, args); + va_end(args); +} @@ -0,0 +1,16 @@ +#ifndef LOG_H_ +#define LOG_H_ + +#include "util.h" + +enum { + LOG_WARNING = 20, + LOG_ERROR = 30, +}; + +void log_init(const char *out); +void log_message(int severity, const char *fmt, va_list args); +void log_error(PRINTF_FORMAT_STRING const char *fmt, ...) ATTRIBUTE_PRINTF(1, 2); +void log_warning(PRINTF_FORMAT_STRING const char *fmt, ...) ATTRIBUTE_PRINTF(1, 2); + +#endif @@ -21,6 +21,7 @@ TODO #include "util.h" #include "camera.h" #include "video.h" +#include "log.h" // pixel format used for convenience #define PIX_FMT_XXXGRAY 0x47585858 @@ -114,6 +115,9 @@ static const int timer_options[] = {0, 2, 5, 10, 15, 30}; #endif static GlProcs gl; +static char home_dir[PATH_MAX]; +static char config_dir[PATH_MAX]; + static void select_camera(State *state); static void fatal_error(PRINTF_FORMAT_STRING const char *fmt, ...) ATTRIBUTE_PRINTF(1, 2); @@ -123,6 +127,7 @@ static void fatal_error(const char *fmt, ...) { static char message[256]; vsnprintf(message, sizeof message, fmt, args); va_end(args); + log_error("%s", message); SDL_ShowSimpleMessageBox(SDL_MESSAGEBOX_ERROR, "camlet error", message, NULL); exit(EXIT_FAILURE); } @@ -623,7 +628,6 @@ static void get_cameras_from_udev_device(State *state, struct udev_device *dev) str_builder_free(&serial); } -static char home_dir[PATH_MAX]; static bool get_expanded_output_dir(State *state, char path[PATH_MAX]) { Settings *settings = &state->settings; while (settings->output_dir && settings->output_dir[0] && @@ -707,22 +711,8 @@ int main(void) { static State state_data; State *state = &state_data; Settings *settings = &state->settings; - SDL_SetHint(SDL_HINT_NO_SIGNAL_HANDLERS, "1"); // if this program is sent a SIGTERM/SIGINT, don't turn it into a quit event - if (SDL_Init(SDL_INIT_EVERYTHING) < 0) { - fprintf(stderr, "couldn't initialize SDL\n"); - return EXIT_FAILURE; - } - if (sodium_init() < 0) { - fatal_error("couldn't initialize libsodium"); - } - if (!FcInit()) { - fatal_error("couldn't initialize fontconfig"); - } - #define FcFini "don't call FcFini: it's broken on certain versions of fontconfig - https://github.com/brndnmtthws/conky/pull/1755" - if (TTF_Init() < 0) { - fatal_error("couldn't initialize SDL2_ttf: %s\n", TTF_GetError()); - } { + // get home directory const char *home = getenv("HOME"); if (home) { snprintf(home_dir, sizeof home_dir, "%s", home); @@ -736,6 +726,48 @@ int main(void) { } } } + { + // get config directory + const char *cfg = getenv("XDG_CONFIG_HOME"); + if (cfg) { + snprintf(config_dir, sizeof config_dir, "%s/camlet", cfg); + } else { + snprintf(config_dir, sizeof config_dir, "%s/.config/camlet", home_dir); + } + mkdir_with_parents(config_dir); + // set log path + char *log_path = a_sprintf("%s/log.txt", config_dir); + struct stat statbuf = {0}; + stat(log_path, &statbuf); + if (statbuf.st_size > (128l << 10)) { + // keep old log around and start a new one + char *old_log_path = a_sprintf("%s/log_old.txt", config_dir); + remove(old_log_path); + rename(log_path, old_log_path); + free(old_log_path); + } + if (log_path) { + log_init(log_path); + } else { + perror("a_sprintf"); + } + free(log_path); + } + SDL_SetHint(SDL_HINT_NO_SIGNAL_HANDLERS, "1"); // if this program is sent a SIGTERM/SIGINT, don't turn it into a quit event + if (SDL_Init(SDL_INIT_EVERYTHING) < 0) { + log_error("couldn't initialize SDL"); + return EXIT_FAILURE; + } + if (sodium_init() < 0) { + fatal_error("couldn't initialize libsodium"); + } + if (!FcInit()) { + fatal_error("couldn't initialize fontconfig"); + } + #define FcFini "don't call FcFini: it's broken on certain versions of fontconfig - https://github.com/brndnmtthws/conky/pull/1755" + if (TTF_Init() < 0) { + fatal_error("couldn't initialize SDL2_ttf: %s", TTF_GetError()); + } char *font_path = NULL; { // find a suitable font @@ -1037,7 +1069,7 @@ void main() {\n\ for (size_t i = 0; i < arr_len(state->cameras); i++) { Camera *camera = state->cameras[i]; printf("[%zu] %s ", i, camera_name(camera)); - char buf[HASH_SIZE * 2 + 1] = {0}; + char buf[HASH_STR_SIZE] = {0}; camera_hash_str(camera, buf); printf("%s", buf); printf("\n"); diff --git a/meson.build b/meson.build index 706a021..ccceffb 100644 --- a/meson.build +++ b/meson.build @@ -27,6 +27,6 @@ if get_option('debug') else debug_def = '-DDEBUG=0' endif -executable('camlet', 'main.c', 'camera.c', 'video.c', '3rd_party/stb_image_write.c', +executable('camlet', 'main.c', 'camera.c', 'video.c', 'log.c', '3rd_party/stb_image_write.c', dependencies: [v4l2, sdl2, sdl2_ttf, gl, udev, sodium, fontconfig, jpeg, avcodec, avformat, avutil, pulse, pulse_simple], c_args: ['-Wno-unused-function', '-Wno-format-truncation', '-Wshadow', debug_def]) @@ -1,3 +1,6 @@ +#ifndef UTIL_H_ +#define UTIL_H_ + #include <stdarg.h> #include <stddef.h> #include <stdlib.h> @@ -44,3 +47,5 @@ static uint8_t popcount64(uint64_t x) { } return cnt; } + +#endif |