Recently Written · git

sad

sad (2f30.org simple audio daemon) with a Cygwin/OSS port on branch cygwin

git clone https://github.com/equwal/sad

Log | Files | Refs


playlist.c (3529 bytes)

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; }