diff --git a/src/dbs-sqlite.c b/src/dbs-sqlite.c index b8068d1c..7917f3b4 100644 --- a/src/dbs-sqlite.c +++ b/src/dbs-sqlite.c @@ -413,6 +413,11 @@ int db_sqlite_enum_start(DBQUERYINFO *pinfo) { const char *ptail; + query[0] = '\0'; + query_select[0] = '\0'; + query_count[0] = '\0'; + query_rest[0] = '\0'; + switch(pinfo->query_type) { case queryTypeItems: strcpy(query_select,"SELECT * FROM songs "); @@ -452,8 +457,8 @@ int db_sqlite_enum_start(DBQUERYINFO *pinfo) { /* Note that sqlite doesn't support COUNT(DISTINCT x) */ case queryTypeBrowseAlbums: - strcpy(query_select,"SELECT DISTINCT albums FROM songs "); - strcpy(query_count,"SELECT COUNT(albums) FROM (SELECT DISTINCT albums FROM songs "); + strcpy(query_select,"SELECT DISTINCT album FROM songs "); + strcpy(query_count,"SELECT COUNT(album) FROM (SELECT DISTINCT album FROM songs "); browse=1; break; @@ -572,13 +577,18 @@ int db_sqlite_enum_size(DBQUERYINFO *pinfo, int *count) { char *perr; int cols; int total_size=0; + int record_size; + + DPRINTF(E_DBG,L_DB,"Enumerating size\n"); *count=0; db_sqlite_lock(); while((err=sqlite_step(db_sqlite_pvm,&cols,&valarray,&colarray)) == SQLITE_ROW) { - total_size += db_sqlite_get_size(pinfo,(char**)valarray); - *count = *count + 1; + if((record_size = db_sqlite_get_size(pinfo,(char**)valarray))) { + total_size += record_size; + *count = *count + 1; + } } if(err != SQLITE_DONE) { @@ -590,6 +600,7 @@ int db_sqlite_enum_size(DBQUERYINFO *pinfo, int *count) { db_sqlite_unlock(); db_sqlite_enum_reset(pinfo); + DPRINTF(E_DBG,L_DB,"Got size: %d\n",total_size); return total_size; } @@ -603,23 +614,27 @@ int db_sqlite_enum_fetch(DBQUERYINFO *pinfo, unsigned char **pdmap) { int err; char *perr; int cols; - int result_size; + int result_size=-1; unsigned char *presult; db_sqlite_lock(); err=sqlite_step(db_sqlite_pvm,&cols,&valarray,&colarray); db_sqlite_unlock(); - if(err == SQLITE_ROW) { + while((err == SQLITE_ROW) && (result_size)) { result_size=db_sqlite_get_size(pinfo,(char**)valarray); - presult=(unsigned char*)malloc(result_size); - if(!presult) - return 0; - db_sqlite_build_dmap(pinfo,(char**)valarray,presult,result_size); - DPRINTF(E_DBG,L_DB,"Building response for %s (size %d)\n",valarray[3],result_size); - *pdmap = presult; - return result_size; - } else if(err == SQLITE_DONE) { + if(result_size) { + presult=(unsigned char*)malloc(result_size); + if(!presult) + return 0; + db_sqlite_build_dmap(pinfo,(char**)valarray,presult,result_size); + DPRINTF(E_DBG,L_DB,"Building response for %s (size %d)\n",valarray[3],result_size); + *pdmap = presult; + return result_size; + } + } + + if(err == SQLITE_DONE) { return -1; } @@ -653,19 +668,15 @@ int db_sqlite_enum_end(void) { return 0; } - int db_sqlite_get_size(DBQUERYINFO *pinfo, char **valarray) { int size; switch(pinfo->query_type) { case queryTypeBrowseArtists: /* simple 'mlit' entry */ - return 8 + strlen(valarray[4]); case queryTypeBrowseAlbums: - return 8 + strlen(valarray[5]); case queryTypeBrowseGenres: - return 8 + strlen(valarray[6]); case queryTypeBrowseComposers: - return 8 + strlen(valarray[11]); + return valarray[0] ? (8 + strlen(valarray[0])) : 0; case queryTypePlaylists: size = 8; /* mlit */ size += 12; /* miid */ @@ -783,13 +794,10 @@ int db_sqlite_build_dmap(DBQUERYINFO *pinfo, char **valarray, char *presult, int switch(pinfo->query_type) { case queryTypeBrowseArtists: /* simple 'mlit' entry */ - return db_dmap_add_string(current,"mlit",valarray[4]); case queryTypeBrowseAlbums: - return db_dmap_add_string(current,"mlit",valarray[5]); case queryTypeBrowseGenres: - return db_dmap_add_string(current,"mlit",valarray[6]); case queryTypeBrowseComposers: - return db_dmap_add_string(current,"mlit",valarray[11]); + return db_dmap_add_string(current,"mlit",valarray[0]); case queryTypePlaylists: /* do I want to include the mlit? */ current += db_dmap_add_container(current,"mlit",len - 8); diff --git a/src/dispatch.c b/src/dispatch.c index 507a2a63..4a1ec4b9 100644 --- a/src/dispatch.c +++ b/src/dispatch.c @@ -394,9 +394,6 @@ void dispatch_playlistitems(WS_CONNINFO *pwsc, DBQUERYINFO *pqi) { (1ll << metaParentContainerId)); } - /* should build the query string here, too */ - pqi->whereclause = NULL; - pqi->query_type = queryTypePlaylistItems; pqi->index_type=indexTypeNone; if(db_enum_start(pqi)) { @@ -438,6 +435,70 @@ void dispatch_playlistitems(WS_CONNINFO *pwsc, DBQUERYINFO *pqi) { } void dispatch_browse(WS_CONNINFO *pwsc, DBQUERYINFO *pqi) { + char browse_response[52]; + char *current=browse_response; + int item_count; + int list_length; + unsigned char *block; + char *response_type; + + if(!strcmp(pqi->uri_sections[3],"artists")) { + response_type = "abar"; + pqi->query_type=queryTypeBrowseArtists; + } else if(!strcmp(pqi->uri_sections[3],"genres")) { + response_type = "abgn"; + pqi->query_type=queryTypeBrowseGenres; + } else if(!strcmp(pqi->uri_sections[3],"albums")) { + response_type = "abal"; + pqi->query_type=queryTypeBrowseAlbums; + } else if(!strcmp(pqi->uri_sections[3],"composers")) { + response_type = "abcp"; + pqi->query_type=queryTypeBrowseComposers; + } else { + DPRINTF(E_WARN,L_DAAP|L_BROW,"Invalid browse request type %s\n",pqi->uri_sections[3]); + ws_returnerror(pwsc,404,"Invalid browse type"); + config_set_status(pwsc,pqi->session_id,NULL); + free(pqi); + return; + } + + pqi->index_type = indexTypeNone; + + if(db_enum_start(pqi)) { + DPRINTF(E_LOG,L_DAAP|L_BROW,"Could not start enum\n"); + ws_returnerror(pwsc,500,"Internal server error: out of memory!\n"); + return; + } + + DPRINTF(E_DBG,L_DAAP|L_BROW,"Getting enum size.\n"); + + list_length=db_enum_size(pqi,&item_count); + + DPRINTF(E_DBG,L_DAAP|L_BROW,"Item enum: got %d items, dmap size: %d\n", + item_count,list_length); + + current += db_dmap_add_container(current,"abro",list_length + 44); + current += db_dmap_add_int(current,"mstt",200); /* 12 */ + current += db_dmap_add_int(current,"mtco",item_count); /* 12 */ + current += db_dmap_add_int(current,"mrco",item_count); /* 12 */ + current += db_dmap_add_container(current,response_type,list_length); /* 8 + length */ + + ws_addresponseheader(pwsc,"Content-Length","%d",52+list_length); + ws_writefd(pwsc,"HTTP/1.1 200 OK\r\n"); + ws_emitheaders(pwsc); + + r_write(pwsc->fd,browse_response,52); + + while((list_length=db_enum_fetch(pqi,&block)) > 0) { + DPRINTF(E_DBG,L_DAAP|L_BROW,"Got block of size %d\n",list_length); + r_write(pwsc->fd,block,list_length); + free(block); + } + + DPRINTF(E_DBG,L_DAAP|L_BROW,"Done enumerating\n"); + + db_enum_end(); + config_set_status(pwsc,pqi->session_id,NULL); free(pqi); return; @@ -457,14 +518,12 @@ void dispatch_playlists(WS_CONNINFO *pwsc, DBQUERYINFO *pqi) { pqi->meta = (MetaField_t) -1ll; } - /* should build the query string here, too */ - pqi->whereclause = NULL; pqi->query_type = queryTypePlaylists; - pqi->index_type=indexTypeNone; + pqi->index_type = indexTypeNone; if(db_enum_start(pqi)) { DPRINTF(E_LOG,L_DAAP,"Could not start enum\n"); - ws_returnerror(pwsc,500,"Internal server error: out of memory!"); + ws_returnerror(pwsc,500,"Internal server error: out of memory!\n"); return; } @@ -513,9 +572,6 @@ void dispatch_items(WS_CONNINFO *pwsc, DBQUERYINFO *pqi) { pqi->meta = (MetaField_t) -1ll; } - /* should build the query string here, too */ - pqi->whereclause = NULL; - pqi->query_type = queryTypeItems; pqi->index_type=indexTypeNone; if(db_enum_start(pqi)) {