summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorUlf Lilleengen <lulf@carrot.studby.ntnu.no>2008-08-09 14:41:29 +0200
committerUlf Lilleengen <lulf@carrot.studby.ntnu.no>2008-08-09 14:41:29 +0200
commitcfa01e2eded5e91a9272d1578e48540199c8b2d8 (patch)
tree5e6b63b4feb7f8e3604fcdf90d3d35b2ce33d712
parente8793de12358e0f6f9239cd93cdf4e6f54a40702 (diff)
- Rename list to lookup, and change it, so a generic lookup callback that
will be called with the retrieved data can be specified. - Add filepath to the database schema.
-rw-r--r--dbschema.sql1
-rw-r--r--include/mp3fs.h18
-rw-r--r--src/mp3_subr.c91
-rwxr-xr-xsrc/mp3_vnops.c18
4 files changed, 79 insertions, 49 deletions
diff --git a/dbschema.sql b/dbschema.sql
index 7528591..efa89f5 100644
--- a/dbschema.sql
+++ b/dbschema.sql
@@ -11,6 +11,7 @@ CREATE TABLE song (
album varchar(200),
artistname varchar(200),
genrename varchar(200),
+ filepath varchar(255),
year int,
PRIMARY KEY(title, artistname, year)
);
diff --git a/include/mp3fs.h b/include/mp3fs.h
index 46d4deb..aac7435 100644
--- a/include/mp3fs.h
+++ b/include/mp3fs.h
@@ -17,7 +17,7 @@ void traverse_hierarchy(char *, traverse_fn_t);
traverse_fn_t mp3_scan;
/*
- * Data passed to mp3_list.
+ * Data passed to mp3_lookup.
*/
struct filler_data {
void *buf;
@@ -27,13 +27,17 @@ struct filler_data {
#define LIST_DATATYPE_STRING 1
#define LIST_DATATYPE_INT 2
-struct listhandle;
-struct listhandle *mp3_list_start(int, struct filler_data *, const char *);
-void mp3_list_insert(struct listhandle *, void *, int);
-void mp3_list_finish(struct listhandle *);
+typedef void lookup_fn_t(void *, const char *);
+lookup_fn_t mp3_lookup_list;
+struct lookuphandle;
-void mp3_list_artist(const char *, struct filler_data *);
-void mp3_list_genre(const char *, struct filler_data *);
+struct lookuphandle *mp3_lookup_start(int, void *, lookup_fn_t *, const char *);
+void mp3_lookup_insert(struct lookuphandle *, void *, int);
+void mp3_lookup_finish(struct lookuphandle *);
+
+void mp3_lookup_artist(const char *, struct filler_data *);
+void mp3_lookup_genre(const char *, struct filler_data *);
char *mp3_gettoken(const char *, int);
int mp3_numtoken(const char *);
+
#endif
diff --git a/src/mp3_subr.c b/src/mp3_subr.c
index 896bbba..e6a0ba6 100644
--- a/src/mp3_subr.c
+++ b/src/mp3_subr.c
@@ -16,14 +16,14 @@
#include <sqlite3.h>
#include <debug.h>
-struct listhandle {
+struct lookuphandle {
sqlite3 *handle;
sqlite3_stmt *st;
const char *query;
int field;
int count;
- void *buf;
- fuse_fill_dir_t filler;
+ void *priv;
+ lookup_fn_t *lookup;
};
sqlite3 *handle;
@@ -209,7 +209,8 @@ mp3_scan(char *filepath)
break;
/* Now, finally insert it. */
ret = sqlite3_prepare_v2(handle, "INSERT INTO song(title, "
- "artistname, album, genrename, year) VALUES(?, ?, ?, ?, ?)",
+ "artistname, album, genrename, year, filepath) "
+ "VALUES(?, ?, ?, ?, ?, ?)",
-1, &st, NULL);
if (ret != SQLITE_OK) {
warnx("Error preparing insert statement: %s\n",
@@ -221,6 +222,7 @@ mp3_scan(char *filepath)
sqlite3_bind_text(st, 3, album, -1, SQLITE_STATIC);
sqlite3_bind_text(st, 4, genre, -1, SQLITE_STATIC);
sqlite3_bind_int(st, 5, year);
+ sqlite3_bind_text(st, 6, filepath, -1, SQLITE_STATIC);
ret = sqlite3_step(st);
sqlite3_finalize(st);
if (ret != SQLITE_DONE) {
@@ -237,18 +239,18 @@ mp3_scan(char *filepath)
* Create a handle for listing music with a certain query. Allocate the
* resources and return the handle.
*/
-struct listhandle *
-mp3_list_start(int field, struct filler_data *fd, const char *query)
+struct lookuphandle *
+mp3_lookup_start(int field, void *data, lookup_fn_t *fn, const char *query)
{
- struct listhandle *lh;
+ struct lookuphandle *lh;
int ret, error;
lh = malloc(sizeof(*lh));
if (lh == NULL)
return (NULL);
- lh->filler = fd->filler;
- lh->buf = fd->buf;
lh->field = field;
+ lh->lookup = fn;
+ lh->priv = data;
/* Open database. */
error = sqlite3_open(DBNAME, &lh->handle);
if (error) {
@@ -269,10 +271,10 @@ mp3_list_start(int field, struct filler_data *fd, const char *query)
/*
* Insert data that should be searched for in the list. The data is assumed to
- * be dynamically allocated, and will be free'd when mp3_list_finish is called!
+ * be dynamically allocated, and will be free'd when mp3_lookup_finish is called!
*/
void
-mp3_list_insert(struct listhandle *lh, void *data, int type)
+mp3_lookup_insert(struct lookuphandle *lh, void *data, int type)
{
char *str;
int val;
@@ -290,11 +292,11 @@ mp3_list_insert(struct listhandle *lh, void *data, int type)
}
/*
- * Finish a statement buildup and use the filler to put the returned query data.
- * Free the handle when done.
+ * Finish a statement buildup and use the lookup function to operate on the
+ * returned data. Free the handle when done.
*/
void
-mp3_list_finish(struct listhandle *lh)
+mp3_lookup_finish(struct lookuphandle *lh)
{
char buf[1024];
const unsigned char *value;
@@ -309,11 +311,11 @@ mp3_list_finish(struct listhandle *lh)
case SQLITE_INTEGER:
val = sqlite3_column_int(lh->st, lh->field);
snprintf(buf, sizeof(buf), "%d", val);
- lh->filler(lh->buf, (const char *)buf, NULL, 0);
+ lh->lookup(lh->priv, (const char *)buf);
break;
case SQLITE_TEXT:
value = sqlite3_column_text(lh->st, lh->field);
- lh->filler(lh->buf, (const char *)value, NULL, 0);
+ lh->lookup(lh->priv, (const char *)value);
break;
// default:
// lh->filler(lh->buf, "UNKNOWN TYPE", NULL, 0);
@@ -401,24 +403,26 @@ mp3_gettoken(const char *str, int toknum)
* List artist given a path.
*/
void
-mp3_list_artist(const char *path, struct filler_data *fd)
+mp3_lookup_artist(const char *path, struct filler_data *fd)
{
- struct listhandle *lh;
+ struct lookuphandle *lh;
char *name, *album;
switch (mp3_numtoken(path)) {
case 1:
- lh = mp3_list_start(0, fd, "SELECT name FROM artist");
+ lh = mp3_lookup_start(0, fd, mp3_lookup_list,
+ "SELECT name FROM artist");
break;
case 2:
/* So, now we got to find out the artist and list its albums. */
name = mp3_gettoken(path, 2);
if (name == NULL)
break;
- lh = mp3_list_start(0, fd, "SELECT DISTINCT album FROM song, "
+ lh = mp3_lookup_start(0, fd, mp3_lookup_list,
+ "SELECT DISTINCT album FROM song, "
"artist WHERE song.artistname = artist.name AND artist.name"
" LIKE ?");
- mp3_list_insert(lh, name, LIST_DATATYPE_STRING);
+ mp3_lookup_insert(lh, name, LIST_DATATYPE_STRING);
break;
case 3:
/* List songs in an album. */
@@ -428,34 +432,40 @@ mp3_list_artist(const char *path, struct filler_data *fd)
album = mp3_gettoken(path, 3);
if (album == NULL)
break;
- lh = mp3_list_start(0, fd, "SELECT title FROM song, artist "
+ lh = mp3_lookup_start(0, fd, mp3_lookup_list,
+ "SELECT title FROM song, artist "
"WHERE song.artistname = artist.name AND artist.name "
"LIKE ? AND song.album LIKE ?");
- mp3_list_insert(lh, name, LIST_DATATYPE_STRING);
- mp3_list_insert(lh, album, LIST_DATATYPE_STRING);
+ mp3_lookup_insert(lh, name, LIST_DATATYPE_STRING);
+ mp3_lookup_insert(lh, album, LIST_DATATYPE_STRING);
break;
}
- mp3_list_finish(lh);
+ mp3_lookup_finish(lh);
}
+/*
+ * Looks up tracks given a genre, or all genres.
+ */
void
-mp3_list_genre(const char *path, struct filler_data *fd)
+mp3_lookup_genre(const char *path, struct filler_data *fd)
{
- struct listhandle *lh;
+ struct lookuphandle *lh;
char *genre, *album;
switch (mp3_numtoken(path)) {
case 1:
- lh = mp3_list_start(0, fd, "SELECT name FROM genre");
+ lh = mp3_lookup_start(0, fd, mp3_lookup_list,
+ "SELECT name FROM genre");
break;
case 2:
genre = mp3_gettoken(path, 2);
if (genre == NULL)
break;
- lh = mp3_list_start(0, fd, "SELECT DISTINCT album FROM song, "
+ lh = mp3_lookup_start(0, fd, mp3_lookup_list,
+ "SELECT DISTINCT album FROM song, "
"genre WHERE song.genrename = genre.name AND genre.name "
"LIKE ?");
- mp3_list_insert(lh, genre, LIST_DATATYPE_STRING);
+ mp3_lookup_insert(lh, genre, LIST_DATATYPE_STRING);
break;
case 3:
genre = mp3_gettoken(path, 2);
@@ -464,12 +474,25 @@ mp3_list_genre(const char *path, struct filler_data *fd)
album = mp3_gettoken(path, 3);
if (album == NULL)
break;
- lh = mp3_list_start(0, fd, "SELECT title FROM song, genre WHERE"
+ lh = mp3_lookup_start(0, fd, mp3_lookup_list,
+ "SELECT title FROM song, genre WHERE"
" song.genrename = genre.name AND genre.name LIKE ? "
" AND song.album LIKE ?");
- mp3_list_insert(lh, genre, LIST_DATATYPE_STRING);
- mp3_list_insert(lh, album, LIST_DATATYPE_STRING);
+ mp3_lookup_insert(lh, genre, LIST_DATATYPE_STRING);
+ mp3_lookup_insert(lh, album, LIST_DATATYPE_STRING);
break;
}
- mp3_list_finish(lh);
+ mp3_lookup_finish(lh);
+}
+
+/*
+ * Lookup function for filling given data into a filler.
+ */
+void
+mp3_lookup_list(void *data, const char *str)
+{
+ struct filler_data *fd;
+
+ fd = (struct filler_data *)data;
+ fd->filler(fd->buf, str, NULL, 0);
}
diff --git a/src/mp3_vnops.c b/src/mp3_vnops.c
index 1b5c031..fd90883 100755
--- a/src/mp3_vnops.c
+++ b/src/mp3_vnops.c
@@ -61,7 +61,7 @@ static int mp3_readdir (const char *path, void *buf, fuse_fill_dir_t filler,
off_t offset, struct fuse_file_info *fi)
{
struct filler_data fd;
- struct listhandle *lh;
+ struct lookuphandle *lh;
filler (buf, ".", NULL, 0);
filler (buf, "..", NULL, 0);
@@ -82,18 +82,20 @@ static int mp3_readdir (const char *path, void *buf, fuse_fill_dir_t filler,
* 3. Return the list of those mp3s.
*/
if (strncmp(path, "/Artists", 8) == 0) {
- mp3_list_artist(path, &fd);
+ mp3_lookup_artist(path, &fd);
return (0);
} else if (strncmp(path, "/Genres", 7) == 0) {
- mp3_list_genre(path, &fd);
+ mp3_lookup_genre(path, &fd);
return (0);
} else if (strcmp(path, "/Tracks") == 0) {
- lh = mp3_list_start(0, &fd, "SELECT title FROM song");
- mp3_list_finish(lh);
+ lh = mp3_lookup_start(0, &fd, mp3_lookup_list,
+ "SELECT title FROM song");
+ mp3_lookup_finish(lh);
return (0);
} else if (strcmp(path, "/Albums") == 0) {
- lh = mp3_list_start(0, &fd, "SELECT DISTINCT album FROM song");
- mp3_list_finish(lh);
+ lh = mp3_lookup_start(0, &fd, mp3_lookup_list,
+ "SELECT DISTINCT album FROM song");
+ mp3_lookup_finish(lh);
return (0);
}
@@ -102,7 +104,7 @@ static int mp3_readdir (const char *path, void *buf, fuse_fill_dir_t filler,
static int mp3_open (const char *path, struct fuse_file_info *fi)
{
- if (strcmp (path, "/Artists") == 0)
+ if (strcmp (path, "/Tracks") == 0)
return 0;
/*
* 1. Have a lookup cache for names?.