mpd_insert_next.c (2428B)
1 #define _POSIX_C_SOURCE 200809L 2 3 #include "mpd_common.h" 4 5 #include <limits.h> 6 #include <string.h> 7 #include <unistd.h> 8 9 static void usage(FILE *file, const char *program) { 10 fprintf(file, "Usage: %s [--verbose] [FILE|-]\n", program); 11 } 12 13 int main(int argc, char **argv) { 14 bool verbose = false; 15 const char *path = NULL; 16 for (int i = 1; i < argc; i++) { 17 if (strcmp(argv[i], "-h") == 0 || strcmp(argv[i], "--help") == 0) { 18 usage(stdout, argv[0]); 19 return 0; 20 } 21 if (strcmp(argv[i], "--verbose") == 0) { 22 verbose = true; 23 } else if (argv[i][0] == '-' && strcmp(argv[i], "-") != 0) { 24 usage(stderr, argv[0]); 25 return 2; 26 } else if (path == NULL) { 27 path = argv[i]; 28 } else { 29 usage(stderr, argv[0]); 30 return 2; 31 } 32 } 33 34 bool close_input; 35 FILE *input = mt_open_input(path, &close_input); 36 if (input == NULL) 37 return 1; 38 if (path == NULL && isatty(STDIN_FILENO)) 39 fprintf(stderr, "Reading tracks from stdin; press Ctrl-D to finish.\n"); 40 41 struct mt_strvec tracks; 42 mt_strvec_init(&tracks); 43 bool ok = mt_read_lines(input, &tracks); 44 if (close_input && fclose(input) != 0) { 45 perror("mpd: close input"); 46 ok = false; 47 } 48 if (!ok) { 49 mt_strvec_clear(&tracks); 50 return 1; 51 } 52 53 struct mpd_connection *connection = mt_connect(); 54 if (connection == NULL) { 55 mt_strvec_clear(&tracks); 56 return 1; 57 } 58 struct mt_player_state state; 59 ok = mt_get_player_state(connection, &state); 60 unsigned position = 0U; 61 if (ok && state.song_pos != UINT_MAX) { 62 if (state.song_pos == UINT_MAX - 1U) { 63 fprintf(stderr, "mpd: current queue position is too large\n"); 64 ok = false; 65 } else { 66 position = state.song_pos + 1U; 67 } 68 } 69 if (ok) { 70 enum mt_state_match match = 71 mt_player_state_is(connection, state.queue_version, state.song_id); 72 if (match == MT_STATE_CHANGED) { 73 fprintf(stderr, 74 "mpd: player or queue changed before insertion; retry the " 75 "command\n"); 76 ok = false; 77 } else if (match == MT_STATE_ERROR) { 78 ok = false; 79 } 80 } 81 if (ok) 82 ok = mt_insert_queue(connection, &tracks, position, verbose); 83 if (ok) 84 printf("Inserted %zu track%s at queue position %u.\n", tracks.len, 85 tracks.len == 1U ? "" : "s", position); 86 87 mt_player_state_clear(&state); 88 mpd_connection_free(connection); 89 mt_strvec_clear(&tracks); 90 return ok ? 0 : 1; 91 }