mirror of
https://gitlab.com/thebiblelover7/dotfiles.git
synced 2025-09-13 15:13:49 +00:00
Clean up, update configs to be actually useful now...
This commit is contained in:
122
.config/sketchybar/helper/cpu.h
Normal file
122
.config/sketchybar/helper/cpu.h
Normal file
@@ -0,0 +1,122 @@
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <unistd.h>
|
||||
#include <mach/mach.h>
|
||||
#include <stdbool.h>
|
||||
#include <time.h>
|
||||
|
||||
#define MAX_TOPPROC_LEN 28
|
||||
|
||||
static const char TOPPROC[] = { "/bin/ps -Aceo pid,pcpu,comm -r" };
|
||||
static const char FILTER_PATTERN[] = { "com.apple." };
|
||||
|
||||
struct cpu {
|
||||
host_t host;
|
||||
mach_msg_type_number_t count;
|
||||
host_cpu_load_info_data_t load;
|
||||
host_cpu_load_info_data_t prev_load;
|
||||
bool has_prev_load;
|
||||
|
||||
char command[256];
|
||||
};
|
||||
|
||||
static inline void cpu_init(struct cpu* cpu) {
|
||||
cpu->host = mach_host_self();
|
||||
cpu->count = HOST_CPU_LOAD_INFO_COUNT;
|
||||
cpu->has_prev_load = false;
|
||||
snprintf(cpu->command, 100, "");
|
||||
}
|
||||
|
||||
static inline void cpu_update(struct cpu* cpu) {
|
||||
kern_return_t error = host_statistics(cpu->host,
|
||||
HOST_CPU_LOAD_INFO,
|
||||
(host_info_t)&cpu->load,
|
||||
&cpu->count );
|
||||
|
||||
if (error != KERN_SUCCESS) {
|
||||
printf("Error: Could not read cpu host statistics.\n");
|
||||
return;
|
||||
}
|
||||
|
||||
if (cpu->has_prev_load) {
|
||||
uint32_t delta_user = cpu->load.cpu_ticks[CPU_STATE_USER]
|
||||
- cpu->prev_load.cpu_ticks[CPU_STATE_USER];
|
||||
|
||||
uint32_t delta_system = cpu->load.cpu_ticks[CPU_STATE_SYSTEM]
|
||||
- cpu->prev_load.cpu_ticks[CPU_STATE_SYSTEM];
|
||||
|
||||
uint32_t delta_idle = cpu->load.cpu_ticks[CPU_STATE_IDLE]
|
||||
- cpu->prev_load.cpu_ticks[CPU_STATE_IDLE];
|
||||
|
||||
double user_perc = (double)delta_user / (double)(delta_system
|
||||
+ delta_user
|
||||
+ delta_idle);
|
||||
|
||||
double sys_perc = (double)delta_system / (double)(delta_system
|
||||
+ delta_user
|
||||
+ delta_idle);
|
||||
|
||||
double total_perc = user_perc + sys_perc;
|
||||
|
||||
FILE* file;
|
||||
char line[1024];
|
||||
|
||||
file = popen(TOPPROC, "r");
|
||||
if (!file) {
|
||||
printf("Error: TOPPROC command errored out...\n" );
|
||||
return;
|
||||
}
|
||||
|
||||
fgets(line, sizeof(line), file);
|
||||
fgets(line, sizeof(line), file);
|
||||
|
||||
char* start = strstr(line, FILTER_PATTERN);
|
||||
char topproc[MAX_TOPPROC_LEN + 4];
|
||||
uint32_t caret = 0;
|
||||
for (int i = 0; i < sizeof(line); i++) {
|
||||
if (start && i == start - line) {
|
||||
i+=9;
|
||||
continue;
|
||||
}
|
||||
|
||||
if (caret >= MAX_TOPPROC_LEN && caret <= MAX_TOPPROC_LEN + 2) {
|
||||
topproc[caret++] = '.';
|
||||
continue;
|
||||
}
|
||||
if (caret > MAX_TOPPROC_LEN + 2) break;
|
||||
topproc[caret++] = line[i];
|
||||
if (line[i] == '\0') break;
|
||||
}
|
||||
|
||||
topproc[MAX_TOPPROC_LEN + 3] = '\0';
|
||||
|
||||
pclose(file);
|
||||
|
||||
char color[16];
|
||||
if (total_perc >= .7) {
|
||||
snprintf(color, 16, "%s", getenv("RED"));
|
||||
} else if (total_perc >= .3) {
|
||||
snprintf(color, 16, "%s", getenv("ORANGE"));
|
||||
} else if (total_perc >= .1) {
|
||||
snprintf(color, 16, "%s", getenv("YELLOW"));
|
||||
} else {
|
||||
snprintf(color, 16, "%s", getenv("LABEL_COLOR"));
|
||||
}
|
||||
|
||||
snprintf(cpu->command, 256, "--push cpu.sys %.2f "
|
||||
"--push cpu.user %.2f "
|
||||
"--set cpu.top label='%s' "
|
||||
"--set cpu.percent label=%.0f%% label.color=%s ",
|
||||
sys_perc,
|
||||
user_perc,
|
||||
topproc,
|
||||
total_perc*100.,
|
||||
color );
|
||||
}
|
||||
else {
|
||||
snprintf(cpu->command, 256, "");
|
||||
}
|
||||
|
||||
cpu->prev_load = cpu->load;
|
||||
cpu->has_prev_load = true;
|
||||
}
|
BIN
.config/sketchybar/helper/helper
Executable file
BIN
.config/sketchybar/helper/helper
Executable file
Binary file not shown.
31
.config/sketchybar/helper/helper.c
Normal file
31
.config/sketchybar/helper/helper.c
Normal file
@@ -0,0 +1,31 @@
|
||||
#include "cpu.h"
|
||||
#include "sketchybar.h"
|
||||
|
||||
struct cpu g_cpu;
|
||||
|
||||
void handler(env env) {
|
||||
// Environment variables passed from sketchybar can be accessed as seen below
|
||||
char* name = env_get_value_for_key(env, "NAME");
|
||||
char* sender = env_get_value_for_key(env, "SENDER");
|
||||
char* info = env_get_value_for_key(env, "INFO");
|
||||
char* selected = env_get_value_for_key(env, "SELECTED");
|
||||
|
||||
if ((strcmp(name, "cpu.percent") == 0)) {
|
||||
// CPU graph updates
|
||||
cpu_update(&g_cpu);
|
||||
|
||||
if (strlen(g_cpu.command) > 0) sketchybar(g_cpu.command);
|
||||
}
|
||||
}
|
||||
|
||||
int main (int argc, char** argv) {
|
||||
cpu_init(&g_cpu);
|
||||
|
||||
if (argc < 2) {
|
||||
printf("Usage: helper \"<bootstrap name>\"\n");
|
||||
exit(1);
|
||||
}
|
||||
|
||||
event_server_begin(handler, argv[1]);
|
||||
return 0;
|
||||
}
|
3
.config/sketchybar/helper/makefile
Normal file
3
.config/sketchybar/helper/makefile
Normal file
@@ -0,0 +1,3 @@
|
||||
|
||||
helper: helper.c cpu.h sketchybar.h
|
||||
clang -std=c99 -O3 helper.c -o helper
|
227
.config/sketchybar/helper/sketchybar.h
Normal file
227
.config/sketchybar/helper/sketchybar.h
Normal file
@@ -0,0 +1,227 @@
|
||||
#pragma once
|
||||
|
||||
#include <mach/mach.h>
|
||||
#include <mach/message.h>
|
||||
#include <bootstrap.h>
|
||||
#include <stdlib.h>
|
||||
#include <pthread.h>
|
||||
#include <stdio.h>
|
||||
|
||||
typedef char* env;
|
||||
|
||||
#define MACH_HANDLER(name) void name(env env)
|
||||
typedef MACH_HANDLER(mach_handler);
|
||||
|
||||
struct mach_message {
|
||||
mach_msg_header_t header;
|
||||
mach_msg_size_t msgh_descriptor_count;
|
||||
mach_msg_ool_descriptor_t descriptor;
|
||||
};
|
||||
|
||||
struct mach_buffer {
|
||||
struct mach_message message;
|
||||
mach_msg_trailer_t trailer;
|
||||
};
|
||||
|
||||
struct mach_server {
|
||||
bool is_running;
|
||||
mach_port_name_t task;
|
||||
mach_port_t port;
|
||||
mach_port_t bs_port;
|
||||
|
||||
pthread_t thread;
|
||||
mach_handler* handler;
|
||||
};
|
||||
|
||||
static struct mach_server g_mach_server;
|
||||
static mach_port_t g_mach_port = 0;
|
||||
|
||||
static inline char* env_get_value_for_key(env env, char* key) {
|
||||
uint32_t caret = 0;
|
||||
for(;;) {
|
||||
if (!env[caret]) break;
|
||||
if (strcmp(&env[caret], key) == 0)
|
||||
return &env[caret + strlen(&env[caret]) + 1];
|
||||
|
||||
caret += strlen(&env[caret])
|
||||
+ strlen(&env[caret + strlen(&env[caret]) + 1])
|
||||
+ 2;
|
||||
}
|
||||
return (char*)"";
|
||||
}
|
||||
|
||||
static inline mach_port_t mach_get_bs_port() {
|
||||
mach_port_name_t task = mach_task_self();
|
||||
|
||||
mach_port_t bs_port;
|
||||
if (task_get_special_port(task,
|
||||
TASK_BOOTSTRAP_PORT,
|
||||
&bs_port ) != KERN_SUCCESS) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
mach_port_t port;
|
||||
if (bootstrap_look_up(bs_port,
|
||||
"git.felix.sketchybar",
|
||||
&port ) != KERN_SUCCESS) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
return port;
|
||||
}
|
||||
|
||||
static inline void mach_receive_message(mach_port_t port, struct mach_buffer* buffer, bool timeout) {
|
||||
*buffer = (struct mach_buffer) { 0 };
|
||||
mach_msg_return_t msg_return;
|
||||
if (timeout)
|
||||
msg_return = mach_msg(&buffer->message.header,
|
||||
MACH_RCV_MSG | MACH_RCV_TIMEOUT,
|
||||
0,
|
||||
sizeof(struct mach_buffer),
|
||||
port,
|
||||
100,
|
||||
MACH_PORT_NULL );
|
||||
else
|
||||
msg_return = mach_msg(&buffer->message.header,
|
||||
MACH_RCV_MSG,
|
||||
0,
|
||||
sizeof(struct mach_buffer),
|
||||
port,
|
||||
MACH_MSG_TIMEOUT_NONE,
|
||||
MACH_PORT_NULL );
|
||||
|
||||
if (msg_return != MACH_MSG_SUCCESS) {
|
||||
buffer->message.descriptor.address = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
static inline char* mach_send_message(mach_port_t port, char* message, uint32_t len) {
|
||||
if (!message || !port) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
mach_port_t response_port;
|
||||
mach_port_name_t task = mach_task_self();
|
||||
if (mach_port_allocate(task, MACH_PORT_RIGHT_RECEIVE,
|
||||
&response_port ) != KERN_SUCCESS) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if (mach_port_insert_right(task, response_port,
|
||||
response_port,
|
||||
MACH_MSG_TYPE_MAKE_SEND)!= KERN_SUCCESS) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
struct mach_message msg = { 0 };
|
||||
msg.header.msgh_remote_port = port;
|
||||
msg.header.msgh_local_port = response_port;
|
||||
msg.header.msgh_id = response_port;
|
||||
msg.header.msgh_bits = MACH_MSGH_BITS_SET(MACH_MSG_TYPE_COPY_SEND,
|
||||
MACH_MSG_TYPE_MAKE_SEND,
|
||||
0,
|
||||
MACH_MSGH_BITS_COMPLEX );
|
||||
|
||||
msg.header.msgh_size = sizeof(struct mach_message);
|
||||
msg.msgh_descriptor_count = 1;
|
||||
msg.descriptor.address = message;
|
||||
msg.descriptor.size = len * sizeof(char);
|
||||
msg.descriptor.copy = MACH_MSG_VIRTUAL_COPY;
|
||||
msg.descriptor.deallocate = false;
|
||||
msg.descriptor.type = MACH_MSG_OOL_DESCRIPTOR;
|
||||
|
||||
mach_msg(&msg.header,
|
||||
MACH_SEND_MSG,
|
||||
sizeof(struct mach_message),
|
||||
0,
|
||||
MACH_PORT_NULL,
|
||||
MACH_MSG_TIMEOUT_NONE,
|
||||
MACH_PORT_NULL );
|
||||
|
||||
struct mach_buffer buffer = { 0 };
|
||||
mach_receive_message(response_port, &buffer, true);
|
||||
if (buffer.message.descriptor.address)
|
||||
return (char*)buffer.message.descriptor.address;
|
||||
mach_msg_destroy(&buffer.message.header);
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
#pragma clang diagnostic push
|
||||
#pragma clang diagnostic ignored "-Wdeprecated-declarations"
|
||||
static inline bool mach_server_begin(struct mach_server* mach_server, mach_handler handler, char* bootstrap_name) {
|
||||
mach_server->task = mach_task_self();
|
||||
|
||||
if (mach_port_allocate(mach_server->task,
|
||||
MACH_PORT_RIGHT_RECEIVE,
|
||||
&mach_server->port ) != KERN_SUCCESS) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (mach_port_insert_right(mach_server->task,
|
||||
mach_server->port,
|
||||
mach_server->port,
|
||||
MACH_MSG_TYPE_MAKE_SEND) != KERN_SUCCESS) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (task_get_special_port(mach_server->task,
|
||||
TASK_BOOTSTRAP_PORT,
|
||||
&mach_server->bs_port) != KERN_SUCCESS) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (bootstrap_register(mach_server->bs_port,
|
||||
bootstrap_name,
|
||||
mach_server->port ) != KERN_SUCCESS) {
|
||||
return false;
|
||||
}
|
||||
|
||||
mach_server->handler = handler;
|
||||
mach_server->is_running = true;
|
||||
struct mach_buffer buffer;
|
||||
while (mach_server->is_running) {
|
||||
mach_receive_message(mach_server->port, &buffer, false);
|
||||
mach_server->handler((env)buffer.message.descriptor.address);
|
||||
mach_msg_destroy(&buffer.message.header);
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
#pragma clang diagnostic pop
|
||||
|
||||
static inline char* sketchybar(char* message) {
|
||||
uint32_t message_length = strlen(message) + 1;
|
||||
char formatted_message[message_length + 1];
|
||||
|
||||
char quote = '\0';
|
||||
uint32_t caret = 0;
|
||||
for (int i = 0; i < message_length; ++i) {
|
||||
if (message[i] == '"' || message[i] == '\'') {
|
||||
if (quote == message[i]) quote = '\0';
|
||||
else quote = message[i];
|
||||
continue;
|
||||
}
|
||||
formatted_message[caret] = message[i];
|
||||
if (message[i] == ' ' && !quote) formatted_message[caret] = '\0';
|
||||
caret++;
|
||||
}
|
||||
|
||||
if (caret > 0 && formatted_message[caret] == '\0'
|
||||
&& formatted_message[caret - 1] == '\0') {
|
||||
caret--;
|
||||
}
|
||||
|
||||
formatted_message[caret] = '\0';
|
||||
if (!g_mach_port) g_mach_port = mach_get_bs_port();
|
||||
char* response = mach_send_message(g_mach_port,
|
||||
formatted_message,
|
||||
caret + 1 );
|
||||
|
||||
if (response) return response;
|
||||
else return (char*)"";
|
||||
}
|
||||
|
||||
static inline void event_server_begin(mach_handler event_handler, char* bootstrap_name) {
|
||||
mach_server_begin(&g_mach_server, event_handler, bootstrap_name);
|
||||
}
|
Reference in New Issue
Block a user