From 2726432fe1091713bc5a70932dd5a0e2d435395a Mon Sep 17 00:00:00 2001 From: klein panic Date: Mon, 24 Feb 2025 15:18:44 -0500 Subject: [PATCH] moved code here. still needs to update gh --- backups/bat0daemonbak/Makefile | 22 + backups/bat0daemonbak/README.md | 0 backups/bat0daemonbak/battery_daemon.sh | 29 + backups/bat0daemonbak/battery_monitor | Bin 0 -> 27112 bytes backups/bat0daemonbak/battery_monitor.service | 17 + .../bat0daemonbak/docs/battery_monitor.log | 4 + backups/bat0daemonbak/docs/procress_list.txt | 0 .../bat0daemonbak/include/battery_monitor.h | 16 + .../bat0daemonbak/include/process_monitor.h | 8 + backups/bat0daemonbak/install.sh | 63 ++ backups/bat0daemonbak/obj/battery_monitor.o | Bin 0 -> 2904 bytes backups/bat0daemonbak/obj/notification.o | Bin 0 -> 11216 bytes backups/bat0daemonbak/obj/process_monitor.o | Bin 0 -> 2528 bytes backups/bat0daemonbak/src/battery_monitor.c | 70 +++ backups/bat0daemonbak/src/notification.c | 281 +++++++++ backups/bat0daemonbak/src/notification.c.bak | 143 +++++ backups/bat0daemonbak/src/process_monitor.c | 45 ++ brightness_control_two/Makefile | 27 + brightness_control_two/obj/brightness.d | 2 + brightness_control_two/obj/brightness.o | Bin 0 -> 7576 bytes brightness_control_two/obj/display.d | 1 + brightness_control_two/obj/display.o | Bin 0 -> 5440 bytes brightness_control_two/obj/main.d | 1 + brightness_control_two/src/brightness.c | 184 ++++++ brightness_control_two/src/brightness.h | 21 + brightness_control_two/src/display.c | 95 +++ brightness_control_two/src/display.h | 9 + brightness_control_two/src/main.c | 113 ++++ brightness_control_two/src/utils.c | 29 + brightness_control_two/src/utils.h | 6 + brightness_menu/Makefile | 20 + brightness_menu/README.md | 0 brightness_menu/build/brightness.o | Bin 0 -> 3808 bytes brightness_menu/build/color_temperature.o | Bin 0 -> 2416 bytes brightness_menu/build/display.o | Bin 0 -> 3280 bytes brightness_menu/build/main.o | Bin 0 -> 3408 bytes brightness_menu/build/refresh_rate.o | Bin 0 -> 4392 bytes brightness_menu/build/resolution.o | Bin 0 -> 4160 bytes brightness_menu/build/screen_control | Bin 0 -> 26984 bytes brightness_menu/include/brightness.h | 6 + brightness_menu/include/color_temperature.h | 6 + brightness_menu/include/display.h | 7 + brightness_menu/include/refresh_rate.h | 6 + brightness_menu/include/resolution.h | 6 + brightness_menu/src/brightness.c | 53 ++ brightness_menu/src/brightness.o | Bin 0 -> 3808 bytes brightness_menu/src/color_temperature.c | 26 + brightness_menu/src/display.c | 49 ++ brightness_menu/src/display.o | Bin 0 -> 2368 bytes brightness_menu/src/main.c | 60 ++ brightness_menu/src/main.o | Bin 0 -> 1616 bytes brightness_menu/src/refresh_rate.c | 76 +++ brightness_menu/src/resolution.c | 66 ++ mpvd/build/Install | 1 + mpvd/build/Makefile | 19 + mpvd/build/mpvd | Bin 0 -> 36472 bytes mpvd/include/audio.h | 6 + mpvd/include/dir.h | 10 + mpvd/include/ui.h | 14 + mpvd/obj/audio.o | Bin 0 -> 14136 bytes mpvd/obj/dir.o | Bin 0 -> 8904 bytes mpvd/obj/main.o | Bin 0 -> 7976 bytes mpvd/obj/ui.o | Bin 0 -> 11400 bytes mpvd/src/audio.c | 41 ++ mpvd/src/dir.c | 49 ++ mpvd/src/main.c | 55 ++ mpvd/src/mpvd.c | 282 +++++++++ mpvd/src/ui.c | 87 +++ ncursescalander/backup/Makefile | 33 + ncursescalander/backup/calendar | Bin 0 -> 27536 bytes ncursescalander/backup/main.c | 326 ++++++++++ ncursescalander/backup/main.o | Bin 0 -> 21968 bytes ncursescalander/build/Makefile | 26 + ncursescalander/build/add_event.o | Bin 0 -> 11288 bytes ncursescalander/build/calendar.o | Bin 0 -> 2496 bytes ncursescalander/build/calendar_app | Bin 0 -> 31336 bytes ncursescalander/build/day_view.o | Bin 0 -> 5552 bytes ncursescalander/build/main.o | Bin 0 -> 3904 bytes ncursescalander/build/repeat_tui.o | Bin 0 -> 3312 bytes .../databases/calendar_database.db | Bin 0 -> 12288 bytes ncursescalander/include/add_event.h | 29 + ncursescalander/include/calendar.h | 8 + ncursescalander/include/day_view.h | 7 + ncursescalander/include/repeat_tui.h | 7 + ncursescalander/src/add_event.c | 292 +++++++++ ncursescalander/src/add_event.c.bak | 225 +++++++ ncursescalander/src/calendar.c | 56 ++ ncursescalander/src/day_view.c | 127 ++++ ncursescalander/src/main.c | 106 ++++ ncursescalander/src/repeat_tui.c | 48 ++ ssh_gui | 1 + terrarium_bk/terrarium/Makefile | 24 + terrarium_bk/terrarium/ascii_plant_data.c | 581 ++++++++++++++++++ terrarium_bk/terrarium/ascii_plant_data.h | 14 + terrarium_bk/terrarium/ascii_plant_data.o | Bin 0 -> 9928 bytes terrarium_bk/terrarium/game.c | 259 ++++++++ terrarium_bk/terrarium/game.h | 67 ++ terrarium_bk/terrarium/game.o | Bin 0 -> 10192 bytes terrarium_bk/terrarium/main.c | 57 ++ terrarium_bk/terrarium/main.o | Bin 0 -> 2288 bytes terrarium_bk/terrarium/terrarium | Bin 0 -> 25984 bytes terrarium_bk/terrarium/terrarium.c | 388 ++++++++++++ terrarium_bk/terrarium/terrarium_save.dat | Bin 0 -> 3224 bytes testfunctions/readme.md | 3 + testfunctions/source/test.c | 0 website-tests | 1 + 106 files changed, 4816 insertions(+) create mode 100644 backups/bat0daemonbak/Makefile create mode 100644 backups/bat0daemonbak/README.md create mode 100755 backups/bat0daemonbak/battery_daemon.sh create mode 100755 backups/bat0daemonbak/battery_monitor create mode 100755 backups/bat0daemonbak/battery_monitor.service create mode 100644 backups/bat0daemonbak/docs/battery_monitor.log create mode 100644 backups/bat0daemonbak/docs/procress_list.txt create mode 100644 backups/bat0daemonbak/include/battery_monitor.h create mode 100644 backups/bat0daemonbak/include/process_monitor.h create mode 100755 backups/bat0daemonbak/install.sh create mode 100644 backups/bat0daemonbak/obj/battery_monitor.o create mode 100644 backups/bat0daemonbak/obj/notification.o create mode 100644 backups/bat0daemonbak/obj/process_monitor.o create mode 100644 backups/bat0daemonbak/src/battery_monitor.c create mode 100644 backups/bat0daemonbak/src/notification.c create mode 100644 backups/bat0daemonbak/src/notification.c.bak create mode 100644 backups/bat0daemonbak/src/process_monitor.c create mode 100644 brightness_control_two/Makefile create mode 100644 brightness_control_two/obj/brightness.d create mode 100644 brightness_control_two/obj/brightness.o create mode 100644 brightness_control_two/obj/display.d create mode 100644 brightness_control_two/obj/display.o create mode 100644 brightness_control_two/obj/main.d create mode 100644 brightness_control_two/src/brightness.c create mode 100644 brightness_control_two/src/brightness.h create mode 100644 brightness_control_two/src/display.c create mode 100644 brightness_control_two/src/display.h create mode 100644 brightness_control_two/src/main.c create mode 100644 brightness_control_two/src/utils.c create mode 100644 brightness_control_two/src/utils.h create mode 100644 brightness_menu/Makefile create mode 100644 brightness_menu/README.md create mode 100644 brightness_menu/build/brightness.o create mode 100644 brightness_menu/build/color_temperature.o create mode 100644 brightness_menu/build/display.o create mode 100644 brightness_menu/build/main.o create mode 100644 brightness_menu/build/refresh_rate.o create mode 100644 brightness_menu/build/resolution.o create mode 100755 brightness_menu/build/screen_control create mode 100644 brightness_menu/include/brightness.h create mode 100644 brightness_menu/include/color_temperature.h create mode 100644 brightness_menu/include/display.h create mode 100644 brightness_menu/include/refresh_rate.h create mode 100644 brightness_menu/include/resolution.h create mode 100644 brightness_menu/src/brightness.c create mode 100644 brightness_menu/src/brightness.o create mode 100644 brightness_menu/src/color_temperature.c create mode 100644 brightness_menu/src/display.c create mode 100644 brightness_menu/src/display.o create mode 100644 brightness_menu/src/main.c create mode 100644 brightness_menu/src/main.o create mode 100644 brightness_menu/src/refresh_rate.c create mode 100644 brightness_menu/src/resolution.c create mode 100644 mpvd/build/Install create mode 100644 mpvd/build/Makefile create mode 100755 mpvd/build/mpvd create mode 100644 mpvd/include/audio.h create mode 100644 mpvd/include/dir.h create mode 100644 mpvd/include/ui.h create mode 100644 mpvd/obj/audio.o create mode 100644 mpvd/obj/dir.o create mode 100644 mpvd/obj/main.o create mode 100644 mpvd/obj/ui.o create mode 100644 mpvd/src/audio.c create mode 100644 mpvd/src/dir.c create mode 100644 mpvd/src/main.c create mode 100644 mpvd/src/mpvd.c create mode 100644 mpvd/src/ui.c create mode 100644 ncursescalander/backup/Makefile create mode 100755 ncursescalander/backup/calendar create mode 100644 ncursescalander/backup/main.c create mode 100644 ncursescalander/backup/main.o create mode 100644 ncursescalander/build/Makefile create mode 100644 ncursescalander/build/add_event.o create mode 100644 ncursescalander/build/calendar.o create mode 100755 ncursescalander/build/calendar_app create mode 100644 ncursescalander/build/day_view.o create mode 100644 ncursescalander/build/main.o create mode 100644 ncursescalander/build/repeat_tui.o create mode 100644 ncursescalander/databases/calendar_database.db create mode 100644 ncursescalander/include/add_event.h create mode 100644 ncursescalander/include/calendar.h create mode 100644 ncursescalander/include/day_view.h create mode 100644 ncursescalander/include/repeat_tui.h create mode 100644 ncursescalander/src/add_event.c create mode 100644 ncursescalander/src/add_event.c.bak create mode 100644 ncursescalander/src/calendar.c create mode 100644 ncursescalander/src/day_view.c create mode 100644 ncursescalander/src/main.c create mode 100644 ncursescalander/src/repeat_tui.c create mode 160000 ssh_gui create mode 100644 terrarium_bk/terrarium/Makefile create mode 100644 terrarium_bk/terrarium/ascii_plant_data.c create mode 100644 terrarium_bk/terrarium/ascii_plant_data.h create mode 100644 terrarium_bk/terrarium/ascii_plant_data.o create mode 100644 terrarium_bk/terrarium/game.c create mode 100644 terrarium_bk/terrarium/game.h create mode 100644 terrarium_bk/terrarium/game.o create mode 100644 terrarium_bk/terrarium/main.c create mode 100644 terrarium_bk/terrarium/main.o create mode 100755 terrarium_bk/terrarium/terrarium create mode 100644 terrarium_bk/terrarium/terrarium.c create mode 100644 terrarium_bk/terrarium/terrarium_save.dat create mode 100644 testfunctions/readme.md create mode 100755 testfunctions/source/test.c create mode 160000 website-tests diff --git a/backups/bat0daemonbak/Makefile b/backups/bat0daemonbak/Makefile new file mode 100644 index 0000000..63be530 --- /dev/null +++ b/backups/bat0daemonbak/Makefile @@ -0,0 +1,22 @@ +CC = gcc +CFLAGS = `pkg-config --cflags gtk+-3.0` -I$(INC_DIR) +LDFLAGS = `pkg-config --libs gtk+-3.0` +SRC_DIR = src +INC_DIR = include +OBJ_DIR = obj +OBJS = $(OBJ_DIR)/battery_monitor.o $(OBJ_DIR)/notification.o $(OBJ_DIR)/process_monitor.o +TARGET = battery_monitor + +$(OBJ_DIR)/%.o: $(SRC_DIR)/%.c + @mkdir -p $(OBJ_DIR) + $(CC) $(CFLAGS) -I$(INC_DIR) -o $@ -c $< + +all: $(TARGET) + +$(TARGET): $(OBJS) + $(CC) -o $(TARGET) $(OBJS) $(LDFLAGS) + +clean: + rm -rf $(OBJ_DIR) $(TARGET) + +.PHONY: all clean diff --git a/backups/bat0daemonbak/README.md b/backups/bat0daemonbak/README.md new file mode 100644 index 0000000..e69de29 diff --git a/backups/bat0daemonbak/battery_daemon.sh b/backups/bat0daemonbak/battery_daemon.sh new file mode 100755 index 0000000..13fbf9a --- /dev/null +++ b/backups/bat0daemonbak/battery_daemon.sh @@ -0,0 +1,29 @@ +#!/usr/bin/env bash + +# Set up environment if needed +export DISPLAY=:0 +export XAUTHORITY="$HOME/.Xauthority" + +# Path to the battery monitor binary +BINARY_PATH="/usr/local/bin/battery_monitor" + +# Log file +LOG_FILE="/tmp/battery_monitor.log" + +# Create log directory if it doesn't exist +mkdir -p "$(dirname "$LOG_FILE")" + +# Log starting message and environment variables +echo "Starting battery monitor script" >> "$LOG_FILE" +echo "DISPLAY=$DISPLAY" >> "$LOG_FILE" +echo "XAUTHORITY=$XAUTHORITY" >> "$LOG_FILE" + +# Check if binary exists and is executable +if [ ! -x "$BINARY_PATH" ]; then + echo "Binary not found or not executable: $BINARY_PATH" >> "$LOG_FILE" + exit 1 +fi + +# Start the battery monitor and redirect output to log file +exec "$BINARY_PATH" >> "$LOG_FILE" 2>&1 + diff --git a/backups/bat0daemonbak/battery_monitor b/backups/bat0daemonbak/battery_monitor new file mode 100755 index 0000000000000000000000000000000000000000..1364d400d5c418db9bc302075f59ddfb4da2a8ea GIT binary patch literal 27112 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 C>G;h6 literal 0 HcmV?d00001 diff --git a/backups/bat0daemonbak/battery_monitor.service b/backups/bat0daemonbak/battery_monitor.service new file mode 100755 index 0000000..d7a23b4 --- /dev/null +++ b/backups/bat0daemonbak/battery_monitor.service @@ -0,0 +1,17 @@ +[Unit] +Description=Battery Monitor Service +PartOf=graphical.target +After=graphical.target + +[Service] +Type=simple +ExecStart=/usr/local/bin/battery_daemon.sh +Restart=always +Environment=DISPLAY=:0 +Environment=XAUTHORITY=%h/.Xauthority +StandardOutput=journal +StandardError=journal + +[Install] +WantedBy=graphical.target + diff --git a/backups/bat0daemonbak/docs/battery_monitor.log b/backups/bat0daemonbak/docs/battery_monitor.log new file mode 100644 index 0000000..6e8306c --- /dev/null +++ b/backups/bat0daemonbak/docs/battery_monitor.log @@ -0,0 +1,4 @@ +Starting battery monitor script +DISPLAY=:0 +XAUTHORITY=/home/klein/.Xauthority +Failed to open log file: Permission denied diff --git a/backups/bat0daemonbak/docs/procress_list.txt b/backups/bat0daemonbak/docs/procress_list.txt new file mode 100644 index 0000000..e69de29 diff --git a/backups/bat0daemonbak/include/battery_monitor.h b/backups/bat0daemonbak/include/battery_monitor.h new file mode 100644 index 0000000..e7e52b0 --- /dev/null +++ b/backups/bat0daemonbak/include/battery_monitor.h @@ -0,0 +1,16 @@ +#ifndef BATTERY_MONITOR_H +#define BATTERY_MONITOR_H + +void show_notification(const char *message, const char *title); +int get_battery_level(); +int is_charging(); +int activate_battery_saving_mode(); +int enter_sleep_mode(); +int kill_processes(const char *filename); +int set_brightness(int brightness); +void log_message(const char *message); + +// New function declaration for process monitoring +int get_high_cpu_processes(char *process_list[], int max_processes); + +#endif // BATTERY_MONITOR_H diff --git a/backups/bat0daemonbak/include/process_monitor.h b/backups/bat0daemonbak/include/process_monitor.h new file mode 100644 index 0000000..7b55b05 --- /dev/null +++ b/backups/bat0daemonbak/include/process_monitor.h @@ -0,0 +1,8 @@ +#ifndef PROCESS_MONITOR_H +#define PROCESS_MONITOR_H + +int get_high_cpu_processes(char *process_list[], int max_processes); +void free_process_list(char *process_list[], int count); + +#endif // PROCESS_MONITOR_H + diff --git a/backups/bat0daemonbak/install.sh b/backups/bat0daemonbak/install.sh new file mode 100755 index 0000000..e97ee39 --- /dev/null +++ b/backups/bat0daemonbak/install.sh @@ -0,0 +1,63 @@ +#!/usr/bin/env bash + +# Function to check if a command exists +check_dependency() { + if ! command -v "$1" &> /dev/null; then + echo "$1 is not installed. Installing..." + sudo apt-get install -y "$1" + else + echo "$1 is already installed." + fi +} + +# Step 1: Finding the current working directory and script location +SCRIPT_DIR=$(pwd) +BASH_SCRIPT="$SCRIPT_DIR/battery_daemon.sh" +SRC_SCRIPT="$SCRIPT_DIR/battery_monitor" + +# Check if battery_daemon.sh exists +if [[ -f "$BASH_SCRIPT" ]]; then + echo "Found battery_daemon.sh. Moving to /usr/local/bin." + sudo cp "$BASH_SCRIPT" /usr/local/bin/battery_daemon.sh + sudo cp "$SRC_SCRIPT" /usr/local/bin/battery_monitor + sudo chmod +x /usr/local/bin/battery_daemon + sudo chmod +x /usr/local/bin/battery_daemon.sh +else + echo "battery_daemon.sh not found in the current directory!" + exit 1 +fi + +# Step 2: Check for dependencies and install if not present +dependencies=("gcc" "make" "brightnessctl") + +for dep in "${dependencies[@]}"; do + check_dependency "$dep" +done + +# Step 3: Copy battery_monitor.service to systemd folder +SYSTEMD_SERVICE="$SCRIPT_DIR/battery_monitor.service" +if [[ -f "$SYSTEMD_SERVICE" ]]; then + echo "Found battery_monitor.service. Copying to /etc/systemd/system/" + sudo cp "$SYSTEMD_SERVICE" /etc/systemd/system/ +else + echo "battery_monitor.service not found in the current directory!" + exit 1 +fi + +# Step 4: Reload the systemd daemon, enable and restart the service +echo "Reloading systemd daemon..." +sudo systemctl daemon-reload + +echo "Enabling battery_monitor.service..." +sudo systemctl enable battery_monitor.service + +echo "Restarting battery_monitor.service..." +sudo systemctl restart battery_monitor.service + +# Check if the service was successfully started +if systemctl is-active --quiet battery_monitor.service; then + echo "Service started successfully!" +else + echo "Failed to start the service." + exit 1 +fi diff --git a/backups/bat0daemonbak/obj/battery_monitor.o b/backups/bat0daemonbak/obj/battery_monitor.o new file mode 100644 index 0000000000000000000000000000000000000000..9391284ad90a791ae9bc9fc96ab76ddce05b3932 GIT binary patch literal 2904 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 +#include +#include +#include "battery_monitor.h" + +// Define the battery thresholds +#define THRESHOLD_LOW 15 +#define THRESHOLD_CRITICAL 5 +#define THRESHOLD_HIGH 80 + +// Track if notifications have been sent +int notified_low = 0; +int notified_critical = 0; + +int main() { + log_message("Battery monitor started"); + + while (1) { + if (is_charging()) { + // Reset notifications if the battery is charging + log_message("Battery is charging, notifications reset"); + notified_low = 0; + notified_critical = 0; + sleep(300); // Sleep for 5 minutes while charging + continue; + } + + int battery_level = get_battery_level(); + if (battery_level == -1) { + log_message("Battery level read failed, retrying in 1 minute"); + sleep(60); + continue; + } + + // Dynamic sleep interval based on battery level + int sleep_duration = 60; // Default 1 minute + + if (battery_level > THRESHOLD_HIGH) { + sleep_duration = 300; // Sleep for 5 minutes + } else if (battery_level <= THRESHOLD_CRITICAL) { + sleep_duration = 30; // Sleep for 30 seconds when critically low + } else if (battery_level <= THRESHOLD_LOW) { + sleep_duration = 60; // Sleep for 1 minute when low + } + + // Check if the battery level is below the critical threshold + if (battery_level <= THRESHOLD_CRITICAL && !notified_critical) { + log_message("Battery critically low, showing notification"); + show_notification("Battery is critically low, below 5%", "Critical Battery Warning"); + notified_critical = 1; + } else if (battery_level <= THRESHOLD_LOW && !notified_low) { + log_message("Battery low, showing notification"); + show_notification("Battery is low, below 15%", "Low Battery Warning"); + notified_low = 1; + } + + // Reset notifications if battery level goes back up + if (battery_level > THRESHOLD_LOW) { + notified_low = 0; + } + if (battery_level > THRESHOLD_CRITICAL) { + notified_critical = 0; + } + + // Wait for the dynamically determined duration before checking again + sleep(sleep_duration); + } + + return 0; +} diff --git a/backups/bat0daemonbak/src/notification.c b/backups/bat0daemonbak/src/notification.c new file mode 100644 index 0000000..e675567 --- /dev/null +++ b/backups/bat0daemonbak/src/notification.c @@ -0,0 +1,281 @@ +#include +#include +#include +#include +#include +#include +#include +#include "battery_monitor.h" +#include "process_monitor.h" + +#define CSS_STYLE "\ + * { \ + background-color: #333333; \ + color: white; \ + } \ + button { \ + background-color: #555555; \ + color: white; \ + } \ +" + +// Function to get the battery level +int get_battery_level() { + const char *battery_paths[] = { + "/sys/class/power_supply/BAT0/capacity", + "/sys/class/power_supply/BAT1/capacity" + }; + FILE *file; + int battery_level = -1; + + for (int i = 0; i < sizeof(battery_paths) / sizeof(battery_paths[0]); i++) { + file = fopen(battery_paths[i], "r"); + if (file != NULL) { + break; + } + } + + if (file == NULL) { + perror("Failed to open capacity file"); + log_message("Failed to open capacity file"); + return -1; + } + + if (fscanf(file, "%d", &battery_level) != 1) { + perror("Failed to read battery level"); + log_message("Failed to read battery level"); + fclose(file); + return -1; + } + + fclose(file); + return battery_level; +} + +// Function to get the base directory of the executable +char *get_base_directory() { + static char base_dir[PATH_MAX]; + ssize_t count = readlink("/proc/self/exe", base_dir, PATH_MAX); + if (count != -1) { + dirname(base_dir); + } + return base_dir; +} + +// Function to log messages to a file +void log_message(const char *message) { + char log_file[PATH_MAX]; + snprintf(log_file, PATH_MAX, "/tmp/battery_monitor.log"); + + FILE *log_file_ptr = fopen(log_file, "a"); + if (log_file_ptr) { + fprintf(log_file_ptr, "%s\n", message); + fclose(log_file_ptr); + } else { + perror("Failed to open log file"); + } +} + +// Function to activate battery saving mode +int activate_battery_saving_mode() { + log_message("Activating battery saving mode"); + + char process_list_file[PATH_MAX]; + snprintf(process_list_file, PATH_MAX, "%s/../docs/process_list.txt", get_base_directory()); + + if (kill_processes(process_list_file) == -1) { + return -1; // Return failure if processes couldn't be killed + } + + if (set_brightness(50) == -1) { + return -1; // Return failure if brightness couldn't be set + } + + return 0; // Success +} + +// Function to enter sleep mode +int enter_sleep_mode() { + log_message("Entering sleep mode"); + return system("systemctl suspend"); // Return system command result +} + +// Function to apply custom CSS styles to the GTK widgets +void apply_css(GtkWidget *widget, const char *css) { + GtkCssProvider *provider = gtk_css_provider_new(); + gtk_css_provider_load_from_data(provider, css, -1, NULL); + GtkStyleContext *context = gtk_widget_get_style_context(widget); + gtk_style_context_add_provider(context, GTK_STYLE_PROVIDER(provider), GTK_STYLE_PROVIDER_PRIORITY_USER); + g_object_unref(provider); +} + +// Function to check the battery status and close the dialog if charging +gboolean check_battery_status(gpointer user_data) { + GtkWidget *dialog = GTK_WIDGET(user_data); + if (is_charging()) { + log_message("Battery started charging, closing notification"); + gtk_widget_destroy(dialog); + gtk_main_quit(); // Exit the GTK main loop + return FALSE; // Stop checking + } + return TRUE; // Continue checking +} + +// Function to handle dialog response +void on_dialog_response(GtkDialog *dialog, gint response_id, gpointer user_data) { + switch (response_id) { + case GTK_RESPONSE_OK: + log_message("User clicked OK"); + break; + case GTK_RESPONSE_APPLY: + log_message("User activated Battery Saving Mode"); + activate_battery_saving_mode(); + break; + case GTK_RESPONSE_CLOSE: + log_message("User triggered Sleep Mode"); + enter_sleep_mode(); + break; + default: + break; + } + gtk_widget_destroy(GTK_WIDGET(dialog)); + gtk_main_quit(); // Exit the GTK main loop +} + +// Function to show the notification dialog +void show_notification(const char *message, const char *title) { + log_message("Showing notification"); + + GtkWidget *dialog; + gtk_init(0, NULL); + + dialog = gtk_message_dialog_new(NULL, + GTK_DIALOG_DESTROY_WITH_PARENT, + GTK_MESSAGE_INFO, + GTK_BUTTONS_NONE, + "%s", message); + gtk_dialog_add_button(GTK_DIALOG(dialog), "OK", GTK_RESPONSE_OK); + gtk_dialog_add_button(GTK_DIALOG(dialog), "Battery Saving Mode", GTK_RESPONSE_APPLY); + + if (g_strcmp0(title, "Critical Battery Warning") == 0) { + gtk_dialog_add_button(GTK_DIALOG(dialog), "Sleep", GTK_RESPONSE_CLOSE); + } + + gtk_window_set_title(GTK_WINDOW(dialog), title); + + // Apply CSS styles + apply_css(dialog, CSS_STYLE); + + // Set up the callback to check battery status and close if charging + g_timeout_add(1000, check_battery_status, dialog); + + // Connect the dialog response to handle button clicks and ensure proper cleanup + g_signal_connect(dialog, "response", G_CALLBACK(on_dialog_response), NULL); + + // Show the dialog and enter the GTK main loop + gtk_widget_show_all(dialog); + gtk_main(); // Start the GTK main loop +} + +// Function to check if the battery is charging +int is_charging() { + const char *status_paths[] = { + "/sys/class/power_supply/BAT0/status", + "/sys/class/power_supply/BAT1/status" + }; + FILE *file; + char status[16]; + + for (int i = 0; i < sizeof(status_paths) / sizeof(status_paths[0]); i++) { + file = fopen(status_paths[i], "r"); + if (file != NULL) { + break; + } + } + + if (file == NULL) { + perror("Failed to open status file"); + log_message("Failed to open status file"); + return -1; + } + + if (fscanf(file, "%15s", status) != 1) { + perror("Failed to read battery status"); + log_message("Failed to read battery status"); + fclose(file); + return -1; + } + + fclose(file); + return (strcmp(status, "Charging") == 0); +} + +// Function to kill processes based on a dynamic process list +int kill_processes(const char *filename) { + // Dynamic process list based on CPU usage + char *process_list[100]; // Assuming a max of 100 processes to kill + int process_count = get_high_cpu_processes(process_list, 100); + + if (process_count == -1) { + log_message("Failed to get high CPU processes"); + return -1; + } + + for (int i = 0; i < process_count; i++) { + char command[300]; + snprintf(command, sizeof(command), "pkill %s", process_list[i]); + log_message(command); // Log the command being executed + if (system(command) == -1) { + free_process_list(process_list, process_count); + return -1; // Return failure if the command fails + } + } + + free_process_list(process_list, process_count); + return 0; // Success +} + +// Function to set the screen brightness +int set_brightness(int brightness) { + const char *brightness_path = "/sys/class/backlight/intel_backlight/brightness"; + const char *max_brightness_path = "/sys/class/backlight/intel_backlight/max_brightness"; + int max_brightness = 100; + int new_brightness = 0; + char buffer[4]; + + int fd = open(max_brightness_path, O_RDONLY); + if (fd == -1) { + perror("Failed to open max brightness file"); + log_message("Failed to open max brightness file"); + return -1; // Return failure if the file can't be opened + } + + if (read(fd, buffer, sizeof(buffer)) != -1) { + max_brightness = atoi(buffer); + } else { + perror("Failed to read max brightness"); + log_message("Failed to read max brightness"); + close(fd); + return -1; // Return failure if the file can't be read + } + close(fd); + + new_brightness = max_brightness * brightness / 100; + fd = open(brightness_path, O_WRONLY); + if (fd == -1) { + perror("Failed to open brightness file"); + log_message("Failed to open brightness file"); + return -1; // Return failure if the file can't be opened + } + + snprintf(buffer, sizeof(buffer), "%d", new_brightness); + if (write(fd, buffer, strlen(buffer)) == -1) { + perror("Failed to write to brightness file"); + log_message("Failed to write to brightness file"); + close(fd); + return -1; // Return failure if the write fails + } + + close(fd); + return 0; // Success +} diff --git a/backups/bat0daemonbak/src/notification.c.bak b/backups/bat0daemonbak/src/notification.c.bak new file mode 100644 index 0000000..38a0526 --- /dev/null +++ b/backups/bat0daemonbak/src/notification.c.bak @@ -0,0 +1,143 @@ +#include +#include +#include +#include +#include +#include +#include "battery_monitor.h" + +#define LOG_FILE "/home/klein/codeWS/C/bat0daemon/docs/battery_monitor.log" + +void log_message(const char *message) { + FILE *log_file = fopen(LOG_FILE, "a"); + if (log_file) { + fprintf(log_file, "%s\n", message); + fclose(log_file); + } else { + perror("Failed to open log file"); + } +} + +void activate_battery_saving_mode() { + log_message("Activating battery saving mode"); + kill_processes("/home/klein/codeWS/C/bat0daemon/docs/procress_list.txt"); + set_brightness(50); +} + +void enter_sleep_mode() { + log_message("Entering sleep mode"); + system("systemctl suspend"); +} + +void show_notification(const char *message, const char *title) { + log_message("Showing notification"); + GtkWidget *dialog; + gtk_init(0, NULL); + dialog = gtk_message_dialog_new(NULL, + GTK_DIALOG_DESTROY_WITH_PARENT, + GTK_MESSAGE_INFO, + GTK_BUTTONS_NONE, + "%s", message); + gtk_dialog_add_button(GTK_DIALOG(dialog), "OK", GTK_RESPONSE_OK); + gtk_dialog_add_button(GTK_DIALOG(dialog), "Battery Saving Mode", GTK_RESPONSE_APPLY); + + if (g_strcmp0(title, "Critical Battery Warning") == 0) { + gtk_dialog_add_button(GTK_DIALOG(dialog), "Sleep", GTK_RESPONSE_CLOSE); + } + + gtk_window_set_title(GTK_WINDOW(dialog), title); + + gint response = gtk_dialog_run(GTK_DIALOG(dialog)); + if (response == GTK_RESPONSE_APPLY) { + activate_battery_saving_mode(); + } else if (response == GTK_RESPONSE_CLOSE) { + enter_sleep_mode(); + } + + gtk_widget_destroy(dialog); + while (g_main_context_iteration(NULL, FALSE)); +} + +int get_battery_level() { + FILE *file; + int battery_level = -1; + + file = fopen("/sys/class/power_supply/BAT0/capacity", "r"); + if (file == NULL) { + perror("Failed to open capacity file"); + log_message("Failed to open capacity file"); + return -1; + } + + if (fscanf(file, "%d", &battery_level) != 1) { + perror("Failed to read battery level"); + log_message("Failed to read battery level"); + fclose(file); + return -1; + } + + fclose(file); + + return battery_level; +} + +void kill_processes(const char *filename) { + FILE *file = fopen(filename, "r"); + if (file == NULL) { + perror("Failed to open process list file"); + log_message("Failed to open process list file"); + return; + } + + char process_name[256]; + while (fgets(process_name, sizeof(process_name), file)) { + process_name[strcspn(process_name, "\n")] = 0; // Remove newline character + if (strlen(process_name) > 0) { + char command[300]; + snprintf(command, sizeof(command), "pkill %s", process_name); + log_message(command); // Log the command being executed + system(command); + } + } + + fclose(file); +} + +void set_brightness(int brightness) { + const char *brightness_path = "/sys/class/backlight/intel_backlight/brightness"; + const char *max_brightness_path = "/sys/class/backlight/intel_backlight/max_brightness"; + int max_brightness = 100; + int new_brightness = 0; + char buffer[4]; + + int fd = open(max_brightness_path, O_RDONLY); + if (fd == -1) { + perror("Failed to open max brightness file"); + log_message("Failed to open max brightness file"); + return; + } + + if (read(fd, buffer, sizeof(buffer)) != -1) { + max_brightness = atoi(buffer); + } else { + perror("Failed to read max brightness"); + log_message("Failed to read max brightness"); + } + close(fd); + + new_brightness = max_brightness * brightness / 100; + fd = open(brightness_path, O_WRONLY); + if (fd == -1) { + perror("Failed to open brightness file"); + log_message("Failed to open brightness file"); + return; + } + + snprintf(buffer, sizeof(buffer), "%d", new_brightness); + if (write(fd, buffer, strlen(buffer)) == -1) { + perror("Failed to write to brightness file"); + log_message("Failed to write to brightness file"); + } + + close(fd); +} diff --git a/backups/bat0daemonbak/src/process_monitor.c b/backups/bat0daemonbak/src/process_monitor.c new file mode 100644 index 0000000..6c3d785 --- /dev/null +++ b/backups/bat0daemonbak/src/process_monitor.c @@ -0,0 +1,45 @@ +#include +#include +#include +#include +#include "battery_monitor.h" + +#define BUFFER_SIZE 1024 + +int get_high_cpu_processes(char *process_list[], int max_processes) { + FILE *fp; + char buffer[BUFFER_SIZE]; + int process_count = 0; + + // Command to get the top CPU-using processes for the user 'klein', excluding vi, neovim, vim, and root processes + const char *command = "ps -eo user,pid,comm,%cpu --sort=-%cpu | grep '^klein' | grep -vE '(vi|vim|neovim|root)'"; + + fp = popen(command, "r"); + if (fp == NULL) { + log_message("Failed to run command to get high CPU processes"); + return -1; + } + + while (fgets(buffer, sizeof(buffer), fp) != NULL && process_count < max_processes) { + char user[50], command_name[100]; + int pid; + float cpu_usage; + + // Parse the line to extract the user, PID, command name, and CPU usage + sscanf(buffer, "%49s %d %99s %f", user, &pid, command_name, &cpu_usage); + + // Store the command in the process list + process_list[process_count] = malloc(BUFFER_SIZE); + snprintf(process_list[process_count], BUFFER_SIZE, "%d", pid); + process_count++; + } + + pclose(fp); + return process_count; +} + +void free_process_list(char *process_list[], int count) { + for (int i = 0; i < count; i++) { + free(process_list[i]); + } +} diff --git a/brightness_control_two/Makefile b/brightness_control_two/Makefile new file mode 100644 index 0000000..7a23987 --- /dev/null +++ b/brightness_control_two/Makefile @@ -0,0 +1,27 @@ +CC = gcc +CFLAGS = -Wall -Wextra -std=c99 +LDFLAGS = -lX11 + +SRC_DIR = src +OBJ_DIR = obj +BIN_DIR = bin + +SRCS = $(wildcard $(SRC_DIR)/*.c) +OBJS = $(patsubst $(SRC_DIR)/%.c, $(OBJ_DIR)/%.o, $(SRCS)) +DEPS = $(OBJS:.o=.d) +TARGET = $(BIN_DIR)/brightnessctl + +$(TARGET): $(OBJS) + @mkdir -p $(BIN_DIR) + $(CC) $(CFLAGS) -o $@ $^ $(LDFLAGS) + +$(OBJ_DIR)/%.o: $(SRC_DIR)/%.c + @mkdir -p $(OBJ_DIR) + $(CC) $(CFLAGS) -MMD -c $< -o $@ + +-include $(DEPS) + +clean: + rm -rf $(OBJ_DIR) $(BIN_DIR) + +.PHONY: clean diff --git a/brightness_control_two/obj/brightness.d b/brightness_control_two/obj/brightness.d new file mode 100644 index 0000000..31ebd53 --- /dev/null +++ b/brightness_control_two/obj/brightness.d @@ -0,0 +1,2 @@ +obj/brightness.o: src/brightness.c src/brightness.h src/display.h \ + src/utils.h diff --git a/brightness_control_two/obj/brightness.o b/brightness_control_two/obj/brightness.o new file mode 100644 index 0000000000000000000000000000000000000000..bc6220397a3cf498474eb08ddc8b5658004c1e65 GIT binary patch literal 7576 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 literal 0 HcmV?d00001 diff --git a/brightness_control_two/obj/display.d b/brightness_control_two/obj/display.d new file mode 100644 index 0000000..8921907 --- /dev/null +++ b/brightness_control_two/obj/display.d @@ -0,0 +1 @@ +obj/display.o: src/display.c src/display.h src/brightness.h src/utils.h diff --git a/brightness_control_two/obj/display.o b/brightness_control_two/obj/display.o new file mode 100644 index 0000000000000000000000000000000000000000..e767b66f77ea0bcb3adada5849fdd82f77d28772 GIT binary patch literal 5440 zcmb<-^>JfjWMqH=Mg}_u1P><4z`!7cU^{@B4h*~uJPe^8oliZQ-#B=5*52^wEWO~- z8G6E_8-zvj|W#hQhhJk^>aR(Oz1H(=?1_lO?&f_mYhIup} zQ8@1U2gH1t&B(xz#{d50Cw?v8KcDyoSV5wn_#+Q~;uqkBu;UJP_5njF*M3myfe3cHKIm?Ez`(%J>3YYb+x3A*cLPYGJM@l6@+FUh zkJvpJFLXOdbh_TaEi2RMdIguPN4G}=Zn=O2a46LN0EI>A70qLvA1=Od>^$7<`lGw_ z28??M*?`hJ9?9Q44nAY|VEo|GT_6CKYktEK7?j26+Ii5i^M_04O_$C~NMWep(dl}^ zqucicNbRo6moGDTbe@CDL&ZIMML|J@Bm)Wu29HkH10LP32jJ2m3lY2k4v+5812D6Z zG=ufPat_prU5pJ(s8)mWpz8yV&T9zQl!9Hk6Xcd%AObGa>AJ(C8;|S;kngZXpGS8< zf=9RS4zN73$Faw@M|VJkN4GD;IArCeU=tj{PIKG=N&(G6mPiwQ`8?Ev``651dsSg7?*eE?C796;TzAi?Gz!X-?v?@sXO z4&8w@@FC9MwQ}W3Q9^lPK1k(85ANa(t z)e6dG-K`+Ur}4kP^od{VLK?ruiBJ4-r=TiaKR`-9P*Ju7R!X)pFfeqx{;_slQY!_E zfL;Ip|3`MxYYDgvx?^kK>;O4!=J(nU%`cc7I}gCQ{Oeu+^m=eXd=E(yAisoz(*F*S zN09vhDnP)l_`u(j_a7Ym4`A}h1p$_{2uhle=$mlzFav{AQD%BZNnUDkv2%W2Nl|_d zLlRsh87fl5z`&qiTv@E2oRe5wte=#aoSg&GrJtEslA05b;O8b*#3QsbsHQM5Na(tR z{8r?IR9y@LP}&YkM?z^A2;Jc3z~JueY^9*#lA4s6n5ST9q-UgOplfKN31u>ffYKEM z0|R4K5Cda{0HZVyJI4e@1_l`h2nI=?2c=_2K7lqSXI?huQ;a<99AJ4+B?yu)X91-S zn0yfnNFF4P4TFqgVfgqTn;bLt8k>Qc0i0n_v~Yu~a*$~dVXzw+7#KhWlmJ8sg_L7p zV8AA>ghN~nhqwXMUYLDgzcVl}IO9+sfI~bKhj=Cq@j4vhojAm2;t*esLwqd`aZve+ zE!>XcP=6kW_&prrZ*ho&k^(k+*%-0MqZkfxSsdaTIK<6yh}+>1cflbZj6<9uC9}97 zC$Um5nIWYpu{=IAIX{mf!lfv&+_5N`AvwR8p*RyN;FFn`3R8|;3`F=Bq~^ImjA2Nv z$Sh%qa4t$sEJ+Q{%q_@C4bRL=$uDP!2u>}5Fr5;Uv(t<6OY>3~B7#fui&Fg(b5j{2 z9CLE=lbt~&kVj@-30OT6&#fpm6(p9Enq1EY451w2V(HPEO2AV@ONR$uCZ2i116T zC~+-I1v$qpGbbk~HMt})FFhxfA;K-Ev^ayII43o=fFZ&qwYa1xzY^{mkY-qbKy$ql zlm-<|pwi>de+Wp1iZd}VFn}uM7$`ppn-kVTym^m4sP5llVIUS4R? z2@{9es{j=T*^BI7P<{a!2~*z!;xI5Um_XIT#9{soKof`A8-peevo{|q4zd^7zvWPI znE5b!o6*E!{@n@{2bsfx6mCo)1EBE;YQezbQ5;DeRHwkieK&29#gNQTM-mrD63>H* z!@@xU6bK9q3>9eNDp2tTs5pp{Kr&|~4stjcA&G<9STOZ7ki?PIZ^9w|4M`l?95GO)h1x5NS1yMpu&TJ zfgu7KU!bxFq!&~+fz*J~Du@QPH$mdiYy}bm<2E#V!GfUnI*b9Obr={JKxUGw-wsgz5*ikCDYCK!rI20|O|0k;OrN1@U1tsJ@1=LEWNMYZMUxeE+=m literal 0 HcmV?d00001 diff --git a/brightness_control_two/obj/main.d b/brightness_control_two/obj/main.d new file mode 100644 index 0000000..2d8da03 --- /dev/null +++ b/brightness_control_two/obj/main.d @@ -0,0 +1 @@ +obj/main.o: src/main.c src/brightness.h diff --git a/brightness_control_two/src/brightness.c b/brightness_control_two/src/brightness.c new file mode 100644 index 0000000..d8fb52d --- /dev/null +++ b/brightness_control_two/src/brightness.c @@ -0,0 +1,184 @@ +#include "brightness.h" +#include "display.h" +#include "utils.h" + +#include +#include +#include // Include string.h for strdup + +static int min_value = 0; +static float exponent = 1.0; +static char *device = NULL; +static char *class = NULL; +static int quiet_mode = 0; +static int pretend_mode = 0; + +void set_brightness(int value, int raw) { + if (pretend_mode) { + if (!quiet_mode) { + printf("Pretend mode: setting brightness to %d\n", value); + } + return; + } + + FILE *brightness_file = fopen(BRIGHTNESS_PATH, "w"); + if (brightness_file == NULL) { + perror("Failed to open brightness file"); + exit(EXIT_FAILURE); + } + + if (!raw) { + FILE *max_brightness_file = fopen(MAX_BRIGHTNESS_PATH, "r"); + if (max_brightness_file == NULL) { + perror("Failed to open max brightness file"); + fclose(brightness_file); + exit(EXIT_FAILURE); + } + + int max_brightness; + fscanf(max_brightness_file, "%d", &max_brightness); + fclose(max_brightness_file); + + value = (value * max_brightness) / 100; + } + + fprintf(brightness_file, "%d", value); + fclose(brightness_file); + display_brightness(value); +} + +void adjust_brightness(const char *direction) { + if (pretend_mode) { + if (!quiet_mode) { + printf("Pretend mode: adjusting brightness %s\n", direction); + } + return; + } + + FILE *brightness_file = fopen(BRIGHTNESS_PATH, "r+"); + if (brightness_file == NULL) { + perror("Failed to open brightness file"); + exit(EXIT_FAILURE); + } + + int brightness; + fscanf(brightness_file, "%d", &brightness); + + FILE *max_brightness_file = fopen(MAX_BRIGHTNESS_PATH, "r"); + if (max_brightness_file == NULL) { + perror("Failed to open max brightness file"); + fclose(brightness_file); + exit(EXIT_FAILURE); + } + + int max_brightness; + fscanf(max_brightness_file, "%d", &max_brightness); + fclose(max_brightness_file); + + if (strcmp(direction, "up") == 0) { + brightness += max_brightness / 10; + } else if (strcmp(direction, "down") == 0) { + brightness -= max_brightness / 10; + } + + if (brightness < 0) { + brightness = 0; + } else if (brightness > max_brightness) { + brightness = max_brightness; + } + + rewind(brightness_file); + fprintf(brightness_file, "%d", brightness); + fclose(brightness_file); + + display_brightness(brightness); +} + +void save_brightness(void) { + if (pretend_mode) { + if (!quiet_mode) { + printf("Pretend mode: saving brightness\n"); + } + return; + } + + FILE *brightness_file = fopen(BRIGHTNESS_PATH, "r"); + if (brightness_file == NULL) { + perror("Failed to open brightness file"); + exit(EXIT_FAILURE); + } + + int brightness; + fscanf(brightness_file, "%d", &brightness); + fclose(brightness_file); + + FILE *save_file = fopen("/tmp/brightnessctl_save", "w"); + if (save_file == NULL) { + perror("Failed to open save file"); + exit(EXIT_FAILURE); + } + + fprintf(save_file, "%d", brightness); + fclose(save_file); + + if (!quiet_mode) { + printf("Brightness saved: %d\n", brightness); + } +} + +void restore_brightness(void) { + if (pretend_mode) { + if (!quiet_mode) { + printf("Pretend mode: restoring brightness\n"); + } + return; + } + + FILE *save_file = fopen("/tmp/brightnessctl_save", "r"); + if (save_file == NULL) { + perror("Failed to open save file"); + exit(EXIT_FAILURE); + } + + int brightness; + fscanf(save_file, "%d", &brightness); + fclose(save_file); + + set_brightness(brightness, 1); + + if (!quiet_mode) { + printf("Brightness restored: %d\n", brightness); + } +} + +void list_devices(void) { + printf("Listing available devices...\n"); +} + +void print_info(void) { + printf("Printing device info...\n"); +} + +void set_min_value(int value) { + min_value = value; +} + +void set_exponent(float exp) { + exponent = exp; +} + +void set_device(char *device_name) { + device = strdup(device_name); +} + +void set_class(char *class_name) { + class = strdup(class_name); +} + +void enable_quiet_mode(void) { + quiet_mode = 1; +} + +void enable_pretend_mode(void) { + pretend_mode = 1; +} diff --git a/brightness_control_two/src/brightness.h b/brightness_control_two/src/brightness.h new file mode 100644 index 0000000..9252300 --- /dev/null +++ b/brightness_control_two/src/brightness.h @@ -0,0 +1,21 @@ +#ifndef BRIGHTNESS_H +#define BRIGHTNESS_H + +#define BRIGHTNESS_PATH "/sys/class/backlight/intel_backlight/brightness" +#define MAX_BRIGHTNESS_PATH "/sys/class/backlight/intel_backlight/max_brightness" + +void set_brightness(int value, int raw); +void adjust_brightness(const char *direction); +void display_brightness(int brightness); +void save_brightness(void); +void restore_brightness(void); +void list_devices(void); +void print_info(void); +void set_min_value(int value); +void set_exponent(float exponent); +void set_device(char *device_name); +void set_class(char *class_name); +void enable_quiet_mode(void); +void enable_pretend_mode(void); + +#endif diff --git a/brightness_control_two/src/display.c b/brightness_control_two/src/display.c new file mode 100644 index 0000000..51b38ef --- /dev/null +++ b/brightness_control_two/src/display.c @@ -0,0 +1,95 @@ +#include "display.h" +#include "brightness.h" +#include "utils.h" + +#include +#include +#include +#include +#include +#include + +#ifndef M_PI +#define M_PI 3.14159265358979323846 +#endif + +void draw_icon(Display *d, Window w, GC gc) { + XDrawArc(d, w, gc, 70, 10, 60, 60, 0, 360 * 64); + for (int i = 0; i < 8; ++i) { + int x1 = 100 + 30 * cos(i * M_PI / 4); + int y1 = 40 + 30 * sin(i * M_PI / 4); + int x2 = 100 + 45 * cos(i * M_PI / 4); + int y2 = 40 + 45 * sin(i * M_PI / 4); + XDrawLine(d, w, gc, x1, y1, x2, y2); + } +} + +void display_brightness(int brightness) { + Display *d; + Window w; + XEvent e; + int screen; + unsigned int display_width, display_height; + int width = 200, height = 120; + int sections = 10; + int graph_height = 10; + + if ((d = XOpenDisplay(NULL)) == NULL) { + exit(1); + } + + screen = DefaultScreen(d); + display_width = DisplayWidth(d, screen); + display_height = DisplayHeight(d, screen); + + w = XCreateSimpleWindow(d, RootWindow(d, screen), (display_width - width) / 2, (display_height - height) / 2, width, height, 1, + BlackPixel(d, screen), WhitePixel(d, screen)); + XSetWindowBackground(d, w, 0xD3D3D3); + XStoreName(d, w, "BrightnessControl"); + XClassHint *classHint = XAllocClassHint(); + classHint->res_name = "brightnesscontrol"; + classHint->res_class = "BrightnessControl"; + XSetClassHint(d, w, classHint); + XFree(classHint); + + XSelectInput(d, w, ExposureMask | KeyPressMask | StructureNotifyMask); + XMapWindow(d, w); + + GC gc = XCreateGC(d, w, 0, NULL); + GC bg_gc = XCreateGC(d, w, 0, NULL); + XSetForeground(d, gc, BlackPixel(d, screen)); + XSetBackground(d, bg_gc, WhitePixel(d, screen)); + XSetLineAttributes(d, gc, 3, LineSolid, CapButt, JoinMiter); + + FILE *max_brightness_file = fopen(MAX_BRIGHTNESS_PATH, "r"); + int max_brightness; + fscanf(max_brightness_file, "%d", &max_brightness); + fclose(max_brightness_file); + + while (1) { + XNextEvent(d, &e); + if (e.type == MapNotify) { + break; + } + } + + draw_icon(d, w, gc); + + XSetForeground(d, bg_gc, 0xA9A9A9); + XFillRectangle(d, w, bg_gc, 10, 100, 180, graph_height); + + int filled_sections = (int)((brightness / (double)max_brightness) * sections); + for (int i = 0; i < sections; ++i) { + if (i < filled_sections) { + XSetForeground(d, gc, 0xFFFFFF); + } else { + XSetForeground(d, gc, 0xA9A9A9); + } + XFillRectangle(d, w, gc, 10 + i * (180 / sections), 100, 180 / sections - 2, graph_height); + } + + XFlush(d); + sleep(1); + XDestroyWindow(d, w); + XCloseDisplay(d); +} diff --git a/brightness_control_two/src/display.h b/brightness_control_two/src/display.h new file mode 100644 index 0000000..52c38c6 --- /dev/null +++ b/brightness_control_two/src/display.h @@ -0,0 +1,9 @@ +#ifndef DISPLAY_H +#define DISPLAY_H + +#include // Include X11 headers for Display, Window, and GC types + +void draw_icon(Display *d, Window w, GC gc); +void display_brightness(int brightness); + +#endif diff --git a/brightness_control_two/src/main.c b/brightness_control_two/src/main.c new file mode 100644 index 0000000..7ecf95f --- /dev/null +++ b/brightness_control_two/src/main.c @@ -0,0 +1,113 @@ +#include "brightness.h" + +#include +#include +#include +#include + +void print_usage(const char *prog_name) { + printf("Usage: %s [OPTION]...\n", prog_name); + printf("Options:\n"); + printf(" -s, --save Save current brightness\n"); + printf(" -r, --restore Restore saved brightness\n"); + printf(" --set VALUE Set brightness to VALUE\n"); + printf(" -a, --adjust DIR Adjust brightness up or down\n"); + printf(" -h, --help Display this help and exit\n"); + printf(" -l, --list List devices with available brightness controls\n"); + printf(" -q, --quiet Suppress output\n"); + printf(" -p, --pretend Do not perform write operations\n"); + printf(" -n, --min-value MIN_VALUE Set minimum brightness value\n"); + printf(" -e, --exponent EXPONENT Change percentage curve to exponential\n"); + printf(" -c, --class CLASS Specify device class\n"); + printf(" -d, --device DEVICE Specify device name\n"); + printf(" -v, --version Print version and exit\n"); +} + +int main(int argc, char *argv[]) { + int opt; + static struct option long_options[] = { + {"save", no_argument, NULL, 's'}, + {"restore", no_argument, NULL, 'r'}, + {"set", required_argument, NULL, 0}, + {"adjust", required_argument, NULL, 'a'}, + {"help", no_argument, NULL, 'h'}, + {"list", no_argument, NULL, 'l'}, + {"quiet", no_argument, NULL, 'q'}, + {"pretend", no_argument, NULL, 'p'}, + {"min-value", required_argument, NULL, 'n'}, + {"exponent", required_argument, NULL, 'e'}, + {"class", required_argument, NULL, 'c'}, + {"device", required_argument, NULL, 'd'}, + {"version", no_argument, NULL, 'v'}, + {NULL, 0, NULL, 0} + }; + + while ((opt = getopt_long(argc, argv, "sra:hlqpne:c:d:v", long_options, NULL)) != -1) { + switch (opt) { + case 's': + save_brightness(); + break; + case 'r': + restore_brightness(); + break; + case 0: // --set + if (optarg) { + int value = atoi(optarg); + set_brightness(value, 0); + } + break; + case 'a': + if (optarg) { + adjust_brightness(optarg); + } + break; + case 'h': + print_usage(argv[0]); + return EXIT_SUCCESS; + case 'l': + list_devices(); + break; + case 'q': + enable_quiet_mode(); + break; + case 'p': + enable_pretend_mode(); + break; + case 'n': + if (optarg) { + int min_value = atoi(optarg); + set_min_value(min_value); + } + break; + case 'e': + if (optarg) { + float exponent = atof(optarg); + set_exponent(exponent); + } + break; + case 'c': + if (optarg) { + set_class(optarg); + } + break; + case 'd': + if (optarg) { + set_device(optarg); + } + break; + case 'v': + printf("Version 1.0\n"); + return EXIT_SUCCESS; + default: + print_usage(argv[0]); + return EXIT_FAILURE; + } + } + + if (argc == 1) { + print_usage(argv[0]); + return EXIT_FAILURE; + } + + return EXIT_SUCCESS; +} diff --git a/brightness_control_two/src/utils.c b/brightness_control_two/src/utils.c new file mode 100644 index 0000000..d0edacb --- /dev/null +++ b/brightness_control_two/src/utils.c @@ -0,0 +1,29 @@ +#include "utils.h" + +#include +#include + +char *read_file_to_string(const char *filepath) { + FILE *file = fopen(filepath, "r"); + if (!file) { + perror("Failed to open file"); + exit(EXIT_FAILURE); + } + + fseek(file, 0, SEEK_END); + long length = ftell(file); + fseek(file, 0, SEEK_SET); + + char *content = malloc(length + 1); + if (!content) { + perror("Failed to allocate memory"); + fclose(file); + exit(EXIT_FAILURE); + } + + fread(content, 1, length, file); + content[length] = '\0'; + + fclose(file); + return content; +} diff --git a/brightness_control_two/src/utils.h b/brightness_control_two/src/utils.h new file mode 100644 index 0000000..4e16e88 --- /dev/null +++ b/brightness_control_two/src/utils.h @@ -0,0 +1,6 @@ +#ifndef UTILS_H +#define UTILS_H + +char *read_file_to_string(const char *filepath); + +#endif diff --git a/brightness_menu/Makefile b/brightness_menu/Makefile new file mode 100644 index 0000000..30b97e4 --- /dev/null +++ b/brightness_menu/Makefile @@ -0,0 +1,20 @@ +CC = gcc +CFLAGS = -Wall -Wextra -Iinclude `pkg-config --cflags gtk+-3.0` +LDFLAGS = -lncurses -lX11 -lXrandr `pkg-config --libs gtk+-3.0` + +SRC = $(wildcard src/*.c) +OBJ = $(patsubst src/%.c, build/%.o, $(SRC)) +TARGET = build/screen_control + +all: $(TARGET) + +$(TARGET): $(OBJ) + $(CC) -o $(TARGET) $(OBJ) $(LDFLAGS) + +build/%.o: src/%.c + $(CC) $(CFLAGS) -c $< -o $@ + +clean: + rm -f build/*.o $(TARGET) + +.PHONY: all clean diff --git a/brightness_menu/README.md b/brightness_menu/README.md new file mode 100644 index 0000000..e69de29 diff --git a/brightness_menu/build/brightness.o b/brightness_menu/build/brightness.o new file mode 100644 index 0000000000000000000000000000000000000000..dd45c47a7bb672b22984758e456b332ab0eaff1a GIT binary patch literal 3808 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 literal 0 HcmV?d00001 diff --git a/brightness_menu/build/display.o b/brightness_menu/build/display.o new file mode 100644 index 0000000000000000000000000000000000000000..fe98dc345fcdf38ff39fd563928897c4cb42c8aa GIT binary patch literal 3280 zcmb<-^>JfjWMqH=Mg}_u1P><4z!1QRU^{@B4h(z@ybPfpoliZQ-w1g0vVufCIuGpw z(fdKf4iNDIM4-!pY``tc#K6FSTb3EGEDK&)kQ$-^+ucGmuBuKmMWp49F7$D>!I70HX;EKD9VJbFdJLW~#wKR{Ubx&Votg2awM zV*7xd0uDYf3q9o6Q2mGMWDivC1cbR0P9A1p2u{sOO)gPL%u~oOD9OyvvtlsRQwUBj zN=?mEa4O17&nU@DEiPs-f(r(v7U$=bf|N2C>nQ}KrWK_YXD9?EmZUP6=qWho=j0bD zgrw#cq!uNXloq8jnCdCGR%Dhic;=NQ=47TotpNoEcI@u#Y^9*#lA4s6n5ST9q-UgO zplfKN31x!yh=5532F9u&2F3~jMrj^)jtPtm3^EK543d5eA{_Yy+L)Yq*_dANuya7< zY(U}+3=DfgG+cfMSRN#V4TDl93&Y3%*yNb8<_rb~W(IINLeav_z`!7cq#o=>1_lOs z1_lNJ6qOK;1`ct39O4!@#O!t4Y4oq>VD7l-7ItBw)A*I1$Geff6xPEE$xL<4ceda%x^md1f9%Dkw2S z;s+F;AQq@>0+m32{zHHgNRWYn0aWgQQUOd{6Dkf<&j;m0%1%u6?ofG{dSxg-4oah& zp9&R+sRyM8kWdYXz~Y`}s5nf$2b4bxN~4><5GoE+9}DG!ixe#8gG($11_qFNP#Faa zhvQIvAoJN77#LvU=b+-~>aRh?LFze>)IUQK2USHdb9g`*7HTgjUP_?qByfnUL&ZVn zb0L{;j3f?b;S~d6C3}kiNw!{W6HDh_fd za=L1Sii6Z6hjS-X9HbsOoIzzJC`i!N&p=X-9L|f8#6f1k++P7Q1RBmDvl5`{VCfAc z2EwXP@dh;Yrcm(~G;vp`cn6wzC{(-$O*|DUu7D;EwmB#|W0xD3+Jya`heQ>p<< zL?8|*kufkZfYLZfFDULo!V(~Yfq_AdfdO1=L6t#885mxH6vKH42D-2g0|NudOmg*` zLG1^{9l{m{hBr`)CLjw!{faDP2o=NdKgdxG3=A;+Ape7c1S-q`^S>R`egkAf85kI9 zpbi4X53&^0S>P}OiG#{7r;!*iheVSE^kt~Lg0Kf3Y-P=N@TMkoz)Ka|T5j>G>u zpbBCB0{I_QjzWdu{s*}SY8A{#F#Q86*Z@+%z`y`13qj=rx_*$E=y4A+paP_rfq`Ka eh=YWo#=%7d89?nRI2X=%0ktR%E&^eo>jwbt$Mnnq literal 0 HcmV?d00001 diff --git a/brightness_menu/build/main.o b/brightness_menu/build/main.o new file mode 100644 index 0000000000000000000000000000000000000000..21ac4ce3effadce383900b81dd1236252e3d3520 GIT binary patch literal 3408 zcmb<-^>JfjWMqH=Mg}_u1P><4z#zbdU^{@B4h*~uJPe^8oliZQ-zap}zVYZReQ@0M z4@mO0U32Y^^is~_u75y=z1H{Wc75Q{E#T433X=BdFQiM8cyx6s)ZC8nQ93xe!KzStk#J zTnRP+K|r0d4`inY)OfIJgpvudV2w!L^XLtI;L+>)#-sBZOwWFh3&DCkI$eKwbi4j= z+zAqL1RDlsdUQj)(Q68lfN6y4IRw&zWS&RoA&*{2D0Lq5=)4YA1|~o<-L5~7)b7$@ zWMJ4gfsug$W+=okNMM0AO*nZtv^X(6)k;CNSRq<0!01`Y-W z1_2b65Dq^Mad8~tps>Majxqzp-un<^A%16IV97#D@<9fG1hZ2s3ldWpQZkDRauO@!L8iwSgR?P1YF(!o@Gaz<)0$hzW^#JuFx_~gXm5@hAYAmy1Q zIjQJ^DXD3Rr8y<>#hFzwxfGDu#TohK@rgM(VD%t(L9+#eA(X+yzyQv@fBr*&1(G;3 z0|Nt0+yg4k!oa}5h9n+@B+iZ`o&XgGnGZ6D2g=Wa(jap{WdY3mek5^DBy(mXiG!+4 znEKU7;@n8;Hz0|F?1ZV`iX;xIEMek%pyD8R@*$aX5-JXIC#YAj6eiBq1WWFSl`gA05Wb-SL#F5SKMiQ4o zGG{uHxHOXZ93*j2Sr2o+0?1Je3=AN5f-scJ0BJ)Z#9`$;aykU5ht&%Vdc~EwC5cH4 zdc`G05IO_KDoV{s)GJA?C}Ge8=U2U?;$jB9qI?J^IX^cyHLrw0FE76&RnOfoRJXV! zF*%z-53DUUBR;JtF*g>S0P(Kn>gh z3KRwg22kDt=>_FUkQz|jfoL^Q+k^pB$AfqX{1~Jd!G*KXg>|5HJ}Aw?6)`X{5UU?l zPJzsXIumXLOusH%1i}ERg|HwbsGbLj89=yjQUGcoD1709P``rsAUz-&RNuqcAU+Hm zK=s4;FdAJgsGbLjp(}^!uYhTU(y;J{av4D7E4KJc02Pu93=FVx85DmYy&w$I3yVK& zc7x&ySDhsjcUjZ_hfq@|rst-n? G>jwZ_13|6; literal 0 HcmV?d00001 diff --git a/brightness_menu/build/refresh_rate.o b/brightness_menu/build/refresh_rate.o new file mode 100644 index 0000000000000000000000000000000000000000..2d9438128443f69e084316110c100ea83294fdeb GIT binary patch literal 4392 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 W99#rcmSEFA1M2=nxJn2ET|WS1s&)qe literal 0 HcmV?d00001 diff --git a/brightness_menu/build/screen_control b/brightness_menu/build/screen_control new file mode 100755 index 0000000000000000000000000000000000000000..87de6899dd7bebce1e878921d8dde7ce4b909f7f GIT binary patch literal 26984 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 amSI6z5DIj_4>tX +#include +#include +#include +#include "brightness.h" + +void adjust_brightness() { + FILE *brightness_file; + int brightness; + char path[] = "/sys/class/backlight/intel_backlight/brightness"; + char max_brightness_path[] = "/sys/class/backlight/intel_backlight/max_brightness"; + int max_brightness; + + brightness_file = fopen(path, "r+"); + if (brightness_file == NULL) { + mvprintw(4, 0, "Error: %s", strerror(errno)); + refresh(); + return; + } + + FILE *max_brightness_file = fopen(max_brightness_path, "r"); + if (max_brightness_file == NULL) { + mvprintw(4, 0, "Error: %s", strerror(errno)); + fclose(brightness_file); + refresh(); + return; + } + fscanf(max_brightness_file, "%d", &max_brightness); + fclose(max_brightness_file); + + fscanf(brightness_file, "%d", &brightness); + mvprintw(4, 0, "Current Brightness: %d", brightness); + mvprintw(5, 0, "Max Brightness: %d", max_brightness); + mvprintw(6, 0, "Enter new brightness (0-%d): ", max_brightness); + + refresh(); + echo(); + scanw("%d", &brightness); + noecho(); + + if (brightness < 0 || brightness > max_brightness) { + mvprintw(7, 0, "Invalid brightness value"); + } else { + rewind(brightness_file); + fprintf(brightness_file, "%d", brightness); + fflush(brightness_file); + mvprintw(7, 0, "Brightness set to %d", brightness); + } + + fclose(brightness_file); + refresh(); + getch(); +} diff --git a/brightness_menu/src/brightness.o b/brightness_menu/src/brightness.o new file mode 100644 index 0000000000000000000000000000000000000000..dd45c47a7bb672b22984758e456b332ab0eaff1a GIT binary patch literal 3808 zcmb<-^>JfjWMqH=Mg}_u1P><4z_5TD!FB*M9T<2Sco;%GI-hzpzFEM)z~He%zqqnk zKRGASV^?vpeo|s`c8*7<>jsa`&>bH8GSf3k^fU8HJocyN#6#su4|sIep77iOmP;zi z^xT=AQIeNhT+HCp>3YGZ)Axo)XKTU#|NlKYr&fTe(gu&t+71thj@-lwk6rOeMIh~Y z9-XceJUT;X9Cuv+GQgwPb%RH*D9EKAo!2}%kH3I0U4M8q*ZyEAbq4dh8Q>BJJ$hLo zN)GJ<(fe5#7#MbdSYVYN-B4MGK`*747#KWyA&$dl%?FR>+7Aq+{$S0dSmXKw?pQP{ zmotK_oSFj)h;G*p9=*IE*LifF^XNQ|>`>Paa1(k%-*|Mp{=lKM+x1N+0dIG=f~><- z1quv=ow!u7;R`}=$awU+zVYZh1`m5AkAUU7UEj1GsNn4meFL$>@=%=uTro7F*imeG z9SQa^G+w*$1^|jmY=MDlG_rEE^nk`adALZM!L_I;zsO2KwV0uZK{bWJxwNP#HLpa$ z36fq@i;JxkR8tsy6D!b#T=Pm&ixl!w%N3w$JGHo2LBl{-HAT}(fx$DcEHNiD1zD~v zF{d<@0b#I0acYS|Nj}JU26ty?D+LXg)TGSBJOx7|JtI8>T|*O1D3d`1l!h1>7#OR9 z7#J%A7^QjGIVLbNFvu`KFi2X0nSp`9kx!tF$(fgpS(urJodYC{6@$tS7KV@iu}Lyx zEm;^Cm>EFH2~`Il0|SE)l6tTk7#J877#J7?P?dstYB{;!q!eLp&0P zcmfXb3LN4EIK<0vh}Yr}Z^0qngF}2W4sixV($h<3NKDBpEiQo-wV?7fEx#Z&k0Cxj zwWugBKRzcvIk6-&KaZifq$m}X>=|;)3W_rGO3E3EOHzuHix|p_Qqzi3i!&I~l5_Hl zQyJppGmG<+EiL2Iijx!b(ilKwIYVB4YH~(CLs4pZW?l+I8rX<5hP1St(&7w;^7Pb_ z&@xw^spxh1UogDVJ4C|NG;6#6;N?>b9O+*(akvm6^E$@l^-B`Z$rgF>XH5X z3Mvj$uL@EODhELV3=9nD>II0jN31;WHaa z98^xi%wGu=2T>q%VD8xo5`dZ`h-B|kByk}m@rzJ#5Ct+PAL^bLAOWa3$nN=qBo49@ z=APeBaS(+Z&deY~q2?fmGZ$1GUA+)g92D=uNbUsHHz22h)PpdH4aR!KmANH}Nep_$ zB}EWA1I8*!%}LZNNv$Yh&`U`yNo3GVDlTTwE6Rs(lJj$OQ}ap~^z!mcQuW;ZLUoHv z5|gtT^uXFuGvd>V5_40*c2I!;xgV6&L1hNAaiIDS#D~?ZAT|ht)PiUjmWGBQOg&6| z2h_j}P=GNoFo41sq!$!tAT<&of`NenR4;?Xp}`9kWnhRv7l6uu)IynHN{4}g0c0k+ za$@xxg7P%9oCO;QC1CnHpnMpGZoef|zX41Elzsqp5GZ`1LSPD}A4WSt^@Amm323+> z3xU`$eIPanheP$Fq&<)XR6nd70ttaID6Bv<3 +#include +#include +#include "color_temperature.h" + +void adjust_color_temperature() { + mvprintw(4, 0, "Enter the desired color temperature (in Kelvin, e.g., 6500): "); + refresh(); + + echo(); + int color_temp; + scanw("%d", &color_temp); + noecho(); + + char command[128]; + snprintf(command, sizeof(command), "xcalib -co %d", color_temp); + + int result = system(command); + if (result == -1) { + mvprintw(6, 0, "Failed to set color temperature"); + } else { + mvprintw(6, 0, "Color temperature set to %dK", color_temp); + } + refresh(); + getch(); +} diff --git a/brightness_menu/src/display.c b/brightness_menu/src/display.c new file mode 100644 index 0000000..5481848 --- /dev/null +++ b/brightness_menu/src/display.c @@ -0,0 +1,49 @@ +#include +#include +#include "display.h" +#include "brightness.h" +#include "resolution.h" +#include "refresh_rate.h" +#include "color_temperature.h" + +void display_main_screen() { + int option; + mvprintw(0, 0, "Select an option:"); + mvprintw(1, 0, "1. Screen Brightness"); + mvprintw(2, 0, "2. Screen Resolution"); + mvprintw(3, 0, "3. Refresh Rate"); + mvprintw(4, 0, "4. Color Temperature"); + mvprintw(5, 0, "5. Exit"); + + refresh(); + option = getch() - '0'; + + handle_option(option); +} + +void handle_option(int option) { + switch(option) { + case 1: + adjust_brightness(); + break; + case 2: + adjust_resolution(); + break; + case 3: + adjust_refresh_rate(); + break; + case 4: + adjust_color_temperature(); + break; + case 5: + endwin(); + exit(0); + default: + mvprintw(6, 0, "Invalid option"); + refresh(); + getch(); + break; + } + display_main_screen(); +} + diff --git a/brightness_menu/src/display.o b/brightness_menu/src/display.o new file mode 100644 index 0000000000000000000000000000000000000000..c3c71786110e2c3f9546fbf918b02dec09da6257 GIT binary patch literal 2368 zcmb<-^>JfjWMqH=Mg}_u1P><4z`($UU^{@B4h*~uJPe^8oliZQ-w1g0vVufCIuGpw z(fdKf4iNDIM4-!pY``tc#K6FSB-;%&`8dQVRBrPNgHG2!-L8K+A<`309)>xov-VGO z?H|Sxj^^4wOeK7;r4eSnwgsC7b|sjF?m!lNPMCl&Xu`?E!Kpc^$t4Pjc?$UjC7Jno zRt$!E3c<-msi}DiPDPpN86|nC#l;LpdJ3);nI#OKd1Z+?nJG}k3=Hnh&Q=N{ z=4E5*<6-B3$k~9z85kJyK{Q-G3oH*3!iGUH!@}_KKQ=jL>?wnRnE@O_C|bA~7#M_* z)Pvo~z`!8Sz`!7Yq7uTM;vn_xNbW3wileKq zfr^9Fb0DejK@#Ug65oU*&V?kt6GiQhy364ss7DJhh?xhfo^i9^~)@ zmktaJ3?TK${{4WY9@)RYk;Fk}!Q7(&6$hCE!cZ;)EM7ojAPh^l40^?txh08740^>S zMG!gz#wtq9Nz^Mzttes8OGzwAWY9}0E@sdx%7<{0^K)}k^GX=>^72bk_1yhJb&E?9 zld~E0z}iwX;?s%}b79d4a|YQo$X}o`0~9vMhQR#=l0=d~<1$D?(=bduOz8qpEis3v216^2$fq?;JCb{|zq4tB~ z4q*$zemi7As9IzpOQ@IuvLFKkLj%;IpzuYOf(pY+Rwt-_WHli60+>P&2MMDKheP$F zyC0@M0!c532?{F^4Z}e=;x7Y~i5M6dVEzKdA4o3Hut tl(#|o30*&^j6jb&kbVQGU^a+@grUa4MFg>=9gyS +#include +#include +#include +#include +#include "display.h" + +void run_cli(); +void run_gui(); + +int main(int argc, char *argv[]) { + int opt; + int gui_mode = 0; + + // Parse command-line arguments + while ((opt = getopt(argc, argv, "g")) != -1) { + switch (opt) { + case 'g': + gui_mode = 1; + break; + default: + fprintf(stderr, "Usage: %s [-g]\n", argv[0]); + exit(EXIT_FAILURE); + } + } + + if (gui_mode) { + run_gui(argc, argv); + } else { + run_cli(); + } + + return 0; +} + +void run_cli() { + initscr(); + cbreak(); + noecho(); + keypad(stdscr, TRUE); + + display_main_screen(); + + endwin(); +} + +void run_gui(int argc, char *argv[]) { + GtkWidget *window; + + gtk_init(&argc, &argv); + + window = gtk_window_new(GTK_WINDOW_TOPLEVEL); + g_signal_connect(window, "destroy", G_CALLBACK(gtk_main_quit), NULL); + gtk_window_set_title(GTK_WINDOW(window), "Screen Control GUI"); + gtk_window_set_default_size(GTK_WINDOW(window), 400, 300); + + gtk_widget_show_all(window); + + gtk_main(); +} diff --git a/brightness_menu/src/main.o b/brightness_menu/src/main.o new file mode 100644 index 0000000000000000000000000000000000000000..cc6eae778b1d12b4a8c2a09a9f78d03986eb61b2 GIT binary patch literal 1616 zcmb<-^>JfjWMqH=Mg}_u1P><4z!1QUU^{@B4h%dD+zg=}oljqY_z1$In-wIm4`hr- z=W(#a4v+|#1t!4U*uxC&&dyc}8ZN0xnTdG{hDLfudIq|NCYn$tNRJ4JU|?WitO{aa ztPo(7=3(cUz{tQL!vMh`X+BW(gsQ zgY9BqVBlq7U=YA!h$s$mkbAMISH_`U3x~KN4sll;;taWonR$B2V2U9#FSDdLxriY- zsVFrun;|bhH8~@np|~UkB$%CAS&*2*kdj$kkds&$57HN3oLrQen#Yiumr|aY2lg#E zY8e<9SfKdNe+b|L%RmdnvoipU;u?7NG~XiK|&HBf`NfS z4V2dy7#NVUJ6NU`OkxrsGmu4f7#J8pW|FHPl)gb`8Xz0Wz`y{r9~3^wQXsV;K8&`4 zx*sHljOQYAkk~MNFd=`aerRyPgc%k +#include +#include +#include +#include +#include "refresh_rate.h" + +void list_refresh_rates(XRRScreenResources *res, XRRCrtcInfo *crtc_info) { + mvprintw(5, 0, "Available Refresh Rates:"); + int rate_count = 0; + for (int i = 0; i < res->nmode; i++) { + XRRModeInfo mode = res->modes[i]; + for (int j = 0; j < crtc_info->noutput; j++) { + if (crtc_info->outputs[j] == mode.id) { + double refresh_rate = (double)mode.dotClock / (mode.hTotal * mode.vTotal); + mvprintw(6 + rate_count, 0, "%d: %.2f Hz", rate_count, refresh_rate); + rate_count++; + } + } + } + refresh(); +} + +void set_refresh_rate() { + // Placeholder for setting the refresh rate based on selected index + mvprintw(7, 0, "Setting refresh rate feature coming soon..."); + refresh(); +} + +void adjust_refresh_rate() { + Display *dpy = XOpenDisplay(NULL); + if (dpy == NULL) { + mvprintw(4, 0, "Unable to open X display"); + refresh(); + getch(); + return; + } + + Window root = DefaultRootWindow(dpy); + XRRScreenResources *res = XRRGetScreenResources(dpy, root); + if (res == NULL) { + mvprintw(4, 0, "Unable to get screen resources"); + XCloseDisplay(dpy); + refresh(); + getch(); + return; + } + + XRRCrtcInfo *crtc_info = XRRGetCrtcInfo(dpy, res, res->crtcs[0]); + if (crtc_info == NULL) { + mvprintw(4, 0, "Unable to get CRTC info"); + XRRFreeScreenResources(res); + XCloseDisplay(dpy); + refresh(); + getch(); + return; + } + + list_refresh_rates(res, crtc_info); + + mvprintw(6 + res->nmode, 0, "Enter the index of the desired refresh rate: "); + refresh(); + + echo(); + int rate_index; + scanw("%d", &rate_index); + noecho(); + + set_refresh_rate(); + + XRRFreeCrtcInfo(crtc_info); + XRRFreeScreenResources(res); + XCloseDisplay(dpy); + + getch(); +} diff --git a/brightness_menu/src/resolution.c b/brightness_menu/src/resolution.c new file mode 100644 index 0000000..d567a3c --- /dev/null +++ b/brightness_menu/src/resolution.c @@ -0,0 +1,66 @@ +#include +#include +#include +#include +#include +#include "resolution.h" + +void list_resolutions(XRRScreenResources *res) { + mvprintw(5, 0, "Available Resolutions:"); + for (int i = 0; i < res->nmode; i++) { + XRRModeInfo mode = res->modes[i]; + mvprintw(6 + i, 0, "%d: %dx%d", i, mode.width, mode.height); + } + refresh(); +} + +void set_resolution(Display *dpy, Window root, XRRScreenResources *res, int mode_index) { + if (mode_index < 0 || mode_index >= res->nmode) { + mvprintw(7 + res->nmode, 0, "Invalid mode index"); + return; + } + + XRRModeInfo mode = res->modes[mode_index]; + XRRSetScreenSize(dpy, root, mode.width, mode.height, mode.width, mode.height); + XRRSetCrtcConfig(dpy, res, res->crtcs[0], CurrentTime, 0, 0, mode.id, RR_Rotate_0, NULL, 0); + + mvprintw(7 + res->nmode, 0, "Resolution set to %dx%d", mode.width, mode.height); + refresh(); +} + +void adjust_resolution() { + Display *dpy = XOpenDisplay(NULL); + if (dpy == NULL) { + mvprintw(4, 0, "Unable to open X display"); + refresh(); + getch(); + return; + } + + Window root = DefaultRootWindow(dpy); + XRRScreenResources *res = XRRGetScreenResources(dpy, root); + if (res == NULL) { + mvprintw(4, 0, "Unable to get screen resources"); + XCloseDisplay(dpy); + refresh(); + getch(); + return; + } + + list_resolutions(res); + + mvprintw(6 + res->nmode, 0, "Enter the index of the desired resolution: "); + refresh(); + + echo(); + int mode_index; + scanw("%d", &mode_index); + noecho(); + + set_resolution(dpy, root, res, mode_index); + + XRRFreeScreenResources(res); + XCloseDisplay(dpy); + + getch(); +} diff --git a/mpvd/build/Install b/mpvd/build/Install new file mode 100644 index 0000000..cfffc91 --- /dev/null +++ b/mpvd/build/Install @@ -0,0 +1 @@ +libasound2-dev diff --git a/mpvd/build/Makefile b/mpvd/build/Makefile new file mode 100644 index 0000000..f88e318 --- /dev/null +++ b/mpvd/build/Makefile @@ -0,0 +1,19 @@ +CC = gcc +CFLAGS = -I../include -Wall -g +LDFLAGS = -lasound -lncurses # Added -lncurses for ncurses functions +OBJDIR = ../obj +SRCDIR = ../src +INCLUDEDIR = ../include + +OBJS = $(OBJDIR)/main.o $(OBJDIR)/audio.o $(OBJDIR)/ui.o $(OBJDIR)/dir.o + +all: mpvd + +mpvd: $(OBJS) + $(CC) $(CFLAGS) -o mpvd $(OBJS) $(LDFLAGS) + +$(OBJDIR)/%.o: $(SRCDIR)/%.c + $(CC) $(CFLAGS) -c $< -o $@ + +clean: + rm -f $(OBJDIR)/*.o mpvd diff --git a/mpvd/build/mpvd b/mpvd/build/mpvd new file mode 100755 index 0000000000000000000000000000000000000000..dee475dfa4b8d7f7dd8b39cfd65a6d81c276e0c9 GIT binary patch literal 36472 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 literal 0 HcmV?d00001 diff --git a/mpvd/include/audio.h b/mpvd/include/audio.h new file mode 100644 index 0000000..40ebd25 --- /dev/null +++ b/mpvd/include/audio.h @@ -0,0 +1,6 @@ +#ifndef AUDIO_H +#define AUDIO_H + +void play_audio(const char *file_path); + +#endif diff --git a/mpvd/include/dir.h b/mpvd/include/dir.h new file mode 100644 index 0000000..d7c8d3b --- /dev/null +++ b/mpvd/include/dir.h @@ -0,0 +1,10 @@ +#ifndef DIR_H +#define DIR_H + +#define MAX_PATH_LEN 512 // Declare MAX_PATH_LEN for use across files + +char* get_music_directory(); +char** load_songs(int *count, const char *music_dir); +void navigate_directory(const char *dir, char **songs, int *song_count); // Declare navigate_directory + +#endif diff --git a/mpvd/include/ui.h b/mpvd/include/ui.h new file mode 100644 index 0000000..0697565 --- /dev/null +++ b/mpvd/include/ui.h @@ -0,0 +1,14 @@ +#ifndef UI_H +#define UI_H + +#include + +void init_ncurses(); +void end_ncurses(); +void display_songs(WINDOW *win, char **songs, int song_count, int selected); +void display_controls(WINDOW *control_win, int is_playing); + +// Update handle_input to accept current_directory +void handle_input(int ch, char **songs, int *selected_song, int *song_count, WINDOW *song_win, WINDOW *control_win, int *is_playing, char *current_directory); + +#endif diff --git a/mpvd/obj/audio.o b/mpvd/obj/audio.o new file mode 100644 index 0000000000000000000000000000000000000000..76e00a48f32041687d5379bb708e9037db9e8b17 GIT binary patch literal 14136 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 literal 0 HcmV?d00001 diff --git a/mpvd/src/audio.c b/mpvd/src/audio.c new file mode 100644 index 0000000..9742397 --- /dev/null +++ b/mpvd/src/audio.c @@ -0,0 +1,41 @@ +#include "audio.h" +#include + +void play_audio(const char *file_path) { + snd_pcm_t *handle; + snd_pcm_hw_params_t *params; + unsigned int rate = 44100; + int dir; + snd_pcm_uframes_t frames; + int rc; + + // Open PCM device for playback + rc = snd_pcm_open(&handle, "default", SND_PCM_STREAM_PLAYBACK, 0); + if (rc < 0) { + fprintf(stderr, "Unable to open PCM device: %s\n", snd_strerror(rc)); + return; + } + + snd_pcm_hw_params_alloca(¶ms); + snd_pcm_hw_params_any(handle, params); + snd_pcm_hw_params_set_access(handle, params, SND_PCM_ACCESS_RW_INTERLEAVED); + snd_pcm_hw_params_set_format(handle, params, SND_PCM_FORMAT_S16_LE); + snd_pcm_hw_params_set_channels(handle, params, 2); + snd_pcm_hw_params_set_rate_near(handle, params, &rate, &dir); + snd_pcm_hw_params(handle, params); + + // Simulate audio playback (replace this with actual file reading and playback) + unsigned char *buffer = malloc(128 * 4); + memset(buffer, 0, 128 * 4); + + for (int i = 0; i < 100; ++i) { + rc = snd_pcm_writei(handle, buffer, 128); + if (rc == -EPIPE) { + snd_pcm_prepare(handle); + } + } + + free(buffer); + snd_pcm_drain(handle); + snd_pcm_close(handle); +} diff --git a/mpvd/src/dir.c b/mpvd/src/dir.c new file mode 100644 index 0000000..56dbea3 --- /dev/null +++ b/mpvd/src/dir.c @@ -0,0 +1,49 @@ +#include +#include +#include +#include +#include +#include +#include "dir.h" + +char* get_music_directory() { + struct passwd *pw = getpwuid(getuid()); + const char *homedir = pw->pw_dir; + char *music_dir = malloc(strlen(homedir) + strlen("/Music/mpvd") + 1); + strcpy(music_dir, homedir); + strcat(music_dir, "/Music/mpvd"); + return music_dir; +} + +char** load_songs(int *count, const char *music_dir) { + DIR *d; + struct dirent *dir; + d = opendir(music_dir); + if (!d) { + perror("Failed to open music directory"); + exit(1); + } + + char **songs = malloc(sizeof(char*) * 100); + int index = 0; + + while ((dir = readdir(d)) != NULL) { + if (dir->d_type == DT_REG) { + songs[index] = strdup(dir->d_name); + index++; + } else if (dir->d_type == DT_DIR && strcmp(dir->d_name, ".") != 0 && strcmp(dir->d_name, "..") != 0) { + char dir_name[512]; + snprintf(dir_name, sizeof(dir_name), "%s/", dir->d_name); + songs[index] = strdup(dir_name); // Append '/' to indicate a directory + index++; + } + } + closedir(d); + *count = index; + return songs; +} + +void navigate_directory(const char *dir, char **songs, int *song_count) { + free(songs); // Free old song list + songs = load_songs(song_count, dir); // Load new song list +} diff --git a/mpvd/src/main.c b/mpvd/src/main.c new file mode 100644 index 0000000..ef0295d --- /dev/null +++ b/mpvd/src/main.c @@ -0,0 +1,55 @@ +// src/main.c + +#include +#include "audio.h" +#include "ui.h" +#include "dir.h" + +int main() { + // Initialize ncurses + initscr(); + noecho(); + cbreak(); + curs_set(FALSE); + keypad(stdscr, TRUE); + + // Initialize UI and audio + init_ui(); + init_audio(); + + // Load the directory contents + load_directory("/Music/mpvd"); + + int ch; + while ((ch = getch()) != 'q') { + // Handle navigation and controls + switch (ch) { + case KEY_UP: + navigate_up(); + break; + case KEY_DOWN: + navigate_down(); + break; + case '\n': // Enter key + select_item(); + break; + case ' ': // Spacebar + toggle_playback(); + break; + case KEY_LEFT: + decrease_volume(); + break; + case KEY_RIGHT: + increase_volume(); + break; + } + update_ui(); + } + + // Cleanup + cleanup_ui(); + cleanup_audio(); + endwin(); + + return 0; +} diff --git a/mpvd/src/mpvd.c b/mpvd/src/mpvd.c new file mode 100644 index 0000000..a51cd1f --- /dev/null +++ b/mpvd/src/mpvd.c @@ -0,0 +1,282 @@ +#include +#include +#include +#include +#include +#include +#include + +#define MAX_SONGS 100 +#define MAX_PATH_LEN 512 + +// Function declarations +void init_ncurses(); +void end_ncurses(); +void display_songs(WINDOW *win, char **songs, int song_count, int selected); +char** load_songs(int *count, const char *music_dir); +char* get_music_directory(); +void display_controls(WINDOW *control_win, int is_playing); +void play_audio(const char *file_path); +void stop_audio(); +void add_to_queue(const char *song); +void play_next_in_queue(); +void navigate_directory(const char *dir, char **songs, int *song_count); + +// Global variables +char *queue[MAX_SONGS]; +int queue_size = 0; +int queue_position = 0; +int is_playing = 0; +char current_directory[MAX_PATH_LEN]; + +int main() { + int song_count; + char **songs; + int selected_song = 0; + int ch; + + // Initialize music directory + strcpy(current_directory, get_music_directory()); + songs = load_songs(&song_count, current_directory); + + // Initialize ncurses + init_ncurses(); + + // Set up windows + int half_height = LINES / 2; + int width = COLS; + + WINDOW *song_win = newwin(half_height, width, 0, 0); + WINDOW *control_win = newwin(half_height, width, half_height, 0); + + // Display initial songs and controls + display_songs(song_win, songs, song_count, selected_song); + display_controls(control_win, is_playing); + + // Main loop to handle input + while ((ch = getch()) != 'q') { + switch (ch) { + case KEY_UP: + case 'k': + if (selected_song > 0) selected_song--; + break; + case KEY_DOWN: + case 'j': + if (selected_song < song_count - 1) selected_song++; + break; + case '\n': + if (songs[selected_song][strlen(songs[selected_song]) - 1] == '/') { + // Enter directory + char new_dir[MAX_PATH_LEN]; + snprintf(new_dir, MAX_PATH_LEN, "%s/%s", current_directory, songs[selected_song]); + navigate_directory(new_dir, songs, &song_count); + selected_song = 0; // Reset selection + } else { + if (is_playing) { + // Add to queue if something is playing + add_to_queue(songs[selected_song]); + } else { + // Play selected song immediately + char song_path[MAX_PATH_LEN]; + snprintf(song_path, MAX_PATH_LEN, "%s/%s", current_directory, songs[selected_song]); + play_audio(song_path); + is_playing = 1; + } + } + break; + case ' ': // Pause/play functionality + if (is_playing) { + stop_audio(); + is_playing = 0; + } else { + play_next_in_queue(); + is_playing = 1; + } + break; + case KEY_RIGHT: + case 'l': // Fast-forward (skipping in the queue) + play_next_in_queue(); + break; + case KEY_LEFT: + case 'h': // Go back in the queue (not implemented yet) + break; + case KEY_NPAGE: + case 'L': // Skip track + play_next_in_queue(); + break; + case KEY_PPAGE: + case 'H': // Go back track (not implemented yet) + break; + } + display_songs(song_win, songs, song_count, selected_song); // Update song selection + display_controls(control_win, is_playing); // Update controls display + } + + // Clean up ncurses + end_ncurses(); + return 0; +} + +void init_ncurses() { + initscr(); + noecho(); + cbreak(); + keypad(stdscr, TRUE); +} + +void end_ncurses() { + endwin(); +} + +char* get_music_directory() { + struct passwd *pw = getpwuid(getuid()); + const char *homedir = pw->pw_dir; + char *music_dir = malloc(strlen(homedir) + strlen("/Music/mpvd") + 1); + strcpy(music_dir, homedir); + strcat(music_dir, "/Music/mpvd"); + return music_dir; +} + +char** load_songs(int *count, const char *music_dir) { + DIR *d; + struct dirent *dir; + d = opendir(music_dir); + if (!d) { + perror("Failed to open music directory"); + exit(1); + } + + char **songs = malloc(sizeof(char*) * MAX_SONGS); + int index = 0; + + while ((dir = readdir(d)) != NULL) { + if (dir->d_type == DT_REG) { + songs[index] = strdup(dir->d_name); + index++; + } else if (dir->d_type == DT_DIR) { + if (strcmp(dir->d_name, ".") != 0 && strcmp(dir->d_name, "..") != 0) { + char dir_name[MAX_PATH_LEN]; + snprintf(dir_name, MAX_PATH_LEN, "%s/", dir->d_name); + songs[index] = strdup(dir_name); + index++; + } + } + } + closedir(d); + *count = index; + return songs; +} + +void display_songs(WINDOW *win, char **songs, int song_count, int selected) { + werase(win); + box(win, 0, 0); + mvwprintw(win, 0, 1, "Select a song or directory to play/open (Up/Down to navigate, Enter to select)"); + + for (int i = 0; i < song_count; i++) { + if (i == selected) + wattron(win, A_REVERSE); + mvwprintw(win, i + 1, 1, "%s", songs[i]); + wattroff(win, A_REVERSE); + } + wrefresh(win); +} + +void display_controls(WINDOW *control_win, int is_playing) { + werase(control_win); + box(control_win, 0, 0); + + // Display Unicode controls for play/pause, forward, and back + if (is_playing) { + mvwprintw(control_win, 1, 1, "⏸ Pausing"); + } else { + mvwprintw(control_win, 1, 1, "⏵ Playing"); + } + mvwprintw(control_win, 1, 20, "⏪ Previous"); + mvwprintw(control_win, 1, 40, "⏩ Next"); + wrefresh(control_win); +} + +void navigate_directory(const char *dir, char **songs, int *song_count) { + strcpy(current_directory, dir); + songs = load_songs(song_count, current_directory); +} + +void add_to_queue(const char *song) { + if (queue_size < MAX_SONGS) { + queue[queue_size] = strdup(song); + queue_size++; + } +} + +void play_next_in_queue() { + if (queue_position < queue_size) { + char song_path[MAX_PATH_LEN]; + snprintf(song_path, MAX_PATH_LEN, "%s/%s", current_directory, queue[queue_position]); + play_audio(song_path); + queue_position++; + } else { + // Queue is empty + stop_audio(); + } +} + +void play_audio(const char *file_path) { + snd_pcm_t *handle; + snd_pcm_hw_params_t *params; + unsigned int rate = 44100; // Default sample rate + int dir; + snd_pcm_uframes_t frames; + int rc; + + // Open PCM device for playback + rc = snd_pcm_open(&handle, "default", SND_PCM_STREAM_PLAYBACK, 0); + if (rc < 0) { + fprintf(stderr, "Unable to open PCM device: %s\n", snd_strerror(rc)); + return; + } + + // Allocate a hardware parameters object + snd_pcm_hw_params_alloca(¶ms); + + // Fill it in with default values + snd_pcm_hw_params_any(handle, params); + + // Set the desired hardware parameters + snd_pcm_hw_params_set_access(handle, params, SND_PCM_ACCESS_RW_INTERLEAVED); + snd_pcm_hw_params_set_format(handle, params, SND_PCM_FORMAT_S16_LE); + snd_pcm_hw_params_set_channels(handle, params, 2); + snd_pcm_hw_params_set_rate_near(handle, params, &rate, &dir); + + // Write the parameters to the driver + rc = snd_pcm_hw_params(handle, params); + if (rc < 0) { + fprintf(stderr, "Unable to set HW parameters: %s\n", snd_strerror(rc)); + return; + } + + // Playback the audio (This is a simplified example, you would actually need to read the file) + unsigned char *buffer = malloc(128 * 4); + memset(buffer, 0, 128 * 4); + + for (int i = 0; i < 100; ++i) { + rc = snd_pcm_writei(handle, buffer, 128); + if (rc == -EPIPE) { + // EPIPE means underrun + fprintf(stderr, "Underrun occurred\n"); + snd_pcm_prepare(handle); + } else if (rc < 0) { + fprintf(stderr, "Error writing to PCM device: %s\n", snd_strerror(rc)); + } + } + + // Cleanup + free(buffer); + snd_pcm_drain(handle); + snd_pcm_close(handle); +} + +void stop_audio() { + // Placeholder for stopping audio playback + mvprintw(LINES - 1, 0, "Audio stopped."); + refresh(); +} diff --git a/mpvd/src/ui.c b/mpvd/src/ui.c new file mode 100644 index 0000000..c222a0c --- /dev/null +++ b/mpvd/src/ui.c @@ -0,0 +1,87 @@ +#include +#include +#include +#include "ui.h" +#include "dir.h" +#include "audio.h" + +void init_ncurses() { + initscr(); + noecho(); + cbreak(); + keypad(stdscr, TRUE); +} + +void end_ncurses() { + endwin(); +} + +void display_songs(WINDOW *win, char **songs, int song_count, int selected) { + werase(win); + box(win, 0, 0); + mvwprintw(win, 0, 1, "Select a song or directory to play/open"); + + for (int i = 0; i < song_count; i++) { + if (i == selected) + wattron(win, A_REVERSE); + mvwprintw(win, i + 1, 1, "%s", songs[i]); + wattroff(win, A_REVERSE); + } + wrefresh(win); +} + +void display_controls(WINDOW *control_win, int is_playing, const char *current_song, int volume) { + werase(control_win); + box(control_win, 0, 0); + + // Display current song and volume + mvwprintw(control_win, 1, 1, "Now Playing: %s", current_song); + mvwprintw(control_win, 2, 1, "Volume: %d%%", volume); + + // Display if song is playing or paused + if (is_playing) { + mvwprintw(control_win, 1, COLS - 10, "⏸ Paused"); + } else { + mvwprintw(control_win, 1, COLS - 10, "⏵ Playing"); + } + wrefresh(control_win); +} + +void handle_input(int ch, char **songs, int *selected_song, int *song_count, WINDOW *song_win, WINDOW *control_win, int *is_playing, char *current_directory, char *current_song, int *volume) { + switch (ch) { + case KEY_UP: + case 'k': + if (*selected_song > 0) (*selected_song)--; + break; + case KEY_DOWN: + case 'j': + if (*selected_song < *song_count - 1) (*selected_song)++; + break; + case '\n': // Handle directory or song selection + if (songs[*selected_song][strlen(songs[*selected_song]) - 1] == '/') { + char new_dir[MAX_PATH_LEN]; + snprintf(new_dir, MAX_PATH_LEN, "%s/%s", current_directory, songs[*selected_song]); + navigate_directory(new_dir, songs, song_count); + strcpy(current_directory, new_dir); // Update current directory + *selected_song = 0; // Reset selection after entering directory + } else { + char song_path[MAX_PATH_LEN]; + snprintf(song_path, MAX_PATH_LEN, "%s/%s", current_directory, songs[*selected_song]); + play_audio(song_path); + strcpy(current_song, songs[*selected_song]); // Update current song + *is_playing = 1; + } + break; + case ' ': // Pause/Play toggle + *is_playing = !(*is_playing); + break; + case KEY_RIGHT: // Increase volume + if (*volume < 100) (*volume)++; + break; + case KEY_LEFT: // Decrease volume + if (*volume > 0) (*volume)--; + break; + } + display_songs(song_win, songs, *song_count, *selected_song); + display_controls(control_win, *is_playing, current_song, *volume); +} diff --git a/ncursescalander/backup/Makefile b/ncursescalander/backup/Makefile new file mode 100644 index 0000000..d9d6f3b --- /dev/null +++ b/ncursescalander/backup/Makefile @@ -0,0 +1,33 @@ +# Compiler and Flags +CC = gcc +CFLAGS = -Wall -Wextra -std=c11 -g +LDFLAGS = -lncurses + +# Source Files +SRCS = main.c +OBJS = $(SRCS:.c=.o) + +# Output Binary +TARGET = calendar + +# Default Target +all: $(TARGET) + +# Build Target +$(TARGET): $(OBJS) + $(CC) $(CFLAGS) -o $(TARGET) $(OBJS) $(LDFLAGS) + +# Object Files +%.o: %.c + $(CC) $(CFLAGS) -c $< -o $@ + +# Clean Target +clean: + rm -f $(OBJS) $(TARGET) + +# Run Target +run: $(TARGET) + ./$(TARGET) + +# Phony Targets +.PHONY: all clean run diff --git a/ncursescalander/backup/calendar b/ncursescalander/backup/calendar new file mode 100755 index 0000000000000000000000000000000000000000..341d78db16eb3b88d693ff8754eb601e7b33e1e8 GIT binary patch literal 27536 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 +#include +#include + +#define MAX_TITLE_LEN 50 +#define MAX_CALENDAR_LEN 30 +#define MAX_NOTES_LEN 256 + +void draw_calendar(int month, int year, int selected_day); +void draw_day_view(int *day, int *month, int *year); +void open_add_event_tui(); +void open_repeat_tui(); + +int main() { + int ch, month, year, day = 1; + time_t now; + struct tm *local; + + // Initialize ncurses + initscr(); + cbreak(); + noecho(); + keypad(stdscr, TRUE); + start_color(); + init_pair(1, COLOR_RED, COLOR_BLACK); // Red color pair for the current time + + // Get current date + now = time(NULL); + local = localtime(&now); + month = local->tm_mon + 1; + year = local->tm_year + 1900; + day = local->tm_mday; + + // Main loop + while ((ch = getch()) != 'q') { + bool redraw = false; + switch (ch) { + case KEY_LEFT: + case 'j': + if (day > 1) { + day--; + redraw = true; + } + break; + case KEY_RIGHT: + case 'k': + if (day < 31) { // Simplified for demo purposes + day++; + redraw = true; + } + break; + case 'a': // 'a' for "Add Event" + open_add_event_tui(); + redraw = true; + break; + case '\n': // Enter key to open the day view + draw_day_view(&day, &month, &year); + redraw = true; + break; + } + + if (redraw) { + clear(); + mvprintw(0, 0, "Calendar View - Press 'a' to Add Event"); + draw_calendar(month, year, day); + refresh(); + } + } + + // End ncurses mode + endwin(); + return 0; +} + +void draw_calendar(int month, int year, int selected_day) { + mvprintw(1, 0, "Month: %d, Year: %d", month, year); + mvprintw(2, 0, "Su Mo Tu We Th Fr Sa"); + + // Placeholder for calendar drawing + for (int i = 1; i <= 30; i++) { // Simplified example for 30 days + if (i == selected_day) { + attron(A_REVERSE); // Highlight the selected day + } + mvprintw(3 + (i / 7), (i % 7) * 3, "%2d", i); + if (i == selected_day) { + attroff(A_REVERSE); + } + } +} + +void draw_day_view(int *day, int *month, int *year) { + time_t now; + struct tm *local; + int ch; + bool redraw = true; + + while (true) { + if (redraw) { + clear(); + mvprintw(0, 0, "Day View"); + mvprintw(1, 0, "Date: %02d-%02d-%04d", *day, *month, *year); + + // Draw the hours of the day + for (int i = 0; i < 24; i++) { + mvprintw(i + 3, 0, "%02d:00 |", i); + mvhline(i + 3, 8, ' ', COLS - 8); + } + + now = time(NULL); + local = localtime(&now); + + if (local->tm_mday == *day && (local->tm_mon + 1) == *month && (local->tm_year + 1900) == *year) { + int current_hour = local->tm_hour; + int current_minute = local->tm_min; + + attron(COLOR_PAIR(1)); // Red color + mvhline(current_hour + 3, 8, '-', COLS - 8); + mvprintw(current_hour + 3, 0, "%02d:%02d |", current_hour, current_minute); + attroff(COLOR_PAIR(1)); + } + + refresh(); + redraw = false; + } + + nodelay(stdscr, TRUE); // Make getch non-blocking + ch = getch(); + + if (ch == 'q') break; // Exit to Calendar View + if (ch == KEY_LEFT || ch == 'j') { + if (*day > 1) { + (*day)--; + } else { + if (*month > 1) { + (*month)--; + } else { + *month = 12; + (*year)--; + } + *day = 31; // Simplified for demo purposes + } + redraw = true; + } else if (ch == KEY_RIGHT || ch == 'k') { + if (*day < 31) { // Simplified for demo purposes + (*day)++; + } else { + *day = 1; + if (*month < 12) { + (*month)++; + } else { + *month = 1; + (*year)++; + } + } + redraw = true; + } + + napms(1000); + } + + nodelay(stdscr, FALSE); +} + +void open_add_event_tui() { + char title[MAX_TITLE_LEN] = ""; + char calendar[MAX_CALENDAR_LEN] = ""; + char notes[MAX_NOTES_LEN] = ""; + int ch; + bool all_day = false; + int start_day = 1, end_day = 1; + int start_hour = 9, start_minute = 0; + int end_hour = 10, end_minute = 0; + int repeat_option = 0; + char repeat_options[4][20] = {"Never", "Every Day", "Every Week", "Custom"}; + + int cursor_pos = 0; + + while (true) { + clear(); + mvprintw(0, 0, "Add New Event"); + + // Title input + mvprintw(2, 0, "Title: "); + if (cursor_pos == 0) attron(A_REVERSE); + mvprintw(2, 7, title); + if (cursor_pos == 0) attroff(A_REVERSE); + + // All-day toggle + mvprintw(4, 0, "All Day: "); + if (cursor_pos == 1) attron(A_REVERSE); + mvprintw(4, 9, all_day ? "[X]" : "[ ]"); + if (cursor_pos == 1) attroff(A_REVERSE); + + // Start day and time + mvprintw(6, 0, "Start Day: %02d", start_day); + mvprintw(7, 0, "Start Time: "); + if (cursor_pos == 2) attron(A_REVERSE); + mvprintw(7, 12, "%02d:%02d", start_hour, start_minute); + if (cursor_pos == 2) attroff(A_REVERSE); + + // End day and time + mvprintw(9, 0, "End Day: %02d", end_day); + mvprintw(10, 0, "End Time: "); + if (cursor_pos == 3) attron(A_REVERSE); + mvprintw(10, 10, "%02d:%02d", end_hour, end_minute); + if (cursor_pos == 3) attroff(A_REVERSE); + + // Repeat options + mvprintw(12, 0, "Repeat: "); + if (cursor_pos == 4) attron(A_REVERSE); + mvprintw(12, 8, repeat_options[repeat_option]); + if (cursor_pos == 4) attroff(A_REVERSE); + + // Calendar name input + mvprintw(14, 0, "Calendar: "); + if (cursor_pos == 5) attron(A_REVERSE); + mvprintw(14, 10, calendar); + if (cursor_pos == 5) attroff(A_REVERSE); + + // Notes input + mvprintw(16, 0, "Notes: "); + if (cursor_pos == 6) attron(A_REVERSE); + mvprintw(17, 0, notes); + if (cursor_pos == 6) attroff(A_REVERSE); + + // Instructions + mvprintw(19, 0, "Press 'q' to cancel, 's' to save"); + + refresh(); + + ch = getch(); + if (ch == 'q') break; // Exit without saving + if (ch == 's') { + // Here, you would normally save the event + break; + } + + // Handle navigation + if (ch == KEY_DOWN || ch == 'j') { + cursor_pos = (cursor_pos + 1) % 7; + } else if (ch == KEY_UP || ch == 'k') { + cursor_pos = (cursor_pos - 1 + 7) % 7; + } + + // Handle specific field input + if (cursor_pos == 0 && ch != KEY_DOWN && ch != KEY_UP && ch != 's' && ch != 'q') { + int len = strlen(title); + if (ch == KEY_BACKSPACE || ch == 127) { + if (len > 0) title[len - 1] = '\0'; + } else if (len < MAX_TITLE_LEN - 1) { + title[len] = ch; + title[len + 1] = '\0'; + } + } else if (cursor_pos == 1 && (ch == ' ' || ch == '\n')) { + all_day = !all_day; + } else if (cursor_pos == 2 && (ch == ' ' || ch == '\n')) { + // Placeholder: Handle start day and time input + } else if (cursor_pos == 3 && (ch == ' ' || ch == '\n')) { + // Placeholder: Handle end day and time input + } else if (cursor_pos == 4 && (ch == ' ' || ch == '\n')) { + // Open repeat TUI + open_repeat_tui(); + } else if (cursor_pos == 5 && ch != KEY_DOWN && ch != KEY_UP && ch != 's' && ch != 'q') { + int len = strlen(calendar); + if (ch == KEY_BACKSPACE || ch == 127) { + if (len > 0) calendar[len - 1] = '\0'; + } else if (len < MAX_CALENDAR_LEN - 1) { + calendar[len] = ch; + calendar[len + 1] = '\0'; + } + } else if (cursor_pos == 6 && ch != KEY_DOWN && ch != KEY_UP && ch != 's' && ch != 'q') { + int len = strlen(notes); + if (ch == KEY_BACKSPACE || ch == 127) { + if (len > 0) notes[len - 1] = '\0'; + } else if (len < MAX_NOTES_LEN - 1) { + notes[len] = ch; + notes[len + 1] = '\0'; + } + } + } +} + +void open_repeat_tui() { + int ch; + int cursor_pos = 0; + + while (true) { + clear(); + mvprintw(0, 0, "Repeat Options"); + + mvprintw(2, 0, "1. Never"); + if (cursor_pos == 0) attron(A_REVERSE); + mvprintw(2, 10, "Select"); + if (cursor_pos == 0) attroff(A_REVERSE); + + mvprintw(4, 0, "2. Every Day"); + if (cursor_pos == 1) attron(A_REVERSE); + mvprintw(4, 10, "Select"); + if (cursor_pos == 1) attroff(A_REVERSE); + + mvprintw(6, 0, "3. Every Week"); + if (cursor_pos == 2) attron(A_REVERSE); + mvprintw(6, 10, "Select"); + if (cursor_pos == 2) attroff(A_REVERSE); + + mvprintw(8, 0, "4. Custom"); + if (cursor_pos == 3) attron(A_REVERSE); + mvprintw(8, 10, "Select"); + if (cursor_pos == 3) attroff(A_REVERSE); + + mvprintw(10, 0, "Press 'q' to return"); + + refresh(); + + ch = getch(); + if (ch == 'q') break; // Return to the add event TUI + if (ch == KEY_DOWN || ch == 'j') { + cursor_pos = (cursor_pos + 1) % 4; + } else if (ch == KEY_UP || ch == 'k') { + cursor_pos = (cursor_pos - 1 + 4) % 4; + } else if (ch == '\n') { + // Here, you would handle selection logic + break; // Return after selection for now + } + } +} diff --git a/ncursescalander/backup/main.o b/ncursescalander/backup/main.o new file mode 100644 index 0000000000000000000000000000000000000000..81ea559179c21f5c358ad242797a4344f2d9cb14 GIT binary patch literal 21968 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 literal 0 HcmV?d00001 diff --git a/ncursescalander/build/Makefile b/ncursescalander/build/Makefile new file mode 100644 index 0000000..7b50c34 --- /dev/null +++ b/ncursescalander/build/Makefile @@ -0,0 +1,26 @@ +# Makefile for ncurses calendar app + +CC = gcc +CFLAGS = -Wall -Wextra -I../include +LDFLAGS = -lncurses -lsqlite3 +SRC_DIR = ../src +BUILD_DIR = ../build + +SRC_FILES = $(wildcard $(SRC_DIR)/*.c) +OBJ_FILES = $(patsubst $(SRC_DIR)/%.c, $(BUILD_DIR)/%.o, $(SRC_FILES)) + +TARGET = calendar_app + +all: $(TARGET) + +$(TARGET): $(OBJ_FILES) + $(CC) -o $@ $^ $(LDFLAGS) + +$(BUILD_DIR)/%.o: $(SRC_DIR)/%.c + $(CC) $(CFLAGS) -c -o $@ $< + +clean: + rm -f $(BUILD_DIR)/*.o $(TARGET) + +.PHONY: all clean + diff --git a/ncursescalander/build/add_event.o b/ncursescalander/build/add_event.o new file mode 100644 index 0000000000000000000000000000000000000000..a67420047d56d72ef89690ede11ef1344c0aa8a9 GIT binary patch literal 11288 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 JF*K}@g#bJGe-;1$ literal 0 HcmV?d00001 diff --git a/ncursescalander/build/calendar.o b/ncursescalander/build/calendar.o new file mode 100644 index 0000000000000000000000000000000000000000..79820073d57be4860a175e841bb0cacd14346107 GIT binary patch literal 2496 zcmb<-^>JfjWMqH=Mg}_u1P><4z|g>kU^{@B4h*~uJPe^8oliS!|8%?lX@0=mdZ09= zJM@o7@*$7R1M;n}13eDDP&oL5we#Y^pYoa~vQMORUeG+zdZ5%Ciz;@gs>~A;7#SF# z3fXsn9P?Uu2gu6TJP;l$m=}8(WVc828;;J}Kb@sNKu-9qs7-ysVUBwYg{9Qg#=n4Edpn96zBIT#o~ayB4w1_p*c5Dk~_gv-Z(#2FYE96;d? zlV`SO1S^2bp;I8GEDRt2ql<(1%vf_A0|PSyI2J)l;FyPjfk6mKJ=hNn3=EP`aTp)$ zb_NCpb*MNO$N?}nGcYiiGB7X*z)eLk>~M&?;t==4AN$|iSq&8jspmuzX8|c>U|;}IAor+3{UZnxfcgp9Jql295QS{M5l8^4 zo(su*1*mx-X%L2T86agg#9oj%ES)4k6@bJ*7?w^L^olEUOA?b9^omQ0Aan+dRg{{O zs8^C&QNo~?l30?+pqEr!%%E4458))|=jNv7l`!b#<(H)Dx%-9c7MCO@XEW%5wWVgn zrxhjUrb4Zym;(716x2x76WC0cf4xAS0*gQhkXi@}LP|r!5T+g?%D}Jz6mbj;3<^*U zpfCn8L2&?5BLN~97#P$*Wefu-uR;Z&R2Q1PP+_E;3lY&_U|;~52}%nP5eP}FenY7J z=+?pX>q3l!lOR99ISdR8mQei$$bt+E4BMdwg2ESB3Z@@MJ3;j$s{ygEL-m8$$QY&% zCKe9WkFNX%RG3d#giK{(>?0;mvRU|{e7t72dP#UDs72!n)R@dt7b)GClL z90x!ngaf32fq{V=Y7e@8P~L_rh3f?|BB1Ff0>nYWP~+etf>_cHNKyitpc6qHB#f>f E0Puje=Kufz literal 0 HcmV?d00001 diff --git a/ncursescalander/build/calendar_app b/ncursescalander/build/calendar_app new file mode 100755 index 0000000000000000000000000000000000000000..4d123a2ea22c37f63083f62858a59c3a23310383 GIT binary patch literal 31336 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 Pf|-GVK?+R+8kYe8+xspo literal 0 HcmV?d00001 diff --git a/ncursescalander/build/day_view.o b/ncursescalander/build/day_view.o new file mode 100644 index 0000000000000000000000000000000000000000..17010cf872564e62f50b5efcd5e0a3a9cc3be666 GIT binary patch literal 5552 zcmb<-^>JfjWMqH=Mg}_u1P><4z)&EBU^{@B4h*~uJPe^8oliX)-#9QbFnDzCz47n= ze~-?s7ykYK-#PURi0nP_@Be?7&ekI!nO;_qPLIxG9x&GN7Z4HGA0ExMKN$F17BDd| zyv$=_VDRWIedE#V`@y3(^ovJt>w|y)|9f_R@aQ##XgIzDM1yrV|6t~CwPs>q=yv^L z*$T3izf}j!{b1P&vYx+H7R-HP33dj5D<8=G?$94lbN7LK?9mBzOLr^C`P~d2$rn62 zFL)e$z~sRQqF6jS4|#OAg1yLi!K2s1!h=|)0VYtJusPp@Vuv^o?+_arI;8Uu+;Cn{ zo zquccdEQw4wc^I1P8<@e#e#RegvY!B^rgr@K|Noflf5zjjYySNI4-Sd$R*+yfD8+yj zb#r)hw}Lcv3wZQy1*!7rZQbza|9{6$xFrp>{~7pOct93(L$eJufx`06p?x5;_k##T zX7GSo1+oEbl>p2t2FK2mj-3}e55hAa)BsR+M;LJ2^#{nr*J<6ZKYA;eyIp@^=s+k2 zsqtX;fH-g$2Ll5GIL@Kj@_&geM5Z_32UN{I1qM)vL44Be`h&5#_J?@gl;f^nK$gC| z2a@gW1qDU7>le%%$aoOD@Cy%J8D<8CZieOq%pSd>AhY&yfn0-}{P3B30v5N;2e>+q z5wN5e?&Z!;IQ;tt=3iZqkDx_Mv+EbeZg8Tobp68LBmDpWe{k%9gUh4S^@2yQ>jjuY zJUU%pcyznI=nmk4$DrjQ{?_Lp13}^r0+0j@j%5ar)ET&xNbiIkb_NDmVgSpogUfPs zx;_CL?ZDFM`T*+EUEn}NE(yC`pCEinROBLi7Nom^xjXbhx9byZ$qtc-a5?}g0Sl31 zuKyXJLi<2z7A6iAgK;}u?=;umDdcZ4U}Ruuti8j+$iPs-)m(cgi@&uA90riA$I$$P zu}&Nww!H!Wq3lk9*C8I=t&nhqDT44Iia_j6f!9hH~0y zhvN`Wz#*Q7Lp&RYco7cqIvnDaIK-QAh=cMaws4+?L;ZXl;>&S}gGyg)<};)uR>qfQ zrk3j^Gvwqaro=`)=5T^I3=9nQP#UD3 z4axkoNaE~B;)bA%$bfJUDBpmT+Cjz9%?U#iM>b~{R2=3WO^_iB3=GGi;^^kwM-oRi zM;v4Tl6x$m=BPu((apJyB#vy(2PAP&`wA9rp`bu#U|;~51Hv%zG^jX88>j^Y6VHQ+ zgVb^(g|?qd`SM%MiNIh#{w!2qWF>2PX!4;%>g+r zAL`C!P;n52?5{H*0ciMu@-@sozo6nE|03JV21@i$^~mlQgo=aIBfDQ3NgUZ64X8NC z8f5poB8dwk`70Dj9Mpw}x$`Jg9Aq!D`PZT1AoGQh%y|M8M_2zDDh^VQ?5}@Nagcgs ze{p~^Gc=r$?G=TJgUmtpmo8KsWDY1^VC989R2-xpIbPhL;vn_N=0`xqLFz$m1Xwu4 zL&ee6r$fa->OuVpnEE29IJ)|Js5nTy7*e>kLB-M4_d&%$>cx@N9|L86XgUFvVK93y zL&ed}c>om$nS*REsGkK&!XWh^3}S;YWb6h~PJ+Z?^*)1Mab<2vViJR1aY+$`&VaFs zQgagZN>VFI81zySOA;CMl8TEN^osH!oaFr6+|;}h2EDxel2ko+zfj%clEma}20gI0 z)QtGFqQqQSwg)+ZA`J2usK|u|AKWaMzn(+G1114d3uA+5X=vEO)Pux8*aDP@7#J89 zK+`QK?SS-x%3P28mMi_0BXa5cnGWxQ-}}(vp{Bm8Bjupfq?;}6qJ^sLSTwm z{f1EcL2(Dx2qj?pK|LI(5ST)@A5=es#0HJ}ZT2<AbtEWHq3Z`JLytR<{sxc+1_p*LAPy1+*@whs067zzehyIK O%)r2qh^!b(SOWl6q0}q@ literal 0 HcmV?d00001 diff --git a/ncursescalander/build/main.o b/ncursescalander/build/main.o new file mode 100644 index 0000000000000000000000000000000000000000..f3ac65fc94f69493791fc83255327a82dc173c20 GIT binary patch literal 3904 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 +#include + +#define MAX_TITLE_LEN 50 +#define MAX_CALENDAR_LEN 30 +#define MAX_NOTES_LEN 256 +#define MAX_DATE_LEN 50 + +typedef struct { + char title[MAX_TITLE_LEN]; + bool all_day; + char start_date[MAX_DATE_LEN]; + char end_date[MAX_DATE_LEN]; + int start_hour, start_minute; + int end_hour, end_minute; + int repeat_option; + char calendar[MAX_CALENDAR_LEN]; + char notes[MAX_NOTES_LEN]; +} Event; + +Event *create_event(); +void save_event_to_db(sqlite3 *db, Event *event); +sqlite3* open_database(); +void open_add_event_tui(sqlite3 *db); + +#endif diff --git a/ncursescalander/include/calendar.h b/ncursescalander/include/calendar.h new file mode 100644 index 0000000..877f57c --- /dev/null +++ b/ncursescalander/include/calendar.h @@ -0,0 +1,8 @@ +#ifndef CALENDAR_H +#define CALENDAR_H + +int is_leap_year(int year); +int days_in_month(int month, int year); +void draw_calendar(int month, int year, int selected_day); + +#endif diff --git a/ncursescalander/include/day_view.h b/ncursescalander/include/day_view.h new file mode 100644 index 0000000..a224fbc --- /dev/null +++ b/ncursescalander/include/day_view.h @@ -0,0 +1,7 @@ +#ifndef DAY_VIEW_H +#define DAY_VIEW_H + +void draw_day_view(int *day, int *month, int *year); + +#endif + diff --git a/ncursescalander/include/repeat_tui.h b/ncursescalander/include/repeat_tui.h new file mode 100644 index 0000000..52282c9 --- /dev/null +++ b/ncursescalander/include/repeat_tui.h @@ -0,0 +1,7 @@ +#ifndef REPEAT_TUI_H +#define REPEAT_TUI_H + +void open_repeat_tui(); + +#endif + diff --git a/ncursescalander/src/add_event.c b/ncursescalander/src/add_event.c new file mode 100644 index 0000000..d38a50a --- /dev/null +++ b/ncursescalander/src/add_event.c @@ -0,0 +1,292 @@ +#include "add_event.h" +#include "repeat_tui.h" +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +// Create and initialize a new event +Event *create_event() { + Event *event = (Event *)malloc(sizeof(Event)); + if (event) { + memset(event, 0, sizeof(Event)); + strcpy(event->start_date, "01/01/2000"); + strcpy(event->end_date, "01/01/2000"); + event->start_hour = 9; + event->start_minute = 0; + event->end_hour = 10; + event->end_minute = 0; + event->repeat_option = 0; + } + return event; +} + +// Function to open the SQLite database + +sqlite3* open_database() { + char path[PATH_MAX]; + char base_dir[PATH_MAX]; + char db_path[PATH_MAX]; + + // Get the current working directory + if (getcwd(path, sizeof(path)) != NULL) { + printf("Current working directory: %s\n", path); + + // Go up one directory level to the 'ncursescalander' directory + strncpy(base_dir, path, sizeof(base_dir)); + dirname(base_dir); + printf("Base directory (one level up): %s\n", base_dir); + + // Calculate required size + int required_size = snprintf(NULL, 0, "%s/databases/calendar_database.db", base_dir) + 1; + if (required_size > (int)sizeof(db_path)) { // Cast to int for comparison + fprintf(stderr, "Error: Path length exceeds buffer size.\n"); + return NULL; + } + + // Construct the final path to the database file + snprintf(db_path, sizeof(db_path), "%s/databases/calendar_database.db", base_dir); + printf("Final database path: %s\n", db_path); + + sqlite3 *db; + if (sqlite3_open(db_path, &db)) { + fprintf(stderr, "Can't open database: %s\n", sqlite3_errmsg(db)); + return NULL; + } else { + printf("Opened database successfully\n"); + return db; + } + } else { + perror("getcwd() error"); + return NULL; + } +} + +// Function to save an event to the SQLite database +void save_event_to_db(sqlite3 *db, Event *event) { + // Set default values if necessary + if (strlen(event->title) == 0) { + strcpy(event->title, "Untitled"); + } + if (strlen(event->calendar) == 0) { + strcpy(event->calendar, ""); + } + if (strlen(event->notes) == 0) { + strcpy(event->notes, ""); + } + + // Prepare SQL statement + char *sql = "INSERT INTO events (title, all_day, start_date, end_date, start_time, end_time, repeat_option, calendar, notes) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?);"; + sqlite3_stmt *stmt; + + if (sqlite3_prepare_v2(db, sql, -1, &stmt, 0) == SQLITE_OK) { + // Bind values to SQL statement + sqlite3_bind_text(stmt, 1, event->title, -1, SQLITE_STATIC); + sqlite3_bind_int(stmt, 2, event->all_day); + sqlite3_bind_text(stmt, 3, event->start_date, -1, SQLITE_STATIC); + sqlite3_bind_text(stmt, 4, event->end_date, -1, SQLITE_STATIC); + + // Format time as HH:MM + char start_time[6]; + snprintf(start_time, sizeof(start_time), "%02d:%02d", event->start_hour, event->start_minute); + sqlite3_bind_text(stmt, 5, start_time, -1, SQLITE_STATIC); + + char end_time[6]; + snprintf(end_time, sizeof(end_time), "%02d:%02d", event->end_hour, event->end_minute); + sqlite3_bind_text(stmt, 6, end_time, -1, SQLITE_STATIC); + + sqlite3_bind_int(stmt, 7, event->repeat_option); + sqlite3_bind_text(stmt, 8, event->calendar, -1, SQLITE_STATIC); + sqlite3_bind_text(stmt, 9, event->notes, -1, SQLITE_STATIC); + + // Execute the SQL statement + if (sqlite3_step(stmt) != SQLITE_DONE) { + fprintf(stderr, "SQL error: %s\n", sqlite3_errmsg(db)); + } else { + printf("Event saved successfully.\n"); + } + sqlite3_finalize(stmt); + } else { + fprintf(stderr, "SQL error: %s\n", sqlite3_errmsg(db)); + } +} + +// Function to display the Add Event TUI and handle user input +void open_add_event_tui(sqlite3 *db) { + Event *event = create_event(); + int ch; + int cursor_pos = 0; + bool exit = false; + + while (!exit) { + clear(); + mvprintw(0, 0, "Add New Event"); + + // Title input + mvprintw(2, 0, "Title: "); + if (cursor_pos == 0) attron(A_REVERSE); + mvprintw(2, 7, event->title); + if (cursor_pos == 0) attroff(A_REVERSE); + + // All-day toggle + mvprintw(4, 0, "All Day: "); + if (cursor_pos == 1) attron(A_REVERSE); + mvprintw(4, 9, event->all_day ? "[X]" : "[ ]"); + if (cursor_pos == 1) attroff(A_REVERSE); + + // Start date input + mvprintw(6, 0, "Start Date: "); + if (cursor_pos == 2) attron(A_REVERSE); + mvprintw(6, 12, event->start_date); + if (cursor_pos == 2) attroff(A_REVERSE); + + // End date input + mvprintw(8, 0, "End Date: "); + if (cursor_pos == 3) attron(A_REVERSE); + mvprintw(8, 10, event->end_date); + if (cursor_pos == 3) attroff(A_REVERSE); + + // Start time input + mvprintw(10, 0, "Start Time: "); + if (cursor_pos == 4) attron(A_REVERSE); + mvprintw(10, 12, "%02d:%02d", event->start_hour, event->start_minute); + if (cursor_pos == 4) attroff(A_REVERSE); + + // End time input + mvprintw(12, 0, "End Time: "); + if (cursor_pos == 5) attron(A_REVERSE); + mvprintw(12, 10, "%02d:%02d", event->end_hour, event->end_minute); + if (cursor_pos == 5) attroff(A_REVERSE); + + // Repeat options + mvprintw(14, 0, "Repeat: "); + if (cursor_pos == 6) attron(A_REVERSE); + mvprintw(14, 8, "Choose..."); // Display the repeat choice interactively + if (cursor_pos == 6) attroff(A_REVERSE); + + // Calendar name input + mvprintw(16, 0, "Calendar: "); + if (cursor_pos == 7) attron(A_REVERSE); + mvprintw(16, 10, event->calendar); + if (cursor_pos == 7) attroff(A_REVERSE); + + // Notes input + mvprintw(18, 0, "Notes: "); + if (cursor_pos == 8) attron(A_REVERSE); + mvprintw(19, 0, event->notes); + if (cursor_pos == 8) attroff(A_REVERSE); + + // Instructions + mvprintw(21, 0, "Esc: Cancel Ctrl+S: Save"); + + refresh(); + + ch = getch(); + switch (ch) { + case 27: // ESC to cancel + exit = true; + break; + case 19: // Ctrl+S to save (^S) + save_event_to_db(db, event); + exit = true; // Return to calendar view after saving + break; + case KEY_DOWN: // Navigate down + cursor_pos = (cursor_pos + 1) % 9; + break; + case KEY_UP: // Navigate up + cursor_pos = (cursor_pos - 1 + 9) % 9; + break; + case KEY_LEFT: + case 'j': // Decrease minute + if (cursor_pos == 4) { + event->start_minute = (event->start_minute > 0) ? event->start_minute - 1 : 59; + } else if (cursor_pos == 5) { + event->end_minute = (event->end_minute > 0) ? event->end_minute - 1 : 59; + } + break; + case KEY_RIGHT: + case 'k': // Increase minute + if (cursor_pos == 4) { + event->start_minute = (event->start_minute < 59) ? event->start_minute + 1 : 0; + } else if (cursor_pos == 5) { + event->end_minute = (event->end_minute < 59) ? event->end_minute + 1 : 0; + } + break; + case KEY_SLEFT: + case 'h': // Decrease hour (Shift+Left or 'h') + if (cursor_pos == 4) { + event->start_hour = (event->start_hour > 0) ? event->start_hour - 1 : 23; + } else if (cursor_pos == 5) { + event->end_hour = (event->end_hour > 0) ? event->end_hour - 1 : 23; + } + break; + case KEY_SRIGHT: + case 'l': // Increase hour (Shift+Right or 'l') + if (cursor_pos == 4) { + event->start_hour = (event->start_hour < 23) ? event->start_hour + 1 : 0; + } else if (cursor_pos == 5) { + event->end_hour = (event->end_hour < 23) ? event->end_hour + 1 : 0; + } + break; + case ' ': + case '\n': + if (cursor_pos == 1) { + event->all_day = !event->all_day; + } else if (cursor_pos == 6) { + open_repeat_tui(); // Placeholder for opening the repeat TUI + } + break; + default: + if (cursor_pos == 0 && ch != KEY_DOWN && ch != KEY_UP) { + int len = strlen(event->title); + if ((ch == KEY_BACKSPACE || ch == 127) && len > 0) { + event->title[len - 1] = '\0'; + } else if (isprint(ch) && len < MAX_TITLE_LEN - 1) { + event->title[len] = ch; + event->title[len + 1] = '\0'; + } + } else if (cursor_pos == 2 && ch != KEY_DOWN && ch != KEY_UP) { + int len = strlen(event->start_date); + if ((ch == KEY_BACKSPACE || ch == 127) && len > 0) { + event->start_date[len - 1] = '\0'; + } else if (isprint(ch) && len < MAX_DATE_LEN - 1) { + event->start_date[len] = ch; + event->start_date[len + 1] = '\0'; + } + } else if (cursor_pos == 3 && ch != KEY_DOWN && ch != KEY_UP) { + int len = strlen(event->end_date); + if ((ch == KEY_BACKSPACE || ch == 127) && len > 0) { + event->end_date[len - 1] = '\0'; + } else if (isprint(ch) && len < MAX_DATE_LEN - 1) { + event->end_date[len] = ch; + event->end_date[len + 1] = '\0'; + } + } else if (cursor_pos == 7 && ch != KEY_DOWN && ch != KEY_UP) { + int len = strlen(event->calendar); + if ((ch == KEY_BACKSPACE || ch == 127) && len > 0) { + event->calendar[len - 1] = '\0'; + } else if (isprint(ch) && len < MAX_CALENDAR_LEN - 1) { + event->calendar[len] = ch; + event->calendar[len + 1] = '\0'; + } + } else if (cursor_pos == 8 && ch != KEY_DOWN && ch != KEY_UP) { + int len = strlen(event->notes); + if ((ch == KEY_BACKSPACE || ch == 127) && len > 0) { + event->notes[len - 1] = '\0'; + } else if (isprint(ch) && len < MAX_NOTES_LEN - 1) { + event->notes[len] = ch; + event->notes[len + 1] = '\0'; + } + } + break; + } + } + + free(event); // Free the allocated memory +} diff --git a/ncursescalander/src/add_event.c.bak b/ncursescalander/src/add_event.c.bak new file mode 100644 index 0000000..718710e --- /dev/null +++ b/ncursescalander/src/add_event.c.bak @@ -0,0 +1,225 @@ +#include "add_event.h" +#include "repeat_tui.h" +#include +#include +#include +#include + +#define MAX_TITLE_LEN 50 +#define MAX_CALENDAR_LEN 30 +#define MAX_NOTES_LEN 256 +#define MAX_DATE_LEN 50 + +typedef struct { + char title[MAX_TITLE_LEN]; + bool all_day; + char start_date[MAX_DATE_LEN]; + char end_date[MAX_DATE_LEN]; + int start_hour, start_minute; + int end_hour, end_minute; + int repeat_option; + char calendar[MAX_CALENDAR_LEN]; + char notes[MAX_NOTES_LEN]; +} Event; + +Event *create_event() { + Event *event = (Event *)malloc(sizeof(Event)); + if (event) { + memset(event, 0, sizeof(Event)); + strcpy(event->start_date, "01/01/2000"); + strcpy(event->end_date, "01/01/2000"); + event->start_hour = 9; + event->start_minute = 0; + event->end_hour = 10; + event->end_minute = 0; + event->repeat_option = 0; + } + return event; +} + +void save_event(Event *event) { + FILE *file = fopen("events.txt", "a"); + if (file) { + fprintf(file, "Title: %s\nAll Day: %d\nStart Date: %s\nEnd Date: %s\nStart: %02d:%02d\nEnd: %02d:%02d\nRepeat: %d\nCalendar: %s\nNotes: %s\n\n", + event->title, event->all_day, event->start_date, event->end_date, event->start_hour, event->start_minute, + event->end_hour, event->end_minute, event->repeat_option, event->calendar, event->notes); + fclose(file); + } else { + mvprintw(23, 0, "Error saving event!"); // Error message + refresh(); + getch(); // Pause to let the user see the error + } +} + +void open_add_event_tui() { + Event *event = create_event(); + int ch; + int cursor_pos = 0; + bool exit = false; + + while (!exit) { + clear(); + mvprintw(0, 0, "Add New Event"); + + // Title input + mvprintw(2, 0, "Title: "); + if (cursor_pos == 0) attron(A_REVERSE); + mvprintw(2, 7, event->title); + if (cursor_pos == 0) attroff(A_REVERSE); + + // All-day toggle + mvprintw(4, 0, "All Day: "); + if (cursor_pos == 1) attron(A_REVERSE); + mvprintw(4, 9, event->all_day ? "[X]" : "[ ]"); + if (cursor_pos == 1) attroff(A_REVERSE); + + // Start date input + mvprintw(6, 0, "Start Date: "); + if (cursor_pos == 2) attron(A_REVERSE); + mvprintw(6, 12, event->start_date); + if (cursor_pos == 2) attroff(A_REVERSE); + + // End date input + mvprintw(8, 0, "End Date: "); + if (cursor_pos == 3) attron(A_REVERSE); + mvprintw(8, 10, event->end_date); + if (cursor_pos == 3) attroff(A_REVERSE); + + // Start time input + mvprintw(10, 0, "Start Time: "); + if (cursor_pos == 4) attron(A_REVERSE); + mvprintw(10, 12, "%02d:%02d", event->start_hour, event->start_minute); + if (cursor_pos == 4) attroff(A_REVERSE); + + // End time input + mvprintw(12, 0, "End Time: "); + if (cursor_pos == 5) attron(A_REVERSE); + mvprintw(12, 10, "%02d:%02d", event->end_hour, event->end_minute); + if (cursor_pos == 5) attroff(A_REVERSE); + + // Repeat options + mvprintw(14, 0, "Repeat: "); + if (cursor_pos == 6) attron(A_REVERSE); + mvprintw(14, 8, "Choose..."); // Display the repeat choice interactively + if (cursor_pos == 6) attroff(A_REVERSE); + + // Calendar name input + mvprintw(16, 0, "Calendar: "); + if (cursor_pos == 7) attron(A_REVERSE); + mvprintw(16, 10, event->calendar); + if (cursor_pos == 7) attroff(A_REVERSE); + + // Notes input + mvprintw(18, 0, "Notes: "); + if (cursor_pos == 8) attron(A_REVERSE); + mvprintw(19, 0, event->notes); + if (cursor_pos == 8) attroff(A_REVERSE); + + // Instructions + mvprintw(21, 0, "Esc: Cancel Ctrl+S: Save"); + + refresh(); + + ch = getch(); + switch (ch) { + case 27: // ESC to cancel + exit = true; + break; + case 19: // Ctrl+S to save (^S) + save_event(event); + exit = true; // Return to calendar view after saving + break; + case KEY_DOWN: // Navigate down + cursor_pos = (cursor_pos + 1) % 9; + break; + case KEY_UP: // Navigate up + cursor_pos = (cursor_pos - 1 + 9) % 9; + break; + case KEY_LEFT: + case 'j': // Decrease minute + if (cursor_pos == 4) { + event->start_minute = (event->start_minute > 0) ? event->start_minute - 1 : 59; + } else if (cursor_pos == 5) { + event->end_minute = (event->end_minute > 0) ? event->end_minute - 1 : 59; + } + break; + case KEY_RIGHT: + case 'k': // Increase minute + if (cursor_pos == 4) { + event->start_minute = (event->start_minute < 59) ? event->start_minute + 1 : 0; + } else if (cursor_pos == 5) { + event->end_minute = (event->end_minute < 59) ? event->end_minute + 1 : 0; + } + break; + case KEY_SLEFT: + case 'h': // Decrease hour (Shift+Left or 'h') + if (cursor_pos == 4) { + event->start_hour = (event->start_hour > 0) ? event->start_hour - 1 : 23; + } else if (cursor_pos == 5) { + event->end_hour = (event->end_hour > 0) ? event->end_hour - 1 : 23; + } + break; + case KEY_SRIGHT: + case 'l': // Increase hour (Shift+Right or 'l') + if (cursor_pos == 4) { + event->start_hour = (event->start_hour < 23) ? event->start_hour + 1 : 0; + } else if (cursor_pos == 5) { + event->end_hour = (event->end_hour < 23) ? event->end_hour + 1 : 0; + } + break; + case ' ': + case '\n': + if (cursor_pos == 1) { + event->all_day = !event->all_day; + } else if (cursor_pos == 6) { + open_repeat_tui(); // Placeholder for opening the repeat TUI + } + break; + default: + if (cursor_pos == 0 && ch != KEY_DOWN && ch != KEY_UP) { + int len = strlen(event->title); + if ((ch == KEY_BACKSPACE || ch == 127) && len > 0) { + event->title[len - 1] = '\0'; + } else if (isprint(ch) && len < MAX_TITLE_LEN - 1) { + event->title[len] = ch; + event->title[len + 1] = '\0'; + } + } else if (cursor_pos == 2 && ch != KEY_DOWN && ch != KEY_UP) { + int len = strlen(event->start_date); + if ((ch == KEY_BACKSPACE || ch == 127) && len > 0) { + event->start_date[len - 1] = '\0'; + } else if (isprint(ch) && len < MAX_DATE_LEN - 1) { + event->start_date[len] = ch; + event->start_date[len + 1] = '\0'; + } + } else if (cursor_pos == 3 && ch != KEY_DOWN && ch != KEY_UP) { + int len = strlen(event->end_date); + if ((ch == KEY_BACKSPACE || ch == 127) && len > 0) { + event->end_date[len - 1] = '\0'; + } else if (isprint(ch) && len < MAX_DATE_LEN - 1) { + event->end_date[len] = ch; + event->end_date[len + 1] = '\0'; + } + } else if (cursor_pos == 7 && ch != KEY_DOWN && ch != KEY_UP) { + int len = strlen(event->calendar); + if ((ch == KEY_BACKSPACE || ch == 127) && len > 0) { + event->calendar[len - 1] = '\0'; + } else if (isprint(ch) && len < MAX_CALENDAR_LEN - 1) { + event->calendar[len] = ch; + event->calendar[len + 1] = '\0'; + } + } else if (cursor_pos == 8 && ch != KEY_DOWN && ch != KEY_UP) { + int len = strlen(event->notes); + if ((ch == KEY_BACKSPACE || ch == 127) && len > 0) { + event->notes[len - 1] = '\0'; + } else if (isprint(ch) && len < MAX_NOTES_LEN - 1) { + event->notes[len] = ch; + event->notes[len + 1] = '\0'; + } + } + break; + } + } + + free(event); // Free the allocated memory +} diff --git a/ncursescalander/src/calendar.c b/ncursescalander/src/calendar.c new file mode 100644 index 0000000..aeff0ac --- /dev/null +++ b/ncursescalander/src/calendar.c @@ -0,0 +1,56 @@ +#include "calendar.h" +#include + +// Function to determine if a year is a leap year +int is_leap_year(int year) { + if (year % 4 == 0) { + if (year % 100 == 0) { + if (year % 400 == 0) + return 1; + else + return 0; + } else + return 1; + } else + return 0; +} + +// Function to get the number of days in a given month and year +int days_in_month(int month, int year) { + switch (month) { + case 1: case 3: case 5: case 7: case 8: case 10: case 12: + return 31; + case 4: case 6: case 9: case 11: + return 30; + case 2: + if (is_leap_year(year)) + return 29; + else + return 28; + default: + return 30; // Fallback, though we shouldn't hit this + } +} + +void draw_calendar(int month, int year, int selected_day) { + int days = days_in_month(month, year); + + // Adjust selected_day if it exceeds the number of days in the month + if (selected_day > days) { + selected_day = days; + } + + mvprintw(1, 0, "Month: %d, Year: %d", month, year); + mvprintw(2, 0, "Su Mo Tu We Th Fr Sa"); + + // Placeholder for calendar drawing + for (int i = 1; i <= days; i++) { + if (i == selected_day) { + attron(A_REVERSE); // Highlight the selected day + } + mvprintw(3 + (i / 7), (i % 7) * 3, "%2d", i); + if (i == selected_day) { + attroff(A_REVERSE); + } + } +} diff --git a/ncursescalander/src/day_view.c b/ncursescalander/src/day_view.c new file mode 100644 index 0000000..aac91fa --- /dev/null +++ b/ncursescalander/src/day_view.c @@ -0,0 +1,127 @@ +#include "day_view.h" +#include +#include +#include +#include + +#define MAX_TITLE_LEN 50 + +typedef struct { + char title[MAX_TITLE_LEN]; + int start_hour; + int start_minute; + int end_hour; + int end_minute; + int event_day; + int event_month; + int event_year; +} DisplayEvent; + +void load_events(DisplayEvent *events, int *count, int day, int month, int year) { + FILE *file = fopen("events.txt", "r"); + if (file) { + char line[256]; + int current_day, current_month, current_year; + while (fgets(line, sizeof(line), file)) { + if (sscanf(line, "Date: %d-%d-%d", ¤t_day, ¤t_month, ¤t_year) == 3) { + if (current_day == day && current_month == month && current_year == year) { + fgets(line, sizeof(line), file); + sscanf(line, "Start: %02d:%02d", &events[*count].start_hour, &events[*count].start_minute); + fgets(line, sizeof(line), file); + sscanf(line, "End: %02d:%02d", &events[*count].end_hour, &events[*count].end_minute); + fgets(line, sizeof(line), file); + sscanf(line, "Title: %49[^\n]", events[*count].title); + events[*count].event_day = current_day; + events[*count].event_month = current_month; + events[*count].event_year = current_year; + (*count)++; + } + } + } + fclose(file); + } +} + +void draw_day_view(int *day, int *month, int *year) { + time_t now; + struct tm *local; + int ch; + bool redraw = true; + + DisplayEvent events[10]; + int event_count = 0; + load_events(events, &event_count, *day, *month, *year); + + while (true) { + if (redraw) { + clear(); + mvprintw(0, 0, "Day View"); + mvprintw(1, 0, "Date: %02d-%02d-%04d", *day, *month, *year); + + // Draw the hours of the day + for (int i = 0; i < 24; i++) { + mvprintw(i + 3, 0, "%02d:00 |", i); + mvhline(i + 3, 8, ' ', COLS - 8); + } + + // Display events + for (int i = 0; i < event_count; i++) { + mvprintw(events[i].start_hour + 3, 10, "%s", events[i].title); + mvhline(events[i].start_hour + 3, 10 + strlen(events[i].title), '-', COLS - 20); + } + + now = time(NULL); + local = localtime(&now); + + if (local->tm_mday == *day && (local->tm_mon + 1) == *month && (local->tm_year + 1900) == *year) { + int current_hour = local->tm_hour; + int current_minute = local->tm_min; + + attron(COLOR_PAIR(1)); // Red color + mvhline(current_hour + 3, 8, '-', COLS - 8); + mvprintw(current_hour + 3, 0, "%02d:%02d |", current_hour, current_minute); + attroff(COLOR_PAIR(1)); + } + + refresh(); + redraw = false; + } + + nodelay(stdscr, TRUE); // Make getch non-blocking + ch = getch(); + + if (ch == 'q') break; // Exit to Calendar View + if (ch == KEY_LEFT || ch == 'j') { + if (*day > 1) { + (*day)--; + } else { + if (*month > 1) { + (*month)--; + } else { + *month = 12; + (*year)--; + } + *day = 31; // Simplified for demo purposes + } + redraw = true; + } else if (ch == KEY_RIGHT || ch == 'k') { + if (*day < 31) { // Simplified for demo purposes + (*day)++; + } else { + *day = 1; + if (*month < 12) { + (*month)++; + } else { + *month = 1; + (*year)++; + } + } + redraw = true; + } + + napms(1000); + } + + nodelay(stdscr, FALSE); +} + diff --git a/ncursescalander/src/main.c b/ncursescalander/src/main.c new file mode 100644 index 0000000..dcd439f --- /dev/null +++ b/ncursescalander/src/main.c @@ -0,0 +1,106 @@ +#include +#include +#include +#include "calendar.h" +#include "day_view.h" +#include "add_event.h" + +int main() { + int ch, month, year, day = 1; + time_t now; + struct tm *local; + + // Open the SQLite database + sqlite3 *db = open_database(); + if (db == NULL) { + return 1; // Exit if the database can't be opened + } + + // Initialize ncurses + initscr(); + cbreak(); + noecho(); + keypad(stdscr, TRUE); + start_color(); + init_pair(1, COLOR_RED, COLOR_BLACK); // Red color pair for the current time + + // Get current date + now = time(NULL); + local = localtime(&now); + month = local->tm_mon + 1; + year = local->tm_year + 1900; + day = local->tm_mday; + + // Main loop + while ((ch = getch()) != 'q') { + int days_in_current_month = days_in_month(month, year); + bool redraw = false; + + switch (ch) { + case KEY_LEFT: + case 'j': + if (day > 1) { + day--; + redraw = true; + } + break; + case KEY_RIGHT: + case 'k': + if (day < days_in_current_month) { + day++; + redraw = true; + } + break; + case 'a': // 'a' for "Add Event" + open_add_event_tui(db); // Pass the database connection here + redraw = true; + break; + case '\n': // Enter key to open the day view + draw_day_view(&day, &month, &year); + redraw = true; + break; + case 'h': // 'h' for previous month + case KEY_SLEFT: // Left Shift for previous month + if (month > 1) { + month--; + } else { + month = 12; + year--; + } + // Adjust the day if it exceeds the number of days in the new month + if (day > days_in_month(month, year)) { + day = days_in_month(month, year); + } + redraw = true; + break; + case 'l': // 'l' for next month + case KEY_SRIGHT: // Right Shift for next month + if (month < 12) { + month++; + } else { + month = 1; + year++; + } + // Adjust the day if it exceeds the number of days in the new month + if (day > days_in_month(month, year)) { + day = days_in_month(month, year); + } + redraw = true; + break; + } + + if (redraw) { + clear(); + mvprintw(0, 0, "Calendar View - Press 'a' to Add Event"); + draw_calendar(month, year, day); + refresh(); + } + } + + // Close the SQLite database connection + sqlite3_close(db); + + // End ncurses mode + endwin(); + return 0; +} diff --git a/ncursescalander/src/repeat_tui.c b/ncursescalander/src/repeat_tui.c new file mode 100644 index 0000000..cfe264d --- /dev/null +++ b/ncursescalander/src/repeat_tui.c @@ -0,0 +1,48 @@ +#include +#include "repeat_tui.h" + +void open_repeat_tui() { + int ch; + int cursor_pos = 0; + + while (true) { + clear(); + mvprintw(0, 0, "Repeat Options"); + + mvprintw(2, 0, "1. Never"); + if (cursor_pos == 0) attron(A_REVERSE); + mvprintw(2, 10, "Select"); + if (cursor_pos == 0) attroff(A_REVERSE); + + mvprintw(4, 0, "2. Every Day"); + if (cursor_pos == 1) attron(A_REVERSE); + mvprintw(4, 10, "Select"); + if (cursor_pos == 1) attroff(A_REVERSE); + + mvprintw(6, 0, "3. Every Week"); + if (cursor_pos == 2) attron(A_REVERSE); + mvprintw(6, 10, "Select"); + if (cursor_pos == 2) attroff(A_REVERSE); + + mvprintw(8, 0, "4. Every Other Day"); + if (cursor_pos == 3) attron(A_REVERSE); + mvprintw(8, 18, "Select"); + if (cursor_pos == 3) attroff(A_REVERSE); + + mvprintw(10, 0, "Press 'q' to return"); + + refresh(); + + ch = getch(); + if (ch == 'q') break; // Return to the add event TUI + if (ch == KEY_DOWN || ch == 'j') { + cursor_pos = (cursor_pos + 1) % 4; + } else if (ch == KEY_UP || ch == 'k') { + cursor_pos = (cursor_pos - 1 + 4) % 4; + } else if (ch == '\n') { + // Here, you would handle selection logic + break; // Return after selection for now + } + } +} + diff --git a/ssh_gui b/ssh_gui new file mode 160000 index 0000000..ed35ae7 --- /dev/null +++ b/ssh_gui @@ -0,0 +1 @@ +Subproject commit ed35ae7f3a1e71e4667064bc18b9d15582924a9a diff --git a/terrarium_bk/terrarium/Makefile b/terrarium_bk/terrarium/Makefile new file mode 100644 index 0000000..900737e --- /dev/null +++ b/terrarium_bk/terrarium/Makefile @@ -0,0 +1,24 @@ +CC = gcc +CFLAGS = -Wall -Wextra -std=c11 + +# The final executable name +TARGET = terrarium + +# Source files +SRCS = main.c game.c ascii_plant_data.c + +# Object files +OBJS = $(SRCS:.c=.o) + +all: $(TARGET) + +$(TARGET): $(OBJS) + $(CC) $(CFLAGS) -o $@ $(OBJS) + +%.o: %.c + $(CC) $(CFLAGS) -c $< + +clean: + rm -f $(TARGET) *.o + rm -f terrarium_save.dat + diff --git a/terrarium_bk/terrarium/ascii_plant_data.c b/terrarium_bk/terrarium/ascii_plant_data.c new file mode 100644 index 0000000..79536c7 --- /dev/null +++ b/terrarium_bk/terrarium/ascii_plant_data.c @@ -0,0 +1,581 @@ +/****************************************************************************** + * ascii_plant_data.c + * + * Defines 40 unique ASCII plants, each 10 lines of up to 20 chars. + * + * For demonstration, they’ll all be similar in shape, but each one will have + * some small text or symbol changes so that no two are exactly alike. + * You can replace these with more distinct art as desired. + ******************************************************************************/ + +#include "ascii_plant_data.h" + +/* + * We store all 40 plants’ ASCII lines in a 2D array of strings: + * PLANTS[40][10] + * where each string is up to 20 chars + null terminator. + * + * Each plant: 10 lines. Each line up to 20 chars wide. + */ + +/* + Template shape (10 lines, 20 chars each): + " . " + " .. # " + " . ==+*- . - " + " :++*====.# " + " ==++-=#*+ " + " -%*=-#+#. " + " .-+**#. " + " .**+#. " + " .:=*++ " + " :--=. " + We’ll introduce slight variations for each plant to ensure uniqueness. +*/ + +static const char PLANT_ART[40][10][21] = { + /* 0: Snake Plant */ + { + " . ", + " .. # ", + " . ==+*- . - ", + " :++*====.# ", + " S==++-=#*+ ", + " -%*=-#+#. ", + " .-+**#. S ", + " .**+#. ", + " .:=*++ S ", + " :--=. " + }, + /* 1: Aloe Vera */ + { + " . ", + " .. A ", + " . ==+*- . - ", + " :++*====.# A ", + " ==++-=#*+ ", + " A -%*=-#+#. ", + " .-+**#. ", + " .**+#. A ", + " .:=*++ ", + " :--=. " + }, + /* 2: Rubber fig */ + { + " (Rubber) ", + " .. # ", + " R . ==+*- . - ", + " :++*====.# ", + " ==++-=#*+ R ", + " -%*=-#+#. ", + " R .-+**#. ", + " .**+#. R ", + " .:=*++ ", + " :--=. R " + }, + /* 3: Maidenhair fern */ + { + " M ", + " fern .. # ", + " . ==+*- . - ", + " :++*====.# M ", + " ==++-=#*+ f ", + " -%*=-#+#. ", + " .-+**#. ", + " .**+#. fern ", + " .:=*++ M ", + " :--=. " + }, + /* 4: Zebra Plant */ + { + " Z e b r a ", + " .. Z ", + " . ==+*- . - ", + " :++*====.# Z ", + " Z ==++-=#*+ ", + " -%*=-#+#.Z ", + " .-+**#. ", + " .**+#. ", + " Z .:=*++ ", + " :--=. Z " + }, + + /* 5: Jade plant */ + { + " J ", + " .. # ", + " . ==+*- . - ", + " :++*====.# J ", + " ==++-=#*+ ", + " -%*=-#+#. ", + " Jade.-+**#. ", + " .**+#. ", + " pl. :=*++ ", + " :--=. Jade " + }, + /* 6: Yucca */ + { + " Yucca ", + " .. Y ", + " . ==+*- . - Y ", + " :++*====.# ", + " ==++-=#*+ Y ", + " -%*=-#+#. ", + " .-+**#. Y ", + " .**+#. ", + " .:=*++ Y ", + " :--=. " + }, + /* 7: Chain of Hearts */ + { + " Chain <3 Hearts ", + " .. # ", + " . ==+*- . - <3 ", + " :++*====.# ", + " ==++-=#*+ <3 ", + " <3 -%*=-#+#. ", + " .-+**#. ", + " .**+#. <3 ", + " Chain.:=*++ ", + " :--=. Hearts" + }, + /* 8: ZZ plant */ + { + " ZZZ ", + " .. # Z ", + " . ==+*- . - ", + " Z :++*====.# ", + " ==++-=#*+ ", + " Z -%*=-#+#. ", + " .-+**#. Z ", + " ZZ .**+#. ", + " .:=*++ ", + " :--=. ZZ " + }, + /* 9: Moonstones */ + { + " (Moon) ", + " .. # ", + " . ==+*- . - ", + " :++*====.# M ", + " ==++-=#*+ ", + " oo -%*=-#+#. ", + " .-+**#. oo ", + " .**+#. ", + " stones:=*++ ", + " :--=. " + }, + + /* 10: Chinese Money plant */ + { + " Chinese Money ", + " .. # $ ", + " . ==+*- . - ", + " :++*====.# $ ", + " ==++-=#*+ $$ ", + " $$ -%*=-#+#. ", + " .-+**#. ", + " $$ .**+#. ", + " .:=*++ $$ ", + " :--=. " + }, + /* 11: String of pearls */ + { + " String pearls ", + " ... # o o ", + " . ==+*- . - o ", + " :++*====.# o ", + " ==++-=#*+ o ", + " -%*=-#+#. o ", + " .-+**#. o ", + " .**+#. o ", + " .:=*++ o ", + " :--=. " + }, + /* 12: Air plant */ + { + " Air plant ", + " .. # ~ ", + " . ==+*- . - ~ ", + " :++*====.# ", + " A ==++-=#*+ ~ ", + " -%*=-#+#. ", + " .-+**#. ~ ", + " ~ .**+#. ", + " .:=*++ ", + " :--=. " + }, + /* 13: African milk tree */ + { + " African milk tree ", + " AMT .. # ", + " . ==+*- . - AMT ", + " :++*====.# ", + " ==++-=#*+ AMT ", + " -%*=-#+#. ", + " .-+**#. AMT ", + " .**+#. ", + " .:=*++ ", + " :--=. " + }, + /* 14: pine bonsai */ + { + " pine bonsai ", + " .. # ^ ", + " . ==+*- . - ^ ", + " :++*====.# ", + " ==++-=#*+ ^ ", + " -%*=-#+#. ", + " ^ .-+**#. ", + " .**+#. ^ ", + " ^ .:=*++ ", + " :--=. " + }, + + /* 15: Lotus */ + { + " Lotus ", + " .. # * ", + " . ==+*- . - * ", + " :++*====.# ", + " ==++-=#*+ * ", + " -%*=-#+#. ", + " .-+**#. ", + " * .**+#. ", + " .:=*++ * ", + " :--=. " + }, + /* 16: Heart fern */ + { + " Heart fern <3 ", + " .. # ", + " . ==+*- . - <3 ", + " :++*====.# <3 ", + " ==++-=#*+ ", + " <3 -%*=-#+#. ", + " .-+**#. <3 ", + " .**+#. ", + " <3 .:=*++ ", + " :--=. " + }, + /* 17: Corkscrew rush */ + { + " Corkscrew rush ~@ ", + " .. # ~@ ", + " . ==+*- . - ~@ ", + " :++*====.# ", + " ~@==++-=#*+ ", + " -%*=-#+#. ~@ ", + " .-+**#. ", + " .**+#. ~@ ", + " .:=*++ ", + " :--=. ~@ " + }, + /* 18: Weeping fig */ + { + " Weeping fig ~ ", + " .. # ~ ", + " . ==+*- . - ", + " ~ :++*====.# ", + " ==++-=#*+ ~ ", + " -%*=-#+#. ", + " .-+**#. ~ ", + " .**+#. ", + " ~ .:=*++ ", + " :--=. " + }, + /* 19: Corkscrew albuca */ + { + " Corkscrew albuca ", + " Cka .. # ~@ ", + " . ==+*- . - ~@ ", + " :++*====.# ", + " ~@==++-=#*+ ", + " -%*=-#+#. ~@ ", + " .-+**#. ", + " ~@ .**+#. ", + " .:=*++ ", + " :--=. ~@ " + }, + + /* 20: Fiddle leaf fig */ + { + " Fiddle leaf fig F ", + " .. # (leaf) ", + " ==+*- . - F ", + " :++*====.# ", + " ==++-=#*+ (leaf) ", + " -%*=-#+#. ", + " .-+**#. F ", + " .**+#. ", + " .:=*++ (leaf) ", + " :--=. " + }, + /* 21: Mikado */ + { + " Mikado | ", + " .. # | ", + " . ==+*- . - | ", + " :++*====.# ", + " ==++-=#*+ | ", + " -%*=-#+#. ", + " .-+**#. ", + " .**+#. | ", + " .:=*++ ", + " :--=. | " + }, + /* 22: Kebab bush */ + { + " Kebab bush ~o ", + " .. # o ", + " . ==+*- . - o ", + " :++*====.# ~ ", + " ~ ==++-=#*+ o ", + " -%*=-#+#. ", + " .-+**#. ~ o ", + " .**+#. ", + " o .:=*++ ~ ", + " :--=. o " + }, + /* 23: Dwarf Papyrus */ + { + " Dwarf Papyrus ^ ", + " .. # ^ ", + " . ==+*- . - ^ ", + " :++*====.# ", + " ==++-=#*+ ^ ", + " ^ -%*=-#+#. ", + " .-+**#. ^ ", + " .**+#. ", + " ^ .:=*++ ", + " :--=. " + }, + /* 24: Hobbit Crassula */ + { + " Hobbit Crassula (H) ", + " .. # ", + " . ==+*- . - (H) ", + " :++*====.# ", + " ==++-=#*+ ", + " -%*=-#+#. (H) ", + " .-+**#. ", + " (H) .**+#. ", + " .:=*++ ", + " :--=. (H) " + }, + + /* 25: Bunny ear cactus */ + { + " Bunny ear cactus * ", + " .. # (ears) ", + " . ==+*- . - * ", + " :++*====.# (ears) ", + " ==++-=#*+ * ", + " -%*=-#+#. ", + " .-+**#. (ears) ", + " .**+#. * ", + " .:=*++ ", + " :--=. * " + }, + /* 26: ghost echoversia */ + { + " ghost echoversia # ", + " g.. # # ", + " . ==+*- . - # ", + " :++*====.# ", + " ==++-=#*+ # ", + " -%*=-#+#. # ", + " .-+**#. # ", + " .**+#. # ", + " .:=*++ # ", + " :--=. " + }, + /* 27: chinese lantern */ + { + " chinese lantern ", + " .. # (lantern) ", + " . ==+*- . - ", + " :++*====.# (lamp) ", + " ==++-=#*+ ", + " -%*=-#+#. (lamp) ", + " .-+**#. ", + " .**+#. (lantern) ", + " .:=*++ ", + " :--=. " + }, + /* 28: ginseng ficus */ + { + " ginseng ficus Gf ", + " .. # Gf ", + " . ==+*- . - Gf ", + " :++*====.# ", + " ==++-=#*+ ", + " -%*=-#+#. Gf ", + " .-+**#. ", + " .**+#. Gf ", + " .:=*++ ", + " :--=. " + }, + /* 29: venus flytrap */ + { + " venus flytrap V ", + " .. # x ", + " . ==+*- . - x ", + " :++*====.# ", + " V ==++-=#*+ x ", + " -%*=-#+#. ", + " .-+**#. x ", + " V .**+#. ", + " .:=*++ ", + " :--=. x " + }, + + /* 30: Flamingo flower */ + { + " Flamingo flower F ", + " .. # (fl) ", + " . ==+*- . - F ", + " :++*====.# ", + " (fl)==++-=#*+ F ", + " -%*=-#+#. ", + " .-+**#. (fl) ", + " .**+#. ", + " F .:=*++ ", + " :--=. (fl) " + }, + /* 31: Japanese maple bonsai */ + { + " Japanese maple bns ", + " .. # Jmb ", + " . ==+*- . - ", + " :++*====.# Jmb ", + " ==++-=#*+ ", + " -%*=-#+#. ", + " Jmb .-+**#. ", + " .**+#. ", + " .:=*++ Jmb ", + " :--=. " + }, + /* 32: Fshbone cactus */ + { + " Fshbone cactus ~^ ", + " .. # ~^ ", + " . ==+*- . - ~^ ", + " :++*====.# ", + " ==++-=#*+ ~^ ", + " -%*=-#+#. ", + " .-+**#. ~^ ", + " .**+#. ", + " .:=*++ ~^ ", + " :--=. " + }, + /* 33: Paddle plant */ + { + " Paddle plant ", + " .. # == ", + " . ==+*- . - == ", + " :++*====.# ", + " ==++-=#*+ == ", + " -%*=-#+#. ", + " .-+**#. ", + " == .**+#. ", + " .:=*++ == ", + " :--=. " + }, + /* 34: Donkey's tail */ + { + " Donkey's tail ~ ", + " .. # ~ ", + " . ==+*- . - ~ ", + " :++*====.# ", + " ~ ==++-=#*+ ", + " -%*=-#+#. ~ ", + " .-+**#. ", + " ~ .**+#. ", + " .:=*++ ", + " :--=. ~ " + }, + + /* 35: Common ivy */ + { + " Common ivy ivy ", + " .. # iv ", + " . ==+*- . - iv ", + " iv:++*====.# ", + " ==++-=#*+ ", + " -%*=-#+#. iv ", + " .-+**#. ", + " .**+#. ", + " iv .:=*++ ", + " :--=. ivy " + }, + /* 36: Chinese Crassula */ + { + " Chinese Crassula C ", + " .. # (Cr) ", + " . ==+*- . - (Cr) ", + " :++*====.# ", + " ==++-=#*+ ", + " -%*=-#+#. (Cr) ", + " .-+**#. ", + " .**+#. (Cr) ", + " .:=*++ ", + " :--=. (Cr) " + }, + /* 37: Blue Chalksticks */ + { + " Blue Chalksticks B ", + " .. # Bc ", + " . ==+*- . - Bc ", + " :++*====.# ", + " ==++-=#*+ Bc ", + " -%*=-#+#. ", + " .-+**#. Bc ", + " .**+#. ", + " .:=*++ Bc ", + " :--=. " + }, + /* 38: Angel's tears */ + { + " Angel's tears @A ", + " .. # tears ", + " . ==+*- . - @A ", + " :++*====.# ", + " ==++-=#*+ ", + " -%*=-#+#. @A ", + " .-+**#. ", + " .**+#. tears ", + " .:=*++ @A ", + " :--=. " + }, + /* 39: White clover */ + { + " White clover (wc) ", + " .. # (wc) ", + " . ==+*- . - ", + " :++*====.# (wc) ", + " ==++-=#*+ ", + " -%*=-#+#. ", + " .-+**#. (wc) ", + " .**+#. ", + " .:=*++ (wc)", + " :--=. " + } +}; + +/****************************************************************************** + * getPlantArt + * + * Returns the (line)-th line of ASCII art for plantIndex + ******************************************************************************/ +const char* getPlantArt(int plantIndex, int line) { + if(plantIndex < 0 || plantIndex >= 40) { + /* Safety: return empty string if out of range */ + return " "; + } + if(line < 0 || line >= 10) { + return " "; + } + return PLANT_ART[plantIndex][line]; +} + diff --git a/terrarium_bk/terrarium/ascii_plant_data.h b/terrarium_bk/terrarium/ascii_plant_data.h new file mode 100644 index 0000000..519d610 --- /dev/null +++ b/terrarium_bk/terrarium/ascii_plant_data.h @@ -0,0 +1,14 @@ +/****************************************************************************** + * ascii_plant_data.h + * + * Exposes function(s) to retrieve the 10-line ASCII art for each of the 40 plants. + ******************************************************************************/ + +#ifndef ASCII_PLANT_DATA_H +#define ASCII_PLANT_DATA_H + +/* Returns the line-th line (0..9) of ASCII art for plant index (0..39). */ +const char* getPlantArt(int plantIndex, int line); + +#endif + diff --git a/terrarium_bk/terrarium/ascii_plant_data.o b/terrarium_bk/terrarium/ascii_plant_data.o new file mode 100644 index 0000000000000000000000000000000000000000..f013472f13286bd3411226707a43cc33c2ea748d GIT binary patch literal 9928 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 literal 0 HcmV?d00001 diff --git a/terrarium_bk/terrarium/game.c b/terrarium_bk/terrarium/game.c new file mode 100644 index 0000000..b6f57a9 --- /dev/null +++ b/terrarium_bk/terrarium/game.c @@ -0,0 +1,259 @@ +/****************************************************************************** + * game.c + * + * Implements core game logic: initialization, update, rendering, input, etc. + ******************************************************************************/ +/* + * game.c - Contains the implementation of the Terrarium game logic + */ + +#define _POSIX_C_SOURCE 200809L + +#include "game.h" + +/* System / standard headers */ +#include +#include /* for system() */ +#include /* for clock_gettime, etc. */ +#include /* for usleep() */ +#include +#include +#include /* for strncpy() */ + +/****************************************************************************** + * Terminal-handling variables/functions (non-blocking input, etc.) + *****************************************************************************/ +static struct termios old, current; + +/* Initialize new terminal i/o settings */ +void initTermios(int echo) { + tcgetattr(0, &old); + current = old; + current.c_lflag &= ~ICANON; /* disable buffered i/o */ + if (echo) { + current.c_lflag |= ECHO; + } else { + current.c_lflag &= ~ECHO; + } + tcsetattr(0, TCSANOW, ¤t); +} + +/* Restore old terminal i/o settings */ +void resetTermios(void) { + tcsetattr(0, TCSANOW, &old); +} + +/* Check if a key has been pressed (non-blocking) */ +int kbhit(void) { + struct termios oldt, newt; + int ch; + int oldf; + + tcgetattr(STDIN_FILENO, &oldt); + newt = oldt; + newt.c_lflag &= ~(ICANON | ECHO); + tcsetattr(STDIN_FILENO, TCSANOW, &newt); + oldf = fcntl(STDIN_FILENO, F_GETFL, 0); + fcntl(STDIN_FILENO, F_SETFL, oldf | O_NONBLOCK); + + ch = getchar(); + + tcsetattr(STDIN_FILENO, TCSANOW, &oldt); + fcntl(STDIN_FILENO, F_SETFL, oldf); + + if(ch != EOF) { + ungetc(ch, stdin); + return 1; + } + return 0; +} + +/* Read one character (like getch in Windows) */ +char getch(void) { + return getchar(); +} + +/* Clear the screen (Unix-like) */ +void clearScreen(void) { + system("clear"); +} + +/****************************************************************************** + * Elapsed Time (we store the old time in a static variable) + *****************************************************************************/ +double getElapsedTime(void) { + static struct timespec lastTime = {0, 0}; + struct timespec now; + + /* If first call, initialize lastTime */ + if (lastTime.tv_sec == 0 && lastTime.tv_nsec == 0) { + clock_gettime(CLOCK_MONOTONIC, &now); + lastTime = now; + return 0.0; + } + + /* current time */ + clock_gettime(CLOCK_MONOTONIC, &now); + + double elapsed = (now.tv_sec - lastTime.tv_sec) + + (now.tv_nsec - lastTime.tv_nsec) / 1000000000.0; + lastTime = now; + return elapsed; +} + +/****************************************************************************** + * Game Logic & Rendering + *****************************************************************************/ + +/* Forward-declarations (private to this file) */ +static double calcTotalProduction(const GameState *gs); +static void buyPlant(GameState *gs); + +/* initGame: brand-new game (if load fails or for fresh start) */ +void initGame(GameState *gs) { + gs->oxygen = 0.0; + gs->plantCost = BASE_PLANT_COST; + gs->plantCount = 0; + + /* The 40 plants (names). Adjust as you wish. */ + const char* plantNames[MAX_PLANTS] = { + "Snake Plant", "Aloe Vera", "Rubber fig", "Maidenhair fern", "Zebra Plant", + "Jade plant", "Yucca", "Chain of Hearts", "ZZ plant", "Moonstones", + "Chinese Money plant", "String of pearls.", "Air plant", "African milk tree", + "pine bonsai", "Lotus", "Heart fern", "Corkscrew rush", "Weeping fig", "Corkscrew albuca", + "Fiddle leaf fig", "Mikado", "Kebab bush", "Dwarf Papyrus", "Hobbit Crassula", + "Bunny ear cactus", "ghost echoversia", "chinese lantern", "ginseng ficus", "venus flytrap", + "Flamingo flower", "Japanese maple bonsai", "Fshbone cactus", "Paddle plant", + "Donkey's tail", "Common ivy", "Chinese Crassula", "Blue Chalksticks", "Angel's tears", "White clover" + }; + + for(int i = 0; i < MAX_PLANTS; i++) { + strncpy(gs->plants[i].name, plantNames[i], sizeof(gs->plants[i].name) - 1); + gs->plants[i].name[sizeof(gs->plants[i].name)-1] = '\0'; + gs->plants[i].active = 0; + gs->plants[i].productionRate = 0.0; + } + + /* Start with the first plant active, if desired */ + gs->plants[0].active = 1; + gs->plants[0].productionRate = BASE_OXYGEN_PER_SECOND; + gs->plantCount = 1; +} + +/* loadGame: tries to read from a file. If it fails, calls initGame(). */ +void loadGame(GameState *gs) { + FILE *f = fopen("terrarium_save.dat", "rb"); + if(!f) { + initGame(gs); + return; + } + if(fread(gs, sizeof(GameState), 1, f) != 1) { + fclose(f); + initGame(gs); + return; + } + fclose(f); + + /* Basic sanity check */ + if(gs->plantCount < 1) { + initGame(gs); + } +} + +/* saveGame: writes the current game state to a file. */ +void saveGame(const GameState *gs) { + FILE *f = fopen("terrarium_save.dat", "wb"); + if(!f) return; + fwrite(gs, sizeof(GameState), 1, f); + fclose(f); +} + +/* updateGame: called each loop to add oxygen from production rate. */ +void updateGame(GameState *gs, double elapsedSeconds) { + double totalProd = calcTotalProduction(gs); + gs->oxygen += totalProd * elapsedSeconds; +} + +/* renderGame: draws shelves + plants in top 3/4, info in bottom 1/4. */ +void renderGame(const GameState *gs) { + clearScreen(); + + printf("========================================\n"); + printf(" T E R R A R I U M \n"); + printf("========================================\n\n"); + + /* + * We have 5 shelves (SHELF_COUNT=5). + * Each shelf displays 8 plants => total 40 plants (PLANTS_PER_SHELF=8). + */ + int plantIdx = 0; + for(int shelf = 0; shelf < SHELF_COUNT; shelf++) { + for(int slot = 0; slot < PLANTS_PER_SHELF; slot++) { + if(plantIdx < MAX_PLANTS && gs->plants[plantIdx].active) { + /* Print the plant name (20 chars padded, e.g.) */ + printf("[%2d] %-20s | ", plantIdx+1, gs->plants[plantIdx].name); + } else { + printf("[ ] %-20s | ", "(empty)"); + } + plantIdx++; + } + printf("\n--------------------------------------------------------\n"); + } + + /* BOTTOM 1/4: info, oxygen, etc. */ + printf("\nOxygen: %.2f O2\n", gs->oxygen); + printf("Total Production: %.3f O2/s\n", calcTotalProduction(gs)); + printf("Next Plant Cost: %.2f O2\n\n", gs->plantCost); + + printf("[SPACE] Tap the first plant for +%.1f O2 (if active)\n", TAP_BONUS_OXYGEN); + printf("[b] Buy a new plant\n"); + printf("[q] Quit\n\n"); +} + +/* handleInput: user keystrokes (tap or buy, etc.) */ +void handleInput(GameState *gs, char input) { + switch(input) { + case ' ': + /* Tap only works on the first plant if active */ + if(gs->plants[0].active) { + gs->oxygen += TAP_BONUS_OXYGEN; + } + break; + case 'b': + case 'B': + buyPlant(gs); + break; + default: + break; + } +} + +/* Internal helper: calculates sum of production rates */ +static double calcTotalProduction(const GameState *gs) { + double total = 0.0; + for(int i = 0; i < MAX_PLANTS; i++) { + if(gs->plants[i].active) { + total += gs->plants[i].productionRate; + } + } + return total; +} + +/* Internal helper: buy the next plant if we can afford it */ +static void buyPlant(GameState *gs) { + if(gs->plantCount >= MAX_PLANTS) { + return; /* can't buy more than 40 */ + } + if(gs->oxygen >= gs->plantCost) { + gs->oxygen -= gs->plantCost; + /* activate next plant in line */ + int index = gs->plantCount; + gs->plants[index].active = 1; + gs->plants[index].productionRate = BASE_OXYGEN_PER_SECOND; /* or custom logic */ + gs->plantCount++; + + /* Increase cost for next time */ + gs->plantCost *= COST_MULTIPLIER; + } +} + diff --git a/terrarium_bk/terrarium/game.h b/terrarium_bk/terrarium/game.h new file mode 100644 index 0000000..497857f --- /dev/null +++ b/terrarium_bk/terrarium/game.h @@ -0,0 +1,67 @@ +/****************************************************************************** + * game.h + * + * Exposes the core game logic and data. + ******************************************************************************/ +#ifndef GAME_H +#define GAME_H + +/* + * This header declares functions/data for the Terrarium game. + * Include it from both main.c and game.c. + */ + +#define MAX_PLANTS 40 +#define SHELF_COUNT 5 /* We'll display 5 shelves total */ +#define PLANTS_PER_SHELF 8 /* 8 plants per shelf => 40 plants total */ +#define GAME_TICK_INTERVAL_MS 200 /* Loop tick (ms) */ + +#define BASE_OXYGEN_PER_SECOND 0.1 +#define TAP_BONUS_OXYGEN 1.0 +#define BASE_PLANT_COST 10.0 +#define COST_MULTIPLIER 1.2 + +/* + * Data Structures + */ + +typedef struct { + char name[64]; /* e.g. "Snake Plant" */ + int active; /* 1 if purchased/visible, 0 if not */ + double productionRate; /* O2 per second contributed by this plant */ +} Plant; + +/* Main Game State container */ +typedef struct { + double oxygen; /* Current total oxygen currency */ + double plantCost; /* Cost to buy the next plant */ + Plant plants[MAX_PLANTS]; /* All 40 plants */ + int plantCount; /* How many plants are active */ +} GameState; + +/* + * Function Prototypes + */ + +/* Game lifecycle */ +void initGame(GameState *gs); +void loadGame(GameState *gs); +void saveGame(const GameState *gs); + +/* Game logic */ +void updateGame(GameState *gs, double elapsedSeconds); +void renderGame(const GameState *gs); +void handleInput(GameState *gs, char input); + +/* Timing: returns elapsed seconds since last call */ +double getElapsedTime(void); + +/* Terminal / I/O helpers */ +void initTermios(int echo); +void resetTermios(void); +int kbhit(void); +char getch(void); +void clearScreen(void); + +#endif /* GAME_H */ + diff --git a/terrarium_bk/terrarium/game.o b/terrarium_bk/terrarium/game.o new file mode 100644 index 0000000000000000000000000000000000000000..f9ef4738915dc77ecbb4892740ecc11cea2d3eb0 GIT binary patch literal 10192 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 {ujfQp06LH1Vy zk~pZ%2J>$Yk~p$^P9lkerXFDGFF?g%?r{Mz7#J9CK*d4!DkFu%eW*A{8OZ%5AO-^i z!*i%Oy83reagZ{QdRRLC1{FtFp9^g=!_*%GF&G#as-WT^^`N=}=Kf}=I7k`D{Hq`a zD4n2*--U|Lf{LS?vl%K5QU)^T4T!8OLuMQQ5nI8&OZvquZS8oj!hpB%8Rqu`_UIG;lfr_J>6AcxInX?M2 zJ{c+wQjZ)CSx|A9dhi4#0|P@5R2*IXZm2j+J`bD{bJpfpUp0?Lno(lGHJ zC_e#8!^G!7`LOm5One1Y9M;}}iGydG85kH~_Q1rCLDj?huQ2g5Q1K2Z4HLf(<%9Zf zASO&4)b9cDXMhN#aQ+14FM!f8^~@j!0|Nuhy&x_q9zp#WkkSnx0?8aHkOBq<2Jl=G zlDH~V9M--9aY5!7gBT1946uG8hzk;T1~C{I7%rfh9|9G>fhL{`6$kbAKvEzs$edCT zgMonoJiUYDo@S`{2asYU@rh7z@Z=kk_(G^SIDsRHZ-o1(U|?X-fYKleB>oq~U|?V{fYKleB+duQ z;0z2579as6cgjG;L3I|$oggj#EIot7Kp5tKSULoWfiP^`0G570 zVjv6~H-N=ENDPEw;{z~zKw=;a8wY^d0}=yaSbtvu>MxKO2*dj64rt=A{y1pa0LXtJ zwIB@Zk2j#HhxM-)pozoAg$|&J!^VXe^olEUOA?b9^omQ0Aan+dRg{{Os8^C&QNo}H zW~L;TBr@nF6&Ew;73D)X$@#gtpsu@KUVcfcp1WVDZgELsayC>$YDRoo5vY?4@&RQS z6z?D}z{+cwX|Q;YhL-m*agbUV8$^Tp$)Gv~rXC~)!V^G^8qoL`R6l6k2&5NQAHd3a zZD?9Vt40_WK=r}m4`e0?gWLgL(rHE18D3K zW+H@s03H5@m6H%r=omDN!@$5`26aCu4Iv3L!1VtBS&Ae9vmYh|>hFWX1y*0d#BV?c zCeZy0QVUW8qe0_JFg8dWhJQfy!}u^7T`j0T4-!LnKTQ7(kR(hqG^~)g4BP2AO{W+CZ294L?xd7i0#yevp|^B_M5ZoB$ml(FR!n e7lpJ>khlz>z9%;QFF=hd(6R$$#n8A$76Jgs(tHpA literal 0 HcmV?d00001 diff --git a/terrarium_bk/terrarium/main.c b/terrarium_bk/terrarium/main.c new file mode 100644 index 0000000..5558a6e --- /dev/null +++ b/terrarium_bk/terrarium/main.c @@ -0,0 +1,57 @@ +/* + * main.c - Entry point of the Terrarium program + */ + +#define _POSIX_C_SOURCE 200809L + +#include +#include /* for system() */ +#include /* for usleep() */ + +#include "game.h" + +int main(void) { + GameState gs; + + /* Load a previous save or start fresh. */ + loadGame(&gs); + + /* Setup terminal for non-blocking input, no echo */ + initTermios(0); + + int running = 1; + while (running) { + /* Time since the last loop in seconds */ + double elapsedSeconds = getElapsedTime(); + + /* Update game logic (oxygen accumulation, etc.) */ + updateGame(&gs, elapsedSeconds); + + /* Render the shelves and the info area */ + renderGame(&gs); + + /* Check user input (non-blocking) */ + if (kbhit()) { + char c = getch(); + if (c == 'q' || c == 'Q') { + running = 0; /* quit */ + } else { + handleInput(&gs, c); + } + } + + /* Control frame/tick rate (~5 times a second) */ + usleep(GAME_TICK_INTERVAL_MS * 1000); + + /* Auto-save each loop (optional) */ + saveGame(&gs); + } + + /* Cleanup */ + resetTermios(); + clearScreen(); + printf("Thanks for playing Terrarium!\n"); + + return 0; +} + diff --git a/terrarium_bk/terrarium/main.o b/terrarium_bk/terrarium/main.o new file mode 100644 index 0000000000000000000000000000000000000000..5311d6046cd6596f5d4d77d81510bcd25bfb850d GIT binary patch literal 2288 zcmb<-^>JfjWMqH=Mg}_u1P><4z_5W8!FB*M9T<2Sco;%GI-hzpzS+RTz~Ir_8u0o5 ze~-@NFF*?Rg9tF|xa%K~kuUog7#P3;X&(G_2Ru4mKX`P9et>FA^We`r1k(!@gK@!{ zS`U;Mff*gH?;C307nZO!)V>ca7g`2YVuSQbop^n$$#Qv%j|@^DB-VqSK!LRx;2LP1VqWoBNwLP%;+QDRYM zX|5szgS)e{m4b##YEoumo`Ru~o{^q`uAzx0l*z!rAOdm%0|NtNRS*MXg#e>84?D*M zMg|5M1_%a8gROVu6KG>{=4E4g%)`zB62*=|0m{Pg@jo_MW~?#Dz`)D^_8E#6kQG8m z>cMVcU|`^7U|IQ;Sg8CA#R96+y;lZI}UMQ9OA(^#N%;@r{NIK$01&WL%air zI74n?W}aR$m}1DuPfT%7%uQv;%*!kZNiE9F%r9n0Pc3oHNh~N%O$o`&O=T!8NJ%V7 z1*3Q9{DN{e$+Qwtc16U$&)ic{exC+DOl z76m64rKaXF6qJ?}gJKL6Um%)=fdL%*fBr*&0!Wa7fdM4W#=yV;69>f?ND3s*jwBug z5`?M;r5Tv|L?m%eB=w+h21$X;;X)Dzg)>Z?8%cZ)NDyj150dz5BymuhgxR|bNt_Q! z{YfNoekAd8NaCP$4KwE|RGf(cls^#Ra2F~La=##wIk0d8sRv=GG6n{{;>z5T#3Tm2 z;*uf=odIJNrRF5+m84dbFzBTumLxLhB^4Jl=oRHdILZ0Bxv6<240?I_C8>JuexbU> zC5g$|40>Q~sTuKUMW7@Ew}>(Z$o-(Q0~F`TCPB({X!(pJ0aA;^Wsru(5llTy?g2A| z6#&%$igOSXlvY485+H(sfk6#a213IcDg>r9K#IXER03UChk=0sWG2))xME`UgVHz1 zOq94|U|@jhmxG%KVSv;^SP;?@>V5+V7f!lC6@tPSE(lc%;zOkwoRGvo;xL>BQvefy z(&)nBQ2prc&wwhlfa-%$ps<3mK{O~IgVHp5{24&223S0S;t!-3ghBdX;vj3#?FPv& z07)<~Fl>O*pu7#T2VFm?j6jb&kp2LuU@wS+grUa4ML>BGsuV5;Vt7E^4=ayAVjzsJ F9{_2qPYVD5 literal 0 HcmV?d00001 diff --git a/terrarium_bk/terrarium/terrarium b/terrarium_bk/terrarium/terrarium new file mode 100755 index 0000000000000000000000000000000000000000..e52103e7bd96834d618157ac3383ef9e3072c4ef GIT binary patch literal 25984 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 N$3b?YX+YyL008lTh3^0W literal 0 HcmV?d00001 diff --git a/terrarium_bk/terrarium/terrarium.c b/terrarium_bk/terrarium/terrarium.c new file mode 100644 index 0000000..73dff5a --- /dev/null +++ b/terrarium_bk/terrarium/terrarium.c @@ -0,0 +1,388 @@ +/****************************************************************************** + * Terrarium - An ASCII-based terminal idle game in C + * + * - Top 3/4 of the screen: shelves to visualize plants with their names. + * - Bottom 1/4 of the screen: oxygen total, controls, etc. + * - Tapping (space bar) works only for the first plant to give bonus oxygen. + * - Press 'b' to buy new plants, which appear on the next available shelf. + * - Press 'q' to quit. + * - Auto-saves and auto-loads from "terrarium_save.dat". + * + * Compile (Linux/Unix): + * gcc terrarium.c -o terrarium -lm + * + * Run: + * ./terrarium + * + *****************************************************************************/ + +#include +#include +#include +#include +#include +#include +#include + +/****************************************************************************** + * Platform/Terminal-Handling Code (Non-Blocking Input, Clear Screen, etc.) + *****************************************************************************/ + +static struct termios old, current; + +/* Initialize new terminal i/o settings */ +void initTermios(int echo) { + tcgetattr(0, &old); /* grab old terminal i/o settings */ + current = old; + current.c_lflag &= ~ICANON; /* disable buffered i/o */ + if (echo) { + current.c_lflag |= ECHO; /* set echo mode */ + } else { + current.c_lflag &= ~ECHO; /* set no echo mode */ + } + tcsetattr(0, TCSANOW, ¤t); /* apply the new settings */ +} + +/* Restore old terminal i/o settings */ +void resetTermios(void) { + tcsetattr(0, TCSANOW, &old); +} + +/* Check if a key has been pressed (non-blocking) */ +int kbhit(void) { + struct termios oldt, newt; + int ch; + int oldf; + + tcgetattr(STDIN_FILENO, &oldt); + newt = oldt; + newt.c_lflag &= ~(ICANON | ECHO); + tcsetattr(STDIN_FILENO, TCSANOW, &newt); + oldf = fcntl(STDIN_FILENO, F_GETFL, 0); + fcntl(STDIN_FILENO, F_SETFL, oldf | O_NONBLOCK); + + ch = getchar(); + + tcsetattr(STDIN_FILENO, TCSANOW, &oldt); + fcntl(STDIN_FILENO, F_SETFL, oldf); + + if(ch != EOF) { + ungetc(ch, stdin); + return 1; + } + + return 0; +} + +/* Read one character without echo */ +char getch() { + return getchar(); +} + +/* Clear the screen (Unix-like) */ +void clearScreen() { + system("clear"); +} + +/****************************************************************************** + * Game Constants + *****************************************************************************/ + +#define MAX_PLANTS 10 /* Max number of plants we can display */ +#define SHELF_COUNT 5 /* How many shelves to visualize */ +#define GAME_TICK_INTERVAL_MS 200 /* Game loop tick interval in ms */ + +#define BASE_OXYGEN_PER_SECOND 0.1 +#define TAP_BONUS_OXYGEN 1.0 +#define BASE_PLANT_COST 10.0 +#define COST_MULTIPLIER 1.2 + +/* Save file name */ +#define SAVE_FILE "terrarium_save.dat" + +/****************************************************************************** + * Data Structures + *****************************************************************************/ + +/* Each Plant has a name and a productionRate. We could expand this in the future. */ +typedef struct { + char name[32]; + int active; /* 1 if this plant is purchased and displayed, 0 otherwise */ + double productionRate; /* Oxygen production contribution from this plant */ +} Plant; + +typedef struct { + double oxygen; /* Current total oxygen */ + double plantCost; /* Cost to buy the next plant */ + Plant plants[MAX_PLANTS]; /* Our plants (0th is the "first" plant that can be tapped) */ + int plantCount; /* How many plants are active/purchased */ +} GameState; + +/****************************************************************************** + * Function Declarations + *****************************************************************************/ + +void initGame(GameState *gs); +void loadGame(GameState *gs); +void saveGame(const GameState *gs); + +void updateGame(GameState *gs, double elapsedSeconds); +void renderGame(const GameState *gs); + +void handleInput(GameState *gs, char input); +void buyPlant(GameState *gs); + +double calcTotalProduction(const GameState *gs); +double getElapsedTime(struct timespec *lastTick); + +/****************************************************************************** + * Main Function + *****************************************************************************/ + +int main(void) { + GameState gs; + + /* Attempt to load a previous save. If no save file is found, initialize. */ + loadGame(&gs); + + /* Terminal setup for non-blocking input */ + initTermios(0); // 0 = no echo + + /* Timing for the game loop */ + struct timespec lastTick; + clock_gettime(CLOCK_MONOTONIC, &lastTick); + + int running = 1; + while(running) { + /* 1) Compute elapsed time */ + double elapsedSeconds = getElapsedTime(&lastTick); + + /* 2) Update game logic */ + updateGame(&gs, elapsedSeconds); + + /* 3) Render the game */ + clearScreen(); + renderGame(&gs); + + /* 4) Check user input (non-blocking) */ + if(kbhit()) { + char input = getch(); + if(input == 'q' || input == 'Q') { + running = 0; + } else { + handleInput(&gs, input); + } + } + + /* 5) Sleep to control game speed */ + usleep(GAME_TICK_INTERVAL_MS * 1000); + + /* 6) Auto-save occasionally (for example, every loop). + * You could also do it less frequently to avoid disk writes. */ + saveGame(&gs); + } + + /* Cleanup */ + resetTermios(); + clearScreen(); + printf("Thanks for playing Terrarium!\n"); + return 0; +} + +/****************************************************************************** + * Initialize Game State (default if no save is found) + *****************************************************************************/ +void initGame(GameState *gs) { + gs->oxygen = 0.0; + gs->plantCost = BASE_PLANT_COST; + + /* Initialize all plants as inactive, except the first one. */ + for(int i = 0; i < MAX_PLANTS; i++){ + snprintf(gs->plants[i].name, sizeof(gs->plants[i].name), "Plant #%d", i+1); + gs->plants[i].active = 0; + gs->plants[i].productionRate = 0.0; + } + + /* Start with one plant active (the first one) */ + gs->plants[0].active = 1; + gs->plants[0].productionRate = BASE_OXYGEN_PER_SECOND; + gs->plantCount = 1; +} + +/****************************************************************************** + * Load Game State from SAVE_FILE (if it exists). Otherwise, init fresh. + *****************************************************************************/ +void loadGame(GameState *gs) { + FILE *f = fopen(SAVE_FILE, "rb"); + if(!f) { + /* No save found, start a new game */ + initGame(gs); + return; + } + + /* Read the saved struct. For a real game, you'd want version checks, etc. */ + fread(gs, sizeof(GameState), 1, f); + fclose(f); + + /* Sanity check that at least one plant is active. If not, re-init. */ + if(gs->plantCount < 1) { + initGame(gs); + } +} + +/****************************************************************************** + * Save Game State to SAVE_FILE + *****************************************************************************/ +void saveGame(const GameState *gs) { + FILE *f = fopen(SAVE_FILE, "wb"); + if(!f) { + return; /* if we can't open it, just skip saving */ + } + fwrite(gs, sizeof(GameState), 1, f); + fclose(f); +} + +/****************************************************************************** + * Update Game State + * - Accumulate oxygen based on the total production rate * elapsed time + *****************************************************************************/ +void updateGame(GameState *gs, double elapsedSeconds) { + double totalProd = calcTotalProduction(gs); + gs->oxygen += totalProd * elapsedSeconds; +} + +/****************************************************************************** + * Render/Draw the game to the terminal + * + * We’ll reserve the top 3/4 of the screen for shelves (with ASCII pots/plants), + * and the bottom 1/4 for stats, cost, etc. + * + * For simplicity, let's assume a typical 24- or 25-line terminal height. + * We'll do 15-16 lines for shelves, then ~8-9 lines for the bottom portion. + * + *****************************************************************************/ +void renderGame(const GameState *gs) { + /* We'll define how many lines we want for shelves, ignoring actual + terminal height detection for simplicity. Adjust as you like. */ + const int shelfLines = 15; + + /* Each shelf is represented by two lines: + 1) The plant pot / name + 2) The "--------" shelf line + We'll show up to SHELF_COUNT shelves from top to bottom. + */ + int shelfIndex = 0; + int plantIndex = 0; + + /* Print the top banner */ + printf("========================================\n"); + printf(" T E R R A R I U M \n"); + printf("========================================\n\n"); + + /* We have SHELF_COUNT shelves to display. Let’s map each shelf to a plant index if available. */ + for(shelfIndex = 0; shelfIndex < SHELF_COUNT; shelfIndex++) { + /* If there's a plant for this shelfIndex, show it. + We'll just go in the order plants are purchased (0,1,2,...) + and display them as long as they are active, up to the number of shelves. */ + if(plantIndex < MAX_PLANTS && gs->plants[plantIndex].active) { + /* Show an ASCII pot and the plant’s name */ + printf(" [%s]\n", gs->plants[plantIndex].name); + printf(" ---------------------- (shelf #%d)\n", shelfIndex+1); + plantIndex++; + } else { + /* Empty shelf */ + printf(" [empty]\n"); + printf(" ---------------------- (shelf #%d)\n", shelfIndex+1); + } + } + + /* Now we display the bottom portion (the UI area). We'll show the last 1/4 lines. */ + /* Let's just put a few blank lines to ensure separation. */ + printf("\n"); + + /* Bottom section with info and controls */ + printf("Oxygen: %.2f O2\n", gs->oxygen); + printf("Total Production Rate: %.3f O2/sec\n", calcTotalProduction(gs)); + printf("Next Plant Cost: %.2f O2\n\n", gs->plantCost); + + printf("[SPACE] Tap the first plant for +%.1f O2 (only if the first plant exists)\n", TAP_BONUS_OXYGEN); + printf("[b] Buy a new plant\n"); + printf("[q] Quit\n"); + printf("\n"); +} + +/****************************************************************************** + * Handle User Input + *****************************************************************************/ +void handleInput(GameState *gs, char input) { + switch(input) { + case ' ': + /* Space bar: Tapping only affects the first plant if active. */ + if(gs->plants[0].active) { + gs->oxygen += TAP_BONUS_OXYGEN; + } + break; + case 'b': + case 'B': + /* Buy a new plant if possible */ + buyPlant(gs); + break; + default: + /* ignore other keys */ + break; + } +} + +/****************************************************************************** + * Buy a new plant (if we can afford it and haven't reached MAX_PLANTS) + *****************************************************************************/ +void buyPlant(GameState *gs) { + if(gs->plantCount >= MAX_PLANTS) { + /* No more plants can be bought */ + return; + } + + /* Check if we have enough oxygen for the next plant */ + if(gs->oxygen >= gs->plantCost) { + gs->oxygen -= gs->plantCost; + + /* Activate the next plant and set its production rate */ + int index = gs->plantCount; /* next available slot */ + gs->plants[index].active = 1; + /* For demonstration: each new plant has the same base production, + or you could do something fancier. */ + gs->plants[index].productionRate = BASE_OXYGEN_PER_SECOND; + + gs->plantCount++; + + /* Increase the cost for the next plant */ + gs->plantCost *= COST_MULTIPLIER; + } +} + +/****************************************************************************** + * Calculate the Total Production from all active plants + *****************************************************************************/ +double calcTotalProduction(const GameState *gs) { + double total = 0.0; + for(int i = 0; i < MAX_PLANTS; i++) { + if(gs->plants[i].active) { + total += gs->plants[i].productionRate; + } + } + return total; +} + +/****************************************************************************** + * Get elapsed time in seconds since the last tick + *****************************************************************************/ +double getElapsedTime(struct timespec *lastTick) { + struct timespec now; + clock_gettime(CLOCK_MONOTONIC, &now); + + double elapsed = (now.tv_sec - lastTick->tv_sec) + + (now.tv_nsec - lastTick->tv_nsec) / 1000000000.0; + *lastTick = now; + return elapsed; +} + diff --git a/terrarium_bk/terrarium/terrarium_save.dat b/terrarium_bk/terrarium/terrarium_save.dat new file mode 100644 index 0000000000000000000000000000000000000000..840a214634582685b0f45ce9f11e39fa398a3d41 GIT binary patch literal 3224 zcmZ40vqxQL4XXnK7^pY|=Ot#RDg@*t=9Pd&NF^Ad8fMJ|ft~h_Ir*syVW~xlP;qjo z5(Q-wn7*LWq@>g$g|y6cmFOi5KJAUirhMxfxx(&S`H;sV7m1_lP_jKs`5h5R%HkJQAXl45jelKD|l z)buR_gKvI*UU5l&UMdAnV?pwTb4F%fYH_N9Z+>2CC7DiLh?HJ}ONuh{(m?@OkeXPO zQ>=$%7qLua^Bgma$aEFLw*N@(b4)ABOis*G$j!{jRwyY-O+_dpnuYAXg3P>Bg{1tv z;>1j%^`k39HqR%&q?CfFMK_uOoQ%mY3c%(ugGmVCoL`h(oLrPzu2583oB3^Jo1y0GD{SkixP{AOLNF8sgccdD$UEQR7g!MQbQAkbB$S+GRD$XR&fuMkc;$&!f3aa7At$&frtMtsg;?%r!g|y6Mvf~5U zyt351(qe_QoXV1-!~&?BNu`kE!!0Ky)MH+@BvSZ>7`N%?uH6r~nq^8ymV)^9 j)ErRor6v|pY#0LrLwH7JNvc9}4yZUlayHpaSpNY4j!)pK literal 0 HcmV?d00001 diff --git a/testfunctions/readme.md b/testfunctions/readme.md new file mode 100644 index 0000000..53b8f8b --- /dev/null +++ b/testfunctions/readme.md @@ -0,0 +1,3 @@ +# Project README + +Details about the project. \ No newline at end of file diff --git a/testfunctions/source/test.c b/testfunctions/source/test.c new file mode 100755 index 0000000..e69de29 diff --git a/website-tests b/website-tests new file mode 160000 index 0000000..2d7b920 --- /dev/null +++ b/website-tests @@ -0,0 +1 @@ +Subproject commit 2d7b9204a5786c538bcf9efe93330ef95148fe7a