add dmap methods to remotely add a playlist

This commit is contained in:
Ron Pedde 2005-04-02 09:27:53 +00:00
parent de9d433b3e
commit 53f8c8166b
5 changed files with 134 additions and 9 deletions

View File

@ -46,6 +46,7 @@ typedef struct tag_db_functions {
int(*dbs_init)(int);
int(*dbs_deinit)(void);
int(*dbs_add)(MP3FILE*);
int(*dbs_add_playlist)(char *, int, char *, int *);
int(*dbs_enum_start)(DBQUERYINFO *);
int(*dbs_enum_size)(DBQUERYINFO *, int *);
int(*dbs_enum_fetch)(DBQUERYINFO *, unsigned char **);
@ -68,6 +69,7 @@ DB_FUNCTIONS db_functions[] = {
db_sqlite_init,
db_sqlite_deinit,
db_sqlite_add,
db_sqlite_add_playlist,
db_sqlite_enum_start,
db_sqlite_enum_size,
db_sqlite_enum_fetch,
@ -185,6 +187,7 @@ DAAP_ITEMS taglist[] = {
/* mt-daapd specific */
{ 0x09, "MSPS", "org.mt-daapd.smart-playlist-spec" },
{ 0x01, "MPTY", "org.mt-daapd.playlist-type" },
{ 0x0C, "MAPR", "org.mt-daapd.addplaylistresponse" },
{ 0x00, NULL, NULL }
};
@ -454,6 +457,27 @@ int db_add(MP3FILE *pmp3) {
return retval;
}
/**
* add a playlist
*
* \param name name of playlist to add
* \param type type of playlist to add: 0 - static, 1 - smart, 2 - m3u
* \param clause where clause (if type 1)
* \param playlistid returns the id of the playlist created
* \returns 0 on success, error code otherwise
*/
int db_add_playlist(char *name, int type, char *clause, int *playlistid) {
int retval;
db_writelock();
retval=db_current->dbs_add_playlist(name,type,clause,playlistid);
if(retval == DB_E_SUCCESS)
db_revision_no++;
db_unlock();
return retval;
}
/**
* start a db enumeration, based info in the DBQUERYINFO struct
*

View File

@ -155,6 +155,8 @@ extern int db_end_scan(void);
extern int db_exists(char *path);
extern int db_scanning(void);
extern int db_add_playlist(char *name, int type, char *clause, int *playlistid);
extern MP3FILE *db_fetch_item(int id);
extern MP3FILE *db_fetch_path(char *path);
@ -177,4 +179,12 @@ extern int db_get_song_count(void);
extern int db_get_playlist_count(void);
extern void db_dispose_item(MP3FILE *pmp3);
#define DB_E_SUCCESS 0
#define DB_E_SQL_ERROR 1 /**< some kind of sql error - typically bad syntax */
#define DB_E_DUPLICATE_PLAYLIST 2 /**< playlist already exists when adding */
#define DB_E_NOCLAUSE 3 /**< adding smart playlist with no clause */
#endif /* _DB_GENERIC_H_ */

View File

@ -53,7 +53,7 @@ void db_sqlite_build_mp3file(char **valarray, MP3FILE *pmp3);
int db_sqlite_exec(int fatal, char *fmt, ...);
int db_sqlite_get_table(int fatal, char ***resarray, int *rows, int *cols, char *fmt, ...);
int db_sqlite_free_table(char **resarray);
int db_sqlite_get_int(int loglevel, char *fmt, ...);
int db_sqlite_get_int(int loglevel, int *result, char *fmt, ...);
int db_sqlite_update(MP3FILE *pmp3);
int db_sqlite_update_version(int from_version);
int db_sqlite_get_version(void);
@ -160,14 +160,13 @@ int db_sqlite_free_table(char **resarray) {
/**
* db_sqlite_get_int
*/
int db_sqlite_get_int(int loglevel, char *fmt, ...) {
int db_sqlite_get_int(int loglevel, int *result, char *fmt, ...) {
int rows, cols;
char **resarray;
va_list ap;
char *query;
int err;
char *perr;
int retval;
va_start(ap,fmt);
query=sqlite_vmprintf(fmt,ap);
@ -187,13 +186,13 @@ int db_sqlite_get_int(int loglevel, char *fmt, ...) {
db_sqlite_lock();
sqlite_freemem(query);
db_sqlite_unlock();
return 0;
return DB_E_SQL_ERROR;
}
retval=atoi(resarray[cols]);
*result=atoi(resarray[cols]);
sqlite_free_table(resarray);
return retval;
return DB_E_SUCCESS;
}
@ -224,10 +223,10 @@ int db_sqlite_open(char *parameters) {
*/
int db_sqlite_init(int reload) {
int items;
int rescan;
int rescan=0;
db_sqlite_update_version(db_sqlite_get_version());
rescan=db_sqlite_get_int(E_DBG,"SELECT value FROM config WHERE term='rescan'");
db_sqlite_get_int(E_DBG,&rescan,"SELECT value FROM config WHERE term='rescan'");
if(rescan)
reload=1;
@ -298,6 +297,43 @@ int db_sqlite_end_scan(void) {
}
/**
* add a playlist
*
* \param name name of the playlist
* \param type playlist type: 0 - static, 1 - smart, 2 - m3u
* \param clause: "where" clause for smart playlist
*/
int db_sqlite_add_playlist(char *name, int type, char *clause, int *playlistid) {
int cnt=0;
int result;
db_sqlite_get_int(E_DBG,&cnt,"select count(*) from playlists where "
"upper(title)=upper('%q')",name);
if(cnt) return DB_E_DUPLICATE_PLAYLIST;
if((type == 1) && (!clause)) return DB_E_NOCLAUSE;
/* Let's throw it in */
if(type == 1) {
result=db_sqlite_get_int(E_DBG,&cnt,"select count (*) from songs where %s",clause);
if(result != DB_E_SUCCESS) return result;
result = db_sqlite_exec(E_LOG,"insert into playlists (title,smart,items,query) "
"values ('%q',1,%d,'%q')",name,cnt,clause);
} else {
result = db_sqlite_exec(E_LOG,"insert into playlists (title,smart,items,query) "
"values ('%q',0,0,NULL)",name);
}
if(result)
return result;
result = db_sqlite_get_int(E_LOG,playlistid,
"select id from playlists where title='%q'", name);
return result;
}
/**
* add a database item
*

View File

@ -37,5 +37,6 @@ extern int db_sqlite_get_count(CountType_t type);
extern MP3FILE *db_sqlite_fetch_item(int id);
extern MP3FILE *db_sqlite_fetch_path(char *path);
extern void db_sqlite_dispose_item(MP3FILE *pmp3);
extern int db_sqlite_add_playlist(char *name, int type, char *clause, int *playlistid);
#endif /* _DBS_SQLITE_H_ */

View File

@ -52,6 +52,7 @@ static void dispatch_playlistitems(WS_CONNINFO *pwsc, DBQUERYINFO *pqi);
static void dispatch_stream(WS_CONNINFO *pwsc, DBQUERYINFO *pqi);
static void dispatch_browse(WS_CONNINFO *pwsc, DBQUERYINFO *pqi);
static void dispatch_playlists(WS_CONNINFO *pqsc, DBQUERYINFO *pqi);
static void dispatch_addplaylist(WS_CONNINFO *pwsc, DBQUERYINFO *pqi);
static void dispatch_items(WS_CONNINFO *pwsc, DBQUERYINFO *pqi);
static void dispatch_logout(WS_CONNINFO *pwsc, DBQUERYINFO *pqi);
@ -177,9 +178,11 @@ void daap_handler(WS_CONNINFO *pwsc) {
}
pqi->db_id=atoi(pqi->uri_sections[1]);
if(pqi->uri_count == 3) {
if(!strcasecmp(pqi->uri_sections[2],"items"))
if(!strcasecmp(pqi->uri_sections[2],"items"))
/* /databases/id/items */
return dispatch_items(pwsc,pqi);
if(!strcasecmp(pqi->uri_sections[2],"containers"))
/* /databases/id/containers */
return dispatch_playlists(pwsc,pqi);
pwsc->close=1;
@ -189,9 +192,15 @@ void daap_handler(WS_CONNINFO *pwsc) {
}
if(pqi->uri_count == 4) {
if(!strcasecmp(pqi->uri_sections[2],"browse"))
/* /databases/id/browse/something */
return dispatch_browse(pwsc,pqi);
if(!strcasecmp(pqi->uri_sections[2],"items"))
/* /databases/id/items/id.mp3 */
return dispatch_stream(pwsc,pqi);
if((!strcasecmp(pqi->uri_sections[2],"containers")) &&
(!strcasecmp(pqi->uri_sections[3],"add")))
/* /databases/id/containers/add */
return dispatch_addplaylist(pwsc,pqi);
pwsc->close=1;
free(pqi);
@ -753,6 +762,51 @@ void dispatch_stream(WS_CONNINFO *pwsc, DBQUERYINFO *pqi) {
free(pqi);
}
/**
* add a playlist
*/
void dispatch_addplaylist(WS_CONNINFO *pwsc, DBQUERYINFO *pqi) {
char playlist_response[32];
char *current=playlist_response;
char *name, *query;
int type;
int retval, playlistid;
if((!ws_getvar(pwsc,"org.mt-daapd.playlist-type")) ||
(!ws_getvar(pwsc,"dmap.itemname"))) {
DPRINTF(E_LOG,L_DAAP,"attempt to add playlist with invalid type\n");
ws_returnerror(pwsc,500,"bad playlist info specified");
return;
}
type=atoi(ws_getvar(pwsc,"org.mt-daapd.playlist-type"));
name=ws_getvar(pwsc,"dmap.itemname");
query=ws_getvar(pwsc,"org.mt-daapd.smart-playlist-spec");
retval=db_add_playlist(name,type,query,&playlistid);
if(retval != DB_E_SUCCESS) {
DPRINTF(E_LOG,L_DAAP,"error adding playlist. aborting\n");
ws_returnerror(pwsc,500,"error adding playlist");
return;
}
/* success... spool out a dmap block */
current += db_dmap_add_container(current,"MAPR",24);
current += db_dmap_add_int(current,"mstt",200); /* 12 */
current += db_dmap_add_int(current,"miid",playlistid); /* 12 */
dispatch_output_start(pwsc,pqi,32);
dispatch_output_write(pwsc,pqi,playlist_response,32);
dispatch_output_end(pwsc,pqi);
pwsc->close=1;
return;
}
/**
* enumerate and return playlistitems
*/
void dispatch_playlistitems(WS_CONNINFO *pwsc, DBQUERYINFO *pqi) {
char items_response[61];
char *current=items_response;