commit 5f931616f8e73c9122997ae57356c5cc2cdf7e46
parent f7f577b0b1dfdb99d96ae8208de822fd6234d5a9
Author: sin <sin@2f30.org>
Date: Sun, 28 Dec 2014 11:11:35 +0000
Add initial library code
Diffstat:
M | Makefile | | | 1 | + |
M | PROTOCOL | | | 27 | ++++++++++++++++++--------- |
M | cmd.c | | | 46 | +++++++++++++++++++++++++++++++++++----------- |
A | library.c | | | 110 | +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ |
M | output.c | | | 11 | ++++++++--- |
M | playlist.c | | | 69 | +++++++-------------------------------------------------------------- |
M | sad.c | | | 5 | ++--- |
M | sad.h | | | 17 | ++++++++++++++--- |
8 files changed, 195 insertions(+), 91 deletions(-)
diff --git a/Makefile b/Makefile
@@ -11,6 +11,7 @@ OBJ =\
cmd.o\
decoder.o\
fifo.o\
+ library.o\
mp3.o\
output.o\
playlist.o\
diff --git a/PROTOCOL b/PROTOCOL
@@ -25,9 +25,6 @@ Pause currently playing song.
play [ID]
Play the song with the given ID or the current song if no ID is provided.
-When the playlist gets populated initially, the first song added is the current song.
-A song ID is just a unique integer identifying the song. ID rolls back at 0 when
-the playlist is cleared.
prev
Play previous song.
@@ -35,23 +32,35 @@ Play previous song.
stop
Stop playback.
-add file
-Add a file to the playlist. Directories are not handled.
+add [ID]
+Add the given song ID from the library to the playlist. If not ID
+is provided, all songs in the library are added.
clear
Clear playlist and stop playback. The next file added will have a song ID
equal to 0.
-delete [ID]
-Delete the song with the given ID or the currently selected song.
+remove [ID]
+Delete the song with the given ID or the currently selected song from
+the playlist.
playlist
Dump the current playlist. The output has the following form:
"%d: %s\n", id, filepath
+playlist
+Dump the library. The output has the following form:
+"%d: %s\n", id, filepath
+
search regex
-Search for a song matching the given regex. At the moment it will only
-consider file names.
+Search for a song matching the given regex in the library. At the moment it
+will only consider file names.
+
+learn path
+Add the path to library.
+
+forget ID
+Forget the song with the given ID from the library.
close
Force the daemon to close the client connection.
diff --git a/cmd.c b/cmd.c
@@ -122,6 +122,7 @@ cmdplay(int fd, char *arg)
}
playsong(s);
+ dprintf(fd, "OK\n");
}
static void
@@ -167,21 +168,16 @@ cmdstop(int fd, char *arg)
static void
cmdadd(int fd, char *arg)
{
- Song *s;
-
if (!arg[0]) {
- dprintf(fd, "ERR expected file path\n");
+ dprintf(fd, "ERR expected ID\n");
return;
}
- if (access(arg, F_OK) < 0) {
- dprintf(fd, "ERR file doesn't exist: %s\n", arg);
- return;
- }
- s = addplaylist(arg);
- if (!s) {
- dprintf(fd, "ERR cannot add file: %s\n", arg);
+
+ if (!addplaylist(atoi(arg))) {
+ dprintf(fd, "ERR cannot add song to playlist\n");
return;
}
+
dprintf(fd, "OK\n");
}
@@ -215,6 +211,31 @@ cmdplaylist(int fd, char *arg)
}
static void
+cmdlibrary(int fd, char *arg)
+{
+ if (arg[0]) {
+ dprintf(fd, "ERR unexpected argument\n");
+ return;
+ }
+ dumplibrary(fd);
+ dprintf(fd, "OK\n");
+}
+
+static void
+cmdlearn(int fd, char *arg)
+{
+ if (!arg[0]) {
+ dprintf(fd, "ERR expected argument file path\n");
+ return;
+ }
+ if (!addlibrary(arg)) {
+ dprintf(fd, "ERR failed to add song to library\n");
+ return;
+ }
+ dprintf(fd, "OK\n");
+}
+
+static void
cmdclose(int fd, char *arg)
{
}
@@ -226,6 +247,7 @@ cmdkill(int fd, char *arg)
dprintf(fd, "ERR unexpected argument\n");
return;
}
+ dprintf(fd, "OK\n");
raise(SIGTERM);
}
@@ -246,7 +268,7 @@ cmdsearch(int fd, char *arg)
dprintf(fd, "ERR expectede search string\n");
return;
}
- if (searchplaylist(fd, arg) != -1)
+ if (searchlibrary(fd, arg) != -1)
dprintf(fd, "OK\n");
}
@@ -272,6 +294,8 @@ static Cmd cmds[] = {
{ "clear", cmdclear },
{ "delete", cmddelete },
{ "playlist", cmdplaylist },
+ { "library", cmdlibrary },
+ { "learn", cmdlearn },
{ "close", cmdclose },
{ "kill", cmdkill },
{ "ping", cmdping },
diff --git a/library.c b/library.c
@@ -0,0 +1,110 @@
+#include <sys/select.h>
+#include <sys/types.h>
+
+#include <err.h>
+#include <limits.h>
+#include <regex.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include "sad.h"
+
+static Library library;
+static int rollingid;
+
+Song *
+addlibrary(const char *path)
+{
+ Decoder *d;
+ Song *s;
+
+ d = matchdecoder(path);
+ if (!d)
+ return NULL;
+
+ if (!library.nsongs || library.nsongs + 1 > library.maxsongs) {
+ library.maxsongs += 4096;
+ library.songs = reallocarray(library.songs, library.maxsongs, sizeof(Song *));
+ if (!library.songs)
+ err(1, "reallocarray");
+ }
+
+ s = malloc(sizeof(*s));
+ if (!s)
+ err(1, "malloc");
+
+ library.songs[library.nsongs] = s;
+ strlcpy(s->path, path, sizeof(s->path));
+ s->id = rollingid++;
+ s->state = NONE;
+ s->decoder = d;
+ library.nsongs++;
+ return s;
+}
+
+Song *
+findsongid(int id)
+{
+ Song *s;
+ int i;
+
+ for (i = 0; i < library.nsongs; i++) {
+ s = library.songs[i];
+ if (s->id == id)
+ return s;
+ }
+ return NULL;
+}
+
+void
+dumplibrary(int fd)
+{
+ Song *s;
+ int i;
+
+ for (i = 0; i < library.nsongs; i++) {
+ s = library.songs[i];
+ dprintf(fd, "%d: %s\n", s->id, s->path);
+ }
+}
+
+static int
+wregcomp(int fd, regex_t *preg, const char *regex, int cflags)
+{
+ char errbuf[BUFSIZ] = "";
+ int r;
+
+ if ((r = regcomp(preg, regex, cflags)) == 0)
+ return r;
+
+ regerror(r, preg, errbuf, sizeof(errbuf));
+ dprintf(fd, "ERR invalid regex: %s\n", errbuf);
+ return r;
+}
+
+int
+searchlibrary(int fd, const char *search)
+{
+ Song *s;
+ int i;
+ regex_t re;
+
+ if (wregcomp(fd, &re, search, REG_EXTENDED | REG_ICASE))
+ return -1; /* invalid regex */
+
+ for (i = 0; i < library.nsongs; i++) {
+ s = library.songs[i];
+ if (!regexec(&re, s->path, 0, NULL, REG_NOSUB))
+ dprintf(fd, "%d: %s\n", s->id, s->path);
+ }
+ regfree(&re);
+ return 0;
+}
+
+void
+clearlibrary(void)
+{
+ library.nsongs = 0;
+ rollingid = 0;
+}
diff --git a/output.c b/output.c
@@ -35,9 +35,14 @@ openoutput(const char *name)
continue;
if (strcmp(desc->name, name))
continue;
- return desc->output->open(desc->bits,
- desc->rate,
- desc->channels);
+ if (desc->output->open(desc->bits,
+ desc->rate,
+ desc->channels) < 0) {
+ printf("Disabling %s output\n",
+ desc->name);
+ desc->enabled = 0;
+ return -1;
+ }
}
return -1;
}
diff --git a/playlist.c b/playlist.c
@@ -3,7 +3,6 @@
#include <err.h>
#include <limits.h>
-#include <regex.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
@@ -14,50 +13,29 @@ static Playlist playlist;
static int rollingid;
Song *
-addplaylist(const char *path)
+addplaylist(int id)
{
- Decoder *d;
- Song *s;
+ Song *s;
- d = matchdecoder(path);
- if (!d)
+ s = findsongid(id);
+ if (!s)
return NULL;
if (!playlist.nsongs || playlist.nsongs + 1 > playlist.maxsongs) {
playlist.maxsongs += 4096;
- if (!(playlist.songs = reallocarray(playlist.songs, playlist.maxsongs, sizeof(Song *))))
+ playlist.songs = reallocarray(playlist.songs, playlist.maxsongs, sizeof(Song *));
+ if (!playlist.songs)
err(1, "reallocarray");
}
- if (!(s = calloc(1, sizeof(Song))))
- err(1, "calloc");
playlist.songs[playlist.nsongs] = s;
- strncpy(s->path, path, sizeof(s->path));
- s->path[sizeof(s->path) - 1] = '\0';
- s->id = rollingid++;
- s->state = 0;
- s->decoder = d;
- if (!s->id)
+ if (!playlist.nsongs)
playlist.cursong = s;
playlist.nsongs++;
return s;
}
Song *
-findsongid(int id)
-{
- Song *s;
- int i;
-
- for (i = 0; i < playlist.nsongs; i++) {
- s = playlist.songs[i];
- if (s->id == id)
- return s;
- }
- return NULL;
-}
-
-Song *
getnextsong(void)
{
Song *s, *cur;
@@ -123,39 +101,6 @@ dumpplaylist(int fd)
}
}
-static int
-wregcomp(int fd, regex_t *preg, const char *regex, int cflags)
-{
- char errbuf[BUFSIZ] = "";
- int r;
-
- if ((r = regcomp(preg, regex, cflags)) == 0)
- return r;
-
- regerror(r, preg, errbuf, sizeof(errbuf));
- dprintf(fd, "ERR invalid regex: %s\n", errbuf);
- return r;
-}
-
-int
-searchplaylist(int fd, const char *search)
-{
- Song *s;
- int i;
- regex_t re;
-
- if (wregcomp(fd, &re, search, REG_EXTENDED | REG_ICASE))
- return -1; /* invalid regex */
-
- for (i = 0; i < playlist.nsongs; i++) {
- s = playlist.songs[i];
- if (!regexec(&re, s->path, 0, NULL, REG_NOSUB))
- dprintf(fd, "%d: %s\n", s->id, s->path);
- }
- regfree(&re);
- return 0;
-}
-
void
clearplaylist(void)
{
diff --git a/sad.c b/sad.c
@@ -82,11 +82,10 @@ playaudio(void)
s->state = PLAYING;
break;
case PLAYING:
- if ((nbytes = s->decoder->decode(buf, sizeof(buf))) <= 0) {
+ if ((nbytes = s->decoder->decode(buf, sizeof(buf))) <= 0)
playnextsong();
- } else {
+ else
playoutput(buf, nbytes);
- }
break;
}
}
diff --git a/sad.h b/sad.h
@@ -46,6 +46,12 @@ typedef struct {
size_t maxsongs;
} Playlist;
+typedef struct {
+ Song **songs;
+ size_t nsongs;
+ size_t maxsongs;
+} Library;
+
/* sad.c */
extern fd_set master;
extern fd_set rfds;
@@ -55,20 +61,25 @@ extern int fdmax;
int docmd(int);
/* playlist.c */
-Song *addplaylist(const char *);
-Song *findsongid(int);
+Song *addplaylist(int);
Song *getnextsong(void);
Song *getprevsong(void);
Song *getcursong(void);
void putcursong(Song *);
void dumpplaylist(int);
void clearplaylist(void);
-int searchplaylist(int, const char *);
Song *playnextsong(void);
Song *playprevsong(void);
void playsong(Song *);
void stopsong(Song *);
+/* library.c */
+Song *addlibrary(const char *);
+Song *findsongid(int);
+void dumplibrary(int);
+int searchlibrary(int, const char *);
+void clearlibrary(void);
+
/* wav.c */
extern Decoder wavdecoder;