mpd_update_library.c (4241B)
1 #include <ctype.h> 2 #include <mpd/client.h> 3 #include <stdbool.h> 4 #include <stdio.h> 5 #include <stdlib.h> 6 #include <string.h> 7 #include <unistd.h> 8 9 #define DEFAULT_HOST "localhost" 10 #define DEFAULT_PORT 6600 11 #define DEFAULT_BACKOFF 5 12 13 struct mpd_connection *conn() { 14 const char *host = getenv("MPD_HOST"); 15 if (host == NULL || strlen(host) == 0) 16 host = DEFAULT_HOST; 17 18 unsigned port = DEFAULT_PORT; 19 const char *port_str = getenv("MPD_PORT"); 20 if (port_str != NULL && strlen(port_str) > 0) 21 port = (unsigned)atoi(port_str); 22 23 struct mpd_connection *c = mpd_connection_new(host, port, 0); 24 if (c == NULL) { 25 fprintf(stderr, "Failed to create MPD connection object\n"); 26 return NULL; 27 } 28 29 if (mpd_connection_get_error(c) != MPD_ERROR_SUCCESS) { 30 fprintf(stderr, "Error connecting to MPD (%s:%u): %s\n", host, port, 31 mpd_connection_get_error_message(c)); 32 mpd_connection_free(c); 33 return NULL; 34 } 35 return c; 36 } 37 38 char *trim_whitespace(char *str) { 39 char *end; 40 while (isspace((unsigned char)*str)) 41 str++; 42 if (*str == 0) 43 return str; 44 end = str + strlen(str) - 1; 45 while (end > str && isspace((unsigned char)*end)) 46 end--; 47 end[1] = '\0'; 48 return str; 49 } 50 51 int main(int argc, char *argv[]) { 52 if (argc > 1 && 53 (strcmp(argv[1], "-h") == 0 || strcmp(argv[1], "--help") == 0)) { 54 printf("Usage: %s [input_file]\n", argv[0]); 55 return 0; 56 } 57 58 FILE *input = stdin; 59 if (argc > 1) { 60 input = fopen(argv[1], "r"); 61 if (input == NULL) { 62 perror("Error opening file"); 63 return 1; 64 } 65 } else if (isatty(STDIN_FILENO)) { 66 fprintf(stderr, "Reading from stdin... (Press Ctrl+D to finish)\n"); 67 } 68 69 char **top_dirs = NULL; 70 int dir_count = 0; 71 char *line = NULL; 72 size_t len = 0; 73 ssize_t read_bytes; 74 75 while ((read_bytes = getline(&line, &len, input)) != -1) { 76 char *trimmed = trim_whitespace(line); 77 if (strlen(trimmed) == 0 || trimmed[0] == '#') 78 continue; 79 80 char *slash = strchr(trimmed, '/'); 81 if (slash != NULL) 82 *slash = '\0'; 83 84 bool found = false; 85 for (int i = 0; i < dir_count; i++) { 86 if (strcmp(top_dirs[i], trimmed) == 0) { 87 found = true; 88 break; 89 } 90 } 91 92 if (!found) { 93 char **temp_dirs = realloc(top_dirs, sizeof(char *) * (dir_count + 1)); 94 if (temp_dirs == NULL) { 95 perror("realloc"); 96 break; 97 } 98 top_dirs = temp_dirs; 99 top_dirs[dir_count] = strdup(trimmed); 100 if (top_dirs[dir_count] == NULL) { 101 perror("strdup"); 102 break; 103 } 104 dir_count++; 105 } 106 } 107 free(line); 108 if (input != stdin) 109 fclose(input); 110 111 if (dir_count == 0) { 112 printf("No directories found in input.\n"); 113 for (int i = 0; i < dir_count; i++) 114 free(top_dirs[i]); 115 free(top_dirs); 116 return 0; 117 } 118 119 printf("Found %d unique top-level directories to update.\n", dir_count); 120 121 struct mpd_connection *c = conn(); 122 if (c == NULL) { 123 for (int i = 0; i < dir_count; i++) 124 free(top_dirs[i]); 125 free(top_dirs); 126 return 1; 127 } 128 129 int backoff = DEFAULT_BACKOFF; 130 const char *backoff_str = getenv("MPD_UPDATE_BACKOFF"); 131 if (backoff_str != NULL && strlen(backoff_str) > 0) 132 backoff = atoi(backoff_str); 133 134 int updated_count = 0; 135 int error_count = 0; 136 137 for (int i = 0; i < dir_count; i++) { 138 printf("Updating: '%s'\n", top_dirs[i]); 139 unsigned job_id = mpd_run_update(c, top_dirs[i]); 140 if (job_id == 0) { 141 fprintf(stderr, " ✗ Failed: %s\n", mpd_connection_get_error_message(c)); 142 error_count++; 143 mpd_connection_clear_error(c); 144 } else { 145 printf(" ✓ Success (Job ID: %u)\n", job_id); 146 updated_count++; 147 } 148 if (i < dir_count - 1 && backoff > 0) 149 sleep(backoff); 150 } 151 152 printf("Update completed!\n"); 153 printf("Total directories processed: %d\n", dir_count); 154 printf("Successfully updated: %d\n", updated_count); 155 printf("Errors: %d\n", error_count); 156 157 struct mpd_status *status = mpd_run_status(c); 158 if (status != NULL) { 159 if (mpd_status_get_update_id(status) > 0) 160 printf("MPD is currently updating...\n"); 161 mpd_status_free(status); 162 } 163 164 for (int i = 0; i < dir_count; i++) 165 free(top_dirs[i]); 166 free(top_dirs); 167 mpd_connection_free(c); 168 return 0; 169 }