summaryrefslogtreecommitdiff
path: root/src/fetch.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/fetch.c')
-rw-r--r--src/fetch.c209
1 files changed, 209 insertions, 0 deletions
diff --git a/src/fetch.c b/src/fetch.c
new file mode 100644
index 0000000..270089e
--- /dev/null
+++ b/src/fetch.c
@@ -0,0 +1,209 @@
+/* SPDX-License-Identifier: GPL-3.0-or-later */
+/*
+ * vfetch - neofetch but the ascii part is a video
+ *
+ * Copyright (C) 2026 Doan Luu Duc Tai
+ *
+ */
+
+#include "fetch.h"
+#include <glib.h>
+#include <sys/ioctl.h>
+#include <pthread.h>
+#include <stdatomic.h>
+#include <stdint.h>
+#include <stdio.h>
+#include <string.h>
+#include <termios.h>
+#include <unistd.h>
+#include "utils.h"
+
+static VfetchError try_fastfetch(AppState *state, const VfetchArgs *args) {
+ VfetchError err =
+ run_command_fork_output("fastfetch --logo none --pipe false",
+ &state->live_fetch_output,
+ args->debug);
+ if (err == VFETCH_SUCCESS) {
+ state->fetch_command = g_strdup("fastfetch --logo none --pipe false");
+ if (!state->fetch_command) {
+ return VFETCH_ERROR_MEMORY_ALLOCATION;
+ }
+ }
+
+ return err;
+}
+
+static VfetchError try_neofetch(AppState *state, const VfetchArgs *args) {
+ log_verbose(state,
+ args->verbose,
+ args->debug,
+ "fastfetch failed, trying neofetch...");
+
+ VfetchError err = run_command_fork_output(
+ "neofetch --off", &state->live_fetch_output, args->debug);
+ if (err == VFETCH_SUCCESS) {
+ state->fetch_command = g_strdup("neofetch --off");
+ if (!state->fetch_command) {
+ err = VFETCH_ERROR_MEMORY_ALLOCATION;
+ return err;
+ }
+ }
+
+ return err;
+}
+
+static VfetchError set_fetch_unavailable(void) {
+ (void)fputs("\nERROR: Neither 'fastfetch' nor 'neofetch' could be found in "
+ "your system's PATH.\n\n",
+ stderr);
+ (void)fputs(" Action Required:\n", stderr);
+ (void)fputs(" - Please install either 'fastfetch' or 'neofetch'.\n",
+ stderr);
+ (void)fputs(" - Alternatively, to disable the system information display, "
+ "use the '--fetch-tool none' flag.\n\n",
+ stderr);
+
+ return VFETCH_ERROR_COMMAND_FAILED;
+}
+
+static VfetchError fail_fetch_unavailable_override(const char *tool_name) {
+ (void)fprintf(stderr,
+ "\nERROR: The specified fetch tool ('%s') is not available in "
+ "your system's PATH.\n\n",
+ tool_name);
+ (void)fputs(" Action Required:\n", stderr);
+ (void)fputs(
+ " - Please install the tool or correct the --fetch-tool argument.\n",
+ stderr);
+ (void)fputs(" - To disable the system information display, use "
+ "'--fetch-tool none'.\n\n",
+ stderr);
+
+ return VFETCH_ERROR_COMMAND_FAILED;
+}
+
+static VfetchError handle_fetch_override(AppState *state,
+ const VfetchArgs *args) {
+ log_verbose(state,
+ args->verbose,
+ args->debug,
+ "User specified fetch tool: '%s'",
+ args->fetch_tool_arg);
+
+ if (strcmp(args->fetch_tool_arg, "fastfetch") == 0) {
+ if (try_fastfetch(state, args) != VFETCH_SUCCESS) {
+ return fail_fetch_unavailable_override("fastfetch");
+ }
+ } else if (strcmp(args->fetch_tool_arg, "neofetch") == 0) {
+ if (try_neofetch(state, args) != VFETCH_SUCCESS) {
+ return fail_fetch_unavailable_override("neofetch");
+ }
+ }
+
+ return VFETCH_SUCCESS;
+}
+
+static VfetchError handle_fetch_fallback(AppState *state,
+ const VfetchArgs *args) {
+ log_verbose(state,
+ args->verbose,
+ args->debug,
+ "No fetch tool specified, using fallback logic.");
+
+ if (try_fastfetch(state, args) == VFETCH_SUCCESS) {
+ return VFETCH_SUCCESS;
+ }
+ if (try_neofetch(state, args) == VFETCH_SUCCESS) {
+ return VFETCH_SUCCESS;
+ }
+
+ return set_fetch_unavailable();
+}
+
+VfetchError initialize_fetch_utility(AppState *state, const VfetchArgs *args) {
+ log_verbose(
+ state, args->verbose, args->debug, "Initializing fetch utility...");
+
+ if (args->fetch_tool_arg) {
+ return handle_fetch_override(state, args);
+ }
+
+ return handle_fetch_fallback(state, args);
+}
+
+VfetchError start_fetch_thread(AppState *state, VfetchArgs *args) {
+ if (args->fetch_tool_arg && strcmp(args->fetch_tool_arg, "none") == 0) {
+ state->fetch_command = g_strdup("echo");
+ state->live_fetch_output = g_strdup("");
+ if (!state->fetch_command || !state->live_fetch_output) {
+ return VFETCH_ERROR_MEMORY_ALLOCATION;
+ }
+ return VFETCH_SUCCESS;
+ }
+
+ if (!state->fetch_command) {
+ VfetchError err = initialize_fetch_utility(state, args);
+ if (err) {
+ return err;
+ }
+ }
+
+ atomic_store_explicit(&state->last_fetch_lines,
+ count_lines(state->live_fetch_output),
+ memory_order_relaxed);
+
+ return VFETCH_SUCCESS;
+}
+
+#define K_DEFAULT_TERMINAL_WIDTH 80
+void render_fetch_panel(char *screen_buffer,
+ size_t screen_buffer_size,
+ size_t *current_len,
+ AppState *state,
+ const VfetchArgs *args) {
+ struct winsize window_size = {0};
+ char *fetch_output_copy = NULL;
+
+ size_t terminal_width = K_DEFAULT_TERMINAL_WIDTH;
+ if (ioctl(STDOUT_FILENO, TIOCGWINSZ, &window_size) == 0 &&
+ window_size.ws_col > 0) {
+ terminal_width = window_size.ws_col;
+ }
+
+ (void)pthread_mutex_lock(&state->fetch_mutex);
+ if (state->live_fetch_output) {
+ fetch_output_copy = g_strdup(state->live_fetch_output);
+ }
+ size_t current_fetch_lines =
+ atomic_load_explicit(&state->last_fetch_lines, memory_order_relaxed);
+ size_t prev_fetch_lines = state->previous_fetch_lines;
+ state->previous_fetch_lines = current_fetch_lines;
+ (void)pthread_mutex_unlock(&state->fetch_mutex);
+
+ uint32_t fetch_x = args->pad_x + args->width + 4;
+ size_t clear_width = terminal_width > fetch_x ? terminal_width - fetch_x : 0;
+ size_t lines_to_clear = (prev_fetch_lines > current_fetch_lines)
+ ? prev_fetch_lines
+ : current_fetch_lines;
+ if (lines_to_clear > 0 && clear_width > 0) {
+ Rect rect_to_clear = {.height = lines_to_clear,
+ .width = clear_width,
+ .start_x = fetch_x,
+ .start_y = args->pad_y};
+ clear_rect_in_buffer(
+ screen_buffer, screen_buffer_size, current_len, &rect_to_clear);
+ }
+
+ const char *fetch_output_to_draw =
+ fetch_output_copy ? fetch_output_copy : "...";
+ append_block_to_buffer(screen_buffer,
+ screen_buffer_size,
+ current_len,
+ fetch_x,
+ args->pad_y,
+ fetch_output_to_draw,
+ strlen(fetch_output_to_draw));
+
+ g_free(fetch_output_copy);
+}
+#undef K_DEFAULT_TERMINAL_WIDTH