uploaded code to gitea
This commit is contained in:
247
daemon.c
Normal file
247
daemon.c
Normal file
@@ -0,0 +1,247 @@
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <unistd.h>
|
||||
#include <string.h>
|
||||
#include <sys/types.h>
|
||||
#include <sys/un.h>
|
||||
#include <sys/socket.h>
|
||||
|
||||
#include <sys/select.h>
|
||||
#include <time.h>
|
||||
#include <signal.h>
|
||||
#include <dirent.h>
|
||||
#include <sys/stat.h>
|
||||
|
||||
|
||||
int initServerSockServer() {
|
||||
int server_fd = socket(AF_UNIX, SOCK_STREAM, 0);
|
||||
struct sockaddr_un addr = {0};
|
||||
addr.sun_family = AF_UNIX;
|
||||
strcpy(addr.sun_path, "/tmp/my_wallpaper.sock");
|
||||
unlink(addr.sun_path);
|
||||
if (server_fd < 0) perror("socket");
|
||||
if (bind(server_fd, (struct sockaddr*)&addr, sizeof(addr)) < 0) perror("bind");
|
||||
if (listen(server_fd, 5) < 0) perror("listen");
|
||||
return server_fd;
|
||||
}
|
||||
|
||||
|
||||
int last_pid = -1;
|
||||
void setBackgroundImage(char* path){
|
||||
printf("changing wallpaper to %s", path);
|
||||
|
||||
int pid = fork();
|
||||
|
||||
if(pid < 0){
|
||||
perror("fork error");
|
||||
return;
|
||||
}
|
||||
|
||||
if(pid == 0) {
|
||||
// child
|
||||
char *args[] = {"/usr/bin/swaybg", "-m", "fit", "-i", path, "-c", "#000000", NULL};
|
||||
execvp("swaybg", args);
|
||||
}
|
||||
|
||||
if(last_pid > 0){
|
||||
usleep(250000);
|
||||
printf("INFO: killing %d", last_pid);
|
||||
kill(last_pid, SIGTERM);
|
||||
}
|
||||
|
||||
last_pid = pid;
|
||||
}
|
||||
|
||||
int image_index = 0;
|
||||
void runBgSwapNext(char** images, size_t count){
|
||||
image_index++;
|
||||
setBackgroundImage(images[image_index%count]);
|
||||
}
|
||||
|
||||
void runBgSwapPrevious(char** images, size_t count){
|
||||
image_index--;
|
||||
if(image_index < 0) image_index = 0;
|
||||
setBackgroundImage(images[image_index%count]);
|
||||
}
|
||||
|
||||
int isImageFile(const char* filename) {
|
||||
const char* validExtensions[] = { ".jpg", ".jpeg", ".png", ".gif", ".bmp", ".tiff" };
|
||||
size_t numExtensions = sizeof(validExtensions) / sizeof(validExtensions[0]);
|
||||
for (size_t i = 0; i < numExtensions; i++) {
|
||||
if (strstr(filename, validExtensions[i])) {
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
#define INITIAL_SIZE 10
|
||||
|
||||
void collectImages(const char* path, char*** images, size_t* count) {
|
||||
DIR* dir = opendir(path);
|
||||
if (dir == NULL) {
|
||||
perror("opendir failed");
|
||||
return;
|
||||
}
|
||||
|
||||
struct dirent* entry;
|
||||
while ((entry = readdir(dir)) != NULL) {
|
||||
if (strcmp(entry->d_name, ".") == 0 || strcmp(entry->d_name, "..") == 0) {
|
||||
continue;
|
||||
}
|
||||
|
||||
char fullPath[1024];
|
||||
snprintf(fullPath, sizeof(fullPath), "%s/%s", path, entry->d_name);
|
||||
|
||||
if (entry->d_type == DT_DIR) {
|
||||
collectImages(fullPath, images, count);
|
||||
} else if (isImageFile(entry->d_name)) {
|
||||
if (*count % INITIAL_SIZE == 0) {
|
||||
*images = realloc(*images, (*count + INITIAL_SIZE) * sizeof(char*));
|
||||
}
|
||||
(*images)[*count] = malloc(strlen(fullPath) + 1);
|
||||
strcpy((*images)[*count], fullPath);
|
||||
(*count)++;
|
||||
}
|
||||
}
|
||||
closedir(dir);
|
||||
}
|
||||
|
||||
void freeImages(char** images, size_t count) {
|
||||
for (size_t i = 0; i < count; i++) {
|
||||
free(images[i]);
|
||||
}
|
||||
free(images);
|
||||
}
|
||||
|
||||
void shuffleImages(char** images, size_t count) {
|
||||
srand(time(NULL)); // Seed for random number generation
|
||||
for (size_t i = 0; i < count; i++) {
|
||||
size_t j = rand() % count;
|
||||
// Swap images[i] and images[j]
|
||||
char* temp = images[i];
|
||||
images[i] = images[j];
|
||||
images[j] = temp;
|
||||
}
|
||||
}
|
||||
|
||||
int paused_wallpaper = 0;
|
||||
int static_wallpaper = 0;
|
||||
char* static_wallpaper_path = NULL;
|
||||
int timeout_interval = 5;
|
||||
void handleCommand(char *buff, int n, char** images, size_t image_count){
|
||||
if(n < 1){
|
||||
perror("ERROR: command missing");
|
||||
return;
|
||||
}
|
||||
printf("INFO: command accepted %c\n", buff[0]);
|
||||
|
||||
switch(buff[0]){
|
||||
case 't': {
|
||||
printf("INFO: time changed to %d\n", buff[1]);
|
||||
timeout_interval = (buff[1] << 8) + buff[2];
|
||||
|
||||
} break;
|
||||
case 'p': {
|
||||
paused_wallpaper = 1 - paused_wallpaper;
|
||||
printf("INFO: wallpaper is now %s\n", paused_wallpaper ? "paused" : "unpaused");
|
||||
} break;
|
||||
case 'c': {
|
||||
static_wallpaper = 1 - static_wallpaper;
|
||||
paused_wallpaper = static_wallpaper;
|
||||
if(static_wallpaper && static_wallpaper_path){
|
||||
setBackgroundImage(static_wallpaper_path);
|
||||
}
|
||||
printf("INFO: wallpaper is now %s\n", static_wallpaper ? "static" : "dynamic");
|
||||
} break;
|
||||
case 'n': {
|
||||
printf("INFO: wallpaper is now next");
|
||||
runBgSwapNext(images, image_count);
|
||||
} break;
|
||||
case 'b': {
|
||||
printf("INFO: wallpaper is now next");
|
||||
runBgSwapPrevious(images, image_count);
|
||||
} break;
|
||||
case 'i': {
|
||||
printf("current wallpaper is: \n%s\n", images[image_index]);
|
||||
} break;
|
||||
}
|
||||
}
|
||||
|
||||
int main(int argc, char** argv) {
|
||||
printf("INFO: daemon started\n");
|
||||
|
||||
char** images = NULL;
|
||||
size_t image_count = 0;
|
||||
|
||||
if(argc < 3){
|
||||
printf("usage: %s dirpath filepath\n", argv[0]);
|
||||
return 1;
|
||||
}
|
||||
|
||||
struct stat stat_buffer;
|
||||
|
||||
if(stat(argv[1], &stat_buffer) != 0){
|
||||
printf("dirpath is invalid\n");
|
||||
return 1;
|
||||
}
|
||||
|
||||
if(stat(argv[2], &stat_buffer) != 0){
|
||||
printf("filepath is invalid\n");
|
||||
return 1;
|
||||
}
|
||||
static_wallpaper_path = argv[2];
|
||||
collectImages(argv[1], &images, &image_count);
|
||||
printf("collected %ld suitable images\n", image_count);
|
||||
shuffleImages(images, image_count);
|
||||
printf("images shuffled\n");
|
||||
|
||||
printf("starting server\n");
|
||||
int server_fd = initServerSockServer();
|
||||
|
||||
setBackgroundImage(images[0]);
|
||||
|
||||
while(1){
|
||||
fd_set fds;
|
||||
FD_ZERO(&fds);
|
||||
FD_SET(server_fd, &fds);
|
||||
|
||||
struct timeval tv;
|
||||
tv.tv_sec = timeout_interval; // N seconds
|
||||
tv.tv_usec = 0;
|
||||
int ret = select(server_fd + 1, &fds, NULL, NULL, &tv);
|
||||
|
||||
if (ret < 0) {
|
||||
perror("select\n");
|
||||
break;
|
||||
}
|
||||
|
||||
if (ret == 0) {
|
||||
if(!paused_wallpaper){
|
||||
runBgSwapNext(images, image_count);
|
||||
}
|
||||
printf("INFO: periodic task\n");
|
||||
continue;
|
||||
}
|
||||
if (FD_ISSET(server_fd, &fds)) {
|
||||
int client = accept(server_fd, NULL, NULL);
|
||||
if (client < 0) continue;
|
||||
|
||||
printf("INFO: client connected\n");
|
||||
|
||||
char buf[256];
|
||||
int n = read(client, buf, sizeof(buf)-1);
|
||||
if (n > 0) {
|
||||
buf[n] = 0;
|
||||
handleCommand(buf, n, images, image_count);
|
||||
}
|
||||
|
||||
close(client);
|
||||
printf("INFO: client disconnected\n");
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
freeImages(images, image_count);
|
||||
return 0;
|
||||
}
|
||||
Reference in New Issue
Block a user