mirror of
https://github.com/owntone/owntone-server.git
synced 2025-02-09 20:58:10 -05:00
add some support towards static file-based playlists
This commit is contained in:
parent
2c059f4bb2
commit
a0143734b7
@ -46,7 +46,7 @@ typedef struct tag_db_functions {
|
|||||||
int(*dbs_init)(int);
|
int(*dbs_init)(int);
|
||||||
int(*dbs_deinit)(void);
|
int(*dbs_deinit)(void);
|
||||||
int(*dbs_add)(MP3FILE*);
|
int(*dbs_add)(MP3FILE*);
|
||||||
int(*dbs_add_playlist)(char *, int, char *, int *);
|
int(*dbs_add_playlist)(char *, int, char *,char *, int *);
|
||||||
int(*dbs_add_playlist_item)(int, int);
|
int(*dbs_add_playlist_item)(int, int);
|
||||||
int(*dbs_enum_start)(DBQUERYINFO *);
|
int(*dbs_enum_start)(DBQUERYINFO *);
|
||||||
int(*dbs_enum_size)(DBQUERYINFO *, int *);
|
int(*dbs_enum_size)(DBQUERYINFO *, int *);
|
||||||
@ -468,11 +468,11 @@ int db_add(MP3FILE *pmp3) {
|
|||||||
* \param playlistid returns the id of the playlist created
|
* \param playlistid returns the id of the playlist created
|
||||||
* \returns 0 on success, error code otherwise
|
* \returns 0 on success, error code otherwise
|
||||||
*/
|
*/
|
||||||
int db_add_playlist(char *name, int type, char *clause, int *playlistid) {
|
int db_add_playlist(char *name, int type, char *clause, char *path, int *playlistid) {
|
||||||
int retval;
|
int retval;
|
||||||
|
|
||||||
db_writelock();
|
db_writelock();
|
||||||
retval=db_current->dbs_add_playlist(name,type,clause,playlistid);
|
retval=db_current->dbs_add_playlist(name,type,clause,path,playlistid);
|
||||||
if(retval == DB_E_SUCCESS)
|
if(retval == DB_E_SUCCESS)
|
||||||
db_revision_no++;
|
db_revision_no++;
|
||||||
db_unlock();
|
db_unlock();
|
||||||
|
@ -155,7 +155,7 @@ extern int db_end_scan(void);
|
|||||||
extern int db_exists(char *path);
|
extern int db_exists(char *path);
|
||||||
extern int db_scanning(void);
|
extern int db_scanning(void);
|
||||||
|
|
||||||
extern int db_add_playlist(char *name, int type, char *clause, int *playlistid);
|
extern int db_add_playlist(char *name, int type, char *clause, char *path,int *playlistid);
|
||||||
extern int db_add_playlist_item(int playlistid, int songid);
|
extern int db_add_playlist_item(int playlistid, int songid);
|
||||||
|
|
||||||
extern MP3FILE *db_fetch_item(int id);
|
extern MP3FILE *db_fetch_item(int id);
|
||||||
|
@ -26,6 +26,7 @@
|
|||||||
#define _XOPEN_SOURCE 500
|
#define _XOPEN_SOURCE 500
|
||||||
|
|
||||||
#include <errno.h>
|
#include <errno.h>
|
||||||
|
#include <fcntl.h>
|
||||||
#include <limits.h>
|
#include <limits.h>
|
||||||
#include <pthread.h>
|
#include <pthread.h>
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
@ -37,6 +38,7 @@
|
|||||||
#include "mp3-scanner.h"
|
#include "mp3-scanner.h"
|
||||||
#include "db-generic.h"
|
#include "db-generic.h"
|
||||||
#include "dbs-sqlite.h"
|
#include "dbs-sqlite.h"
|
||||||
|
#include "restart.h"
|
||||||
#include "ssc.h"
|
#include "ssc.h"
|
||||||
|
|
||||||
/* Globals */
|
/* Globals */
|
||||||
@ -46,6 +48,8 @@ static sqlite_vm *db_sqlite_pvm;
|
|||||||
static int db_sqlite_in_scan=0;
|
static int db_sqlite_in_scan=0;
|
||||||
static int db_sqlite_reload=0;
|
static int db_sqlite_reload=0;
|
||||||
|
|
||||||
|
static char db_path[PATH_MAX + 1];
|
||||||
|
|
||||||
/* Forwards */
|
/* Forwards */
|
||||||
int db_sqlite_get_size(DBQUERYINFO *pinfo, char **valarray);
|
int db_sqlite_get_size(DBQUERYINFO *pinfo, char **valarray);
|
||||||
int db_sqlite_build_dmap(DBQUERYINFO *pinfo, char **valarray, char *presult, int len);
|
int db_sqlite_build_dmap(DBQUERYINFO *pinfo, char **valarray, char *presult, int len);
|
||||||
@ -205,7 +209,6 @@ int db_sqlite_get_int(int loglevel, int *result, char *fmt, ...) {
|
|||||||
* open sqlite database
|
* open sqlite database
|
||||||
*/
|
*/
|
||||||
int db_sqlite_open(char *parameters) {
|
int db_sqlite_open(char *parameters) {
|
||||||
char db_path[PATH_MAX + 1];
|
|
||||||
char *perr;
|
char *perr;
|
||||||
|
|
||||||
snprintf(db_path,sizeof(db_path),"%s/songs.db",parameters);
|
snprintf(db_path,sizeof(db_path),"%s/songs.db",parameters);
|
||||||
@ -313,9 +316,9 @@ int db_sqlite_end_scan(void) {
|
|||||||
* \param type playlist type: 0 - static, 1 - smart, 2 - m3u
|
* \param type playlist type: 0 - static, 1 - smart, 2 - m3u
|
||||||
* \param clause: "where" clause for smart playlist
|
* \param clause: "where" clause for smart playlist
|
||||||
*/
|
*/
|
||||||
int db_sqlite_add_playlist(char *name, int type, char *clause, int *playlistid) {
|
int db_sqlite_add_playlist(char *name, int type, char *clause, char *path, int *playlistid) {
|
||||||
int cnt=0;
|
int cnt=0;
|
||||||
int result;
|
int result=DB_E_SUCCESS;
|
||||||
|
|
||||||
db_sqlite_get_int(E_DBG,&cnt,"select count(*) from playlists where "
|
db_sqlite_get_int(E_DBG,&cnt,"select count(*) from playlists where "
|
||||||
"upper(title)=upper('%q')",name);
|
"upper(title)=upper('%q')",name);
|
||||||
@ -324,14 +327,20 @@ int db_sqlite_add_playlist(char *name, int type, char *clause, int *playlistid)
|
|||||||
if((type == 1) && (!clause)) return DB_E_NOCLAUSE;
|
if((type == 1) && (!clause)) return DB_E_NOCLAUSE;
|
||||||
|
|
||||||
/* Let's throw it in */
|
/* Let's throw it in */
|
||||||
if(type == 1) {
|
switch(type) {
|
||||||
|
case 0: /* static, maintained in web interface */
|
||||||
|
case 2: /* static, from file */
|
||||||
|
result = db_sqlite_exec(E_LOG,"insert into playlists "
|
||||||
|
"(title,type,items,query,db_timestamp,path) "
|
||||||
|
"values ('%q',0,0,NULL,%d)",name,time(NULL),path);
|
||||||
|
break;
|
||||||
|
case 1: /* smart */
|
||||||
result=db_sqlite_get_int(E_DBG,&cnt,"select count (*) from songs where %s",clause);
|
result=db_sqlite_get_int(E_DBG,&cnt,"select count (*) from songs where %s",clause);
|
||||||
if(result != DB_E_SUCCESS) return result;
|
if(result != DB_E_SUCCESS) return result;
|
||||||
result = db_sqlite_exec(E_LOG,"insert into playlists (title,smart,items,query) "
|
result = db_sqlite_exec(E_LOG,"insert into playlists "
|
||||||
"values ('%q',1,%d,'%q')",name,cnt,clause);
|
"(title,type,items,query,db_timestamp) "
|
||||||
} else {
|
"values ('%q',1,%d,'%q',%d)",name,cnt,clause,time(NULL));
|
||||||
result = db_sqlite_exec(E_LOG,"insert into playlists (title,smart,items,query) "
|
break;
|
||||||
"values ('%q',0,0,NULL)",name);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if(result)
|
if(result)
|
||||||
@ -357,7 +366,7 @@ int db_sqlite_add_playlist_item(int playlistid, int songid) {
|
|||||||
|
|
||||||
/* first, check the playlist */
|
/* first, check the playlist */
|
||||||
result=db_sqlite_get_int(E_DBG,&playlist_type,
|
result=db_sqlite_get_int(E_DBG,&playlist_type,
|
||||||
"select smart from playlists where id=%d",playlistid);
|
"select type from playlists where id=%d",playlistid);
|
||||||
|
|
||||||
if(result != DB_E_SUCCESS) {
|
if(result != DB_E_SUCCESS) {
|
||||||
if(result == DB_E_NOROWS)
|
if(result == DB_E_NOROWS)
|
||||||
@ -365,7 +374,7 @@ int db_sqlite_add_playlist_item(int playlistid, int songid) {
|
|||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
if(playlist_type == 1) /* can't add to smart playlists */
|
if(playlist_type != 0) /* can't add to smart playlists, or static */
|
||||||
return DB_E_INVALIDTYPE;
|
return DB_E_INVALIDTYPE;
|
||||||
|
|
||||||
/* make sure the songid is valid */
|
/* make sure the songid is valid */
|
||||||
@ -591,7 +600,7 @@ int db_sqlite_update_playlists(void) {
|
|||||||
|
|
||||||
for(index=1;index <= rows; index ++) {
|
for(index=1;index <= rows; index ++) {
|
||||||
DPRINTF(E_DBG,L_DB,"Updating playlist counts for %s\n",resarray[cols * index + 1]);
|
DPRINTF(E_DBG,L_DB,"Updating playlist counts for %s\n",resarray[cols * index + 1]);
|
||||||
if(atoi(resarray[cols * index + 2])) { // is a smart playlist
|
if(atoi(resarray[cols * index + 2]) == 1) { // is a smart playlist
|
||||||
db_sqlite_exec(E_FATAL,"UPDATE playlists SET items=(SELECT COUNT(*) "
|
db_sqlite_exec(E_FATAL,"UPDATE playlists SET items=(SELECT COUNT(*) "
|
||||||
"FROM songs WHERE %s) WHERE id=%s",resarray[cols * index + 4],
|
"FROM songs WHERE %s) WHERE id=%s",resarray[cols * index + 4],
|
||||||
resarray[cols * index]);
|
resarray[cols * index]);
|
||||||
@ -649,7 +658,7 @@ int db_sqlite_enum_start(DBQUERYINFO *pinfo) {
|
|||||||
|
|
||||||
case queryTypePlaylistItems: /* Figure out if it's smart or dull */
|
case queryTypePlaylistItems: /* Figure out if it's smart or dull */
|
||||||
db_sqlite_lock();
|
db_sqlite_lock();
|
||||||
sprintf(scratch,"SELECT smart,query FROM playlists WHERE id=%d",pinfo->playlist_id);
|
sprintf(scratch,"SELECT type,query FROM playlists WHERE id=%d",pinfo->playlist_id);
|
||||||
DPRINTF(E_DBG,L_DB,"Executing %s\n",scratch);
|
DPRINTF(E_DBG,L_DB,"Executing %s\n",scratch);
|
||||||
err=sqlite_get_table(db_sqlite_songs,scratch,&resarray,&rows,&cols,&perr);
|
err=sqlite_get_table(db_sqlite_songs,scratch,&resarray,&rows,&cols,&perr);
|
||||||
if(err != SQLITE_OK) {
|
if(err != SQLITE_OK) {
|
||||||
@ -657,7 +666,7 @@ int db_sqlite_enum_start(DBQUERYINFO *pinfo) {
|
|||||||
db_sqlite_unlock();
|
db_sqlite_unlock();
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
is_smart=atoi(resarray[2]);
|
is_smart=(atoi(resarray[2]) == 1);
|
||||||
have_clause=1;
|
have_clause=1;
|
||||||
if(is_smart) {
|
if(is_smart) {
|
||||||
sprintf(query_select,"SELECT * FROM songs ");
|
sprintf(query_select,"SELECT * FROM songs ");
|
||||||
@ -1506,7 +1515,7 @@ char *db_sqlite_upgrade_scripts[] = {
|
|||||||
"CREATE TABLE playlists (\n"
|
"CREATE TABLE playlists (\n"
|
||||||
" id INTEGER PRIMARY KEY NOT NULL,\n"
|
" id INTEGER PRIMARY KEY NOT NULL,\n"
|
||||||
" title VARCHAR(255) NOT NULL,\n"
|
" title VARCHAR(255) NOT NULL,\n"
|
||||||
" smart INTEGER NOT NULL,\n"
|
" type INTEGER NOT NULL,\n"
|
||||||
" items INTEGER NOT NULL,\n"
|
" items INTEGER NOT NULL,\n"
|
||||||
" query VARCHAR(1024)\n"
|
" query VARCHAR(1024)\n"
|
||||||
" db_timestamp INTEGER NOT NULL,\n"
|
" db_timestamp INTEGER NOT NULL,\n"
|
||||||
@ -1524,6 +1533,11 @@ char *db_sqlite_upgrade_scripts[] = {
|
|||||||
* \param from_version the current version of the database
|
* \param from_version the current version of the database
|
||||||
*/
|
*/
|
||||||
int db_sqlite_update_version(int from_version) {
|
int db_sqlite_update_version(int from_version) {
|
||||||
|
char db_new_path[PATH_MAX + 1];
|
||||||
|
int from_fd, to_fd;
|
||||||
|
int copied=0;
|
||||||
|
int result;
|
||||||
|
|
||||||
if(from_version > (sizeof(db_sqlite_upgrade_scripts)/sizeof(char*))) {
|
if(from_version > (sizeof(db_sqlite_upgrade_scripts)/sizeof(char*))) {
|
||||||
DPRINTF(E_FATAL,L_DB,"Database version too new (time machine, maybe?)\n");
|
DPRINTF(E_FATAL,L_DB,"Database version too new (time machine, maybe?)\n");
|
||||||
}
|
}
|
||||||
@ -1531,10 +1545,43 @@ int db_sqlite_update_version(int from_version) {
|
|||||||
while(db_sqlite_upgrade_scripts[from_version]) {
|
while(db_sqlite_upgrade_scripts[from_version]) {
|
||||||
DPRINTF(E_LOG,L_DB,"Upgrading database from version %d to version %d\n",from_version,
|
DPRINTF(E_LOG,L_DB,"Upgrading database from version %d to version %d\n",from_version,
|
||||||
from_version+1);
|
from_version+1);
|
||||||
db_sqlite_exec(E_FATAL,db_sqlite_upgrade_scripts[from_version]);
|
|
||||||
|
if(!copied) {
|
||||||
|
/* copy original version */
|
||||||
|
sprintf(db_new_path,"%s.version-%02d",db_path,from_version);
|
||||||
|
from_fd=r_open2(db_path,O_RDONLY);
|
||||||
|
to_fd=r_open2(db_new_path,O_RDWR);
|
||||||
|
|
||||||
|
if((from_fd == -1) || (to_fd == -1)) {
|
||||||
|
DPRINTF(E_FATAL,L_DB,"Could not make backup copy of database (%s). Check write permissions for runas user.\n",db_new_path);
|
||||||
|
}
|
||||||
|
|
||||||
|
while((result=readwrite(from_fd, to_fd) > 0));
|
||||||
|
|
||||||
|
if(result == -1) {
|
||||||
|
DPRINTF(E_FATAL,L_DB,"Could not make backup copy of database (%s)\n",
|
||||||
|
strerror(errno));
|
||||||
|
}
|
||||||
|
|
||||||
|
r_close(from_fd);
|
||||||
|
r_close(to_fd);
|
||||||
|
|
||||||
|
copied=1;
|
||||||
|
}
|
||||||
|
|
||||||
|
if(db_sqlite_exec(E_LOG,db_sqlite_upgrade_scripts[from_version])!=DB_E_SUCCESS) {
|
||||||
|
DPRINTF(E_FATAL,L_DB,"Error upgrading database. A backup copy of your "
|
||||||
|
"original database is located at %s. Please save it somewhere "
|
||||||
|
"and report to the forums at www.mt-daapd.org. Thanks.",
|
||||||
|
db_new_path);
|
||||||
|
}
|
||||||
from_version++;
|
from_version++;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* removed our backup file */
|
||||||
|
if(copied)
|
||||||
|
unlink(db_new_path);
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -37,7 +37,7 @@ extern int db_sqlite_get_count(CountType_t type);
|
|||||||
extern MP3FILE *db_sqlite_fetch_item(int id);
|
extern MP3FILE *db_sqlite_fetch_item(int id);
|
||||||
extern MP3FILE *db_sqlite_fetch_path(char *path);
|
extern MP3FILE *db_sqlite_fetch_path(char *path);
|
||||||
extern void db_sqlite_dispose_item(MP3FILE *pmp3);
|
extern void db_sqlite_dispose_item(MP3FILE *pmp3);
|
||||||
extern int db_sqlite_add_playlist(char *name, int type, char *clause, int *playlistid);
|
extern int db_sqlite_add_playlist(char *name, int type, char *clause, char *path, int *playlistid);
|
||||||
extern int db_sqlite_add_playlist_item(int playlistid, int songid);
|
extern int db_sqlite_add_playlist_item(int playlistid, int songid);
|
||||||
|
|
||||||
|
|
||||||
|
@ -835,7 +835,7 @@ void dispatch_addplaylist(WS_CONNINFO *pwsc, DBQUERYINFO *pqi) {
|
|||||||
name=ws_getvar(pwsc,"dmap.itemname");
|
name=ws_getvar(pwsc,"dmap.itemname");
|
||||||
query=ws_getvar(pwsc,"org.mt-daapd.smart-playlist-spec");
|
query=ws_getvar(pwsc,"org.mt-daapd.smart-playlist-spec");
|
||||||
|
|
||||||
retval=db_add_playlist(name,type,query,&playlistid);
|
retval=db_add_playlist(name,type,query,NULL,&playlistid);
|
||||||
if(retval != DB_E_SUCCESS) {
|
if(retval != DB_E_SUCCESS) {
|
||||||
DPRINTF(E_LOG,L_DAAP,"error adding playlist. aborting\n");
|
DPRINTF(E_LOG,L_DAAP,"error adding playlist. aborting\n");
|
||||||
ws_returnerror(pwsc,500,"error adding playlist");
|
ws_returnerror(pwsc,500,"error adding playlist");
|
||||||
|
Loading…
x
Reference in New Issue
Block a user