sad

simple audio daemon
git clone git://git.2f30.org/sad.git
Log | Files | Refs | LICENSE

playlist.c (3369B)


      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 *
     18 addplaylist(const char *path)
     19 {
     20 	Song    *s;
     21 	Decoder *d;
     22 
     23 	if (access(path, F_OK) < 0)
     24 		return NULL;
     25 
     26 	d = matchdecoder(path);
     27 	if (!d)
     28 		return NULL;
     29 
     30 	if (!playlist.nsongs || playlist.nsongs + 1 > playlist.maxsongs) {
     31 		playlist.maxsongs += 4096;
     32 		playlist.songs = reallocarray(playlist.songs, playlist.maxsongs, sizeof(Song *));
     33 		if (!playlist.songs)
     34 			err(1, "reallocarray");
     35 	}
     36 
     37 	s = malloc(sizeof(*s));
     38 	if (!s)
     39 		err(1, "malloc");
     40 
     41 	playlist.songs[playlist.nsongs] = s;
     42 	strlcpy(s->path, path, sizeof(s->path));
     43 	s->id = rollingid++;
     44 	s->state = NONE;
     45 	s->decoder = d;
     46 	if (!playlist.nsongs)
     47 		playlist.cursong = s;
     48 	playlist.nsongs++;
     49 	return s;
     50 }
     51 
     52 int
     53 rmplaylist(int id)
     54 {
     55 	Song *s;
     56 	size_t i;
     57 
     58 	for (i = 0; i < playlist.nsongs; i++) {
     59 		s = playlist.songs[i];
     60 		if (s->id == id)
     61 			break;
     62 	}
     63 	if (i == playlist.nsongs)
     64 		return -1;
     65 
     66 	free(s);
     67 	s = getnextsong();
     68 	memmove(&playlist.songs[i], &playlist.songs[i + 1],
     69 	        (playlist.nsongs - i - 1) * sizeof(playlist.songs[i]));
     70 	putcursong(s);
     71 	playlist.nsongs--;
     72 	return 0;
     73 }
     74 
     75 Song *
     76 findsong(const char *path)
     77 {
     78 	Song *s;
     79 	size_t i;
     80 
     81 	for (i = 0; i < playlist.nsongs; i++) {
     82 		s = playlist.songs[i];
     83 		if (!strcmp(s->path, path))
     84 			return s;
     85 	}
     86 	return NULL;
     87 }
     88 
     89 Song *
     90 findsongid(int id)
     91 {
     92 	Song *s;
     93 	size_t i;
     94 
     95 	for (i = 0; i < playlist.nsongs; i++) {
     96 		s = playlist.songs[i];
     97 		if (s->id == id)
     98 			return s;
     99 	}
    100 	return NULL;
    101 }
    102 
    103 Song *
    104 getnextsong(void)
    105 {
    106 	Song *s, *cur;
    107 	size_t i;
    108 
    109 	cur = playlist.cursong;
    110 	for (i = 0; i < playlist.nsongs; i++) {
    111 		s = playlist.songs[i];
    112 		if (s->id == cur->id)
    113 			break;
    114 	}
    115 	if (i == playlist.nsongs)
    116 		return NULL;
    117 	if (i == playlist.nsongs - 1)
    118 		s = playlist.songs[0];
    119 	else
    120 		s = playlist.songs[i + 1];
    121 	return s;
    122 }
    123 
    124 Song *
    125 getprevsong(void)
    126 {
    127 	Song *s, *cur;
    128 	size_t i;
    129 
    130 	cur = playlist.cursong;
    131 	for (i = 0; i < playlist.nsongs; i++) {
    132 		s = playlist.songs[i];
    133 		if (s->id == cur->id)
    134 			break;
    135 	}
    136 	if (i == playlist.nsongs)
    137 		return NULL;
    138 	if (i == 0)
    139 		s = playlist.songs[playlist.nsongs - 1];
    140 	else
    141 		s = playlist.songs[i - 1];
    142 	return s;
    143 }
    144 
    145 Song *
    146 getcursong(void)
    147 {
    148 	return playlist.cursong;
    149 }
    150 
    151 void
    152 putcursong(Song *s)
    153 {
    154 	playlist.cursong = s;
    155 }
    156 
    157 void
    158 dumpplaylist(int fd)
    159 {
    160 	Song *s;
    161 	size_t i;
    162 
    163 	for (i = 0; i < playlist.nsongs; i++) {
    164 		s = playlist.songs[i];
    165 		dprintf(fd, "%d: %s\n", s->id, s->path);
    166 	}
    167 }
    168 
    169 void
    170 clearplaylist(void)
    171 {
    172 	size_t i;
    173 
    174 	for (i = 0; i < playlist.nsongs; i++) {
    175 		free(playlist.songs[i]);
    176 		playlist.songs[i] = NULL;
    177 	}
    178 	playlist.nsongs = 0;
    179 	rollingid = 0;
    180 	playlist.cursong = NULL;
    181 }
    182 
    183 Song *
    184 picknextsong(void)
    185 {
    186 	Song *s;
    187 
    188 	switch (playlist.mode) {
    189 	case REPEAT:
    190 		s = getnextsong();
    191 		break;
    192 	case RANDOM:
    193 		srand(time(NULL));
    194 		s = playlist.songs[rand() % playlist.nsongs];
    195 		break;
    196 	default:
    197 		s = NULL;
    198 		break;
    199 	}
    200 	return s;
    201 }
    202 
    203 void
    204 playsong(Song *new)
    205 {
    206 	stopsong(playlist.cursong);
    207 	new->state = PREPARE;
    208 	playlist.cursong = new;
    209 }
    210 
    211 void
    212 stopsong(Song *s)
    213 {
    214 	if (s && s->state != NONE) {
    215 		s->decoder->close();
    216 		s->state = NONE;
    217 	}
    218 }
    219 
    220 void
    221 playlistmode(int mode)
    222 {
    223 	playlist.mode = mode;
    224 }
    225 
    226 int
    227 getplaylistmode(void)
    228 {
    229 	return playlist.mode;
    230 }