Support for streaming audio via .url files -- particularly for the Roku SoundBridge

This commit is contained in:
Ron Pedde 2004-11-04 05:04:46 +00:00
parent baf7ba8bda
commit 493f0bffbf
4 changed files with 93 additions and 9 deletions

View File

@ -147,8 +147,8 @@ static query_field_t song_fields[] = {
{ qft_string, "daap.songcomment", OFFSET_OF(MP3FILE, comment) }, { qft_string, "daap.songcomment", OFFSET_OF(MP3FILE, comment) },
{ qft_i32, "daap.songcompilation", OFFSET_OF(MP3FILE, compilation) }, { qft_i32, "daap.songcompilation", OFFSET_OF(MP3FILE, compilation) },
{ qft_string, "daap.songcomposer", OFFSET_OF(MP3FILE, composer) }, { qft_string, "daap.songcomposer", OFFSET_OF(MP3FILE, composer) },
// { qft_i32_const, "daap.songdatakind", 0 }, { qft_i32, "daap.songdatakind", OFFSET_OF(MP3FILE, data_kind) },
// { qft_string, "daap.songdataurl", OFFSET_OF(MP3FILE, url) }, { qft_string, "daap.songdataurl", OFFSET_OF(MP3FILE, url) },
{ qft_i32, "daap.songdateadded", OFFSET_OF(MP3FILE, time_added) }, { qft_i32, "daap.songdateadded", OFFSET_OF(MP3FILE, time_added) },
{ qft_i32, "daap.songdatemodified",OFFSET_OF(MP3FILE, time_modified) }, { qft_i32, "daap.songdatemodified",OFFSET_OF(MP3FILE, time_modified) },
{ qft_string, "daap.songdescription", OFFSET_OF(MP3FILE, description) }, { 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; query_node_t* filter = 0;
int songs = 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 // if the meta tag is specified, encode it, if it's not specified
// we're given the latitude to select our own subset, for // we're given the latitude to select our own subset, for
// simplicity we just include everything. // simplicity we just include everything.
@ -429,7 +431,7 @@ DAAP_BLOCK *daap_response_songlist(char* metaStr, char* query) {
henum=db_enum_begin(); henum=db_enum_begin();
if((!henum) && (db_get_song_count())) { 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; return NULL;
} }
@ -462,7 +464,7 @@ DAAP_BLOCK *daap_response_songlist(char* metaStr, char* query) {
query_free(filter); query_free(filter);
if(!g) { if(!g) {
DPRINTF(ERR_DEBUG,"Error enumerating database\n"); DPRINTF(ERR_DEBUG,"Error enumerating database - exiting daap_response_songlist\n");
daap_free(root); daap_free(root);
return NULL; 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, "mtco", songs);
daap_set_int(root, "mrco", songs); daap_set_int(root, "mrco", songs);
DPRINTF(ERR_DEBUG,"Exiting daap_response_songlist\n");
return root; 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 */ g = g && daap_add_char(mlit,"mikd",song->item_kind); /* audio */
if(wantsMeta(meta, metaSongDataKind)) 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))) if(song->album && (wantsMeta(meta, metaSongAlbum)))
g = g && daap_add_string(mlit,"asal",song->album); g = g && daap_add_string(mlit,"asal",song->album);

View File

@ -46,7 +46,7 @@
/* /*
* Defines * Defines
*/ */
#define DB_VERSION 4 #define DB_VERSION 5
#define STRLEN(a) (a) ? strlen((a)) + 1 : 1 #define STRLEN(a) (a) ? strlen((a)) + 1 : 1
#define MAYBEFREE(a) { if((a)) free((a)); }; #define MAYBEFREE(a) { if((a)) free((a)); };
@ -121,7 +121,7 @@ typedef struct tag_mp3packed {
int conductor_len; int conductor_len;
int grouping_len; int grouping_len;
/* DB VERSION 4 AND ABOVE GO HERE! */ int url_len; /* DB Version 4 */
char data[1]; char data[1];
} MP3PACKED; } MP3PACKED;
@ -549,6 +549,7 @@ datum *db_packrecord(MP3FILE *pmp3) {
len += STRLEN(pmp3->orchestra); len += STRLEN(pmp3->orchestra);
len += STRLEN(pmp3->conductor); len += STRLEN(pmp3->conductor);
len += STRLEN(pmp3->grouping); len += STRLEN(pmp3->grouping);
len += STRLEN(pmp3->url);
result = (datum*) malloc(sizeof(datum)); result = (datum*) malloc(sizeof(datum));
if(!result) if(!result)
@ -598,6 +599,7 @@ datum *db_packrecord(MP3FILE *pmp3) {
ppacked->orchestra_len=STRLEN(pmp3->orchestra); ppacked->orchestra_len=STRLEN(pmp3->orchestra);
ppacked->conductor_len=STRLEN(pmp3->conductor); ppacked->conductor_len=STRLEN(pmp3->conductor);
ppacked->grouping_len=STRLEN(pmp3->grouping); ppacked->grouping_len=STRLEN(pmp3->grouping);
ppacked->url_len=STRLEN(pmp3->url);
offset=0; offset=0;
if(pmp3->path) if(pmp3->path)
@ -648,6 +650,11 @@ datum *db_packrecord(MP3FILE *pmp3) {
memcpy(&ppacked->data[offset],pmp3->grouping,ppacked->grouping_len); memcpy(&ppacked->data[offset],pmp3->grouping,ppacked->grouping_len);
offset+=ppacked->grouping_len; offset+=ppacked->grouping_len;
if(pmp3->url)
memcpy(&ppacked->data[offset],pmp3->url,ppacked->url_len);
offset+=ppacked->url_len;
/* whew */ /* whew */
return result; return result;
} }
@ -738,6 +745,10 @@ int db_unpackrecord(datum *pdatum, MP3FILE *pmp3) {
pmp3->grouping=strdup(&ppacked->data[offset]); pmp3->grouping=strdup(&ppacked->data[offset]);
offset += ppacked->grouping_len; 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? */ /* shouldn't this have been done when scanning? */
make_composite_tags(pmp3); make_composite_tags(pmp3);
@ -822,6 +833,7 @@ void db_freefile(MP3FILE *pmp3) {
MAYBEFREE(pmp3->conductor); MAYBEFREE(pmp3->conductor);
MAYBEFREE(pmp3->grouping); MAYBEFREE(pmp3->grouping);
MAYBEFREE(pmp3->description); MAYBEFREE(pmp3->description);
MAYBEFREE(pmp3->url);
} }
static int nullstrcmp(const char* a, const char* b) static int nullstrcmp(const char* a, const char* b)

View File

@ -252,9 +252,12 @@ int scan_path(char *path);
int scan_gettags(char *file, MP3FILE *pmp3); int scan_gettags(char *file, MP3FILE *pmp3);
int scan_get_mp3tags(char *file, MP3FILE *pmp3); int scan_get_mp3tags(char *file, MP3FILE *pmp3);
int scan_get_aactags(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_fileinfo(char *file, MP3FILE *pmp3);
int scan_get_mp3fileinfo(char *file, MP3FILE *pmp3); int scan_get_mp3fileinfo(char *file, MP3FILE *pmp3);
int scan_get_aacfileinfo(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); int scan_freetags(MP3FILE *pmp3);
void scan_static_playlist(char *path, struct dirent *pde, struct stat *psb); 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 (*tags)(char* file, MP3FILE* pmp3);
int (*files)(char* file, MP3FILE* pmp3); int (*files)(char* file, MP3FILE* pmp3);
} taghandler; } taghandler;
static taghandler taghandlers[] = { static taghandler taghandlers[] = {
{ "aac", scan_get_aactags, scan_get_aacfileinfo }, { "aac", scan_get_aactags, scan_get_aacfileinfo },
{ "mp4", scan_get_aactags, scan_get_aacfileinfo }, { "mp4", scan_get_aactags, scan_get_aacfileinfo },
{ "m4a", scan_get_aactags, scan_get_aacfileinfo }, { "m4a", scan_get_aactags, scan_get_aacfileinfo },
{ "m4p", scan_get_aactags, scan_get_aacfileinfo }, { "m4p", scan_get_aactags, scan_get_aacfileinfo },
{ "mp3", scan_get_mp3tags, scan_get_mp3fileinfo }, { "mp3", scan_get_mp3tags, scan_get_mp3fileinfo },
{ "url", scan_get_nultags, scan_get_urlfileinfo },
{ NULL, 0 } { NULL, 0 }
}; };
@ -472,7 +477,7 @@ void scan_music_file(char *path, struct dirent *pde, struct stat *psb) {
if(strlen(pde->d_name) > 4) if(strlen(pde->d_name) > 4)
mp3file.type=strdup(strrchr(pde->d_name, '.') + 1); 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 DWB: also assumes that the library is contained entirely within
one file system 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; 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 * scan_get_aacfileinfo
* *
@ -1250,6 +1308,13 @@ void make_composite_tags(MP3FILE *song)
song->description = strdup(fdescr); song->description = strdup(fdescr);
} }
if(song->url) {
song->description = strdup("Playlist URL");
song->data_kind=1;
} else {
song->data_kind=0;
}
if(!song->title) if(!song->title)
song->title = strdup(song->fname); song->title = strdup(song->fname);

View File

@ -37,7 +37,7 @@ typedef struct tag_mp3file {
char *orchestra; /* TPE2 */ char *orchestra; /* TPE2 */
char *conductor; /* TPE3 */ char *conductor; /* TPE3 */
char *grouping; /* TIT1 */ char *grouping; /* TIT1 */
char *url; /* daap.songdataurl (asul) */
int bitrate; int bitrate;
int samplerate; int samplerate;
@ -63,6 +63,7 @@ typedef struct tag_mp3file {
/* generated fields */ /* generated fields */
char* description; /* long file type */ char* description; /* long file type */
int item_kind; /* song or movie */ int item_kind; /* song or movie */
int data_kind; /* dmap.datakind (asdk) */
char compilation; char compilation;
} MP3FILE; } MP3FILE;