Support for streaming audio via .url files -- particularly for the Roku SoundBridge
This commit is contained in:
parent
baf7ba8bda
commit
493f0bffbf
16
src/daap.c
16
src/daap.c
|
@ -147,8 +147,8 @@ static query_field_t song_fields[] = {
|
|||
{ qft_string, "daap.songcomment", OFFSET_OF(MP3FILE, comment) },
|
||||
{ qft_i32, "daap.songcompilation", OFFSET_OF(MP3FILE, compilation) },
|
||||
{ qft_string, "daap.songcomposer", OFFSET_OF(MP3FILE, composer) },
|
||||
// { qft_i32_const, "daap.songdatakind", 0 },
|
||||
// { qft_string, "daap.songdataurl", OFFSET_OF(MP3FILE, url) },
|
||||
{ qft_i32, "daap.songdatakind", OFFSET_OF(MP3FILE, data_kind) },
|
||||
{ qft_string, "daap.songdataurl", OFFSET_OF(MP3FILE, url) },
|
||||
{ qft_i32, "daap.songdateadded", OFFSET_OF(MP3FILE, time_added) },
|
||||
{ qft_i32, "daap.songdatemodified",OFFSET_OF(MP3FILE, time_modified) },
|
||||
{ qft_string, "daap.songdescription", OFFSET_OF(MP3FILE, description) },
|
||||
|
@ -410,6 +410,8 @@ DAAP_BLOCK *daap_response_songlist(char* metaStr, char* query) {
|
|||
query_node_t* filter = 0;
|
||||
int songs = 0;
|
||||
|
||||
DPRINTF(ERR_DEBUG,"enter daap_response_songlist\n");
|
||||
|
||||
// if the meta tag is specified, encode it, if it's not specified
|
||||
// we're given the latitude to select our own subset, for
|
||||
// simplicity we just include everything.
|
||||
|
@ -429,7 +431,7 @@ DAAP_BLOCK *daap_response_songlist(char* metaStr, char* query) {
|
|||
|
||||
henum=db_enum_begin();
|
||||
if((!henum) && (db_get_song_count())) {
|
||||
DPRINTF(ERR_DEBUG,"Can't get enum handle\n");
|
||||
DPRINTF(ERR_DEBUG,"Can't get enum handle - exiting daap_response_songlist\n");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
|
@ -462,7 +464,7 @@ DAAP_BLOCK *daap_response_songlist(char* metaStr, char* query) {
|
|||
query_free(filter);
|
||||
|
||||
if(!g) {
|
||||
DPRINTF(ERR_DEBUG,"Error enumerating database\n");
|
||||
DPRINTF(ERR_DEBUG,"Error enumerating database - exiting daap_response_songlist\n");
|
||||
daap_free(root);
|
||||
return NULL;
|
||||
}
|
||||
|
@ -472,6 +474,7 @@ DAAP_BLOCK *daap_response_songlist(char* metaStr, char* query) {
|
|||
daap_set_int(root, "mtco", songs);
|
||||
daap_set_int(root, "mrco", songs);
|
||||
|
||||
DPRINTF(ERR_DEBUG,"Exiting daap_response_songlist\n");
|
||||
return root;
|
||||
}
|
||||
|
||||
|
@ -491,7 +494,10 @@ DAAP_BLOCK* daap_add_song_entry(DAAP_BLOCK* mlcl, MP3FILE* song, MetaField_t met
|
|||
g = g && daap_add_char(mlit,"mikd",song->item_kind); /* audio */
|
||||
|
||||
if(wantsMeta(meta, metaSongDataKind))
|
||||
g = g && daap_add_char(mlit,"asdk",0); /* local file */
|
||||
g = g && daap_add_char(mlit,"asdk",song->data_kind); /* local file */
|
||||
|
||||
if(wantsMeta(meta, metaSongDataURL))
|
||||
g = g && daap_add_string(mlit,"asul",song->url);
|
||||
|
||||
if(song->album && (wantsMeta(meta, metaSongAlbum)))
|
||||
g = g && daap_add_string(mlit,"asal",song->album);
|
||||
|
|
|
@ -46,7 +46,7 @@
|
|||
/*
|
||||
* Defines
|
||||
*/
|
||||
#define DB_VERSION 4
|
||||
#define DB_VERSION 5
|
||||
#define STRLEN(a) (a) ? strlen((a)) + 1 : 1
|
||||
#define MAYBEFREE(a) { if((a)) free((a)); };
|
||||
|
||||
|
@ -121,7 +121,7 @@ typedef struct tag_mp3packed {
|
|||
int conductor_len;
|
||||
int grouping_len;
|
||||
|
||||
/* DB VERSION 4 AND ABOVE GO HERE! */
|
||||
int url_len; /* DB Version 4 */
|
||||
char data[1];
|
||||
} MP3PACKED;
|
||||
|
||||
|
@ -549,6 +549,7 @@ datum *db_packrecord(MP3FILE *pmp3) {
|
|||
len += STRLEN(pmp3->orchestra);
|
||||
len += STRLEN(pmp3->conductor);
|
||||
len += STRLEN(pmp3->grouping);
|
||||
len += STRLEN(pmp3->url);
|
||||
|
||||
result = (datum*) malloc(sizeof(datum));
|
||||
if(!result)
|
||||
|
@ -598,6 +599,7 @@ datum *db_packrecord(MP3FILE *pmp3) {
|
|||
ppacked->orchestra_len=STRLEN(pmp3->orchestra);
|
||||
ppacked->conductor_len=STRLEN(pmp3->conductor);
|
||||
ppacked->grouping_len=STRLEN(pmp3->grouping);
|
||||
ppacked->url_len=STRLEN(pmp3->url);
|
||||
|
||||
offset=0;
|
||||
if(pmp3->path)
|
||||
|
@ -648,6 +650,11 @@ datum *db_packrecord(MP3FILE *pmp3) {
|
|||
memcpy(&ppacked->data[offset],pmp3->grouping,ppacked->grouping_len);
|
||||
offset+=ppacked->grouping_len;
|
||||
|
||||
if(pmp3->url)
|
||||
memcpy(&ppacked->data[offset],pmp3->url,ppacked->url_len);
|
||||
offset+=ppacked->url_len;
|
||||
|
||||
|
||||
/* whew */
|
||||
return result;
|
||||
}
|
||||
|
@ -738,6 +745,10 @@ int db_unpackrecord(datum *pdatum, MP3FILE *pmp3) {
|
|||
pmp3->grouping=strdup(&ppacked->data[offset]);
|
||||
offset += ppacked->grouping_len;
|
||||
|
||||
if(ppacked->url_len > 1)
|
||||
pmp3->url=strdup(&ppacked->data[offset]);
|
||||
offset += ppacked->url_len;
|
||||
|
||||
/* shouldn't this have been done when scanning? */
|
||||
make_composite_tags(pmp3);
|
||||
|
||||
|
@ -822,6 +833,7 @@ void db_freefile(MP3FILE *pmp3) {
|
|||
MAYBEFREE(pmp3->conductor);
|
||||
MAYBEFREE(pmp3->grouping);
|
||||
MAYBEFREE(pmp3->description);
|
||||
MAYBEFREE(pmp3->url);
|
||||
}
|
||||
|
||||
static int nullstrcmp(const char* a, const char* b)
|
||||
|
|
|
@ -252,9 +252,12 @@ int scan_path(char *path);
|
|||
int scan_gettags(char *file, MP3FILE *pmp3);
|
||||
int scan_get_mp3tags(char *file, MP3FILE *pmp3);
|
||||
int scan_get_aactags(char *file, MP3FILE *pmp3);
|
||||
int scan_get_nultags(char *file, MP3FILE *pmp3) { return 0; };
|
||||
int scan_get_fileinfo(char *file, MP3FILE *pmp3);
|
||||
int scan_get_mp3fileinfo(char *file, MP3FILE *pmp3);
|
||||
int scan_get_aacfileinfo(char *file, MP3FILE *pmp3);
|
||||
int scan_get_nulfileinfo(char *file, MP3FILE *pmp3) { return 0; };
|
||||
int scan_get_urlfileinfo(char *file, MP3FILE *pmp3);
|
||||
|
||||
int scan_freetags(MP3FILE *pmp3);
|
||||
void scan_static_playlist(char *path, struct dirent *pde, struct stat *psb);
|
||||
|
@ -267,12 +270,14 @@ typedef struct {
|
|||
int (*tags)(char* file, MP3FILE* pmp3);
|
||||
int (*files)(char* file, MP3FILE* pmp3);
|
||||
} taghandler;
|
||||
|
||||
static taghandler taghandlers[] = {
|
||||
{ "aac", scan_get_aactags, scan_get_aacfileinfo },
|
||||
{ "mp4", scan_get_aactags, scan_get_aacfileinfo },
|
||||
{ "m4a", scan_get_aactags, scan_get_aacfileinfo },
|
||||
{ "m4p", scan_get_aactags, scan_get_aacfileinfo },
|
||||
{ "mp3", scan_get_mp3tags, scan_get_mp3fileinfo },
|
||||
{ "url", scan_get_nultags, scan_get_urlfileinfo },
|
||||
{ NULL, 0 }
|
||||
};
|
||||
|
||||
|
@ -472,7 +477,7 @@ void scan_music_file(char *path, struct dirent *pde, struct stat *psb) {
|
|||
if(strlen(pde->d_name) > 4)
|
||||
mp3file.type=strdup(strrchr(pde->d_name, '.') + 1);
|
||||
|
||||
/* FIXME; assumes that st_ino is a u_int_32
|
||||
/* FIXME: assumes that st_ino is a u_int_32
|
||||
DWB: also assumes that the library is contained entirely within
|
||||
one file system
|
||||
*/
|
||||
|
@ -953,6 +958,59 @@ off_t aac_drilltoatom(FILE *aac_fp, char *atom_path, unsigned int *atom_length)
|
|||
return ftell(aac_fp) - 8;
|
||||
}
|
||||
|
||||
/*
|
||||
* scan_get_urlfileinfo
|
||||
*
|
||||
* Get info from a "url" file -- a media stream file
|
||||
*/
|
||||
int scan_get_urlfileinfo(char *file, MP3FILE *pmp3) {
|
||||
FILE *infile;
|
||||
char *head, *tail;
|
||||
char linebuffer[256];
|
||||
|
||||
DPRINTF(ERR_DEBUG,"Getting URL file info\n");
|
||||
|
||||
if(!(infile=fopen(file,"rb"))) {
|
||||
DPRINTF(ERR_WARN,"Could not open %s for reading\n",file);
|
||||
return -1;
|
||||
}
|
||||
|
||||
fgets(linebuffer,sizeof(linebuffer),infile);
|
||||
while((linebuffer[strlen(linebuffer)-1] == '\n') ||
|
||||
(linebuffer[strlen(linebuffer)-1] == '\r')) {
|
||||
linebuffer[strlen(linebuffer)-1] = '\0';
|
||||
}
|
||||
|
||||
head=linebuffer;
|
||||
tail=strchr(head,',');
|
||||
if(!tail) {
|
||||
DPRINTF(ERR_LOG,"Badly formatted .url file - must be bitrate,descr,url\n");
|
||||
fclose(infile);
|
||||
return -1;
|
||||
}
|
||||
|
||||
pmp3->bitrate=atoi(head);
|
||||
head=++tail;
|
||||
tail=strchr(head,',');
|
||||
if(!tail) {
|
||||
DPRINTF(ERR_LOG,"Badly formatted .url file - must be bitrate,descr,url\n");
|
||||
fclose(infile);
|
||||
return -1;
|
||||
}
|
||||
|
||||
*tail++='\0';
|
||||
|
||||
pmp3->title=strdup(head);
|
||||
pmp3->url=strdup(tail);
|
||||
fclose(infile);
|
||||
|
||||
DPRINTF(ERR_DEBUG," Title: %s\n",pmp3->title);
|
||||
DPRINTF(ERR_DEBUG," Bitrate: %d\n",pmp3->bitrate);
|
||||
DPRINTF(ERR_DEBUG," URL: %s\n",pmp3->url);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* scan_get_aacfileinfo
|
||||
*
|
||||
|
@ -1250,6 +1308,13 @@ void make_composite_tags(MP3FILE *song)
|
|||
song->description = strdup(fdescr);
|
||||
}
|
||||
|
||||
if(song->url) {
|
||||
song->description = strdup("Playlist URL");
|
||||
song->data_kind=1;
|
||||
} else {
|
||||
song->data_kind=0;
|
||||
}
|
||||
|
||||
if(!song->title)
|
||||
song->title = strdup(song->fname);
|
||||
|
||||
|
|
|
@ -37,7 +37,7 @@ typedef struct tag_mp3file {
|
|||
char *orchestra; /* TPE2 */
|
||||
char *conductor; /* TPE3 */
|
||||
char *grouping; /* TIT1 */
|
||||
|
||||
char *url; /* daap.songdataurl (asul) */
|
||||
|
||||
int bitrate;
|
||||
int samplerate;
|
||||
|
@ -63,6 +63,7 @@ typedef struct tag_mp3file {
|
|||
/* generated fields */
|
||||
char* description; /* long file type */
|
||||
int item_kind; /* song or movie */
|
||||
int data_kind; /* dmap.datakind (asdk) */
|
||||
|
||||
char compilation;
|
||||
} MP3FILE;
|
||||
|
|
Loading…
Reference in New Issue