mirror of
https://github.com/owntone/owntone-server.git
synced 2025-04-29 06:37:56 -04:00
Import streaming stations form iTunes XML file, closing ticket #130, add scan/correct_order to make static playlists return in correct order closing ticket #159
This commit is contained in:
parent
ebbbc0acda
commit
5f3a12c351
@ -129,6 +129,7 @@ typedef struct tag_dbqueryinfo {
|
|||||||
int want_count;
|
int want_count;
|
||||||
int specifiedtotalcount;
|
int specifiedtotalcount;
|
||||||
int uri_count;
|
int uri_count;
|
||||||
|
int correct_order;
|
||||||
char *uri_sections[10];
|
char *uri_sections[10];
|
||||||
PARSETREE pt;
|
PARSETREE pt;
|
||||||
void *output_info;
|
void *output_info;
|
||||||
|
@ -410,7 +410,7 @@ int db_sqlite2_insert_id(void) {
|
|||||||
char *db_sqlite2_initial1 =
|
char *db_sqlite2_initial1 =
|
||||||
"create table songs (\n"
|
"create table songs (\n"
|
||||||
" id INTEGER PRIMARY KEY NOT NULL,\n" /* 0 */
|
" id INTEGER PRIMARY KEY NOT NULL,\n" /* 0 */
|
||||||
" path VARCHAR(4096) UNIQUE NOT NULL,\n"
|
" path VARCHAR(4096) NOT NULL,\n"
|
||||||
" fname VARCHAR(255) NOT NULL,\n"
|
" fname VARCHAR(255) NOT NULL,\n"
|
||||||
" title VARCHAR(1024) DEFAULT NULL,\n"
|
" title VARCHAR(1024) DEFAULT NULL,\n"
|
||||||
" artist VARCHAR(1024) DEFAULT NULL,\n"
|
" artist VARCHAR(1024) DEFAULT NULL,\n"
|
||||||
|
@ -455,7 +455,7 @@ int db_sqlite3_insert_id(void) {
|
|||||||
char *db_sqlite3_initial1 =
|
char *db_sqlite3_initial1 =
|
||||||
"create table songs (\n"
|
"create table songs (\n"
|
||||||
" id INTEGER PRIMARY KEY NOT NULL,\n"
|
" id INTEGER PRIMARY KEY NOT NULL,\n"
|
||||||
" path VARCHAR(4096) UNIQUE NOT NULL,\n"
|
" path VARCHAR(4096) NOT NULL,\n"
|
||||||
" fname VARCHAR(255) NOT NULL,\n"
|
" fname VARCHAR(255) NOT NULL,\n"
|
||||||
" title VARCHAR(1024) DEFAULT NULL,\n"
|
" title VARCHAR(1024) DEFAULT NULL,\n"
|
||||||
" artist VARCHAR(1024) DEFAULT NULL,\n"
|
" artist VARCHAR(1024) DEFAULT NULL,\n"
|
||||||
|
35
src/db-sql.c
35
src/db-sql.c
@ -699,7 +699,7 @@ int db_sql_add(char **pe, MP3FILE *pmp3, int *id) {
|
|||||||
/* Always an add if in song scan on full reload */
|
/* Always an add if in song scan on full reload */
|
||||||
if((!db_sql_reload)||(!db_sql_in_scan)) {
|
if((!db_sql_reload)||(!db_sql_in_scan)) {
|
||||||
err=db_sql_fetch_int(NULL,&count,"select count(*) from songs where "
|
err=db_sql_fetch_int(NULL,&count,"select count(*) from songs where "
|
||||||
"path='%q'",pmp3->path);
|
"path='%q' and idx=%d",pmp3->path,pmp3->index);
|
||||||
|
|
||||||
if((err == DB_E_SUCCESS) && (count == 1)) { /* we should update */
|
if((err == DB_E_SUCCESS) && (count == 1)) { /* we should update */
|
||||||
return db_sql_update(pe,pmp3,id);
|
return db_sql_update(pe,pmp3,id);
|
||||||
@ -856,7 +856,7 @@ int db_sql_update(char **pe, MP3FILE *pmp3, int *id) {
|
|||||||
"rating=%d," // rating
|
"rating=%d," // rating
|
||||||
"sample_count=%d," // sample_count
|
"sample_count=%d," // sample_count
|
||||||
"codectype='%q'" // codec
|
"codectype='%q'" // codec
|
||||||
" WHERE path='%q'",
|
" WHERE path='%q' and idx=%d",
|
||||||
STR(pmp3->title),
|
STR(pmp3->title),
|
||||||
STR(pmp3->artist),
|
STR(pmp3->artist),
|
||||||
STR(pmp3->album),
|
STR(pmp3->album),
|
||||||
@ -885,14 +885,15 @@ int db_sql_update(char **pe, MP3FILE *pmp3, int *id) {
|
|||||||
pmp3->rating,
|
pmp3->rating,
|
||||||
pmp3->sample_count,
|
pmp3->sample_count,
|
||||||
STR(pmp3->codectype),
|
STR(pmp3->codectype),
|
||||||
pmp3->path);
|
pmp3->path,
|
||||||
|
pmp3->index);
|
||||||
|
|
||||||
if(err != DB_E_SUCCESS)
|
if(err != DB_E_SUCCESS)
|
||||||
DPRINTF(E_FATAL,L_DB,"Error updating file: %s\n",pmp3->fname);
|
DPRINTF(E_FATAL,L_DB,"Error updating file: %s\n",pmp3->fname);
|
||||||
|
|
||||||
if(id) { /* we need the insert/update id */
|
if(id) { /* we need the insert/update id */
|
||||||
err=db_sql_fetch_int(pe,id,"select id from songs where path='%q'",pmp3->path);
|
err=db_sql_fetch_int(pe,id,"select id from songs where path='%q' and "
|
||||||
|
"idx=%d",pmp3->path,pmp3->index);
|
||||||
if(err != DB_E_SUCCESS)
|
if(err != DB_E_SUCCESS)
|
||||||
return err;
|
return err;
|
||||||
}
|
}
|
||||||
@ -902,8 +903,8 @@ int db_sql_update(char **pe, MP3FILE *pmp3, int *id) {
|
|||||||
db_sql_exec_fn(NULL,E_FATAL,"insert into updated (id) values (%d)",*id);
|
db_sql_exec_fn(NULL,E_FATAL,"insert into updated (id) values (%d)",*id);
|
||||||
} else {
|
} else {
|
||||||
db_sql_exec_fn(NULL,E_FATAL,"insert into updated (id) "
|
db_sql_exec_fn(NULL,E_FATAL,"insert into updated (id) "
|
||||||
"select id from songs where path='%q'",
|
"select id from songs where path='%q' and idx=%d",
|
||||||
pmp3->path);
|
pmp3->path,pmp3->index);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1064,14 +1065,15 @@ int db_sql_enum_start(char **pe, DBQUERYINFO *pinfo) {
|
|||||||
* of these playlist queries sucks.
|
* of these playlist queries sucks.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
sprintf(query_rest," where (songs.id in (select songid from "
|
if(pinfo->correct_order) {
|
||||||
"playlistitems where playlistid=%d))",
|
sprintf(query_rest," where (songs.id=playlistitems.songid and "
|
||||||
pinfo->playlist_id);
|
"playlistitems.playlistid=%d) order by "
|
||||||
/*
|
"playlistitems.id",pinfo->playlist_id);
|
||||||
sprintf(query_playlist,"(songs.id=playlistitems.songid and "
|
} else {
|
||||||
"playlistitems.playlistid=%d) order by "
|
sprintf(query_rest," where (songs.id in (select songid from "
|
||||||
"playlistitems.id",pinfo->playlist_id);
|
"playlistitems where playlistid=%d))",
|
||||||
*/
|
pinfo->playlist_id);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
have_clause=1;
|
have_clause=1;
|
||||||
db_sql_enum_end_fn(NULL);
|
db_sql_enum_end_fn(NULL);
|
||||||
@ -1797,7 +1799,8 @@ MP3FILE *db_sql_fetch_path(char **pe, char *path, int index) {
|
|||||||
MP3FILE *pmp3=NULL;
|
MP3FILE *pmp3=NULL;
|
||||||
int err;
|
int err;
|
||||||
|
|
||||||
err=db_sql_fetch_row(pe,&row,"select * from songs where path='%q'",path);
|
err=db_sql_fetch_row(pe,&row,"select * from songs where path='%q' "
|
||||||
|
"and idx=%d",path,index);
|
||||||
if(err != DB_E_SUCCESS) {
|
if(err != DB_E_SUCCESS) {
|
||||||
if(err == DB_E_NOROWS) { /* Override generic error */
|
if(err == DB_E_NOROWS) { /* Override generic error */
|
||||||
if(pe) { free(*pe); };
|
if(pe) { free(*pe); };
|
||||||
|
@ -172,6 +172,7 @@ void daap_handler(WS_CONNINFO *pwsc) {
|
|||||||
|
|
||||||
memset(pqi,0x00,sizeof(DBQUERYINFO));
|
memset(pqi,0x00,sizeof(DBQUERYINFO));
|
||||||
pqi->zero_length = conf_get_int("daap","empty_strings",0);
|
pqi->zero_length = conf_get_int("daap","empty_strings",0);
|
||||||
|
pqi->correct_order = conf_get_int("scan","correct_order",0);
|
||||||
pqi->pwsc = pwsc;
|
pqi->pwsc = pwsc;
|
||||||
|
|
||||||
/* we could really pre-parse this to make sure it works */
|
/* we could really pre-parse this to make sure it works */
|
||||||
|
11
src/main.c
11
src/main.c
@ -243,8 +243,10 @@ int main(int argc, char *argv[]) {
|
|||||||
char *perr=NULL;
|
char *perr=NULL;
|
||||||
char *apppath;
|
char *apppath;
|
||||||
|
|
||||||
|
int debuglevel=0;
|
||||||
|
|
||||||
config.use_mdns=1;
|
config.use_mdns=1;
|
||||||
err_setlevel(1);
|
err_setlevel(debuglevel);
|
||||||
|
|
||||||
config.foreground=0;
|
config.foreground=0;
|
||||||
while((option=getopt(argc,argv,"D:d:c:P:mfrysiuva")) != -1) {
|
while((option=getopt(argc,argv,"D:d:c:P:mfrysiuva")) != -1) {
|
||||||
@ -253,7 +255,8 @@ int main(int argc, char *argv[]) {
|
|||||||
appdir = 1;
|
appdir = 1;
|
||||||
break;
|
break;
|
||||||
case 'd':
|
case 'd':
|
||||||
err_setlevel(atoi(optarg));
|
debuglevel = atoi(optarg);
|
||||||
|
err_setlevel(debuglevel);
|
||||||
break;
|
break;
|
||||||
case 'D':
|
case 'D':
|
||||||
if(err_setdebugmask(optarg)) {
|
if(err_setdebugmask(optarg)) {
|
||||||
@ -338,6 +341,10 @@ int main(int argc, char *argv[]) {
|
|||||||
exit(EXIT_FAILURE);
|
exit(EXIT_FAILURE);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
if(debuglevel) /* was specified, should override the config file */
|
||||||
|
err_setlevel(debuglevel);
|
||||||
|
|
||||||
if(convert_conf) {
|
if(convert_conf) {
|
||||||
fprintf(stderr,"Converting config file...\n");
|
fprintf(stderr,"Converting config file...\n");
|
||||||
if(!conf_write()) {
|
if(!conf_write()) {
|
||||||
|
@ -609,10 +609,12 @@ int scan_xml_tracks_section(int action, char *info) {
|
|||||||
static int state;
|
static int state;
|
||||||
static int current_track_id;
|
static int current_track_id;
|
||||||
static int current_field;
|
static int current_field;
|
||||||
|
static int is_streaming;
|
||||||
static MP3FILE mp3;
|
static MP3FILE mp3;
|
||||||
static char *song_path=NULL;
|
static char *song_path=NULL;
|
||||||
char real_path[PATH_MAX];
|
char real_path[PATH_MAX];
|
||||||
MP3FILE *pmp3;
|
MP3FILE *pmp3;
|
||||||
|
int added_id;
|
||||||
|
|
||||||
if(action == RXML_EVT_OPEN) {
|
if(action == RXML_EVT_OPEN) {
|
||||||
state = XML_TRACK_ST_INITIAL;
|
state = XML_TRACK_ST_INITIAL;
|
||||||
@ -670,7 +672,11 @@ int scan_xml_tracks_section(int action, char *info) {
|
|||||||
} else if((action == RXML_EVT_END) && (strcmp(info,"dict")==0)) {
|
} else if((action == RXML_EVT_END) && (strcmp(info,"dict")==0)) {
|
||||||
state = XML_TRACK_ST_MAIN_DICT;
|
state = XML_TRACK_ST_MAIN_DICT;
|
||||||
/* but more importantly, we gotta process the track */
|
/* but more importantly, we gotta process the track */
|
||||||
if(scan_xml_translate_path(song_path,real_path)) {
|
is_streaming = 0;
|
||||||
|
if(strncasecmp(song_path,"http://",7) == 0)
|
||||||
|
is_streaming = 1;
|
||||||
|
|
||||||
|
if((!is_streaming)&&scan_xml_translate_path(song_path,real_path)) {
|
||||||
/* FIXME: Error handling */
|
/* FIXME: Error handling */
|
||||||
pmp3=db_fetch_path(NULL,real_path,0);
|
pmp3=db_fetch_path(NULL,real_path,0);
|
||||||
if(!pmp3) {
|
if(!pmp3) {
|
||||||
@ -697,6 +703,7 @@ int scan_xml_tracks_section(int action, char *info) {
|
|||||||
MAYBECOPY(disc);
|
MAYBECOPY(disc);
|
||||||
MAYBECOPY(total_discs);
|
MAYBECOPY(total_discs);
|
||||||
MAYBECOPY(time_added);
|
MAYBECOPY(time_added);
|
||||||
|
MAYBECOPY(disabled);
|
||||||
|
|
||||||
/* must add to the red-black tree */
|
/* must add to the red-black tree */
|
||||||
scan_xml_add_lookup(current_track_id,pmp3->id);
|
scan_xml_add_lookup(current_track_id,pmp3->id);
|
||||||
@ -707,6 +714,50 @@ int scan_xml_tracks_section(int action, char *info) {
|
|||||||
memset((void*)&mp3,0,sizeof(MP3FILE));
|
memset((void*)&mp3,0,sizeof(MP3FILE));
|
||||||
MAYBEFREE(song_path);
|
MAYBEFREE(song_path);
|
||||||
}
|
}
|
||||||
|
} else if(is_streaming) {
|
||||||
|
/* add/update a http:// url */
|
||||||
|
pmp3=db_fetch_path(NULL,scan_xml_file,current_track_id);
|
||||||
|
if(!pmp3) {
|
||||||
|
/* gotta add it! */
|
||||||
|
DPRINTF(E_DBG,L_SCAN,"Adding %s\n",song_path);
|
||||||
|
pmp3 = calloc(sizeof(MP3FILE),1);
|
||||||
|
|
||||||
|
if(!pmp3)
|
||||||
|
DPRINTF(E_FATAL,L_SCAN,
|
||||||
|
"malloc: scan_xml_tracks_section\n");
|
||||||
|
} else {
|
||||||
|
DPRINTF(E_DBG,L_SCAN,"updating %s\n",song_path);
|
||||||
|
}
|
||||||
|
pmp3->url = strdup(song_path);
|
||||||
|
pmp3->type = strdup("pls");
|
||||||
|
pmp3->description = strdup("Playlist URL");
|
||||||
|
pmp3->data_kind = 1;
|
||||||
|
pmp3->item_kind = 2;
|
||||||
|
|
||||||
|
pmp3->path = strdup(scan_xml_file);
|
||||||
|
pmp3->index = current_track_id;
|
||||||
|
|
||||||
|
MAYBECOPYSTRING(title);
|
||||||
|
MAYBECOPYSTRING(artist);
|
||||||
|
MAYBECOPYSTRING(album);
|
||||||
|
MAYBECOPYSTRING(genre);
|
||||||
|
MAYBECOPY(bitrate);
|
||||||
|
MAYBECOPY(samplerate);
|
||||||
|
MAYBECOPY(play_count);
|
||||||
|
MAYBECOPY(rating);
|
||||||
|
MAYBECOPY(time_added);
|
||||||
|
MAYBECOPY(disabled);
|
||||||
|
|
||||||
|
if(db_add(NULL,pmp3,&added_id) == DB_E_SUCCESS) {
|
||||||
|
scan_xml_add_lookup(current_track_id,added_id);
|
||||||
|
DPRINTF(E_DBG,L_SCAN,"Added %s\n",song_path);
|
||||||
|
} else {
|
||||||
|
DPRINTF(E_DBG,L_SCAN,"Error adding %s\n",song_path);
|
||||||
|
}
|
||||||
|
|
||||||
|
db_dispose_item(pmp3);
|
||||||
|
memset((void*)&mp3,0,sizeof(MP3FILE));
|
||||||
|
MAYBEFREE(song_path);
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
return XML_STATE_ERROR;
|
return XML_STATE_ERROR;
|
||||||
|
Loading…
x
Reference in New Issue
Block a user