playlist.c (3529B)
1 #include <sys/select.h> 2 #include <sys/types.h> 3 4 #include <err.h> 5 #include <limits.h> 6 #include <stdio.h> 7 #include <stdlib.h> 8 #include <string.h> 9 #include <time.h> 10 #include <unistd.h> 11 12 #include "sad.h" 13 14 static Playlist playlist; 15 static int rollingid; 16 17 Song *addplaylist(const char *path) { 18 Song *s; 19 Decoder *d; 20 21 if (access(path, F_OK) < 0) 22 return NULL; 23 24 d = matchdecoder(path); 25 if (!d) 26 return NULL; 27 28 if (!playlist.nsongs || playlist.nsongs + 1 > playlist.maxsongs) { 29 playlist.maxsongs += 4096; 30 playlist.songs = 31 reallocarray(playlist.songs, playlist.maxsongs, sizeof(Song *)); 32 if (!playlist.songs) 33 err(1, "reallocarray"); 34 } 35 36 s = malloc(sizeof(*s)); 37 if (!s) 38 err(1, "malloc"); 39 40 playlist.songs[playlist.nsongs] = s; 41 strlcpy(s->path, path, sizeof(s->path)); 42 s->id = rollingid++; 43 s->state = NONE; 44 s->decoder = d; 45 if (!playlist.nsongs) 46 playlist.cursong = s; 47 playlist.nsongs++; 48 return s; 49 } 50 51 int rmplaylist(int id) { 52 Song *s; 53 size_t i; 54 55 for (i = 0; i < playlist.nsongs; i++) { 56 s = playlist.songs[i]; 57 if (s->id == id) 58 break; 59 } 60 if (i == playlist.nsongs) 61 return -1; 62 63 free(s); 64 s = getnextsong(); 65 memmove(&playlist.songs[i], &playlist.songs[i + 1], 66 (playlist.nsongs - i - 1) * sizeof(playlist.songs[i])); 67 putcursong(s); 68 playlist.nsongs--; 69 return 0; 70 } 71 72 Song *findsong(const char *path) { 73 Song *s; 74 size_t i; 75 76 for (i = 0; i < playlist.nsongs; i++) { 77 s = playlist.songs[i]; 78 if (!strcmp(s->path, path)) 79 return s; 80 } 81 return NULL; 82 } 83 84 Song *findsongid(int id) { 85 Song *s; 86 size_t i; 87 88 for (i = 0; i < playlist.nsongs; i++) { 89 s = playlist.songs[i]; 90 if (s->id == id) 91 return s; 92 } 93 return NULL; 94 } 95 96 Song *getnextsong(void) { 97 Song *s, *cur; 98 size_t i; 99 100 cur = playlist.cursong; 101 for (i = 0; i < playlist.nsongs; i++) { 102 s = playlist.songs[i]; 103 if (s->id == cur->id) 104 break; 105 } 106 if (i == playlist.nsongs) 107 return NULL; 108 if (i == playlist.nsongs - 1) 109 s = playlist.songs[0]; 110 else 111 s = playlist.songs[i + 1]; 112 return s; 113 } 114 115 Song *getprevsong(void) { 116 Song *s, *cur; 117 size_t i; 118 119 cur = playlist.cursong; 120 for (i = 0; i < playlist.nsongs; i++) { 121 s = playlist.songs[i]; 122 if (s->id == cur->id) 123 break; 124 } 125 if (i == playlist.nsongs) 126 return NULL; 127 if (i == 0) 128 s = playlist.songs[playlist.nsongs - 1]; 129 else 130 s = playlist.songs[i - 1]; 131 return s; 132 } 133 134 Song *getcursong(void) { return playlist.cursong; } 135 136 void putcursong(Song *s) { playlist.cursong = s; } 137 138 void dumpplaylist(int fd) { 139 Song *s; 140 size_t i; 141 142 for (i = 0; i < playlist.nsongs; i++) { 143 s = playlist.songs[i]; 144 dprintf(fd, "%d: %s\n", s->id, s->path); 145 } 146 } 147 148 void clearplaylist(void) { 149 size_t i; 150 151 for (i = 0; i < playlist.nsongs; i++) { 152 free(playlist.songs[i]); 153 playlist.songs[i] = NULL; 154 } 155 playlist.nsongs = 0; 156 rollingid = 0; 157 playlist.cursong = NULL; 158 } 159 160 Song *picknextsong(void) { 161 Song *s; 162 163 switch (playlist.mode) { 164 case REPEAT: 165 s = getnextsong(); 166 break; 167 case RANDOM: 168 srand(time(NULL)); 169 s = playlist.songs[rand() % playlist.nsongs]; 170 break; 171 default: 172 s = NULL; 173 break; 174 } 175 return s; 176 } 177 178 void playsong(Song *new) { 179 stopsong(playlist.cursong); 180 new->state = PREPARE; 181 playlist.cursong = new; 182 } 183 184 void stopsong(Song *s) { 185 if (s && s->state != NONE) { 186 s->decoder->close(); 187 s->state = NONE; 188 } 189 } 190 191 void playlistmode(int mode) { playlist.mode = mode; } 192 193 int getplaylistmode(void) { return playlist.mode; }