From a20070339319f16c5494c79e07903af3faff7d53 Mon Sep 17 00:00:00 2001 From: Julien BLACHE Date: Sun, 7 Jun 2009 18:58:02 +0200 Subject: [PATCH] Switch to the new database code --- src/DAAP2SQL.g | 6 +- src/Makefile.am | 8 +- src/RSP2SQL.g | 6 +- src/filescanner.c | 110 +++++++--------- src/filescanner.h | 2 +- src/filescanner_ffmpeg.c | 6 +- src/filescanner_m3u.c | 40 +++--- src/filescanner_urlfile.c | 2 +- src/httpd.c | 41 +++--- src/httpd_daap.c | 264 +++++++++++++++++--------------------- src/httpd_rsp.c | 246 ++++++++++++++--------------------- src/main.c | 22 +--- src/scan-flac.c | 4 +- src/scan-mpc.c | 3 +- src/scan-wma.c | 4 +- src/transcode.c | 2 +- 16 files changed, 334 insertions(+), 432 deletions(-) diff --git a/src/DAAP2SQL.g b/src/DAAP2SQL.g index 892c74d1..41850484 100644 --- a/src/DAAP2SQL.g +++ b/src/DAAP2SQL.g @@ -31,9 +31,7 @@ options { #include #include "logger.h" - #include "ff-dbstruct.h" - #include "db-generic.h" - #include "db-sql.h" + #include "db.h" #include "daap_query.h" } @@ -217,7 +215,7 @@ expr returns [ pANTLR3_STRING result, int valid ] goto STR_result_valid_0; /* ABORT */ } - escaped = (pANTLR3_UINT8)db_sql_escape_dup("\%q", val); + escaped = (pANTLR3_UINT8)db_escape_string((char *)val); if (!escaped) { DPRINTF(E_LOG, L_DAAP, "Could not escape value\n"); diff --git a/src/Makefile.am b/src/Makefile.am index 3833892b..95d1b474 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -24,6 +24,7 @@ ANTLR_PRODUCTS = mt_daapd_CPPFLAGS = -D_GNU_SOURCE @AVAHI_CFLAGS@ @SQLITE3_CFLAGS@ @FFMPEG_CFLAGS@ @CONFUSE_CFLAGS@ @TAGLIB_CFLAGS@ @MINIXML_CFLAGS@ mt_daapd_LDADD = @AVAHI_LIBS@ @SQLITE3_LIBS@ @FFMPEG_LIBS@ @CONFUSE_LIBS@ @FLAC_LIBS@ @TAGLIB_LIBS@ @LIBEVENT_LIBS@ @LIBAVL_LIBS@ @MINIXML_LIBS@ @ANTLR3C_LIBS@ mt_daapd_SOURCES = main.c \ + db.c db.h \ logger.c logger.h \ conffile.c conffile.h \ filescanner.c filescanner.h \ @@ -38,10 +39,7 @@ mt_daapd_SOURCES = main.c \ misc.c misc.h \ rsp_query.c rsp_query.h \ daap_query.c daap_query.h \ - db-generic.c db-generic.h \ scan-wma.c \ - db-sql-updates.c \ - db-sql.c db-sql.h db-sql-sqlite3.c db-sql-sqlite3.h\ $(FLACSRC) $(MUSEPACKSRC) nodist_mt_daapd_SOURCES = \ @@ -50,9 +48,7 @@ nodist_mt_daapd_SOURCES = \ EXTRA_DIST = \ $(ANTLR_GRAMMARS) \ scan-mpc.c \ - scan-flac.c \ - ff-dbstruct.h - + scan-flac.c # Let's help the dependencies a little. rsp_query.c: RSPLexer.h RSPParser.h RSP2SQL.h diff --git a/src/RSP2SQL.g b/src/RSP2SQL.g index e079c29b..50aaa5a5 100644 --- a/src/RSP2SQL.g +++ b/src/RSP2SQL.g @@ -32,9 +32,7 @@ options { #include #include "logger.h" - #include "ff-dbstruct.h" - #include "db-generic.h" - #include "db-sql.h" + #include "db.h" #include "misc.h" #include "rsp_query.h" } @@ -181,7 +179,7 @@ strcrit returns [ pANTLR3_STRING result, int valid ] goto strcrit_valid_0; /* ABORT */ } - escaped = db_sql_escape_dup("\%q", $s->getText($s)->chars); + escaped = db_escape_string((char *)$s->getText($s)->chars); if (!escaped) { DPRINTF(E_LOG, L_RSP, "Could not escape value\n"); diff --git a/src/filescanner.c b/src/filescanner.c index 5c9cbdc4..1ef68eda 100644 --- a/src/filescanner.c +++ b/src/filescanner.c @@ -43,7 +43,7 @@ #include #include "logger.h" -#include "db-generic.h" +#include "db.h" #include "filescanner.h" #include "conffile.h" @@ -144,55 +144,6 @@ pop_dir(void) return ret; } -static void -free_mfi(struct media_file_info *mfi) -{ - if (mfi->path) - free(mfi->path); - - if (mfi->fname) - free(mfi->fname); - - if (mfi->title) - free(mfi->title); - - if (mfi->artist) - free(mfi->artist); - - if (mfi->album) - free(mfi->album); - - if (mfi->genre) - free(mfi->genre); - - if (mfi->comment) - free(mfi->comment); - - if (mfi->type) - free(mfi->type); - - if (mfi->composer) - free(mfi->composer); - - if (mfi->orchestra) - free(mfi->orchestra); - - if (mfi->conductor) - free(mfi->conductor); - - if (mfi->grouping) - free(mfi->grouping); - - if (mfi->description) - free(mfi->description); - - if (mfi->codectype) - free(mfi->codectype); - - if (mfi->album_artist) - free(mfi->album_artist); -} - static void fixup_tags(struct media_file_info *mfi) @@ -256,32 +207,42 @@ fixup_tags(struct media_file_info *mfi) static void process_media_file(char *file, time_t mtime, off_t size, int compilation) { - struct media_file_info *db_mfi; struct media_file_info *mfi; char *filename; char *ext; int need_update; int ret; - db_mfi = db_fetch_path(NULL, file, 0); + mfi = db_file_fetch_bypath(file); - need_update = (!db_mfi || (db_mfi->db_timestamp < mtime) || db_mfi->force_update); - - db_dispose_item(db_mfi); + need_update = (!mfi || (mfi->db_timestamp < mtime) || mfi->force_update); if (!need_update) - return; - - mfi = (struct media_file_info *)malloc(sizeof(struct media_file_info)); - if (!mfi) { - DPRINTF(E_WARN, L_SCAN, "Out of memory for media_file_info\n"); + db_file_ping(mfi->id); - db_dispose_item(db_mfi); + free_mfi(mfi, 0); return; } + if (mfi) + { + ret = mfi->id; + free_mfi(mfi, 1); + } + else + { + ret = 0; + mfi = (struct media_file_info *)malloc(sizeof(struct media_file_info)); + if (!mfi) + { + DPRINTF(E_WARN, L_SCAN, "Out of memory for media_file_info\n"); + return; + } + } + memset(mfi, 0, sizeof(struct media_file_info)); + mfi->id = ret; filename = strrchr(file, '/'); if (!filename) @@ -340,8 +301,7 @@ process_media_file(char *file, time_t mtime, off_t size, int compilation) { DPRINTF(E_LOG, L_SCAN, "Could not extract metadata for %s\n"); - free_mfi(mfi); - free(mfi); + free_mfi(mfi, 0); return; } @@ -350,10 +310,12 @@ process_media_file(char *file, time_t mtime, off_t size, int compilation) fixup_tags(mfi); - db_add(NULL, mfi, NULL); + if (mfi->id == 0) + db_file_add(mfi); + else + db_file_update(mfi); - free_mfi(mfi); - free(mfi); + free_mfi(mfi, 0); } static void @@ -669,6 +631,8 @@ bulk_scan(void) } } + db_pl_update_all(); + if (playlists) process_deferred_playlists(); @@ -681,10 +645,22 @@ bulk_scan(void) static void * filescanner(void *arg) { + int ret; + + ret = db_perthread_init(); + if (ret < 0) + { + DPRINTF(E_LOG, L_SCAN, "Error: DB init failed\n"); + + pthread_exit(NULL); + } + bulk_scan(); if (!scan_exit) { + db_pl_update_all(); + /* Enable inotify */ event_add(&inoev, NULL); @@ -694,6 +670,8 @@ filescanner(void *arg) if (!scan_exit) DPRINTF(E_FATAL, L_SCAN, "Scan event loop terminated ahead of time!\n"); + db_perthread_deinit(); + pthread_exit(NULL); } diff --git a/src/filescanner.h b/src/filescanner.h index 51c457b6..5e2f1d03 100644 --- a/src/filescanner.h +++ b/src/filescanner.h @@ -2,7 +2,7 @@ #ifndef __FILESCANNER_H__ #define __FILESCANNER_H__ -#include "ff-dbstruct.h" +#include "db.h" int filescanner_init(void); diff --git a/src/filescanner_ffmpeg.c b/src/filescanner_ffmpeg.c index 26db05a6..e4572f79 100644 --- a/src/filescanner_ffmpeg.c +++ b/src/filescanner_ffmpeg.c @@ -41,12 +41,12 @@ /* Legacy format-specific scanners */ -extern int scan_get_wmainfo(char *filename, MP3FILE *pmp3); +extern int scan_get_wmainfo(char *filename, struct media_file_info *pmp3); #ifdef FLAC -extern int scan_get_flacinfo(char *filename, MP3FILE *pmp3); +extern int scan_get_flacinfo(char *filename, struct media_file_info *pmp3); #endif #ifdef MUSEPACK -extern int scan_get_mpcinfo(char *filename, MP3FILE *pmp3); +extern int scan_get_mpcinfo(char *filename, struct media_file_info *pmp3); #endif diff --git a/src/filescanner_m3u.c b/src/filescanner_m3u.c index 1ead3bdf..c2029674 100644 --- a/src/filescanner_m3u.c +++ b/src/filescanner_m3u.c @@ -34,8 +34,7 @@ #include #include "logger.h" -#include "ff-dbstruct.h" -#include "db-generic.h" +#include "db.h" #include "filescanner.h" @@ -44,7 +43,6 @@ scan_m3u_playlist(char *file) { FILE *fp; struct playlist_info *pli; - struct media_file_info *mfi; struct stat sb; char buf[PATH_MAX]; char rel_entry[PATH_MAX]; @@ -52,9 +50,9 @@ scan_m3u_playlist(char *file) char *entry; char *filename; char *ptr; - char *db_errmsg; size_t len; int pl_id; + int mf_id; int ret; DPRINTF(E_INFO, L_SCAN, "Processing static playlist: %s\n", file); @@ -73,7 +71,7 @@ scan_m3u_playlist(char *file) else filename++; - pli = db_fetch_playlist(NULL, file, 0); + pli = db_pl_fetch_bypath(file); if (pli) { @@ -81,15 +79,17 @@ scan_m3u_playlist(char *file) { DPRINTF(E_DBG, L_SCAN, "Playlist up-to-date\n"); - db_dispose_playlist(pli); + db_pl_ping(pli->id); + + free_pli(pli, 0); return; } else { DPRINTF(E_DBG, L_SCAN, "Playlist needs update\n"); - db_delete_playlist(NULL, pli->id); - db_dispose_playlist(pli); + db_pl_delete(pli->id); + free_pli(pli, 0); } } @@ -113,13 +113,11 @@ scan_m3u_playlist(char *file) if (ptr) *ptr = '.'; - ret = db_add_playlist(&db_errmsg, buf, PL_STATICFILE, NULL, file, 0, &pl_id); - - if (ret != DB_E_SUCCESS) + ret = db_pl_add(buf, file, &pl_id); + if (ret < 0) { - DPRINTF(E_LOG, L_SCAN, "Error adding m3u playlist '%s': %s\n", file, db_errmsg); + DPRINTF(E_LOG, L_SCAN, "Error adding m3u playlist '%s'\n", file); - free(db_errmsg); return; } @@ -197,19 +195,19 @@ scan_m3u_playlist(char *file) DPRINTF(E_DBG, L_SCAN, "Checking %s\n", filename); - mfi = db_fetch_path(&db_errmsg, filename, 0); - if (!mfi) + ret = db_file_id_bypath(filename, &mf_id); + if (ret < 0) { - DPRINTF(E_WARN, L_SCAN, "Playlist entry '%s' not found: %s\n", entry, db_errmsg); + DPRINTF(E_WARN, L_SCAN, "Playlist entry '%s' not found\n", entry); - free(db_errmsg); free(filename); continue; } - DPRINTF(E_DBG, L_SCAN, "Resolved %s to %d\n", filename, mfi->id); - db_add_playlist_item(NULL, pl_id, mfi->id); - db_dispose_item(mfi); + DPRINTF(E_DBG, L_SCAN, "Resolved %s to %d\n", filename, mf_id); + ret = db_pl_add_item(pl_id, mf_id); + if (ret < 0) + DPRINTF(E_WARN, L_SCAN, "Could not add %s to playlist\n", filename); } if (!feof(fp)) @@ -222,5 +220,7 @@ scan_m3u_playlist(char *file) fclose(fp); + db_pl_update(pl_id); + DPRINTF(E_INFO, L_SCAN, "Done processing playlist\n"); } diff --git a/src/filescanner_urlfile.c b/src/filescanner_urlfile.c index 86ccc3a9..7620a685 100644 --- a/src/filescanner_urlfile.c +++ b/src/filescanner_urlfile.c @@ -31,7 +31,7 @@ #include #include "logger.h" -#include "ff-dbstruct.h" +#include "db.h" #include "filescanner.h" diff --git a/src/httpd.c b/src/httpd.c index dba0bcb0..73004033 100644 --- a/src/httpd.c +++ b/src/httpd.c @@ -35,8 +35,7 @@ #include "evhttp/evhttp.h" #include "logger.h" -#include "ff-dbstruct.h" -#include "db-generic.h" +#include "db.h" #include "conffile.h" #include "misc.h" #include "httpd.h" @@ -199,7 +198,7 @@ stream_chunk_xcode_cb(int fd, short event, void *arg) if (!st->marked && (st->offset > ((st->size * 80) / 100))) { st->marked = 1; - db_playcount_increment(NULL, st->id); + db_file_inc_playcount(st->id); } return; @@ -245,7 +244,7 @@ stream_chunk_raw_cb(int fd, short event, void *arg) if (!st->marked && (st->offset > ((st->size * 80) / 100))) { st->marked = 1; - db_playcount_increment(NULL, st->id); + db_file_inc_playcount(st->id); } } @@ -302,7 +301,7 @@ httpd_stream_file(struct evhttp_request *req, int id) } } - mfi = db_fetch_item(NULL, id); + mfi = db_file_fetch_byid(id); if (!mfi) { DPRINTF(E_LOG, L_HTTPD, "Item %d not found\n", id); @@ -315,7 +314,7 @@ httpd_stream_file(struct evhttp_request *req, int id) { evhttp_send_error(req, 500, "Cannot stream radio station"); - db_dispose_item(mfi); + free_mfi(mfi, 0); return; } @@ -326,7 +325,7 @@ httpd_stream_file(struct evhttp_request *req, int id) evhttp_send_error(req, HTTP_SERVUNAVAIL, "Internal Server Error"); - db_dispose_item(mfi); + free_mfi(mfi, 0); return; } memset(st, 0, sizeof(struct stream_ctx)); @@ -348,7 +347,7 @@ httpd_stream_file(struct evhttp_request *req, int id) evhttp_send_error(req, HTTP_SERVUNAVAIL, "Internal Server Error"); free(st); - db_dispose_item(mfi); + free_mfi(mfi, 0); return; } @@ -370,7 +369,7 @@ httpd_stream_file(struct evhttp_request *req, int id) evhttp_send_error(req, HTTP_NOTFOUND, "Not Found"); free(st); - db_dispose_item(mfi); + free_mfi(mfi, 0); return; } @@ -383,7 +382,7 @@ httpd_stream_file(struct evhttp_request *req, int id) close(st->fd); free(st); - db_dispose_item(mfi); + free_mfi(mfi, 0); return; } st->size = sb.st_size; @@ -397,7 +396,7 @@ httpd_stream_file(struct evhttp_request *req, int id) close(st->fd); free(st); - db_dispose_item(mfi); + free_mfi(mfi, 0); return; } st->offset = offset; @@ -425,7 +424,7 @@ httpd_stream_file(struct evhttp_request *req, int id) else close(st->fd); free(st); - db_dispose_item(mfi); + free_mfi(mfi, 0); return; } @@ -443,7 +442,7 @@ httpd_stream_file(struct evhttp_request *req, int id) close(st->fd); evbuffer_free(st->evbuf); free(st); - db_dispose_item(mfi); + free_mfi(mfi, 0); return; } @@ -464,7 +463,7 @@ httpd_stream_file(struct evhttp_request *req, int id) close(st->fd); evbuffer_free(st->evbuf); free(st); - db_dispose_item(mfi); + free_mfi(mfi, 0); return; } @@ -494,7 +493,7 @@ httpd_stream_file(struct evhttp_request *req, int id) DPRINTF(E_INFO, L_HTTPD, "Kicking off streaming for %s\n", mfi->path); - db_dispose_item(mfi); + free_mfi(mfi, 0); } /* Thread: httpd */ @@ -745,11 +744,23 @@ httpd_gen_cb(struct evhttp_request *req, void *arg) static void * httpd(void *arg) { + int ret; + + ret = db_perthread_init(); + if (ret < 0) + { + DPRINTF(E_LOG, L_HTTPD, "Error: DB init failed\n"); + + pthread_exit(NULL); + } + event_base_dispatch(evbase_httpd); if (!httpd_exit) DPRINTF(E_FATAL, L_HTTPD, "HTTPd event loop terminated ahead of time!\n"); + db_perthread_deinit(); + pthread_exit(NULL); } diff --git a/src/httpd_daap.c b/src/httpd_daap.c index 1fd1b11e..6ae42e0a 100644 --- a/src/httpd_daap.c +++ b/src/httpd_daap.c @@ -26,6 +26,7 @@ #include #include #include +#include #include #include #include @@ -39,8 +40,7 @@ #include #include "logger.h" -#include "ff-dbstruct.h" -#include "db-generic.h" +#include "db.h" #include "conffile.h" #include "misc.h" #include "httpd.h" @@ -569,16 +569,18 @@ dmap_find_field(uint32_t hash) return (struct dmap_field_map *)node->item; } + static void -get_query_params(struct evkeyvalq *query, DBQUERYINFO *qi) +get_query_params(struct evkeyvalq *query, struct query_params *qp) { const char *param; char *ptr; - int val; + int low; + int high; int ret; - qi->index_low = 0; - qi->index_high = 9999999; /* Arbitrarily high number */ + low = 0; + high = -1; /* No limit */ param = evhttp_find_header(query, "index"); if (param) @@ -587,38 +589,40 @@ get_query_params(struct evkeyvalq *query, DBQUERYINFO *qi) DPRINTF(E_LOG, L_DAAP, "Unsupported index range: %s\n", param); else { - ret = safe_atoi(param, &val); + ret = safe_atoi(param, &low); if (ret < 0) DPRINTF(E_LOG, L_DAAP, "Could not parse index range: %s\n", param); else { - qi->index_low = val; - ptr = strchr(param, '-'); if (!ptr) /* single item */ - qi->index_high = qi->index_low; + high = low; else { ptr++; if (*ptr != '\0') /* low-high */ { - ret = safe_atoi(ptr, &val); + ret = safe_atoi(ptr, &high); if (ret < 0) DPRINTF(E_LOG, L_DAAP, "Could not parse high index in range: %s\n", param); - else - qi->index_high = val; } } } } - DPRINTF(E_DBG, L_DAAP, "Index range %s: low %d, high %d\n", param, qi->index_low, qi->index_high); + DPRINTF(E_DBG, L_DAAP, "Index range %s: low %d, high %d (offset %d, limit %d)\n", param, low, high, qp->offset, qp->limit); } - if (qi->index_high < qi->index_low) - qi->index_high = 9999999; /* Arbitrarily high number */ + if (high < low) + high = -1; /* No limit */ - qi->index_type = indexTypeSub; + qp->offset = low; + if (high < 0) + qp->limit = -1; /* No limit */ + else + qp->limit = (high - low) + 1; + + qp->idx_type = I_SUB; param = evhttp_find_header(query, "query"); if (!param) @@ -628,13 +632,10 @@ get_query_params(struct evkeyvalq *query, DBQUERYINFO *qi) { DPRINTF(E_DBG, L_DAAP, "DAAP browse query filter: %s\n", param); - qi->filter = daap_query_parse_sql(param); - if (!qi->filter) + qp->filter = daap_query_parse_sql(param); + if (!qp->filter) DPRINTF(E_LOG, L_DAAP, "Ignoring improper DAAP query\n"); } - - qi->want_count = 1; - qi->correct_order = 1; } static void @@ -879,7 +880,7 @@ daap_reply_update(struct evhttp_request *req, struct evbuffer *evbuf, char **uri { int ret; - /* Just send back the current db revision. + /* Just send back the current time. * * This probably doesn't cut it, but then again we don't claim to support * updates, so... that support should be added eventually. @@ -895,8 +896,8 @@ daap_reply_update(struct evhttp_request *req, struct evbuffer *evbuf, char **uri } dmap_add_container(evbuf, "mupd", 24); - dmap_add_int(evbuf, "mstt", 200); /* 12 */ - dmap_add_int(evbuf, "musr", db_revision()); /* 12 */ + dmap_add_int(evbuf, "mstt", 200); /* 12 */ + dmap_add_int(evbuf, "musr", (int)time(NULL)); /* 12 */ evhttp_send_reply(req, HTTP_OK, "OK", evbuf); } @@ -904,12 +905,10 @@ daap_reply_update(struct evhttp_request *req, struct evbuffer *evbuf, char **uri static void daap_reply_dblist(struct evhttp_request *req, struct evbuffer *evbuf, char **uri, struct evkeyvalq *query) { - int count; - cfg_t *lib; - char *db_errmsg; char *name; int namelen; + int count; int ret; lib = cfg_getnsec(cfg, "library", 0); @@ -936,23 +935,21 @@ daap_reply_dblist(struct evhttp_request *req, struct evbuffer *evbuf, char **uri dmap_add_long(evbuf, "mper", 1); /* 16 */ dmap_add_string(evbuf, "minm", name); /* 8 + namelen */ - ret = db_get_song_count(&db_errmsg, &count); - if (ret != DB_E_SUCCESS) + ret = db_files_get_count(&count); + if (ret < 0) { - DPRINTF(E_LOG, L_DAAP, "Could not get song count: %s\n", db_errmsg); + DPRINTF(E_LOG, L_DAAP, "Could not get song count\n"); count = 0; - free(db_errmsg); } dmap_add_int(evbuf, "mimc", count); /* 12 */ - ret = db_get_playlist_count(&db_errmsg, &count); - if (ret != DB_E_SUCCESS) + ret = db_pl_get_count(&count); + if (ret < 0) { - DPRINTF(E_LOG, L_DAAP, "Could not get playlist count: %s\n", db_errmsg); + DPRINTF(E_LOG, L_DAAP, "Could not get playlist count\n"); count = 0; - free(db_errmsg); } dmap_add_int(evbuf, "mctc", count); /* 12 */ @@ -962,12 +959,11 @@ daap_reply_dblist(struct evhttp_request *req, struct evbuffer *evbuf, char **uri static void daap_reply_songlist_generic(struct evhttp_request *req, struct evbuffer *evbuf, int playlist, struct evkeyvalq *query) { - DBQUERYINFO qi; - struct db_media_file_info *dbmfi; + struct query_params qp; + struct db_media_file_info dbmfi; struct evbuffer *song; struct evbuffer *songlist; struct dmap_field_map *dfm; - char *db_errmsg; const char *param; char *tag; char **strval; @@ -1071,26 +1067,29 @@ daap_reply_songlist_generic(struct evhttp_request *req, struct evbuffer *evbuf, nmeta = 0; } - memset(&qi, 0, sizeof(DBQUERYINFO)); - get_query_params(query, &qi); - qi.query_type = queryTypePlaylistItems; + memset(&qp, 0, sizeof(struct query_params)); + get_query_params(query, &qp); - if (playlist != -1) - qi.playlist_id = playlist; - - ret = db_enum_start(&db_errmsg, &qi); - if (ret != DB_E_SUCCESS) + if (playlist < 2) + qp.type = Q_ITEMS; + else { - DPRINTF(E_LOG, L_DAAP, "Could not fetch song list: %s\n", db_errmsg); + qp.type = Q_PLITEMS; + qp.pl_id = playlist; + } - daap_send_error(req, tag, db_errmsg); + ret = db_query_start(&qp); + if (ret < 0) + { + DPRINTF(E_LOG, L_DAAP, "Could not start query\n"); + + daap_send_error(req, tag, "Could not stat query"); - free(db_errmsg); free(meta); evbuffer_free(song); evbuffer_free(songlist); - if (qi.filter) - free(qi.filter); + if (qp.filter) + free(qp.filter); return; } @@ -1098,11 +1097,11 @@ daap_reply_songlist_generic(struct evhttp_request *req, struct evbuffer *evbuf, want_asdk = 0; oom = 0; nsongs = 0; - while (((ret = db_enum_fetch_row(&db_errmsg, &dbmfi, &qi)) == DB_E_SUCCESS) && (dbmfi)) + while (((ret = db_query_fetch_file(&qp, &dbmfi)) == 0) && (dbmfi.id)) { nsongs++; - transcode = transcode_needed(req->input_headers, dbmfi->codectype); + transcode = transcode_needed(req->input_headers, dbmfi.codectype); i = -1; while (1) @@ -1151,7 +1150,7 @@ daap_reply_songlist_generic(struct evhttp_request *req, struct evbuffer *evbuf, DPRINTF(E_DBG, L_DAAP, "Investigating %s\n", dfm->desc); - strval = (char **) ((char *)dbmfi + dfm->mfi_offset); + strval = (char **) ((char *)&dbmfi + dfm->mfi_offset); if (!(*strval) || (**strval == '\0')) continue; @@ -1174,7 +1173,7 @@ daap_reply_songlist_generic(struct evhttp_request *req, struct evbuffer *evbuf, case dbmfi_offsetof(bitrate): val = 0; - ret = safe_atoi(dbmfi->samplerate, &val); + ret = safe_atoi(dbmfi.samplerate, &val); if ((ret < 0) || (val == 0)) val = 1411; else @@ -1220,14 +1219,14 @@ daap_reply_songlist_generic(struct evhttp_request *req, struct evbuffer *evbuf, if (want_mikd) { /* dmap.itemkind must come first */ - ret = safe_atoi(dbmfi->item_kind, &val); + ret = safe_atoi(dbmfi.item_kind, &val); if (ret < 0) val = 2; /* music by default */ dmap_add_char(songlist, "mikd", val); } if (want_asdk) { - ret = safe_atoi(dbmfi->data_kind, &val); + ret = safe_atoi(dbmfi.data_kind, &val); if (ret < 0) val = 0; dmap_add_char(songlist, "asdk", val); @@ -1248,34 +1247,25 @@ daap_reply_songlist_generic(struct evhttp_request *req, struct evbuffer *evbuf, evbuffer_free(song); - if (qi.filter) - free(qi.filter); + if (qp.filter) + free(qp.filter); - if (ret != DB_E_SUCCESS) + if (ret < 0) { - DPRINTF(E_LOG, L_DAAP, "Error fetching results: %s\n", db_errmsg); + DPRINTF(E_LOG, L_DAAP, "Error fetching results\n"); - daap_send_error(req, tag, db_errmsg); - - free(db_errmsg); + daap_send_error(req, tag, "Error fetching query results"); + db_query_end(&qp); evbuffer_free(songlist); return; } - ret = db_enum_end(&db_errmsg); - if (ret != DB_E_SUCCESS) - { - DPRINTF(E_LOG, L_DAAP, "Error cleaning up DB enum: %s\n", db_errmsg); - - free(db_errmsg); - } - if (oom) { DPRINTF(E_LOG, L_DAAP, "Could not add song to song list for DAAP song list reply\n"); daap_send_error(req, tag, "Out of memory"); - + db_query_end(&qp); evbuffer_free(songlist); return; } @@ -1284,10 +1274,12 @@ daap_reply_songlist_generic(struct evhttp_request *req, struct evbuffer *evbuf, dmap_add_container(evbuf, tag, EVBUFFER_LENGTH(songlist) + 53); dmap_add_int(evbuf, "mstt", 200); /* 12 */ dmap_add_char(evbuf, "muty", 0); /* 9 */ - dmap_add_int(evbuf, "mtco", qi.specifiedtotalcount); /* 12 */ + dmap_add_int(evbuf, "mtco", qp.results); /* 12 */ dmap_add_int(evbuf, "mrco", nsongs); /* 12 */ dmap_add_container(evbuf, "mlcl", EVBUFFER_LENGTH(songlist)); + db_query_end(&qp); + ret = evbuffer_add_buffer(evbuf, songlist); evbuffer_free(songlist); if (ret < 0) @@ -1327,13 +1319,12 @@ daap_reply_plsonglist(struct evhttp_request *req, struct evbuffer *evbuf, char * static void daap_reply_playlists(struct evhttp_request *req, struct evbuffer *evbuf, char **uri, struct evkeyvalq *query) { - DBQUERYINFO qi; + struct query_params qp; + struct db_playlist_info dbpli; struct evbuffer *playlistlist; struct evbuffer *playlist; - struct db_playlist_info *dbpli; struct dmap_field_map *dfm; const char *param; - char *db_errmsg; char **strval; uint32_t *meta; int nmeta; @@ -1415,29 +1406,28 @@ daap_reply_playlists(struct evhttp_request *req, struct evbuffer *evbuf, char ** return; } - memset(&qi, 0, sizeof(DBQUERYINFO)); - get_query_params(query, &qi); - qi.query_type = queryTypePlaylists; + memset(&qp, 0, sizeof(struct query_params)); + get_query_params(query, &qp); + qp.type = Q_PL; - ret = db_enum_start(&db_errmsg, &qi); - if (ret != DB_E_SUCCESS) + ret = db_query_start(&qp); + if (ret < 0) { - DPRINTF(E_LOG, L_DAAP, "Could not fetch playlist list: %s\n", db_errmsg); + DPRINTF(E_LOG, L_DAAP, "Could not start query\n"); - daap_send_error(req, "aply", db_errmsg); + daap_send_error(req, "aply", "Could not start query"); - free(db_errmsg); free(meta); evbuffer_free(playlist); evbuffer_free(playlistlist); - if (qi.filter) - free(qi.filter); + if (qp.filter) + free(qp.filter); return; } npls = 0; oom = 0; - while (((ret = db_enum_fetch_row(&db_errmsg, (struct db_media_file_info **)&dbpli, &qi)) == DB_E_SUCCESS) && (dbpli)) + while (((ret = db_query_fetch_pl(&qp, &dbpli)) == 0) && (dbpli.id)) { npls++; @@ -1451,11 +1441,11 @@ daap_reply_playlists(struct evhttp_request *req, struct evbuffer *evbuf, char ** if (meta[i] == 0x670fc55e) { val = 0; - ret = safe_atoi(dbpli->type, &val); + ret = safe_atoi(dbpli.type, &val); if ((ret == 0) && (val == 1)) { val = 1; - ret = safe_atoi(dbpli->id, &val); + ret = safe_atoi(dbpli.id, &val); if ((ret == 0) && (val != 1)) dmap_add_char(playlist, "aeSP", 1); } @@ -1474,7 +1464,7 @@ daap_reply_playlists(struct evhttp_request *req, struct evbuffer *evbuf, char ** if (dfm->pli_offset < 0) continue; - strval = (char **) ((char *)dbpli + dfm->pli_offset); + strval = (char **) ((char *)&dbpli + dfm->pli_offset); if (!(*strval) || (**strval == '\0')) continue; @@ -1486,13 +1476,13 @@ daap_reply_playlists(struct evhttp_request *req, struct evbuffer *evbuf, char ** /* Item count (mimc) */ val = 0; - ret = safe_atoi(dbpli->items, &val); + ret = safe_atoi(dbpli.items, &val); if ((ret == 0) && (val > 0)) dmap_add_int(playlist, "mimc", val); /* Base playlist (abpl), id = 1 */ val = 0; - ret = safe_atoi(dbpli->id, &val); + ret = safe_atoi(dbpli.id, &val); if ((ret == 0) && (val == 1)) dmap_add_char(playlist, "abpl", 1); @@ -1512,34 +1502,25 @@ daap_reply_playlists(struct evhttp_request *req, struct evbuffer *evbuf, char ** free(meta); evbuffer_free(playlist); - if (qi.filter) - free(qi.filter); + if (qp.filter) + free(qp.filter); - if (ret != DB_E_SUCCESS) + if (ret < 0) { - DPRINTF(E_LOG, L_DAAP, "Error fetching results: %s\n", db_errmsg); + DPRINTF(E_LOG, L_DAAP, "Error fetching results\n"); - daap_send_error(req, "aply", db_errmsg); - - free(db_errmsg); + daap_send_error(req, "aply", "Error fetching query results"); + db_query_end(&qp); evbuffer_free(playlistlist); return; } - ret = db_enum_end(&db_errmsg); - if (ret != DB_E_SUCCESS) - { - DPRINTF(E_LOG, L_DAAP, "Error cleaning up DB enum: %s\n", db_errmsg); - - free(db_errmsg); - } - if (oom) { DPRINTF(E_LOG, L_DAAP, "Could not add playlist to playlist list for DAAP playlists reply\n"); daap_send_error(req, "aply", "Out of memory"); - + db_query_end(&qp); evbuffer_free(playlistlist); return; } @@ -1548,10 +1529,12 @@ daap_reply_playlists(struct evhttp_request *req, struct evbuffer *evbuf, char ** dmap_add_container(evbuf, "aply", EVBUFFER_LENGTH(playlistlist) + 53); dmap_add_int(evbuf, "mstt", 200); /* 12 */ dmap_add_char(evbuf, "muty", 0); /* 9 */ - dmap_add_int(evbuf, "mtco", qi.specifiedtotalcount); /* 12 */ + dmap_add_int(evbuf, "mtco", qp.results); /* 12 */ dmap_add_int(evbuf,"mrco", npls); /* 12 */ dmap_add_container(evbuf, "mlcl", EVBUFFER_LENGTH(playlistlist)); + db_query_end(&qp); + ret = evbuffer_add_buffer(evbuf, playlistlist); evbuffer_free(playlistlist); if (ret < 0) @@ -1568,35 +1551,34 @@ daap_reply_playlists(struct evhttp_request *req, struct evbuffer *evbuf, char ** static void daap_reply_browse(struct evhttp_request *req, struct evbuffer *evbuf, char **uri, struct evkeyvalq *query) { - DBQUERYINFO qi; + struct query_params qp; struct evbuffer *itemlist; - char **item; + char *browse_item; char *tag; - char *db_errmsg; int nitems; int ret; - memset(&qi, 0, sizeof(DBQUERYINFO)); + memset(&qp, 0, sizeof(struct query_params)); if (strcmp(uri[3], "artists") == 0) { tag = "abar"; - qi.query_type = queryTypeBrowseArtists; + qp.type = Q_BROWSE_ARTISTS; } else if (strcmp(uri[3], "genres") == 0) { tag = "abgn"; - qi.query_type = queryTypeBrowseGenres; + qp.type = Q_BROWSE_GENRES; } else if (strcmp(uri[3], "albums") == 0) { tag = "abal"; - qi.query_type = queryTypeBrowseAlbums; + qp.type = Q_BROWSE_ALBUMS; } else if (strcmp(uri[3], "composers") == 0) { tag = "abcp"; - qi.query_type = queryTypeBrowseComposers; + qp.type = Q_BROWSE_COMPOSERS; } else { @@ -1636,58 +1618,50 @@ daap_reply_browse(struct evhttp_request *req, struct evbuffer *evbuf, char **uri return; } - get_query_params(query, &qi); + get_query_params(query, &qp); - ret = db_enum_start(&db_errmsg, &qi); - if (ret != DB_E_SUCCESS) + ret = db_query_start(&qp); + if (ret < 0) { - DPRINTF(E_LOG, L_DAAP, "Could not fetch browse item list: %s\n", db_errmsg); + DPRINTF(E_LOG, L_DAAP, "Could not start query\n"); - daap_send_error(req, "abro", db_errmsg); + daap_send_error(req, "abro", "Could not start query"); - free(db_errmsg); evbuffer_free(itemlist); - if (qi.filter) - free(qi.filter); + if (qp.filter) + free(qp.filter); return; } nitems = 0; - while (((ret = db_enum_fetch_row(&db_errmsg, (struct db_media_file_info **)&item, &qi)) == DB_E_SUCCESS) && (item)) + while (((ret = db_query_fetch_string(&qp, &browse_item)) == 0) && (browse_item)) { nitems++; - dmap_add_string(itemlist, "mlit", *item); + dmap_add_string(itemlist, "mlit", browse_item); } - if (qi.filter) - free(qi.filter); + if (qp.filter) + free(qp.filter); - if (ret != DB_E_SUCCESS) + if (ret < 0) { - DPRINTF(E_LOG, L_DAAP, "Error fetching results: %s\n", db_errmsg); + DPRINTF(E_LOG, L_DAAP, "Error fetching results\n"); - daap_send_error(req, "abro", db_errmsg); - - free(db_errmsg); + daap_send_error(req, "abro", "Error fetching query results"); + db_query_end(&qp); evbuffer_free(itemlist); return; } - ret = db_enum_end(&db_errmsg); - if (ret != DB_E_SUCCESS) - { - DPRINTF(E_LOG, L_DAAP, "Error cleaning up DB enum: %s\n", db_errmsg); - - free(db_errmsg); - } - dmap_add_container(evbuf, "abro", EVBUFFER_LENGTH(itemlist) + 44); dmap_add_int(evbuf, "mstt", 200); /* 12 */ - dmap_add_int(evbuf, "mtco", qi.specifiedtotalcount); /* 12 */ + dmap_add_int(evbuf, "mtco", qp.results); /* 12 */ dmap_add_int(evbuf, "mrco", nitems); /* 12 */ dmap_add_container(evbuf, tag, EVBUFFER_LENGTH(itemlist)); + db_query_end(&qp); + ret = evbuffer_add_buffer(evbuf, itemlist); evbuffer_free(itemlist); if (ret < 0) diff --git a/src/httpd_rsp.c b/src/httpd_rsp.c index c6ad177e..edfa0711 100644 --- a/src/httpd_rsp.c +++ b/src/httpd_rsp.c @@ -38,8 +38,7 @@ #include #include "logger.h" -#include "ff-dbstruct.h" -#include "db-generic.h" +#include "db.h" #include "conffile.h" #include "misc.h" #include "httpd.h" @@ -176,16 +175,16 @@ static void rsp_send_error(struct evhttp_request *req, char *errmsg); static int -get_query_params(struct evhttp_request *req, struct evkeyvalq *query, DBQUERYINFO *qi, int *offset, int *limit) +get_query_params(struct evhttp_request *req, struct evkeyvalq *query, struct query_params *qp) { const char *param; int ret; - *offset = 0; + qp->offset = 0; param = evhttp_find_header(query, "offset"); if (param) { - ret = safe_atoi(param, offset); + ret = safe_atoi(param, &qp->offset); if (ret < 0) { rsp_send_error(req, "Invalid offset"); @@ -193,11 +192,11 @@ get_query_params(struct evhttp_request *req, struct evkeyvalq *query, DBQUERYINF } } - *limit = 0; + qp->limit = 0; param = evhttp_find_header(query, "limit"); if (param) { - ret = safe_atoi(param, limit); + ret = safe_atoi(param, &qp->limit); if (ret < 0) { rsp_send_error(req, "Invalid limit"); @@ -205,29 +204,18 @@ get_query_params(struct evhttp_request *req, struct evkeyvalq *query, DBQUERYINF } } - if (*offset || *limit) - { - qi->index_low = *offset; - qi->index_high = *offset + *limit - 1; - - if (qi->index_high < qi->index_low) - qi->index_high = 9999999; /* Arbitrarily high number */ - - qi->index_type = indexTypeSub; - } + if (qp->offset || qp->limit) + qp->idx_type = I_SUB; else - qi->index_type = indexTypeNone; - - qi->want_count = 1; - qi->correct_order = 1; + qp->idx_type = I_NONE; param = evhttp_find_header(query, "query"); if (param) { DPRINTF(E_DBG, L_RSP, "RSP browse query filter: %s\n", param); - qi->filter = rsp_query_parse_sql(param); - if (!qi->filter) + qp->filter = rsp_query_parse_sql(param); + if (!qp->filter) DPRINTF(E_LOG, L_RSP, "Ignoring improper RSP query\n"); } @@ -291,18 +279,15 @@ rsp_reply_info(struct evhttp_request *req, char **uri, struct evkeyvalq *query) mxml_node_t *node; cfg_t *lib; char *library; - char *db_errmsg; int songcount; int ret; - ret = db_get_song_count(&db_errmsg, &songcount); - if (ret != DB_E_SUCCESS) + ret = db_files_get_count(&songcount); + if (ret < 0) { - DPRINTF(E_LOG, L_RSP, "Could not get song count: %s\n", db_errmsg); + DPRINTF(E_LOG, L_RSP, "Could not get song count\n"); songcount = 0; - - free(db_errmsg); } lib = cfg_getnsec(cfg, "library", 0); @@ -363,10 +348,9 @@ rsp_reply_info(struct evhttp_request *req, char **uri, struct evkeyvalq *query) static void rsp_reply_db(struct evhttp_request *req, char **uri, struct evkeyvalq *query) { - DBQUERYINFO qi; - struct db_playlist_info *dbpli; + struct query_params qp; + struct db_playlist_info dbpli; struct evbuffer *evbuf; - char *db_errmsg; char **strval; mxml_node_t *reply; mxml_node_t *status; @@ -376,20 +360,17 @@ rsp_reply_db(struct evhttp_request *req, char **uri, struct evkeyvalq *query) int i; int ret; - memset(&qi, 0, sizeof(DBQUERYINFO)); + memset(&qp, 0, sizeof(struct db_playlist_info)); - qi.query_type = queryTypePlaylists; - qi.index_type = indexTypeNone; - qi.want_count = 1; + qp.type = Q_PL; + qp.idx_type = I_NONE; - ret = db_enum_start(&db_errmsg, &qi); - if (ret != DB_E_SUCCESS) + ret = db_query_start(&qp); + if (ret < 0) { - DPRINTF(E_LOG, L_RSP, "Could not fetch playlists: %s\n", db_errmsg); + DPRINTF(E_LOG, L_RSP, "Could not start query\n"); - rsp_send_error(req, db_errmsg); - - free(db_errmsg); + rsp_send_error(req, "Could not start query"); return; } @@ -410,13 +391,13 @@ rsp_reply_db(struct evhttp_request *req, char **uri, struct evkeyvalq *query) mxmlNewText(node, 0, ""); node = mxmlNewElement(status, "records"); - mxmlNewTextf(node, 0, "%d", qi.specifiedtotalcount); + mxmlNewTextf(node, 0, "%d", qp.results); node = mxmlNewElement(status, "totalrecords"); - mxmlNewTextf(node, 0, "%d", qi.specifiedtotalcount); + mxmlNewTextf(node, 0, "%d", qp.results); /* Playlists block (all playlists) */ - while (((ret = db_enum_fetch_row(&db_errmsg, (struct db_media_file_info **)&dbpli, &qi)) == DB_E_SUCCESS) && (dbpli)) + while (((ret = db_query_fetch_pl(&qp, &dbpli)) == 0) && (dbpli.id)) { /* Playlist block (one playlist) */ pl = mxmlNewElement(pls, "playlist"); @@ -425,7 +406,7 @@ rsp_reply_db(struct evhttp_request *req, char **uri, struct evkeyvalq *query) { if (pl_fields[i].flags & F_FULL) { - strval = (char **) ((char *)dbpli + pl_fields[i].offset); + strval = (char **) ((char *)&dbpli + pl_fields[i].offset); node = mxmlNewElement(pl, pl_fields[i].field); mxmlNewText(node, 0, *strval); @@ -433,34 +414,26 @@ rsp_reply_db(struct evhttp_request *req, char **uri, struct evkeyvalq *query) } } - if (ret != DB_E_SUCCESS) + if (ret < 0) { - DPRINTF(E_LOG, L_RSP, "Error fetching results: %s\n", db_errmsg); + DPRINTF(E_LOG, L_RSP, "Error fetching results\n"); mxmlDelete(reply); - - rsp_send_error(req, db_errmsg); - - free(db_errmsg); + db_query_end(&qp); + rsp_send_error(req, "Error fetching query results"); return; } - ret = db_enum_end(&db_errmsg); - if (ret != DB_E_SUCCESS) - { - DPRINTF(E_LOG, L_RSP, "Error cleaning up DB enum: %s\n", db_errmsg); - - free(db_errmsg); - } - /* HACK * Add a dummy empty string to the playlists element if there is no data * to return - this prevents mxml from sending out an empty * tag that the SoundBridge does not handle. It's hackish, but it works. */ - if (qi.specifiedtotalcount == 0) + if (qp.results == 0) mxmlNewText(pls, 0, ""); + db_query_end(&qp); + evbuf = mxml_to_evbuf(reply); mxmlDelete(reply); @@ -481,10 +454,9 @@ rsp_reply_db(struct evhttp_request *req, char **uri, struct evkeyvalq *query) static void rsp_reply_playlist(struct evhttp_request *req, char **uri, struct evkeyvalq *query) { - DBQUERYINFO qi; - struct db_media_file_info *dbmfi; + struct query_params qp; + struct db_media_file_info dbmfi; struct evbuffer *evbuf; - char *db_errmsg; const char *param; char **strval; mxml_node_t *reply; @@ -493,25 +465,26 @@ rsp_reply_playlist(struct evhttp_request *req, char **uri, struct evkeyvalq *que mxml_node_t *item; mxml_node_t *node; int mode; - int limit; - int offset; int records; int transcode; int bitrate; int i; int ret; - memset(&qi, 0, sizeof(DBQUERYINFO)); + memset(&qp, 0, sizeof(struct query_params)); - qi.query_type = queryTypePlaylistItems; - - ret = safe_atoi(uri[2], &qi.playlist_id); + ret = safe_atoi(uri[2], &qp.pl_id); if (ret < 0) { rsp_send_error(req, "Invalid playlist ID"); return; } + if (qp.pl_id == 0) + qp.type = Q_ITEMS; + else + qp.type = Q_PLITEMS; + mode = F_FULL; param = evhttp_find_header(query, "type"); if (param) @@ -528,29 +501,28 @@ rsp_reply_playlist(struct evhttp_request *req, char **uri, struct evkeyvalq *que DPRINTF(E_LOG, L_RSP, "Unknown browse mode %s\n", param); } - ret = get_query_params(req, query, &qi, &offset, &limit); + ret = get_query_params(req, query, &qp); if (ret < 0) return; - ret = db_enum_start(&db_errmsg, &qi); - if (ret != DB_E_SUCCESS) + ret = db_query_start(&qp); + if (ret < 0) { - DPRINTF(E_LOG, L_RSP, "Could not fetch data: %s\n", db_errmsg); + DPRINTF(E_LOG, L_RSP, "Could not start query\n"); - rsp_send_error(req, db_errmsg); + rsp_send_error(req, "Could not start query"); - if (qi.filter) - free(qi.filter); - free(db_errmsg); + if (qp.filter) + free(qp.filter); return; } - if (offset > qi.specifiedtotalcount) + if (qp.offset > qp.results) records = 0; - else if (limit > (qi.specifiedtotalcount - offset)) - records = qi.specifiedtotalcount - offset; + else if (qp.limit > (qp.results - qp.offset)) + records = qp.results - qp.offset; else - records = limit; + records = qp.limit; /* We'd use mxmlNewXML(), but then we can't put any attributes * on the root node and we need some. @@ -572,12 +544,12 @@ rsp_reply_playlist(struct evhttp_request *req, char **uri, struct evkeyvalq *que mxmlNewTextf(node, 0, "%d", records); node = mxmlNewElement(status, "totalrecords"); - mxmlNewTextf(node, 0, "%d", qi.specifiedtotalcount); + mxmlNewTextf(node, 0, "%d", qp.results); /* Items block (all items) */ - while (((ret = db_enum_fetch_row(&db_errmsg, &dbmfi, &qi)) == DB_E_SUCCESS) && (dbmfi)) + while (((ret = db_query_fetch_file(&qp, &dbmfi)) == 0) && (dbmfi.id)) { - transcode = transcode_needed(req->input_headers, dbmfi->codectype); + transcode = transcode_needed(req->input_headers, dbmfi.codectype); /* Item block (one item) */ item = mxmlNewElement(items, "item"); @@ -587,7 +559,7 @@ rsp_reply_playlist(struct evhttp_request *req, char **uri, struct evkeyvalq *que if (!(rsp_fields[i].flags & mode)) continue; - strval = (char **) ((char *)dbmfi + rsp_fields[i].offset); + strval = (char **) ((char *)&dbmfi + rsp_fields[i].offset); if (!(*strval) || (strlen(*strval) == 0)) continue; @@ -606,7 +578,7 @@ rsp_reply_playlist(struct evhttp_request *req, char **uri, struct evkeyvalq *que case dbmfi_offsetof(bitrate): bitrate = 0; - ret = safe_atoi(dbmfi->samplerate, &bitrate); + ret = safe_atoi(dbmfi.samplerate, &bitrate); if ((ret < 0) || (bitrate == 0)) bitrate = 1411; else @@ -634,37 +606,29 @@ rsp_reply_playlist(struct evhttp_request *req, char **uri, struct evkeyvalq *que } } - if (qi.filter) - free(qi.filter); + if (qp.filter) + free(qp.filter); - if (ret != DB_E_SUCCESS) + if (ret < 0) { - DPRINTF(E_LOG, L_RSP, "Error fetching results: %s\n", db_errmsg); + DPRINTF(E_LOG, L_RSP, "Error fetching results\n"); mxmlDelete(reply); - - rsp_send_error(req, db_errmsg); - - free(db_errmsg); + db_query_end(&qp); + rsp_send_error(req, "Error fetching query results"); return; } - ret = db_enum_end(&db_errmsg); - if (ret != DB_E_SUCCESS) - { - DPRINTF(E_LOG, L_RSP, "Error cleaning up DB enum: %s\n", db_errmsg); - - free(db_errmsg); - } - /* HACK * Add a dummy empty string to the items element if there is no data * to return - this prevents mxml from sending out an empty * tag that the SoundBridge does not handle. It's hackish, but it works. */ - if (qi.specifiedtotalcount == 0) + if (qp.results == 0) mxmlNewText(items, 0, ""); + db_query_end(&qp); + evbuf = mxml_to_evbuf(reply); mxmlDelete(reply); @@ -685,29 +649,26 @@ rsp_reply_playlist(struct evhttp_request *req, char **uri, struct evkeyvalq *que static void rsp_reply_browse(struct evhttp_request *req, char **uri, struct evkeyvalq *query) { - DBQUERYINFO qi; - struct db_media_file_info *dbmfi; + struct query_params qp; struct evbuffer *evbuf; - char *db_errmsg; + char *browse_item; mxml_node_t *reply; mxml_node_t *status; mxml_node_t *items; mxml_node_t *node; - int limit; - int offset; int records; int ret; - memset(&qi, 0, sizeof(DBQUERYINFO)); + memset(&qp, 0, sizeof(struct query_params)); if (strcmp(uri[3], "artist") == 0) - qi.query_type = queryTypeBrowseArtists; + qp.type = Q_BROWSE_ARTISTS; else if (strcmp(uri[3], "genre") == 0) - qi.query_type = queryTypeBrowseGenres; + qp.type = Q_BROWSE_GENRES; else if (strcmp(uri[3], "album") == 0) - qi.query_type = queryTypeBrowseAlbums; + qp.type = Q_BROWSE_ALBUMS; else if (strcmp(uri[3], "composer") == 0) - qi.query_type = queryTypeBrowseComposers; + qp.type = Q_BROWSE_COMPOSERS; else { DPRINTF(E_LOG, L_RSP, "Unsupported browse type '%s'\n", uri[3]); @@ -716,36 +677,35 @@ rsp_reply_browse(struct evhttp_request *req, char **uri, struct evkeyvalq *query return; } - ret = safe_atoi(uri[2], &qi.playlist_id); + ret = safe_atoi(uri[2], &qp.pl_id); if (ret < 0) { rsp_send_error(req, "Invalid playlist ID"); return; } - ret = get_query_params(req, query, &qi, &offset, &limit); + ret = get_query_params(req, query, &qp); if (ret < 0) return; - ret = db_enum_start(&db_errmsg, &qi); - if (ret != DB_E_SUCCESS) + ret = db_query_start(&qp); + if (ret < 0) { - DPRINTF(E_LOG, L_RSP, "Could not fetch data: %s\n", db_errmsg); + DPRINTF(E_LOG, L_RSP, "Could not start query\n"); - rsp_send_error(req, db_errmsg); + rsp_send_error(req, "Could not start query"); - if (qi.filter) - free(qi.filter); - free(db_errmsg); + if (qp.filter) + free(qp.filter); return; } - if (offset > qi.specifiedtotalcount) + if (qp.offset > qp.results) records = 0; - else if (limit > (qi.specifiedtotalcount - offset)) - records = qi.specifiedtotalcount - offset; + else if (qp.limit > (qp.results - qp.offset)) + records = qp.results - qp.offset; else - records = limit; + records = qp.limit; /* We'd use mxmlNewXML(), but then we can't put any attributes * on the root node and we need some. @@ -767,46 +727,38 @@ rsp_reply_browse(struct evhttp_request *req, char **uri, struct evkeyvalq *query mxmlNewTextf(node, 0, "%d", records); node = mxmlNewElement(status, "totalrecords"); - mxmlNewTextf(node, 0, "%d", qi.specifiedtotalcount); + mxmlNewTextf(node, 0, "%d", qp.results); /* Items block (all items) */ - while (((ret = db_enum_fetch_row(&db_errmsg, &dbmfi, &qi)) == DB_E_SUCCESS) && (dbmfi)) + while (((ret = db_query_fetch_string(&qp, &browse_item)) == 0) && (browse_item)) { node = mxmlNewElement(items, "item"); - mxmlNewText(node, 0, dbmfi->id); + mxmlNewText(node, 0, browse_item); } - if (qi.filter) - free(qi.filter); + if (qp.filter) + free(qp.filter); - if (ret != DB_E_SUCCESS) + if (ret < 0) { - DPRINTF(E_LOG, L_RSP, "Error fetching results: %s\n", db_errmsg); + DPRINTF(E_LOG, L_RSP, "Error fetching results\n"); mxmlDelete(reply); - - rsp_send_error(req, db_errmsg); - - free(db_errmsg); + db_query_end(&qp); + rsp_send_error(req, "Error fetching query results"); return; } - ret = db_enum_end(&db_errmsg); - if (ret != DB_E_SUCCESS) - { - DPRINTF(E_LOG, L_RSP, "Error cleaning up DB enum: %s\n", db_errmsg); - - free(db_errmsg); - } - /* HACK * Add a dummy empty string to the items element if there is no data * to return - this prevents mxml from sending out an empty * tag that the SoundBridge does not handle. It's hackish, but it works. */ - if (qi.specifiedtotalcount == 0) + if (qp.results == 0); mxmlNewText(items, 0, ""); + db_query_end(&qp); + evbuf = mxml_to_evbuf(reply); mxmlDelete(reply); diff --git a/src/main.c b/src/main.c index 88c36c19..eeb7fd27 100644 --- a/src/main.c +++ b/src/main.c @@ -47,11 +47,11 @@ #include #include "conffile.h" +#include "db.h" #include "logger.h" #include "misc.h" #include "filescanner.h" #include "httpd.h" -#include "db-generic.h" #include "mdns_avahi.h" @@ -334,7 +334,6 @@ main(int argc, char **argv) char *logdomains; char *logfile; char *ffid; - char *perr; char *pidfile; sigset_t sigs; int sigfd; @@ -500,23 +499,17 @@ main(int argc, char **argv) goto mdns_fail; } - /* this will require that the db be readable by the runas user */ - ret = db_open(&perr, "sqlite3", "/var/cache/mt-daapd"); /* FIXME */ - if (ret != 0) + /* Initialize the database before starting */ + DPRINTF(E_INFO, L_MAIN, "Initializing database\n"); + ret = db_init(); + if (ret < 0) { - DPRINTF(E_FATAL, L_MAIN, "Error opening db: %s\n", perr); + DPRINTF(E_FATAL, L_MAIN, "Database init failed\n"); ret = EXIT_FAILURE; goto db_fail; } - /* Initialize the database before starting */ - DPRINTF(E_INFO, L_MAIN, "Initializing database\n"); - if (db_init(0)) - { - DPRINTF(E_FATAL, L_MAIN, "Error in db_init: %s\n", strerror(errno)); - } - /* Spawn file scanner thread */ ret = filescanner_init(); if (ret != 0) @@ -582,9 +575,6 @@ main(int argc, char **argv) filescanner_deinit(); filescanner_fail: - DPRINTF(E_LOG, L_MAIN, "Closing database\n"); - db_deinit(); - db_fail: if (ret == EXIT_FAILURE) { diff --git a/src/scan-flac.c b/src/scan-flac.c index 0c7bd47d..049a7f21 100644 --- a/src/scan-flac.c +++ b/src/scan-flac.c @@ -40,13 +40,15 @@ #include #include "logger.h" -#include "ff-dbstruct.h" +#include "db.h" #include #define TRUE ((1 == 1)) #define FALSE (!TRUE) +typedef struct media_file_info MP3FILE; + #define GET_VORBIS_COMMENT(comment, name, len) (char*) \ (((strncasecmp(name, (char*)(comment).entry, strlen(name)) == 0) && \ ((comment).entry[strlen(name)] == '=')) ? \ diff --git a/src/scan-mpc.c b/src/scan-mpc.c index 5ed53d0d..7f4792ec 100644 --- a/src/scan-mpc.c +++ b/src/scan-mpc.c @@ -31,11 +31,12 @@ #include #include "logger.h" -#include "ff-dbstruct.h" +#include "db.h" #define TRUE ((1 == 1)) #define FALSE (!TRUE) +typedef struct media_file_info MP3FILE; /** * scan a musepack file for metainfo. diff --git a/src/scan-wma.c b/src/scan-wma.c index 878f7e49..a9a37a8c 100644 --- a/src/scan-wma.c +++ b/src/scan-wma.c @@ -34,11 +34,13 @@ #include #include "logger.h" -#include "ff-dbstruct.h" +#include "db.h" #define TRUE ((1 == 1)) #define FALSE (!TRUE) +typedef struct media_file_info MP3FILE; + typedef struct tag_wma_guidlist { char *name; char *guid; diff --git a/src/transcode.c b/src/transcode.c index 9d9db690..e200e5b9 100644 --- a/src/transcode.c +++ b/src/transcode.c @@ -41,7 +41,7 @@ #include "logger.h" #include "conffile.h" -#include "ff-dbstruct.h" +#include "db.h" #include "transcode.h"