sad

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

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