mirror of
https://github.com/owntone/owntone-server.git
synced 2025-01-27 22:46:02 -05:00
Switch to the new database code
This commit is contained in:
parent
f2c677462b
commit
a200703393
@ -31,9 +31,7 @@ options {
|
|||||||
#include <errno.h>
|
#include <errno.h>
|
||||||
|
|
||||||
#include "logger.h"
|
#include "logger.h"
|
||||||
#include "ff-dbstruct.h"
|
#include "db.h"
|
||||||
#include "db-generic.h"
|
|
||||||
#include "db-sql.h"
|
|
||||||
#include "daap_query.h"
|
#include "daap_query.h"
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -217,7 +215,7 @@ expr returns [ pANTLR3_STRING result, int valid ]
|
|||||||
goto STR_result_valid_0; /* ABORT */
|
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)
|
if (!escaped)
|
||||||
{
|
{
|
||||||
DPRINTF(E_LOG, L_DAAP, "Could not escape value\n");
|
DPRINTF(E_LOG, L_DAAP, "Could not escape value\n");
|
||||||
|
@ -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_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_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 \
|
mt_daapd_SOURCES = main.c \
|
||||||
|
db.c db.h \
|
||||||
logger.c logger.h \
|
logger.c logger.h \
|
||||||
conffile.c conffile.h \
|
conffile.c conffile.h \
|
||||||
filescanner.c filescanner.h \
|
filescanner.c filescanner.h \
|
||||||
@ -38,10 +39,7 @@ mt_daapd_SOURCES = main.c \
|
|||||||
misc.c misc.h \
|
misc.c misc.h \
|
||||||
rsp_query.c rsp_query.h \
|
rsp_query.c rsp_query.h \
|
||||||
daap_query.c daap_query.h \
|
daap_query.c daap_query.h \
|
||||||
db-generic.c db-generic.h \
|
|
||||||
scan-wma.c \
|
scan-wma.c \
|
||||||
db-sql-updates.c \
|
|
||||||
db-sql.c db-sql.h db-sql-sqlite3.c db-sql-sqlite3.h\
|
|
||||||
$(FLACSRC) $(MUSEPACKSRC)
|
$(FLACSRC) $(MUSEPACKSRC)
|
||||||
|
|
||||||
nodist_mt_daapd_SOURCES = \
|
nodist_mt_daapd_SOURCES = \
|
||||||
@ -50,9 +48,7 @@ nodist_mt_daapd_SOURCES = \
|
|||||||
EXTRA_DIST = \
|
EXTRA_DIST = \
|
||||||
$(ANTLR_GRAMMARS) \
|
$(ANTLR_GRAMMARS) \
|
||||||
scan-mpc.c \
|
scan-mpc.c \
|
||||||
scan-flac.c \
|
scan-flac.c
|
||||||
ff-dbstruct.h
|
|
||||||
|
|
||||||
|
|
||||||
# Let's help the dependencies a little.
|
# Let's help the dependencies a little.
|
||||||
rsp_query.c: RSPLexer.h RSPParser.h RSP2SQL.h
|
rsp_query.c: RSPLexer.h RSPParser.h RSP2SQL.h
|
||||||
|
@ -32,9 +32,7 @@ options {
|
|||||||
#include <time.h>
|
#include <time.h>
|
||||||
|
|
||||||
#include "logger.h"
|
#include "logger.h"
|
||||||
#include "ff-dbstruct.h"
|
#include "db.h"
|
||||||
#include "db-generic.h"
|
|
||||||
#include "db-sql.h"
|
|
||||||
#include "misc.h"
|
#include "misc.h"
|
||||||
#include "rsp_query.h"
|
#include "rsp_query.h"
|
||||||
}
|
}
|
||||||
@ -181,7 +179,7 @@ strcrit returns [ pANTLR3_STRING result, int valid ]
|
|||||||
goto strcrit_valid_0; /* ABORT */
|
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)
|
if (!escaped)
|
||||||
{
|
{
|
||||||
DPRINTF(E_LOG, L_RSP, "Could not escape value\n");
|
DPRINTF(E_LOG, L_RSP, "Could not escape value\n");
|
||||||
|
@ -43,7 +43,7 @@
|
|||||||
#include <avl.h>
|
#include <avl.h>
|
||||||
|
|
||||||
#include "logger.h"
|
#include "logger.h"
|
||||||
#include "db-generic.h"
|
#include "db.h"
|
||||||
#include "filescanner.h"
|
#include "filescanner.h"
|
||||||
#include "conffile.h"
|
#include "conffile.h"
|
||||||
|
|
||||||
@ -144,55 +144,6 @@ pop_dir(void)
|
|||||||
return ret;
|
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
|
static void
|
||||||
fixup_tags(struct media_file_info *mfi)
|
fixup_tags(struct media_file_info *mfi)
|
||||||
@ -256,32 +207,42 @@ fixup_tags(struct media_file_info *mfi)
|
|||||||
static void
|
static void
|
||||||
process_media_file(char *file, time_t mtime, off_t size, int compilation)
|
process_media_file(char *file, time_t mtime, off_t size, int compilation)
|
||||||
{
|
{
|
||||||
struct media_file_info *db_mfi;
|
|
||||||
struct media_file_info *mfi;
|
struct media_file_info *mfi;
|
||||||
char *filename;
|
char *filename;
|
||||||
char *ext;
|
char *ext;
|
||||||
int need_update;
|
int need_update;
|
||||||
int ret;
|
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);
|
need_update = (!mfi || (mfi->db_timestamp < mtime) || mfi->force_update);
|
||||||
|
|
||||||
db_dispose_item(db_mfi);
|
|
||||||
|
|
||||||
if (!need_update)
|
if (!need_update)
|
||||||
return;
|
{
|
||||||
|
db_file_ping(mfi->id);
|
||||||
|
|
||||||
|
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));
|
mfi = (struct media_file_info *)malloc(sizeof(struct media_file_info));
|
||||||
if (!mfi)
|
if (!mfi)
|
||||||
{
|
{
|
||||||
DPRINTF(E_WARN, L_SCAN, "Out of memory for media_file_info\n");
|
DPRINTF(E_WARN, L_SCAN, "Out of memory for media_file_info\n");
|
||||||
|
|
||||||
db_dispose_item(db_mfi);
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
memset(mfi, 0, sizeof(struct media_file_info));
|
memset(mfi, 0, sizeof(struct media_file_info));
|
||||||
|
mfi->id = ret;
|
||||||
|
|
||||||
filename = strrchr(file, '/');
|
filename = strrchr(file, '/');
|
||||||
if (!filename)
|
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");
|
DPRINTF(E_LOG, L_SCAN, "Could not extract metadata for %s\n");
|
||||||
|
|
||||||
free_mfi(mfi);
|
free_mfi(mfi, 0);
|
||||||
free(mfi);
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -350,10 +310,12 @@ process_media_file(char *file, time_t mtime, off_t size, int compilation)
|
|||||||
|
|
||||||
fixup_tags(mfi);
|
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(mfi, 0);
|
||||||
free(mfi);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
@ -669,6 +631,8 @@ bulk_scan(void)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
db_pl_update_all();
|
||||||
|
|
||||||
if (playlists)
|
if (playlists)
|
||||||
process_deferred_playlists();
|
process_deferred_playlists();
|
||||||
|
|
||||||
@ -681,10 +645,22 @@ bulk_scan(void)
|
|||||||
static void *
|
static void *
|
||||||
filescanner(void *arg)
|
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();
|
bulk_scan();
|
||||||
|
|
||||||
if (!scan_exit)
|
if (!scan_exit)
|
||||||
{
|
{
|
||||||
|
db_pl_update_all();
|
||||||
|
|
||||||
/* Enable inotify */
|
/* Enable inotify */
|
||||||
event_add(&inoev, NULL);
|
event_add(&inoev, NULL);
|
||||||
|
|
||||||
@ -694,6 +670,8 @@ filescanner(void *arg)
|
|||||||
if (!scan_exit)
|
if (!scan_exit)
|
||||||
DPRINTF(E_FATAL, L_SCAN, "Scan event loop terminated ahead of time!\n");
|
DPRINTF(E_FATAL, L_SCAN, "Scan event loop terminated ahead of time!\n");
|
||||||
|
|
||||||
|
db_perthread_deinit();
|
||||||
|
|
||||||
pthread_exit(NULL);
|
pthread_exit(NULL);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -2,7 +2,7 @@
|
|||||||
#ifndef __FILESCANNER_H__
|
#ifndef __FILESCANNER_H__
|
||||||
#define __FILESCANNER_H__
|
#define __FILESCANNER_H__
|
||||||
|
|
||||||
#include "ff-dbstruct.h"
|
#include "db.h"
|
||||||
|
|
||||||
int
|
int
|
||||||
filescanner_init(void);
|
filescanner_init(void);
|
||||||
|
@ -41,12 +41,12 @@
|
|||||||
|
|
||||||
|
|
||||||
/* Legacy format-specific scanners */
|
/* 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
|
#ifdef FLAC
|
||||||
extern int scan_get_flacinfo(char *filename, MP3FILE *pmp3);
|
extern int scan_get_flacinfo(char *filename, struct media_file_info *pmp3);
|
||||||
#endif
|
#endif
|
||||||
#ifdef MUSEPACK
|
#ifdef MUSEPACK
|
||||||
extern int scan_get_mpcinfo(char *filename, MP3FILE *pmp3);
|
extern int scan_get_mpcinfo(char *filename, struct media_file_info *pmp3);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|
||||||
|
@ -34,8 +34,7 @@
|
|||||||
#include <errno.h>
|
#include <errno.h>
|
||||||
|
|
||||||
#include "logger.h"
|
#include "logger.h"
|
||||||
#include "ff-dbstruct.h"
|
#include "db.h"
|
||||||
#include "db-generic.h"
|
|
||||||
#include "filescanner.h"
|
#include "filescanner.h"
|
||||||
|
|
||||||
|
|
||||||
@ -44,7 +43,6 @@ scan_m3u_playlist(char *file)
|
|||||||
{
|
{
|
||||||
FILE *fp;
|
FILE *fp;
|
||||||
struct playlist_info *pli;
|
struct playlist_info *pli;
|
||||||
struct media_file_info *mfi;
|
|
||||||
struct stat sb;
|
struct stat sb;
|
||||||
char buf[PATH_MAX];
|
char buf[PATH_MAX];
|
||||||
char rel_entry[PATH_MAX];
|
char rel_entry[PATH_MAX];
|
||||||
@ -52,9 +50,9 @@ scan_m3u_playlist(char *file)
|
|||||||
char *entry;
|
char *entry;
|
||||||
char *filename;
|
char *filename;
|
||||||
char *ptr;
|
char *ptr;
|
||||||
char *db_errmsg;
|
|
||||||
size_t len;
|
size_t len;
|
||||||
int pl_id;
|
int pl_id;
|
||||||
|
int mf_id;
|
||||||
int ret;
|
int ret;
|
||||||
|
|
||||||
DPRINTF(E_INFO, L_SCAN, "Processing static playlist: %s\n", file);
|
DPRINTF(E_INFO, L_SCAN, "Processing static playlist: %s\n", file);
|
||||||
@ -73,7 +71,7 @@ scan_m3u_playlist(char *file)
|
|||||||
else
|
else
|
||||||
filename++;
|
filename++;
|
||||||
|
|
||||||
pli = db_fetch_playlist(NULL, file, 0);
|
pli = db_pl_fetch_bypath(file);
|
||||||
|
|
||||||
if (pli)
|
if (pli)
|
||||||
{
|
{
|
||||||
@ -81,15 +79,17 @@ scan_m3u_playlist(char *file)
|
|||||||
{
|
{
|
||||||
DPRINTF(E_DBG, L_SCAN, "Playlist up-to-date\n");
|
DPRINTF(E_DBG, L_SCAN, "Playlist up-to-date\n");
|
||||||
|
|
||||||
db_dispose_playlist(pli);
|
db_pl_ping(pli->id);
|
||||||
|
|
||||||
|
free_pli(pli, 0);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
DPRINTF(E_DBG, L_SCAN, "Playlist needs update\n");
|
DPRINTF(E_DBG, L_SCAN, "Playlist needs update\n");
|
||||||
|
|
||||||
db_delete_playlist(NULL, pli->id);
|
db_pl_delete(pli->id);
|
||||||
db_dispose_playlist(pli);
|
free_pli(pli, 0);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -113,13 +113,11 @@ scan_m3u_playlist(char *file)
|
|||||||
if (ptr)
|
if (ptr)
|
||||||
*ptr = '.';
|
*ptr = '.';
|
||||||
|
|
||||||
ret = db_add_playlist(&db_errmsg, buf, PL_STATICFILE, NULL, file, 0, &pl_id);
|
ret = db_pl_add(buf, file, &pl_id);
|
||||||
|
if (ret < 0)
|
||||||
if (ret != DB_E_SUCCESS)
|
|
||||||
{
|
{
|
||||||
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;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -197,19 +195,19 @@ scan_m3u_playlist(char *file)
|
|||||||
|
|
||||||
DPRINTF(E_DBG, L_SCAN, "Checking %s\n", filename);
|
DPRINTF(E_DBG, L_SCAN, "Checking %s\n", filename);
|
||||||
|
|
||||||
mfi = db_fetch_path(&db_errmsg, filename, 0);
|
ret = db_file_id_bypath(filename, &mf_id);
|
||||||
if (!mfi)
|
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);
|
free(filename);
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
DPRINTF(E_DBG, L_SCAN, "Resolved %s to %d\n", filename, mfi->id);
|
DPRINTF(E_DBG, L_SCAN, "Resolved %s to %d\n", filename, mf_id);
|
||||||
db_add_playlist_item(NULL, pl_id, mfi->id);
|
ret = db_pl_add_item(pl_id, mf_id);
|
||||||
db_dispose_item(mfi);
|
if (ret < 0)
|
||||||
|
DPRINTF(E_WARN, L_SCAN, "Could not add %s to playlist\n", filename);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!feof(fp))
|
if (!feof(fp))
|
||||||
@ -222,5 +220,7 @@ scan_m3u_playlist(char *file)
|
|||||||
|
|
||||||
fclose(fp);
|
fclose(fp);
|
||||||
|
|
||||||
|
db_pl_update(pl_id);
|
||||||
|
|
||||||
DPRINTF(E_INFO, L_SCAN, "Done processing playlist\n");
|
DPRINTF(E_INFO, L_SCAN, "Done processing playlist\n");
|
||||||
}
|
}
|
||||||
|
@ -31,7 +31,7 @@
|
|||||||
#include <errno.h>
|
#include <errno.h>
|
||||||
|
|
||||||
#include "logger.h"
|
#include "logger.h"
|
||||||
#include "ff-dbstruct.h"
|
#include "db.h"
|
||||||
#include "filescanner.h"
|
#include "filescanner.h"
|
||||||
|
|
||||||
|
|
||||||
|
41
src/httpd.c
41
src/httpd.c
@ -35,8 +35,7 @@
|
|||||||
#include "evhttp/evhttp.h"
|
#include "evhttp/evhttp.h"
|
||||||
|
|
||||||
#include "logger.h"
|
#include "logger.h"
|
||||||
#include "ff-dbstruct.h"
|
#include "db.h"
|
||||||
#include "db-generic.h"
|
|
||||||
#include "conffile.h"
|
#include "conffile.h"
|
||||||
#include "misc.h"
|
#include "misc.h"
|
||||||
#include "httpd.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)))
|
if (!st->marked && (st->offset > ((st->size * 80) / 100)))
|
||||||
{
|
{
|
||||||
st->marked = 1;
|
st->marked = 1;
|
||||||
db_playcount_increment(NULL, st->id);
|
db_file_inc_playcount(st->id);
|
||||||
}
|
}
|
||||||
|
|
||||||
return;
|
return;
|
||||||
@ -245,7 +244,7 @@ stream_chunk_raw_cb(int fd, short event, void *arg)
|
|||||||
if (!st->marked && (st->offset > ((st->size * 80) / 100)))
|
if (!st->marked && (st->offset > ((st->size * 80) / 100)))
|
||||||
{
|
{
|
||||||
st->marked = 1;
|
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)
|
if (!mfi)
|
||||||
{
|
{
|
||||||
DPRINTF(E_LOG, L_HTTPD, "Item %d not found\n", id);
|
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");
|
evhttp_send_error(req, 500, "Cannot stream radio station");
|
||||||
|
|
||||||
db_dispose_item(mfi);
|
free_mfi(mfi, 0);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -326,7 +325,7 @@ httpd_stream_file(struct evhttp_request *req, int id)
|
|||||||
|
|
||||||
evhttp_send_error(req, HTTP_SERVUNAVAIL, "Internal Server Error");
|
evhttp_send_error(req, HTTP_SERVUNAVAIL, "Internal Server Error");
|
||||||
|
|
||||||
db_dispose_item(mfi);
|
free_mfi(mfi, 0);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
memset(st, 0, sizeof(struct stream_ctx));
|
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");
|
evhttp_send_error(req, HTTP_SERVUNAVAIL, "Internal Server Error");
|
||||||
|
|
||||||
free(st);
|
free(st);
|
||||||
db_dispose_item(mfi);
|
free_mfi(mfi, 0);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -370,7 +369,7 @@ httpd_stream_file(struct evhttp_request *req, int id)
|
|||||||
evhttp_send_error(req, HTTP_NOTFOUND, "Not Found");
|
evhttp_send_error(req, HTTP_NOTFOUND, "Not Found");
|
||||||
|
|
||||||
free(st);
|
free(st);
|
||||||
db_dispose_item(mfi);
|
free_mfi(mfi, 0);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -383,7 +382,7 @@ httpd_stream_file(struct evhttp_request *req, int id)
|
|||||||
|
|
||||||
close(st->fd);
|
close(st->fd);
|
||||||
free(st);
|
free(st);
|
||||||
db_dispose_item(mfi);
|
free_mfi(mfi, 0);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
st->size = sb.st_size;
|
st->size = sb.st_size;
|
||||||
@ -397,7 +396,7 @@ httpd_stream_file(struct evhttp_request *req, int id)
|
|||||||
|
|
||||||
close(st->fd);
|
close(st->fd);
|
||||||
free(st);
|
free(st);
|
||||||
db_dispose_item(mfi);
|
free_mfi(mfi, 0);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
st->offset = offset;
|
st->offset = offset;
|
||||||
@ -425,7 +424,7 @@ httpd_stream_file(struct evhttp_request *req, int id)
|
|||||||
else
|
else
|
||||||
close(st->fd);
|
close(st->fd);
|
||||||
free(st);
|
free(st);
|
||||||
db_dispose_item(mfi);
|
free_mfi(mfi, 0);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -443,7 +442,7 @@ httpd_stream_file(struct evhttp_request *req, int id)
|
|||||||
close(st->fd);
|
close(st->fd);
|
||||||
evbuffer_free(st->evbuf);
|
evbuffer_free(st->evbuf);
|
||||||
free(st);
|
free(st);
|
||||||
db_dispose_item(mfi);
|
free_mfi(mfi, 0);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -464,7 +463,7 @@ httpd_stream_file(struct evhttp_request *req, int id)
|
|||||||
close(st->fd);
|
close(st->fd);
|
||||||
evbuffer_free(st->evbuf);
|
evbuffer_free(st->evbuf);
|
||||||
free(st);
|
free(st);
|
||||||
db_dispose_item(mfi);
|
free_mfi(mfi, 0);
|
||||||
return;
|
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);
|
DPRINTF(E_INFO, L_HTTPD, "Kicking off streaming for %s\n", mfi->path);
|
||||||
|
|
||||||
db_dispose_item(mfi);
|
free_mfi(mfi, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Thread: httpd */
|
/* Thread: httpd */
|
||||||
@ -745,11 +744,23 @@ httpd_gen_cb(struct evhttp_request *req, void *arg)
|
|||||||
static void *
|
static void *
|
||||||
httpd(void *arg)
|
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);
|
event_base_dispatch(evbase_httpd);
|
||||||
|
|
||||||
if (!httpd_exit)
|
if (!httpd_exit)
|
||||||
DPRINTF(E_FATAL, L_HTTPD, "HTTPd event loop terminated ahead of time!\n");
|
DPRINTF(E_FATAL, L_HTTPD, "HTTPd event loop terminated ahead of time!\n");
|
||||||
|
|
||||||
|
db_perthread_deinit();
|
||||||
|
|
||||||
pthread_exit(NULL);
|
pthread_exit(NULL);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
274
src/httpd_daap.c
274
src/httpd_daap.c
@ -26,6 +26,7 @@
|
|||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
|
#include <time.h>
|
||||||
#include <errno.h>
|
#include <errno.h>
|
||||||
#include <sys/queue.h>
|
#include <sys/queue.h>
|
||||||
#include <sys/types.h>
|
#include <sys/types.h>
|
||||||
@ -39,8 +40,7 @@
|
|||||||
#include <avl.h>
|
#include <avl.h>
|
||||||
|
|
||||||
#include "logger.h"
|
#include "logger.h"
|
||||||
#include "ff-dbstruct.h"
|
#include "db.h"
|
||||||
#include "db-generic.h"
|
|
||||||
#include "conffile.h"
|
#include "conffile.h"
|
||||||
#include "misc.h"
|
#include "misc.h"
|
||||||
#include "httpd.h"
|
#include "httpd.h"
|
||||||
@ -569,16 +569,18 @@ dmap_find_field(uint32_t hash)
|
|||||||
return (struct dmap_field_map *)node->item;
|
return (struct dmap_field_map *)node->item;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
static void
|
static void
|
||||||
get_query_params(struct evkeyvalq *query, DBQUERYINFO *qi)
|
get_query_params(struct evkeyvalq *query, struct query_params *qp)
|
||||||
{
|
{
|
||||||
const char *param;
|
const char *param;
|
||||||
char *ptr;
|
char *ptr;
|
||||||
int val;
|
int low;
|
||||||
|
int high;
|
||||||
int ret;
|
int ret;
|
||||||
|
|
||||||
qi->index_low = 0;
|
low = 0;
|
||||||
qi->index_high = 9999999; /* Arbitrarily high number */
|
high = -1; /* No limit */
|
||||||
|
|
||||||
param = evhttp_find_header(query, "index");
|
param = evhttp_find_header(query, "index");
|
||||||
if (param)
|
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);
|
DPRINTF(E_LOG, L_DAAP, "Unsupported index range: %s\n", param);
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
ret = safe_atoi(param, &val);
|
ret = safe_atoi(param, &low);
|
||||||
if (ret < 0)
|
if (ret < 0)
|
||||||
DPRINTF(E_LOG, L_DAAP, "Could not parse index range: %s\n", param);
|
DPRINTF(E_LOG, L_DAAP, "Could not parse index range: %s\n", param);
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
qi->index_low = val;
|
|
||||||
|
|
||||||
ptr = strchr(param, '-');
|
ptr = strchr(param, '-');
|
||||||
if (!ptr) /* single item */
|
if (!ptr) /* single item */
|
||||||
qi->index_high = qi->index_low;
|
high = low;
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
ptr++;
|
ptr++;
|
||||||
if (*ptr != '\0') /* low-high */
|
if (*ptr != '\0') /* low-high */
|
||||||
{
|
{
|
||||||
ret = safe_atoi(ptr, &val);
|
ret = safe_atoi(ptr, &high);
|
||||||
if (ret < 0)
|
if (ret < 0)
|
||||||
DPRINTF(E_LOG, L_DAAP, "Could not parse high index in range: %s\n", param);
|
DPRINTF(E_LOG, L_DAAP, "Could not parse high index in range: %s\n", param);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
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 (high < low)
|
||||||
|
high = -1; /* No limit */
|
||||||
|
|
||||||
|
qp->offset = low;
|
||||||
|
if (high < 0)
|
||||||
|
qp->limit = -1; /* No limit */
|
||||||
else
|
else
|
||||||
qi->index_high = val;
|
qp->limit = (high - low) + 1;
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
DPRINTF(E_DBG, L_DAAP, "Index range %s: low %d, high %d\n", param, qi->index_low, qi->index_high);
|
qp->idx_type = I_SUB;
|
||||||
}
|
|
||||||
|
|
||||||
if (qi->index_high < qi->index_low)
|
|
||||||
qi->index_high = 9999999; /* Arbitrarily high number */
|
|
||||||
|
|
||||||
qi->index_type = indexTypeSub;
|
|
||||||
|
|
||||||
param = evhttp_find_header(query, "query");
|
param = evhttp_find_header(query, "query");
|
||||||
if (!param)
|
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);
|
DPRINTF(E_DBG, L_DAAP, "DAAP browse query filter: %s\n", param);
|
||||||
|
|
||||||
qi->filter = daap_query_parse_sql(param);
|
qp->filter = daap_query_parse_sql(param);
|
||||||
if (!qi->filter)
|
if (!qp->filter)
|
||||||
DPRINTF(E_LOG, L_DAAP, "Ignoring improper DAAP query\n");
|
DPRINTF(E_LOG, L_DAAP, "Ignoring improper DAAP query\n");
|
||||||
}
|
}
|
||||||
|
|
||||||
qi->want_count = 1;
|
|
||||||
qi->correct_order = 1;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
@ -879,7 +880,7 @@ daap_reply_update(struct evhttp_request *req, struct evbuffer *evbuf, char **uri
|
|||||||
{
|
{
|
||||||
int ret;
|
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
|
* This probably doesn't cut it, but then again we don't claim to support
|
||||||
* updates, so... that support should be added eventually.
|
* updates, so... that support should be added eventually.
|
||||||
@ -896,7 +897,7 @@ daap_reply_update(struct evhttp_request *req, struct evbuffer *evbuf, char **uri
|
|||||||
|
|
||||||
dmap_add_container(evbuf, "mupd", 24);
|
dmap_add_container(evbuf, "mupd", 24);
|
||||||
dmap_add_int(evbuf, "mstt", 200); /* 12 */
|
dmap_add_int(evbuf, "mstt", 200); /* 12 */
|
||||||
dmap_add_int(evbuf, "musr", db_revision()); /* 12 */
|
dmap_add_int(evbuf, "musr", (int)time(NULL)); /* 12 */
|
||||||
|
|
||||||
evhttp_send_reply(req, HTTP_OK, "OK", evbuf);
|
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
|
static void
|
||||||
daap_reply_dblist(struct evhttp_request *req, struct evbuffer *evbuf, char **uri, struct evkeyvalq *query)
|
daap_reply_dblist(struct evhttp_request *req, struct evbuffer *evbuf, char **uri, struct evkeyvalq *query)
|
||||||
{
|
{
|
||||||
int count;
|
|
||||||
|
|
||||||
cfg_t *lib;
|
cfg_t *lib;
|
||||||
char *db_errmsg;
|
|
||||||
char *name;
|
char *name;
|
||||||
int namelen;
|
int namelen;
|
||||||
|
int count;
|
||||||
int ret;
|
int ret;
|
||||||
|
|
||||||
lib = cfg_getnsec(cfg, "library", 0);
|
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_long(evbuf, "mper", 1); /* 16 */
|
||||||
dmap_add_string(evbuf, "minm", name); /* 8 + namelen */
|
dmap_add_string(evbuf, "minm", name); /* 8 + namelen */
|
||||||
|
|
||||||
ret = db_get_song_count(&db_errmsg, &count);
|
ret = db_files_get_count(&count);
|
||||||
if (ret != DB_E_SUCCESS)
|
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;
|
count = 0;
|
||||||
free(db_errmsg);
|
|
||||||
}
|
}
|
||||||
dmap_add_int(evbuf, "mimc", count); /* 12 */
|
dmap_add_int(evbuf, "mimc", count); /* 12 */
|
||||||
|
|
||||||
ret = db_get_playlist_count(&db_errmsg, &count);
|
ret = db_pl_get_count(&count);
|
||||||
if (ret != DB_E_SUCCESS)
|
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;
|
count = 0;
|
||||||
free(db_errmsg);
|
|
||||||
}
|
}
|
||||||
dmap_add_int(evbuf, "mctc", count); /* 12 */
|
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
|
static void
|
||||||
daap_reply_songlist_generic(struct evhttp_request *req, struct evbuffer *evbuf, int playlist, struct evkeyvalq *query)
|
daap_reply_songlist_generic(struct evhttp_request *req, struct evbuffer *evbuf, int playlist, struct evkeyvalq *query)
|
||||||
{
|
{
|
||||||
DBQUERYINFO qi;
|
struct query_params qp;
|
||||||
struct db_media_file_info *dbmfi;
|
struct db_media_file_info dbmfi;
|
||||||
struct evbuffer *song;
|
struct evbuffer *song;
|
||||||
struct evbuffer *songlist;
|
struct evbuffer *songlist;
|
||||||
struct dmap_field_map *dfm;
|
struct dmap_field_map *dfm;
|
||||||
char *db_errmsg;
|
|
||||||
const char *param;
|
const char *param;
|
||||||
char *tag;
|
char *tag;
|
||||||
char **strval;
|
char **strval;
|
||||||
@ -1071,26 +1067,29 @@ daap_reply_songlist_generic(struct evhttp_request *req, struct evbuffer *evbuf,
|
|||||||
nmeta = 0;
|
nmeta = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
memset(&qi, 0, sizeof(DBQUERYINFO));
|
memset(&qp, 0, sizeof(struct query_params));
|
||||||
get_query_params(query, &qi);
|
get_query_params(query, &qp);
|
||||||
qi.query_type = queryTypePlaylistItems;
|
|
||||||
|
|
||||||
if (playlist != -1)
|
if (playlist < 2)
|
||||||
qi.playlist_id = playlist;
|
qp.type = Q_ITEMS;
|
||||||
|
else
|
||||||
ret = db_enum_start(&db_errmsg, &qi);
|
|
||||||
if (ret != DB_E_SUCCESS)
|
|
||||||
{
|
{
|
||||||
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);
|
free(meta);
|
||||||
evbuffer_free(song);
|
evbuffer_free(song);
|
||||||
evbuffer_free(songlist);
|
evbuffer_free(songlist);
|
||||||
if (qi.filter)
|
if (qp.filter)
|
||||||
free(qi.filter);
|
free(qp.filter);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1098,11 +1097,11 @@ daap_reply_songlist_generic(struct evhttp_request *req, struct evbuffer *evbuf,
|
|||||||
want_asdk = 0;
|
want_asdk = 0;
|
||||||
oom = 0;
|
oom = 0;
|
||||||
nsongs = 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++;
|
nsongs++;
|
||||||
|
|
||||||
transcode = transcode_needed(req->input_headers, dbmfi->codectype);
|
transcode = transcode_needed(req->input_headers, dbmfi.codectype);
|
||||||
|
|
||||||
i = -1;
|
i = -1;
|
||||||
while (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);
|
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'))
|
if (!(*strval) || (**strval == '\0'))
|
||||||
continue;
|
continue;
|
||||||
@ -1174,7 +1173,7 @@ daap_reply_songlist_generic(struct evhttp_request *req, struct evbuffer *evbuf,
|
|||||||
|
|
||||||
case dbmfi_offsetof(bitrate):
|
case dbmfi_offsetof(bitrate):
|
||||||
val = 0;
|
val = 0;
|
||||||
ret = safe_atoi(dbmfi->samplerate, &val);
|
ret = safe_atoi(dbmfi.samplerate, &val);
|
||||||
if ((ret < 0) || (val == 0))
|
if ((ret < 0) || (val == 0))
|
||||||
val = 1411;
|
val = 1411;
|
||||||
else
|
else
|
||||||
@ -1220,14 +1219,14 @@ daap_reply_songlist_generic(struct evhttp_request *req, struct evbuffer *evbuf,
|
|||||||
if (want_mikd)
|
if (want_mikd)
|
||||||
{
|
{
|
||||||
/* dmap.itemkind must come first */
|
/* dmap.itemkind must come first */
|
||||||
ret = safe_atoi(dbmfi->item_kind, &val);
|
ret = safe_atoi(dbmfi.item_kind, &val);
|
||||||
if (ret < 0)
|
if (ret < 0)
|
||||||
val = 2; /* music by default */
|
val = 2; /* music by default */
|
||||||
dmap_add_char(songlist, "mikd", val);
|
dmap_add_char(songlist, "mikd", val);
|
||||||
}
|
}
|
||||||
if (want_asdk)
|
if (want_asdk)
|
||||||
{
|
{
|
||||||
ret = safe_atoi(dbmfi->data_kind, &val);
|
ret = safe_atoi(dbmfi.data_kind, &val);
|
||||||
if (ret < 0)
|
if (ret < 0)
|
||||||
val = 0;
|
val = 0;
|
||||||
dmap_add_char(songlist, "asdk", val);
|
dmap_add_char(songlist, "asdk", val);
|
||||||
@ -1248,34 +1247,25 @@ daap_reply_songlist_generic(struct evhttp_request *req, struct evbuffer *evbuf,
|
|||||||
|
|
||||||
evbuffer_free(song);
|
evbuffer_free(song);
|
||||||
|
|
||||||
if (qi.filter)
|
if (qp.filter)
|
||||||
free(qi.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);
|
daap_send_error(req, tag, "Error fetching query results");
|
||||||
|
db_query_end(&qp);
|
||||||
free(db_errmsg);
|
|
||||||
evbuffer_free(songlist);
|
evbuffer_free(songlist);
|
||||||
return;
|
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)
|
if (oom)
|
||||||
{
|
{
|
||||||
DPRINTF(E_LOG, L_DAAP, "Could not add song to song list for DAAP song list reply\n");
|
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");
|
daap_send_error(req, tag, "Out of memory");
|
||||||
|
db_query_end(&qp);
|
||||||
evbuffer_free(songlist);
|
evbuffer_free(songlist);
|
||||||
return;
|
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_container(evbuf, tag, EVBUFFER_LENGTH(songlist) + 53);
|
||||||
dmap_add_int(evbuf, "mstt", 200); /* 12 */
|
dmap_add_int(evbuf, "mstt", 200); /* 12 */
|
||||||
dmap_add_char(evbuf, "muty", 0); /* 9 */
|
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_int(evbuf, "mrco", nsongs); /* 12 */
|
||||||
dmap_add_container(evbuf, "mlcl", EVBUFFER_LENGTH(songlist));
|
dmap_add_container(evbuf, "mlcl", EVBUFFER_LENGTH(songlist));
|
||||||
|
|
||||||
|
db_query_end(&qp);
|
||||||
|
|
||||||
ret = evbuffer_add_buffer(evbuf, songlist);
|
ret = evbuffer_add_buffer(evbuf, songlist);
|
||||||
evbuffer_free(songlist);
|
evbuffer_free(songlist);
|
||||||
if (ret < 0)
|
if (ret < 0)
|
||||||
@ -1327,13 +1319,12 @@ daap_reply_plsonglist(struct evhttp_request *req, struct evbuffer *evbuf, char *
|
|||||||
static void
|
static void
|
||||||
daap_reply_playlists(struct evhttp_request *req, struct evbuffer *evbuf, char **uri, struct evkeyvalq *query)
|
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 *playlistlist;
|
||||||
struct evbuffer *playlist;
|
struct evbuffer *playlist;
|
||||||
struct db_playlist_info *dbpli;
|
|
||||||
struct dmap_field_map *dfm;
|
struct dmap_field_map *dfm;
|
||||||
const char *param;
|
const char *param;
|
||||||
char *db_errmsg;
|
|
||||||
char **strval;
|
char **strval;
|
||||||
uint32_t *meta;
|
uint32_t *meta;
|
||||||
int nmeta;
|
int nmeta;
|
||||||
@ -1415,29 +1406,28 @@ daap_reply_playlists(struct evhttp_request *req, struct evbuffer *evbuf, char **
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
memset(&qi, 0, sizeof(DBQUERYINFO));
|
memset(&qp, 0, sizeof(struct query_params));
|
||||||
get_query_params(query, &qi);
|
get_query_params(query, &qp);
|
||||||
qi.query_type = queryTypePlaylists;
|
qp.type = Q_PL;
|
||||||
|
|
||||||
ret = db_enum_start(&db_errmsg, &qi);
|
ret = db_query_start(&qp);
|
||||||
if (ret != DB_E_SUCCESS)
|
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);
|
free(meta);
|
||||||
evbuffer_free(playlist);
|
evbuffer_free(playlist);
|
||||||
evbuffer_free(playlistlist);
|
evbuffer_free(playlistlist);
|
||||||
if (qi.filter)
|
if (qp.filter)
|
||||||
free(qi.filter);
|
free(qp.filter);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
npls = 0;
|
npls = 0;
|
||||||
oom = 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++;
|
npls++;
|
||||||
|
|
||||||
@ -1451,11 +1441,11 @@ daap_reply_playlists(struct evhttp_request *req, struct evbuffer *evbuf, char **
|
|||||||
if (meta[i] == 0x670fc55e)
|
if (meta[i] == 0x670fc55e)
|
||||||
{
|
{
|
||||||
val = 0;
|
val = 0;
|
||||||
ret = safe_atoi(dbpli->type, &val);
|
ret = safe_atoi(dbpli.type, &val);
|
||||||
if ((ret == 0) && (val == 1))
|
if ((ret == 0) && (val == 1))
|
||||||
{
|
{
|
||||||
val = 1;
|
val = 1;
|
||||||
ret = safe_atoi(dbpli->id, &val);
|
ret = safe_atoi(dbpli.id, &val);
|
||||||
if ((ret == 0) && (val != 1))
|
if ((ret == 0) && (val != 1))
|
||||||
dmap_add_char(playlist, "aeSP", 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)
|
if (dfm->pli_offset < 0)
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
strval = (char **) ((char *)dbpli + dfm->pli_offset);
|
strval = (char **) ((char *)&dbpli + dfm->pli_offset);
|
||||||
|
|
||||||
if (!(*strval) || (**strval == '\0'))
|
if (!(*strval) || (**strval == '\0'))
|
||||||
continue;
|
continue;
|
||||||
@ -1486,13 +1476,13 @@ daap_reply_playlists(struct evhttp_request *req, struct evbuffer *evbuf, char **
|
|||||||
|
|
||||||
/* Item count (mimc) */
|
/* Item count (mimc) */
|
||||||
val = 0;
|
val = 0;
|
||||||
ret = safe_atoi(dbpli->items, &val);
|
ret = safe_atoi(dbpli.items, &val);
|
||||||
if ((ret == 0) && (val > 0))
|
if ((ret == 0) && (val > 0))
|
||||||
dmap_add_int(playlist, "mimc", val);
|
dmap_add_int(playlist, "mimc", val);
|
||||||
|
|
||||||
/* Base playlist (abpl), id = 1 */
|
/* Base playlist (abpl), id = 1 */
|
||||||
val = 0;
|
val = 0;
|
||||||
ret = safe_atoi(dbpli->id, &val);
|
ret = safe_atoi(dbpli.id, &val);
|
||||||
if ((ret == 0) && (val == 1))
|
if ((ret == 0) && (val == 1))
|
||||||
dmap_add_char(playlist, "abpl", 1);
|
dmap_add_char(playlist, "abpl", 1);
|
||||||
|
|
||||||
@ -1512,34 +1502,25 @@ daap_reply_playlists(struct evhttp_request *req, struct evbuffer *evbuf, char **
|
|||||||
free(meta);
|
free(meta);
|
||||||
evbuffer_free(playlist);
|
evbuffer_free(playlist);
|
||||||
|
|
||||||
if (qi.filter)
|
if (qp.filter)
|
||||||
free(qi.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);
|
daap_send_error(req, "aply", "Error fetching query results");
|
||||||
|
db_query_end(&qp);
|
||||||
free(db_errmsg);
|
|
||||||
evbuffer_free(playlistlist);
|
evbuffer_free(playlistlist);
|
||||||
return;
|
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)
|
if (oom)
|
||||||
{
|
{
|
||||||
DPRINTF(E_LOG, L_DAAP, "Could not add playlist to playlist list for DAAP playlists reply\n");
|
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");
|
daap_send_error(req, "aply", "Out of memory");
|
||||||
|
db_query_end(&qp);
|
||||||
evbuffer_free(playlistlist);
|
evbuffer_free(playlistlist);
|
||||||
return;
|
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_container(evbuf, "aply", EVBUFFER_LENGTH(playlistlist) + 53);
|
||||||
dmap_add_int(evbuf, "mstt", 200); /* 12 */
|
dmap_add_int(evbuf, "mstt", 200); /* 12 */
|
||||||
dmap_add_char(evbuf, "muty", 0); /* 9 */
|
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_int(evbuf,"mrco", npls); /* 12 */
|
||||||
dmap_add_container(evbuf, "mlcl", EVBUFFER_LENGTH(playlistlist));
|
dmap_add_container(evbuf, "mlcl", EVBUFFER_LENGTH(playlistlist));
|
||||||
|
|
||||||
|
db_query_end(&qp);
|
||||||
|
|
||||||
ret = evbuffer_add_buffer(evbuf, playlistlist);
|
ret = evbuffer_add_buffer(evbuf, playlistlist);
|
||||||
evbuffer_free(playlistlist);
|
evbuffer_free(playlistlist);
|
||||||
if (ret < 0)
|
if (ret < 0)
|
||||||
@ -1568,35 +1551,34 @@ daap_reply_playlists(struct evhttp_request *req, struct evbuffer *evbuf, char **
|
|||||||
static void
|
static void
|
||||||
daap_reply_browse(struct evhttp_request *req, struct evbuffer *evbuf, char **uri, struct evkeyvalq *query)
|
daap_reply_browse(struct evhttp_request *req, struct evbuffer *evbuf, char **uri, struct evkeyvalq *query)
|
||||||
{
|
{
|
||||||
DBQUERYINFO qi;
|
struct query_params qp;
|
||||||
struct evbuffer *itemlist;
|
struct evbuffer *itemlist;
|
||||||
char **item;
|
char *browse_item;
|
||||||
char *tag;
|
char *tag;
|
||||||
char *db_errmsg;
|
|
||||||
int nitems;
|
int nitems;
|
||||||
int ret;
|
int ret;
|
||||||
|
|
||||||
memset(&qi, 0, sizeof(DBQUERYINFO));
|
memset(&qp, 0, sizeof(struct query_params));
|
||||||
|
|
||||||
if (strcmp(uri[3], "artists") == 0)
|
if (strcmp(uri[3], "artists") == 0)
|
||||||
{
|
{
|
||||||
tag = "abar";
|
tag = "abar";
|
||||||
qi.query_type = queryTypeBrowseArtists;
|
qp.type = Q_BROWSE_ARTISTS;
|
||||||
}
|
}
|
||||||
else if (strcmp(uri[3], "genres") == 0)
|
else if (strcmp(uri[3], "genres") == 0)
|
||||||
{
|
{
|
||||||
tag = "abgn";
|
tag = "abgn";
|
||||||
qi.query_type = queryTypeBrowseGenres;
|
qp.type = Q_BROWSE_GENRES;
|
||||||
}
|
}
|
||||||
else if (strcmp(uri[3], "albums") == 0)
|
else if (strcmp(uri[3], "albums") == 0)
|
||||||
{
|
{
|
||||||
tag = "abal";
|
tag = "abal";
|
||||||
qi.query_type = queryTypeBrowseAlbums;
|
qp.type = Q_BROWSE_ALBUMS;
|
||||||
}
|
}
|
||||||
else if (strcmp(uri[3], "composers") == 0)
|
else if (strcmp(uri[3], "composers") == 0)
|
||||||
{
|
{
|
||||||
tag = "abcp";
|
tag = "abcp";
|
||||||
qi.query_type = queryTypeBrowseComposers;
|
qp.type = Q_BROWSE_COMPOSERS;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
@ -1636,58 +1618,50 @@ daap_reply_browse(struct evhttp_request *req, struct evbuffer *evbuf, char **uri
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
get_query_params(query, &qi);
|
get_query_params(query, &qp);
|
||||||
|
|
||||||
ret = db_enum_start(&db_errmsg, &qi);
|
ret = db_query_start(&qp);
|
||||||
if (ret != DB_E_SUCCESS)
|
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);
|
evbuffer_free(itemlist);
|
||||||
if (qi.filter)
|
if (qp.filter)
|
||||||
free(qi.filter);
|
free(qp.filter);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
nitems = 0;
|
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++;
|
nitems++;
|
||||||
|
|
||||||
dmap_add_string(itemlist, "mlit", *item);
|
dmap_add_string(itemlist, "mlit", browse_item);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (qi.filter)
|
if (qp.filter)
|
||||||
free(qi.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);
|
daap_send_error(req, "abro", "Error fetching query results");
|
||||||
|
db_query_end(&qp);
|
||||||
free(db_errmsg);
|
|
||||||
evbuffer_free(itemlist);
|
evbuffer_free(itemlist);
|
||||||
return;
|
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_container(evbuf, "abro", EVBUFFER_LENGTH(itemlist) + 44);
|
||||||
dmap_add_int(evbuf, "mstt", 200); /* 12 */
|
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_int(evbuf, "mrco", nitems); /* 12 */
|
||||||
dmap_add_container(evbuf, tag, EVBUFFER_LENGTH(itemlist));
|
dmap_add_container(evbuf, tag, EVBUFFER_LENGTH(itemlist));
|
||||||
|
|
||||||
|
db_query_end(&qp);
|
||||||
|
|
||||||
ret = evbuffer_add_buffer(evbuf, itemlist);
|
ret = evbuffer_add_buffer(evbuf, itemlist);
|
||||||
evbuffer_free(itemlist);
|
evbuffer_free(itemlist);
|
||||||
if (ret < 0)
|
if (ret < 0)
|
||||||
|
246
src/httpd_rsp.c
246
src/httpd_rsp.c
@ -38,8 +38,7 @@
|
|||||||
#include <mxml.h>
|
#include <mxml.h>
|
||||||
|
|
||||||
#include "logger.h"
|
#include "logger.h"
|
||||||
#include "ff-dbstruct.h"
|
#include "db.h"
|
||||||
#include "db-generic.h"
|
|
||||||
#include "conffile.h"
|
#include "conffile.h"
|
||||||
#include "misc.h"
|
#include "misc.h"
|
||||||
#include "httpd.h"
|
#include "httpd.h"
|
||||||
@ -176,16 +175,16 @@ static void
|
|||||||
rsp_send_error(struct evhttp_request *req, char *errmsg);
|
rsp_send_error(struct evhttp_request *req, char *errmsg);
|
||||||
|
|
||||||
static int
|
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;
|
const char *param;
|
||||||
int ret;
|
int ret;
|
||||||
|
|
||||||
*offset = 0;
|
qp->offset = 0;
|
||||||
param = evhttp_find_header(query, "offset");
|
param = evhttp_find_header(query, "offset");
|
||||||
if (param)
|
if (param)
|
||||||
{
|
{
|
||||||
ret = safe_atoi(param, offset);
|
ret = safe_atoi(param, &qp->offset);
|
||||||
if (ret < 0)
|
if (ret < 0)
|
||||||
{
|
{
|
||||||
rsp_send_error(req, "Invalid offset");
|
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");
|
param = evhttp_find_header(query, "limit");
|
||||||
if (param)
|
if (param)
|
||||||
{
|
{
|
||||||
ret = safe_atoi(param, limit);
|
ret = safe_atoi(param, &qp->limit);
|
||||||
if (ret < 0)
|
if (ret < 0)
|
||||||
{
|
{
|
||||||
rsp_send_error(req, "Invalid limit");
|
rsp_send_error(req, "Invalid limit");
|
||||||
@ -205,29 +204,18 @@ get_query_params(struct evhttp_request *req, struct evkeyvalq *query, DBQUERYINF
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (*offset || *limit)
|
if (qp->offset || qp->limit)
|
||||||
{
|
qp->idx_type = I_SUB;
|
||||||
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;
|
|
||||||
}
|
|
||||||
else
|
else
|
||||||
qi->index_type = indexTypeNone;
|
qp->idx_type = I_NONE;
|
||||||
|
|
||||||
qi->want_count = 1;
|
|
||||||
qi->correct_order = 1;
|
|
||||||
|
|
||||||
param = evhttp_find_header(query, "query");
|
param = evhttp_find_header(query, "query");
|
||||||
if (param)
|
if (param)
|
||||||
{
|
{
|
||||||
DPRINTF(E_DBG, L_RSP, "RSP browse query filter: %s\n", param);
|
DPRINTF(E_DBG, L_RSP, "RSP browse query filter: %s\n", param);
|
||||||
|
|
||||||
qi->filter = rsp_query_parse_sql(param);
|
qp->filter = rsp_query_parse_sql(param);
|
||||||
if (!qi->filter)
|
if (!qp->filter)
|
||||||
DPRINTF(E_LOG, L_RSP, "Ignoring improper RSP query\n");
|
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;
|
mxml_node_t *node;
|
||||||
cfg_t *lib;
|
cfg_t *lib;
|
||||||
char *library;
|
char *library;
|
||||||
char *db_errmsg;
|
|
||||||
int songcount;
|
int songcount;
|
||||||
int ret;
|
int ret;
|
||||||
|
|
||||||
ret = db_get_song_count(&db_errmsg, &songcount);
|
ret = db_files_get_count(&songcount);
|
||||||
if (ret != DB_E_SUCCESS)
|
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;
|
songcount = 0;
|
||||||
|
|
||||||
free(db_errmsg);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
lib = cfg_getnsec(cfg, "library", 0);
|
lib = cfg_getnsec(cfg, "library", 0);
|
||||||
@ -363,10 +348,9 @@ rsp_reply_info(struct evhttp_request *req, char **uri, struct evkeyvalq *query)
|
|||||||
static void
|
static void
|
||||||
rsp_reply_db(struct evhttp_request *req, char **uri, struct evkeyvalq *query)
|
rsp_reply_db(struct evhttp_request *req, char **uri, struct evkeyvalq *query)
|
||||||
{
|
{
|
||||||
DBQUERYINFO qi;
|
struct query_params qp;
|
||||||
struct db_playlist_info *dbpli;
|
struct db_playlist_info dbpli;
|
||||||
struct evbuffer *evbuf;
|
struct evbuffer *evbuf;
|
||||||
char *db_errmsg;
|
|
||||||
char **strval;
|
char **strval;
|
||||||
mxml_node_t *reply;
|
mxml_node_t *reply;
|
||||||
mxml_node_t *status;
|
mxml_node_t *status;
|
||||||
@ -376,20 +360,17 @@ rsp_reply_db(struct evhttp_request *req, char **uri, struct evkeyvalq *query)
|
|||||||
int i;
|
int i;
|
||||||
int ret;
|
int ret;
|
||||||
|
|
||||||
memset(&qi, 0, sizeof(DBQUERYINFO));
|
memset(&qp, 0, sizeof(struct db_playlist_info));
|
||||||
|
|
||||||
qi.query_type = queryTypePlaylists;
|
qp.type = Q_PL;
|
||||||
qi.index_type = indexTypeNone;
|
qp.idx_type = I_NONE;
|
||||||
qi.want_count = 1;
|
|
||||||
|
|
||||||
ret = db_enum_start(&db_errmsg, &qi);
|
ret = db_query_start(&qp);
|
||||||
if (ret != DB_E_SUCCESS)
|
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);
|
rsp_send_error(req, "Could not start query");
|
||||||
|
|
||||||
free(db_errmsg);
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -410,13 +391,13 @@ rsp_reply_db(struct evhttp_request *req, char **uri, struct evkeyvalq *query)
|
|||||||
mxmlNewText(node, 0, "");
|
mxmlNewText(node, 0, "");
|
||||||
|
|
||||||
node = mxmlNewElement(status, "records");
|
node = mxmlNewElement(status, "records");
|
||||||
mxmlNewTextf(node, 0, "%d", qi.specifiedtotalcount);
|
mxmlNewTextf(node, 0, "%d", qp.results);
|
||||||
|
|
||||||
node = mxmlNewElement(status, "totalrecords");
|
node = mxmlNewElement(status, "totalrecords");
|
||||||
mxmlNewTextf(node, 0, "%d", qi.specifiedtotalcount);
|
mxmlNewTextf(node, 0, "%d", qp.results);
|
||||||
|
|
||||||
/* Playlists block (all playlists) */
|
/* 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) */
|
/* Playlist block (one playlist) */
|
||||||
pl = mxmlNewElement(pls, "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)
|
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);
|
node = mxmlNewElement(pl, pl_fields[i].field);
|
||||||
mxmlNewText(node, 0, *strval);
|
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);
|
mxmlDelete(reply);
|
||||||
|
db_query_end(&qp);
|
||||||
rsp_send_error(req, db_errmsg);
|
rsp_send_error(req, "Error fetching query results");
|
||||||
|
|
||||||
free(db_errmsg);
|
|
||||||
return;
|
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
|
/* HACK
|
||||||
* Add a dummy empty string to the playlists element if there is no data
|
* Add a dummy empty string to the playlists element if there is no data
|
||||||
* to return - this prevents mxml from sending out an empty <playlists/>
|
* to return - this prevents mxml from sending out an empty <playlists/>
|
||||||
* tag that the SoundBridge does not handle. It's hackish, but it works.
|
* tag that the SoundBridge does not handle. It's hackish, but it works.
|
||||||
*/
|
*/
|
||||||
if (qi.specifiedtotalcount == 0)
|
if (qp.results == 0)
|
||||||
mxmlNewText(pls, 0, "");
|
mxmlNewText(pls, 0, "");
|
||||||
|
|
||||||
|
db_query_end(&qp);
|
||||||
|
|
||||||
evbuf = mxml_to_evbuf(reply);
|
evbuf = mxml_to_evbuf(reply);
|
||||||
mxmlDelete(reply);
|
mxmlDelete(reply);
|
||||||
|
|
||||||
@ -481,10 +454,9 @@ rsp_reply_db(struct evhttp_request *req, char **uri, struct evkeyvalq *query)
|
|||||||
static void
|
static void
|
||||||
rsp_reply_playlist(struct evhttp_request *req, char **uri, struct evkeyvalq *query)
|
rsp_reply_playlist(struct evhttp_request *req, char **uri, struct evkeyvalq *query)
|
||||||
{
|
{
|
||||||
DBQUERYINFO qi;
|
struct query_params qp;
|
||||||
struct db_media_file_info *dbmfi;
|
struct db_media_file_info dbmfi;
|
||||||
struct evbuffer *evbuf;
|
struct evbuffer *evbuf;
|
||||||
char *db_errmsg;
|
|
||||||
const char *param;
|
const char *param;
|
||||||
char **strval;
|
char **strval;
|
||||||
mxml_node_t *reply;
|
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 *item;
|
||||||
mxml_node_t *node;
|
mxml_node_t *node;
|
||||||
int mode;
|
int mode;
|
||||||
int limit;
|
|
||||||
int offset;
|
|
||||||
int records;
|
int records;
|
||||||
int transcode;
|
int transcode;
|
||||||
int bitrate;
|
int bitrate;
|
||||||
int i;
|
int i;
|
||||||
int ret;
|
int ret;
|
||||||
|
|
||||||
memset(&qi, 0, sizeof(DBQUERYINFO));
|
memset(&qp, 0, sizeof(struct query_params));
|
||||||
|
|
||||||
qi.query_type = queryTypePlaylistItems;
|
ret = safe_atoi(uri[2], &qp.pl_id);
|
||||||
|
|
||||||
ret = safe_atoi(uri[2], &qi.playlist_id);
|
|
||||||
if (ret < 0)
|
if (ret < 0)
|
||||||
{
|
{
|
||||||
rsp_send_error(req, "Invalid playlist ID");
|
rsp_send_error(req, "Invalid playlist ID");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (qp.pl_id == 0)
|
||||||
|
qp.type = Q_ITEMS;
|
||||||
|
else
|
||||||
|
qp.type = Q_PLITEMS;
|
||||||
|
|
||||||
mode = F_FULL;
|
mode = F_FULL;
|
||||||
param = evhttp_find_header(query, "type");
|
param = evhttp_find_header(query, "type");
|
||||||
if (param)
|
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);
|
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)
|
if (ret < 0)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
ret = db_enum_start(&db_errmsg, &qi);
|
ret = db_query_start(&qp);
|
||||||
if (ret != DB_E_SUCCESS)
|
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)
|
if (qp.filter)
|
||||||
free(qi.filter);
|
free(qp.filter);
|
||||||
free(db_errmsg);
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (offset > qi.specifiedtotalcount)
|
if (qp.offset > qp.results)
|
||||||
records = 0;
|
records = 0;
|
||||||
else if (limit > (qi.specifiedtotalcount - offset))
|
else if (qp.limit > (qp.results - qp.offset))
|
||||||
records = qi.specifiedtotalcount - offset;
|
records = qp.results - qp.offset;
|
||||||
else
|
else
|
||||||
records = limit;
|
records = qp.limit;
|
||||||
|
|
||||||
/* We'd use mxmlNewXML(), but then we can't put any attributes
|
/* We'd use mxmlNewXML(), but then we can't put any attributes
|
||||||
* on the root node and we need some.
|
* 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);
|
mxmlNewTextf(node, 0, "%d", records);
|
||||||
|
|
||||||
node = mxmlNewElement(status, "totalrecords");
|
node = mxmlNewElement(status, "totalrecords");
|
||||||
mxmlNewTextf(node, 0, "%d", qi.specifiedtotalcount);
|
mxmlNewTextf(node, 0, "%d", qp.results);
|
||||||
|
|
||||||
/* Items block (all items) */
|
/* 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 block (one item) */
|
||||||
item = mxmlNewElement(items, "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))
|
if (!(rsp_fields[i].flags & mode))
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
strval = (char **) ((char *)dbmfi + rsp_fields[i].offset);
|
strval = (char **) ((char *)&dbmfi + rsp_fields[i].offset);
|
||||||
|
|
||||||
if (!(*strval) || (strlen(*strval) == 0))
|
if (!(*strval) || (strlen(*strval) == 0))
|
||||||
continue;
|
continue;
|
||||||
@ -606,7 +578,7 @@ rsp_reply_playlist(struct evhttp_request *req, char **uri, struct evkeyvalq *que
|
|||||||
|
|
||||||
case dbmfi_offsetof(bitrate):
|
case dbmfi_offsetof(bitrate):
|
||||||
bitrate = 0;
|
bitrate = 0;
|
||||||
ret = safe_atoi(dbmfi->samplerate, &bitrate);
|
ret = safe_atoi(dbmfi.samplerate, &bitrate);
|
||||||
if ((ret < 0) || (bitrate == 0))
|
if ((ret < 0) || (bitrate == 0))
|
||||||
bitrate = 1411;
|
bitrate = 1411;
|
||||||
else
|
else
|
||||||
@ -634,37 +606,29 @@ rsp_reply_playlist(struct evhttp_request *req, char **uri, struct evkeyvalq *que
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (qi.filter)
|
if (qp.filter)
|
||||||
free(qi.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);
|
mxmlDelete(reply);
|
||||||
|
db_query_end(&qp);
|
||||||
rsp_send_error(req, db_errmsg);
|
rsp_send_error(req, "Error fetching query results");
|
||||||
|
|
||||||
free(db_errmsg);
|
|
||||||
return;
|
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
|
/* HACK
|
||||||
* Add a dummy empty string to the items element if there is no data
|
* Add a dummy empty string to the items element if there is no data
|
||||||
* to return - this prevents mxml from sending out an empty <items/>
|
* to return - this prevents mxml from sending out an empty <items/>
|
||||||
* tag that the SoundBridge does not handle. It's hackish, but it works.
|
* tag that the SoundBridge does not handle. It's hackish, but it works.
|
||||||
*/
|
*/
|
||||||
if (qi.specifiedtotalcount == 0)
|
if (qp.results == 0)
|
||||||
mxmlNewText(items, 0, "");
|
mxmlNewText(items, 0, "");
|
||||||
|
|
||||||
|
db_query_end(&qp);
|
||||||
|
|
||||||
evbuf = mxml_to_evbuf(reply);
|
evbuf = mxml_to_evbuf(reply);
|
||||||
mxmlDelete(reply);
|
mxmlDelete(reply);
|
||||||
|
|
||||||
@ -685,29 +649,26 @@ rsp_reply_playlist(struct evhttp_request *req, char **uri, struct evkeyvalq *que
|
|||||||
static void
|
static void
|
||||||
rsp_reply_browse(struct evhttp_request *req, char **uri, struct evkeyvalq *query)
|
rsp_reply_browse(struct evhttp_request *req, char **uri, struct evkeyvalq *query)
|
||||||
{
|
{
|
||||||
DBQUERYINFO qi;
|
struct query_params qp;
|
||||||
struct db_media_file_info *dbmfi;
|
|
||||||
struct evbuffer *evbuf;
|
struct evbuffer *evbuf;
|
||||||
char *db_errmsg;
|
char *browse_item;
|
||||||
mxml_node_t *reply;
|
mxml_node_t *reply;
|
||||||
mxml_node_t *status;
|
mxml_node_t *status;
|
||||||
mxml_node_t *items;
|
mxml_node_t *items;
|
||||||
mxml_node_t *node;
|
mxml_node_t *node;
|
||||||
int limit;
|
|
||||||
int offset;
|
|
||||||
int records;
|
int records;
|
||||||
int ret;
|
int ret;
|
||||||
|
|
||||||
memset(&qi, 0, sizeof(DBQUERYINFO));
|
memset(&qp, 0, sizeof(struct query_params));
|
||||||
|
|
||||||
if (strcmp(uri[3], "artist") == 0)
|
if (strcmp(uri[3], "artist") == 0)
|
||||||
qi.query_type = queryTypeBrowseArtists;
|
qp.type = Q_BROWSE_ARTISTS;
|
||||||
else if (strcmp(uri[3], "genre") == 0)
|
else if (strcmp(uri[3], "genre") == 0)
|
||||||
qi.query_type = queryTypeBrowseGenres;
|
qp.type = Q_BROWSE_GENRES;
|
||||||
else if (strcmp(uri[3], "album") == 0)
|
else if (strcmp(uri[3], "album") == 0)
|
||||||
qi.query_type = queryTypeBrowseAlbums;
|
qp.type = Q_BROWSE_ALBUMS;
|
||||||
else if (strcmp(uri[3], "composer") == 0)
|
else if (strcmp(uri[3], "composer") == 0)
|
||||||
qi.query_type = queryTypeBrowseComposers;
|
qp.type = Q_BROWSE_COMPOSERS;
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
DPRINTF(E_LOG, L_RSP, "Unsupported browse type '%s'\n", uri[3]);
|
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;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
ret = safe_atoi(uri[2], &qi.playlist_id);
|
ret = safe_atoi(uri[2], &qp.pl_id);
|
||||||
if (ret < 0)
|
if (ret < 0)
|
||||||
{
|
{
|
||||||
rsp_send_error(req, "Invalid playlist ID");
|
rsp_send_error(req, "Invalid playlist ID");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
ret = get_query_params(req, query, &qi, &offset, &limit);
|
ret = get_query_params(req, query, &qp);
|
||||||
if (ret < 0)
|
if (ret < 0)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
ret = db_enum_start(&db_errmsg, &qi);
|
ret = db_query_start(&qp);
|
||||||
if (ret != DB_E_SUCCESS)
|
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)
|
if (qp.filter)
|
||||||
free(qi.filter);
|
free(qp.filter);
|
||||||
free(db_errmsg);
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (offset > qi.specifiedtotalcount)
|
if (qp.offset > qp.results)
|
||||||
records = 0;
|
records = 0;
|
||||||
else if (limit > (qi.specifiedtotalcount - offset))
|
else if (qp.limit > (qp.results - qp.offset))
|
||||||
records = qi.specifiedtotalcount - offset;
|
records = qp.results - qp.offset;
|
||||||
else
|
else
|
||||||
records = limit;
|
records = qp.limit;
|
||||||
|
|
||||||
/* We'd use mxmlNewXML(), but then we can't put any attributes
|
/* We'd use mxmlNewXML(), but then we can't put any attributes
|
||||||
* on the root node and we need some.
|
* 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);
|
mxmlNewTextf(node, 0, "%d", records);
|
||||||
|
|
||||||
node = mxmlNewElement(status, "totalrecords");
|
node = mxmlNewElement(status, "totalrecords");
|
||||||
mxmlNewTextf(node, 0, "%d", qi.specifiedtotalcount);
|
mxmlNewTextf(node, 0, "%d", qp.results);
|
||||||
|
|
||||||
/* Items block (all items) */
|
/* 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");
|
node = mxmlNewElement(items, "item");
|
||||||
mxmlNewText(node, 0, dbmfi->id);
|
mxmlNewText(node, 0, browse_item);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (qi.filter)
|
if (qp.filter)
|
||||||
free(qi.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);
|
mxmlDelete(reply);
|
||||||
|
db_query_end(&qp);
|
||||||
rsp_send_error(req, db_errmsg);
|
rsp_send_error(req, "Error fetching query results");
|
||||||
|
|
||||||
free(db_errmsg);
|
|
||||||
return;
|
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
|
/* HACK
|
||||||
* Add a dummy empty string to the items element if there is no data
|
* Add a dummy empty string to the items element if there is no data
|
||||||
* to return - this prevents mxml from sending out an empty <items/>
|
* to return - this prevents mxml from sending out an empty <items/>
|
||||||
* tag that the SoundBridge does not handle. It's hackish, but it works.
|
* tag that the SoundBridge does not handle. It's hackish, but it works.
|
||||||
*/
|
*/
|
||||||
if (qi.specifiedtotalcount == 0)
|
if (qp.results == 0);
|
||||||
mxmlNewText(items, 0, "");
|
mxmlNewText(items, 0, "");
|
||||||
|
|
||||||
|
db_query_end(&qp);
|
||||||
|
|
||||||
evbuf = mxml_to_evbuf(reply);
|
evbuf = mxml_to_evbuf(reply);
|
||||||
mxmlDelete(reply);
|
mxmlDelete(reply);
|
||||||
|
|
||||||
|
22
src/main.c
22
src/main.c
@ -47,11 +47,11 @@
|
|||||||
#include <libavformat/avformat.h>
|
#include <libavformat/avformat.h>
|
||||||
|
|
||||||
#include "conffile.h"
|
#include "conffile.h"
|
||||||
|
#include "db.h"
|
||||||
#include "logger.h"
|
#include "logger.h"
|
||||||
#include "misc.h"
|
#include "misc.h"
|
||||||
#include "filescanner.h"
|
#include "filescanner.h"
|
||||||
#include "httpd.h"
|
#include "httpd.h"
|
||||||
#include "db-generic.h"
|
|
||||||
#include "mdns_avahi.h"
|
#include "mdns_avahi.h"
|
||||||
|
|
||||||
|
|
||||||
@ -334,7 +334,6 @@ main(int argc, char **argv)
|
|||||||
char *logdomains;
|
char *logdomains;
|
||||||
char *logfile;
|
char *logfile;
|
||||||
char *ffid;
|
char *ffid;
|
||||||
char *perr;
|
|
||||||
char *pidfile;
|
char *pidfile;
|
||||||
sigset_t sigs;
|
sigset_t sigs;
|
||||||
int sigfd;
|
int sigfd;
|
||||||
@ -500,23 +499,17 @@ main(int argc, char **argv)
|
|||||||
goto mdns_fail;
|
goto mdns_fail;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* this will require that the db be readable by the runas user */
|
/* Initialize the database before starting */
|
||||||
ret = db_open(&perr, "sqlite3", "/var/cache/mt-daapd"); /* FIXME */
|
DPRINTF(E_INFO, L_MAIN, "Initializing database\n");
|
||||||
if (ret != 0)
|
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;
|
ret = EXIT_FAILURE;
|
||||||
goto db_fail;
|
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 */
|
/* Spawn file scanner thread */
|
||||||
ret = filescanner_init();
|
ret = filescanner_init();
|
||||||
if (ret != 0)
|
if (ret != 0)
|
||||||
@ -582,9 +575,6 @@ main(int argc, char **argv)
|
|||||||
filescanner_deinit();
|
filescanner_deinit();
|
||||||
|
|
||||||
filescanner_fail:
|
filescanner_fail:
|
||||||
DPRINTF(E_LOG, L_MAIN, "Closing database\n");
|
|
||||||
db_deinit();
|
|
||||||
|
|
||||||
db_fail:
|
db_fail:
|
||||||
if (ret == EXIT_FAILURE)
|
if (ret == EXIT_FAILURE)
|
||||||
{
|
{
|
||||||
|
@ -40,13 +40,15 @@
|
|||||||
#include <sys/stat.h>
|
#include <sys/stat.h>
|
||||||
|
|
||||||
#include "logger.h"
|
#include "logger.h"
|
||||||
#include "ff-dbstruct.h"
|
#include "db.h"
|
||||||
|
|
||||||
#include <FLAC/metadata.h>
|
#include <FLAC/metadata.h>
|
||||||
|
|
||||||
#define TRUE ((1 == 1))
|
#define TRUE ((1 == 1))
|
||||||
#define FALSE (!TRUE)
|
#define FALSE (!TRUE)
|
||||||
|
|
||||||
|
typedef struct media_file_info MP3FILE;
|
||||||
|
|
||||||
#define GET_VORBIS_COMMENT(comment, name, len) (char*) \
|
#define GET_VORBIS_COMMENT(comment, name, len) (char*) \
|
||||||
(((strncasecmp(name, (char*)(comment).entry, strlen(name)) == 0) && \
|
(((strncasecmp(name, (char*)(comment).entry, strlen(name)) == 0) && \
|
||||||
((comment).entry[strlen(name)] == '=')) ? \
|
((comment).entry[strlen(name)] == '=')) ? \
|
||||||
|
@ -31,11 +31,12 @@
|
|||||||
#include <taglib/tag_c.h>
|
#include <taglib/tag_c.h>
|
||||||
|
|
||||||
#include "logger.h"
|
#include "logger.h"
|
||||||
#include "ff-dbstruct.h"
|
#include "db.h"
|
||||||
|
|
||||||
#define TRUE ((1 == 1))
|
#define TRUE ((1 == 1))
|
||||||
#define FALSE (!TRUE)
|
#define FALSE (!TRUE)
|
||||||
|
|
||||||
|
typedef struct media_file_info MP3FILE;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* scan a musepack file for metainfo.
|
* scan a musepack file for metainfo.
|
||||||
|
@ -34,11 +34,13 @@
|
|||||||
#include <unistd.h>
|
#include <unistd.h>
|
||||||
|
|
||||||
#include "logger.h"
|
#include "logger.h"
|
||||||
#include "ff-dbstruct.h"
|
#include "db.h"
|
||||||
|
|
||||||
#define TRUE ((1 == 1))
|
#define TRUE ((1 == 1))
|
||||||
#define FALSE (!TRUE)
|
#define FALSE (!TRUE)
|
||||||
|
|
||||||
|
typedef struct media_file_info MP3FILE;
|
||||||
|
|
||||||
typedef struct tag_wma_guidlist {
|
typedef struct tag_wma_guidlist {
|
||||||
char *name;
|
char *name;
|
||||||
char *guid;
|
char *guid;
|
||||||
|
@ -41,7 +41,7 @@
|
|||||||
|
|
||||||
#include "logger.h"
|
#include "logger.h"
|
||||||
#include "conffile.h"
|
#include "conffile.h"
|
||||||
#include "ff-dbstruct.h"
|
#include "db.h"
|
||||||
#include "transcode.h"
|
#include "transcode.h"
|
||||||
|
|
||||||
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user