mirror of
https://github.com/owntone/owntone-server.git
synced 2025-04-01 02:03:45 -04:00
Now serving...
This commit is contained in:
parent
20e564ed18
commit
c38085474e
122
src/daap.c
122
src/daap.c
@ -123,10 +123,6 @@ DAAP_ITEMS taglist[] = {
|
|||||||
};
|
};
|
||||||
|
|
||||||
/* Forwards */
|
/* Forwards */
|
||||||
DAAP_BLOCK *daap_response_songlist(void);
|
|
||||||
DAAP_BLOCK *daap_response_playlists(void);
|
|
||||||
DAAP_BLOCK *daap_response_dbinfo(void);
|
|
||||||
DAAP_BLOCK *daap_response_playlist_items(int playlist);
|
|
||||||
|
|
||||||
int daap_add_mdcl(DAAP_BLOCK *root, char *tag, char *name, short int number) {
|
int daap_add_mdcl(DAAP_BLOCK *root, char *tag, char *name, short int number) {
|
||||||
DAAP_BLOCK *mdcl;
|
DAAP_BLOCK *mdcl;
|
||||||
@ -242,7 +238,8 @@ DAAP_BLOCK *daap_response_songlist(void) {
|
|||||||
g = g && daap_add_string(mlit,"asar",current->artist);
|
g = g && daap_add_string(mlit,"asar",current->artist);
|
||||||
|
|
||||||
// g = g && daap_add_short(mlit,"asbt",0); /* bpm */
|
// g = g && daap_add_short(mlit,"asbt",0); /* bpm */
|
||||||
// g = g && daap_add_short(mlit,"asbr",128); /* bitrate!! */
|
if(current->bitrate)
|
||||||
|
g = g && daap_add_short(mlit,"asbr",current->bitrate); /* bitrate!! */
|
||||||
|
|
||||||
if(current->comment)
|
if(current->comment)
|
||||||
g = g && daap_add_string(mlit,"ascm",current->comment); /* comment */
|
g = g && daap_add_string(mlit,"ascm",current->comment); /* comment */
|
||||||
@ -254,7 +251,6 @@ DAAP_BLOCK *daap_response_songlist(void) {
|
|||||||
// g = g && daap_add_short(mlit,"asdc",0); /* # of discs */
|
// g = g && daap_add_short(mlit,"asdc",0); /* # of discs */
|
||||||
// g = g && daap_add_short(mlit,"asdn",0); /* disc number */
|
// g = g && daap_add_short(mlit,"asdn",0); /* disc number */
|
||||||
// g = g && daap_add_char(mlit,"asdk",0); /* song datakind? */
|
// g = g && daap_add_char(mlit,"asdk",0); /* song datakind? */
|
||||||
// g = g && daap_add_string(mlit,"asfm","mp3"); /* song format */
|
|
||||||
// aseq - null string!
|
// aseq - null string!
|
||||||
|
|
||||||
if(current->genre)
|
if(current->genre)
|
||||||
@ -262,6 +258,8 @@ DAAP_BLOCK *daap_response_songlist(void) {
|
|||||||
|
|
||||||
g = g && daap_add_int(mlit,"miid",current->id); /* id */
|
g = g && daap_add_int(mlit,"miid",current->id); /* id */
|
||||||
|
|
||||||
|
/* these quite go hand in hand */
|
||||||
|
g = g && daap_add_string(mlit,"asfm","mp3"); /* song format */
|
||||||
g = g && daap_add_string(mlit,"asdt","MPEG audio file"); /* descr */
|
g = g && daap_add_string(mlit,"asdt","MPEG audio file"); /* descr */
|
||||||
|
|
||||||
if(current->title)
|
if(current->title)
|
||||||
@ -272,11 +270,18 @@ DAAP_BLOCK *daap_response_songlist(void) {
|
|||||||
// mper (long)
|
// mper (long)
|
||||||
// g = g && daap_add_char(mlit,"asdb",0); /* disabled */
|
// g = g && daap_add_char(mlit,"asdb",0); /* disabled */
|
||||||
// g = g && daap_add_char(mlit,"asrv",0); /* rel vol */
|
// g = g && daap_add_char(mlit,"asrv",0); /* rel vol */
|
||||||
// g = g && daap_add_int(mlit,"assr",44100); /* sample rate */
|
if(current->samplerate)
|
||||||
// g = g && daap_add_int(mlit,"assz",1024); /* FIXME: Song size! */
|
g = g && daap_add_int(mlit,"assr",current->samplerate); /* samp rate */
|
||||||
// g = g && daap_add_int(mlit,"asst",0); /* song start time? */
|
|
||||||
// g = g && daap_add_int(mlit,"assp",0); /* songstoptime */
|
if(current->file_size)
|
||||||
// g = g && daap_add_int(mlit,"astm",3600); /* song time */
|
g = g && daap_add_int(mlit,"assz",current->file_size); /* Size! */
|
||||||
|
|
||||||
|
g = g && daap_add_int(mlit,"asst",0); /* song start time? */
|
||||||
|
g = g && daap_add_int(mlit,"assp",0); /* songstoptime */
|
||||||
|
|
||||||
|
if(current->song_length)
|
||||||
|
g = g && daap_add_int(mlit,"astm",current->song_length*1000); /* song time */
|
||||||
|
|
||||||
// g = g && daap_add_short(mlit,"astc",0); /* track count */
|
// g = g && daap_add_short(mlit,"astc",0); /* track count */
|
||||||
// g = g && daap_add_short(mlit,"astn",0); /* track number */
|
// g = g && daap_add_short(mlit,"astn",0); /* track number */
|
||||||
// g = g && daap_add_char(mlit,"asur",3); /* rating */
|
// g = g && daap_add_char(mlit,"asur",3); /* rating */
|
||||||
@ -326,99 +331,6 @@ DAAP_BLOCK *daap_response_update(int clientver) {
|
|||||||
return root;
|
return root;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
|
||||||
* daap_response_databases
|
|
||||||
*
|
|
||||||
* handle the daap block for the /databases URI
|
|
||||||
*/
|
|
||||||
|
|
||||||
DAAP_BLOCK *daap_response_databases(char *path) {
|
|
||||||
char *uri;
|
|
||||||
int db_index;
|
|
||||||
int playlist_index;
|
|
||||||
char *first, *last;
|
|
||||||
|
|
||||||
if(strcmp(path,"/databases")==0) {
|
|
||||||
return daap_response_dbinfo();
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
uri = strdup(path);
|
|
||||||
first=(char*)&uri[11];
|
|
||||||
last=first;
|
|
||||||
while((*last) && (*last != '/')) {
|
|
||||||
last++;
|
|
||||||
}
|
|
||||||
|
|
||||||
if(*last != '/') {
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
*last='\0';
|
|
||||||
db_index=atoi(first);
|
|
||||||
|
|
||||||
/* now we have the db id. Next, we have to figure out
|
|
||||||
* if it's a container request or a
|
|
||||||
* items request
|
|
||||||
*
|
|
||||||
* note we generally don't care about the DB index, since we only
|
|
||||||
* support 1 db.
|
|
||||||
*/
|
|
||||||
|
|
||||||
/* the /databases/ uri will either be
|
|
||||||
*
|
|
||||||
* /databases, which returns an AVDB,
|
|
||||||
* /databases/id/items, which returns items in a db
|
|
||||||
* /databases/id/containers, which returns a container
|
|
||||||
* /databases/id/containers/id/items, which returns playlist elements
|
|
||||||
* /databases/id/items/id.mp3, to spool an mp3
|
|
||||||
*/
|
|
||||||
|
|
||||||
last++;
|
|
||||||
|
|
||||||
if(strncasecmp(last,"items/",6)==0) {
|
|
||||||
/* streaming */
|
|
||||||
free(uri);
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
if(strncasecmp(last,"items",5)==0) {
|
|
||||||
/* songlist */
|
|
||||||
free(uri);
|
|
||||||
return daap_response_songlist();
|
|
||||||
}
|
|
||||||
|
|
||||||
if(strncasecmp(last,"containers/",11)==0) {
|
|
||||||
/* playlist elements */
|
|
||||||
first=last + 11;
|
|
||||||
last=first;
|
|
||||||
while((*last) && (*last != '/')) {
|
|
||||||
last++;
|
|
||||||
}
|
|
||||||
|
|
||||||
if(*last != '/') {
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
*last='\0';
|
|
||||||
playlist_index=atoi(first);
|
|
||||||
|
|
||||||
free(uri);
|
|
||||||
|
|
||||||
return daap_response_playlist_items(playlist_index);
|
|
||||||
}
|
|
||||||
|
|
||||||
if(strncasecmp(last,"containers",10)==0) {
|
|
||||||
/* list of playlists */
|
|
||||||
free(uri);
|
|
||||||
return daap_response_playlists();
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
free(uri);
|
|
||||||
return NULL;
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* daap_response_playlists
|
* daap_response_playlists
|
||||||
@ -587,3 +499,5 @@ DAAP_BLOCK *daap_response_playlist_items(int playlist) {
|
|||||||
|
|
||||||
return root;
|
return root;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -27,7 +27,10 @@ DAAP_BLOCK *daap_response_server_info(void);
|
|||||||
DAAP_BLOCK *daap_response_content_codes(void);
|
DAAP_BLOCK *daap_response_content_codes(void);
|
||||||
DAAP_BLOCK *daap_response_login(void);
|
DAAP_BLOCK *daap_response_login(void);
|
||||||
DAAP_BLOCK *daap_response_update(int clientver);
|
DAAP_BLOCK *daap_response_update(int clientver);
|
||||||
DAAP_BLOCK *daap_response_databases(char *path);
|
DAAP_BLOCK *daap_response_songlist(void);
|
||||||
|
DAAP_BLOCK *daap_response_playlists(void);
|
||||||
|
DAAP_BLOCK *daap_response_dbinfo(void);
|
||||||
|
DAAP_BLOCK *daap_response_playlist_items(int playlist);
|
||||||
|
|
||||||
#endif /* _DAAP_H_ */
|
#endif /* _DAAP_H_ */
|
||||||
|
|
||||||
|
137
src/main.c
137
src/main.c
@ -52,7 +52,6 @@
|
|||||||
*/
|
*/
|
||||||
CONFIG config;
|
CONFIG config;
|
||||||
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* daap_handler
|
* daap_handler
|
||||||
*
|
*
|
||||||
@ -65,8 +64,20 @@ void daap_handler(WS_CONNINFO *pwsc) {
|
|||||||
int compress=0;
|
int compress=0;
|
||||||
int clientrev;
|
int clientrev;
|
||||||
|
|
||||||
|
/* for the /databases URI */
|
||||||
|
char *uri;
|
||||||
|
int db_index;
|
||||||
|
int playlist_index;
|
||||||
|
int item;
|
||||||
|
char *first, *last;
|
||||||
|
int streaming=0;
|
||||||
|
|
||||||
|
MP3FILE *pmp3;
|
||||||
|
int file_fd;
|
||||||
|
|
||||||
close=pwsc->close;
|
close=pwsc->close;
|
||||||
pwsc->close=1;
|
pwsc->close=1; /* in case we have any errors */
|
||||||
|
root=NULL;
|
||||||
|
|
||||||
ws_addresponseheader(pwsc,"Accept-Ranges","bytes");
|
ws_addresponseheader(pwsc,"Accept-Ranges","bytes");
|
||||||
ws_addresponseheader(pwsc,"DAAP-Server","iTunes/4.1 (Mac OS X)");
|
ws_addresponseheader(pwsc,"DAAP-Server","iTunes/4.1 (Mac OS X)");
|
||||||
@ -86,40 +97,118 @@ void daap_handler(WS_CONNINFO *pwsc) {
|
|||||||
clientrev=atoi(ws_getvar(pwsc,"delta"));
|
clientrev=atoi(ws_getvar(pwsc,"delta"));
|
||||||
}
|
}
|
||||||
root=daap_response_update(clientrev);
|
root=daap_response_update(clientrev);
|
||||||
} else if (!strcasecmp(pwsc->uri,"/databases")) {
|
|
||||||
root=daap_response_databases(pwsc->uri);
|
|
||||||
} else if (!strcasecmp(pwsc->uri,"/logout")) {
|
} else if (!strcasecmp(pwsc->uri,"/logout")) {
|
||||||
ws_returnerror(pwsc,204,"Logout Successful");
|
ws_returnerror(pwsc,204,"Logout Successful");
|
||||||
return;
|
return;
|
||||||
} else if (!strncasecmp(pwsc->uri,"/databases/",11)) {
|
} else if(strcmp(pwsc->uri,"/databases")==0) {
|
||||||
root=daap_response_databases(pwsc->uri);
|
root=daap_response_dbinfo();
|
||||||
} else {
|
} else if(strncmp(pwsc->uri,"/databases/",11) == 0) {
|
||||||
DPRINTF(ERR_WARN,"Bad handler! Can't find uri handler for %s\n",
|
|
||||||
pwsc->uri);
|
/* the /databases/ uri will either be:
|
||||||
return;
|
*
|
||||||
|
* /databases/id/items, which returns items in a db
|
||||||
|
* /databases/id/containers, which returns a container
|
||||||
|
* /databases/id/containers/id/items, which returns playlist elements
|
||||||
|
* /databases/id/items/id.mp3, to spool an mp3
|
||||||
|
*/
|
||||||
|
|
||||||
|
uri = strdup(pwsc->uri);
|
||||||
|
first=(char*)&uri[11];
|
||||||
|
last=first;
|
||||||
|
while((*last) && (*last != '/')) {
|
||||||
|
last++;
|
||||||
|
}
|
||||||
|
|
||||||
|
if(*last) {
|
||||||
|
*last='\0';
|
||||||
|
db_index=atoi(first);
|
||||||
|
|
||||||
|
last++;
|
||||||
|
|
||||||
|
if(strncasecmp(last,"items/",6)==0) {
|
||||||
|
/* streaming */
|
||||||
|
first=last+6;
|
||||||
|
while((*last) && (*last != '.'))
|
||||||
|
last++;
|
||||||
|
|
||||||
|
if(*last == '.') {
|
||||||
|
*last='\0';
|
||||||
|
item=atoi(first);
|
||||||
|
streaming=1;
|
||||||
|
}
|
||||||
|
free(uri);
|
||||||
|
} else if (strncasecmp(last,"items",5)==0) {
|
||||||
|
/* songlist */
|
||||||
|
free(uri);
|
||||||
|
root=daap_response_songlist();
|
||||||
|
} else if (strncasecmp(last,"containers/",11)==0) {
|
||||||
|
/* playlist elements */
|
||||||
|
first=last + 11;
|
||||||
|
last=first;
|
||||||
|
while((*last) && (*last != '/')) {
|
||||||
|
last++;
|
||||||
|
}
|
||||||
|
|
||||||
|
if(*last) {
|
||||||
|
*last='\0';
|
||||||
|
playlist_index=atoi(first);
|
||||||
|
root=daap_response_playlist_items(playlist_index);
|
||||||
|
}
|
||||||
|
free(uri);
|
||||||
|
} else if (strncasecmp(last,"containers",10)==0) {
|
||||||
|
/* list of playlists */
|
||||||
|
free(uri);
|
||||||
|
root=daap_response_playlists();
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if(!root) {
|
if((!root)&&(!streaming)) {
|
||||||
ws_returnerror(pwsc,400,"Invalid Request");
|
ws_returnerror(pwsc,400,"Invalid Request");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
pwsc->close=close;
|
pwsc->close=close;
|
||||||
|
|
||||||
ws_addresponseheader(pwsc,"Content-Length","%d",root->reported_size + 8);
|
if(!streaming) {
|
||||||
|
ws_addresponseheader(pwsc,"Content-Length","%d",root->reported_size + 8);
|
||||||
|
ws_writefd(pwsc,"HTTP/1.1 200 OK\r\n");
|
||||||
|
ws_emitheaders(pwsc);
|
||||||
|
|
||||||
ws_writefd(pwsc,"HTTP/1.1 200 OK\r\n");
|
/*
|
||||||
ws_emitheaders(pwsc);
|
if(ws_testrequestheader(pwsc,"Accept-Encoding","gzip")) {
|
||||||
|
ws_addresponseheader(pwsc,"Content-Encoding","gzip");
|
||||||
|
compress=1;
|
||||||
|
}
|
||||||
|
*/
|
||||||
|
|
||||||
/*
|
daap_serialize(root,pwsc->fd,0);
|
||||||
if(ws_testrequestheader(pwsc,"Accept-Encoding","gzip")) {
|
daap_free(root);
|
||||||
ws_addresponseheader(pwsc,"Content-Encoding","gzip");
|
} else {
|
||||||
compress=1;
|
/* stream out the song */
|
||||||
|
pwsc->close=1;
|
||||||
|
|
||||||
|
pmp3=db_find(item);
|
||||||
|
if(!pmp3) {
|
||||||
|
ws_returnerror(pwsc,404,"File Not Found");
|
||||||
|
} else {
|
||||||
|
/* got the file, let's open and serve it */
|
||||||
|
file_fd=r_open2(pmp3->path,O_RDONLY);
|
||||||
|
if(file_fd == -1) {
|
||||||
|
pwsc->error=errno;
|
||||||
|
DPRINTF(ERR_WARN,"Thread %d: Error opening %s: %s\n",
|
||||||
|
pwsc->threadno,pmp3->path,strerror(errno));
|
||||||
|
ws_returnerror(pwsc,404,"Not found");
|
||||||
|
} else {
|
||||||
|
ws_writefd(pwsc,"HTTP/1.1 200 OK\r\n");
|
||||||
|
ws_addresponseheader(pwsc,"Connection","Close");
|
||||||
|
ws_emitheaders(pwsc);
|
||||||
|
|
||||||
|
copyfile(file_fd,pwsc->fd);
|
||||||
|
r_close(file_fd);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
*/
|
|
||||||
|
|
||||||
daap_serialize(root,pwsc->fd,0);
|
|
||||||
daap_free(root);
|
|
||||||
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@ -168,7 +257,7 @@ void config_handler(WS_CONNINFO *pwsc) {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
file_fd=open(resolved_path,O_RDONLY);
|
file_fd=r_open2(resolved_path,O_RDONLY);
|
||||||
if(file_fd == -1) {
|
if(file_fd == -1) {
|
||||||
pwsc->error=errno;
|
pwsc->error=errno;
|
||||||
DPRINTF(ERR_WARN,"Thread %d: Error opening %s: %s\n",
|
DPRINTF(ERR_WARN,"Thread %d: Error opening %s: %s\n",
|
||||||
@ -230,7 +319,7 @@ void config_handler(WS_CONNINFO *pwsc) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
close(file_fd);
|
r_close(file_fd);
|
||||||
DPRINTF(ERR_DEBUG,"Thread %d: Served successfully\n",pwsc->threadno);
|
DPRINTF(ERR_DEBUG,"Thread %d: Served successfully\n",pwsc->threadno);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
@ -1,40 +0,0 @@
|
|||||||
#include <stdlib.h>
|
|
||||||
#include <string.h>
|
|
||||||
|
|
||||||
int makeargv(const char *s, const char *delimiters, char ***argvp) {
|
|
||||||
int i;
|
|
||||||
int numtokens;
|
|
||||||
const char *snew;
|
|
||||||
char *t;
|
|
||||||
|
|
||||||
if ((s == NULL) || (delimiters == NULL) || (argvp == NULL))
|
|
||||||
return -1;
|
|
||||||
*argvp = NULL;
|
|
||||||
snew = s + strspn(s, delimiters); /* snew is real start of string */
|
|
||||||
if ((t = malloc(strlen(snew) + 1)) == NULL)
|
|
||||||
return -1;
|
|
||||||
|
|
||||||
/* count the number of tokens in s */
|
|
||||||
strcpy(t, snew);
|
|
||||||
numtokens = 0;
|
|
||||||
if (strtok(t, delimiters) != NULL)
|
|
||||||
for (numtokens = 1; strtok(NULL, delimiters) != NULL; numtokens++) ;
|
|
||||||
|
|
||||||
/* create argument array for ptrs to the tokens */
|
|
||||||
if ((*argvp = malloc((numtokens + 1)*sizeof(char *))) == NULL) {
|
|
||||||
free(t);
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
/* insert pointers to tokens into the argument array */
|
|
||||||
if (numtokens == 0)
|
|
||||||
free(t);
|
|
||||||
else {
|
|
||||||
strcpy(t, snew);
|
|
||||||
**argvp = strtok(t, delimiters);
|
|
||||||
for (i = 1; i < numtokens; i++)
|
|
||||||
*((*argvp) + i) = strtok(NULL, delimiters);
|
|
||||||
}
|
|
||||||
/* put in the final NULL pointer and return */
|
|
||||||
*((*argvp) + numtokens) = NULL;
|
|
||||||
return numtokens;
|
|
||||||
}
|
|
@ -36,13 +36,30 @@
|
|||||||
/*
|
/*
|
||||||
* Typedefs
|
* Typedefs
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
typedef struct tag_scan_id3header {
|
||||||
|
unsigned char id[3];
|
||||||
|
unsigned char version[2];
|
||||||
|
unsigned char flags;
|
||||||
|
unsigned char size[4];
|
||||||
|
} SCAN_ID3HEADER;
|
||||||
|
|
||||||
#define MAYBEFREE(a) { if((a)) free((a)); };
|
#define MAYBEFREE(a) { if((a)) free((a)); };
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Globals
|
||||||
|
*/
|
||||||
|
int scan_br_table[] = {
|
||||||
|
0,32,40,48,56,64,80,96,112,128,160,192,224,256,320,0
|
||||||
|
};
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Forwards
|
* Forwards
|
||||||
*/
|
*/
|
||||||
int scan_foreground(char *path);
|
int scan_foreground(char *path);
|
||||||
int scan_gettags(char *file, MP3FILE *pmp3);
|
int scan_gettags(char *file, MP3FILE *pmp3);
|
||||||
|
int scan_getfileinfo(char *file, MP3FILE *pmp3);
|
||||||
int scan_freetags(MP3FILE *pmp3);
|
int scan_freetags(MP3FILE *pmp3);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@ -133,6 +150,7 @@ int scan_foreground(char *path) {
|
|||||||
|
|
||||||
/* Do the tag lookup here */
|
/* Do the tag lookup here */
|
||||||
scan_gettags(mp3file.path,&mp3file);
|
scan_gettags(mp3file.path,&mp3file);
|
||||||
|
scan_getfileinfo(mp3file.path,&mp3file);
|
||||||
|
|
||||||
db_add(&mp3file);
|
db_add(&mp3file);
|
||||||
|
|
||||||
@ -230,3 +248,84 @@ int scan_freetags(MP3FILE *pmp3) {
|
|||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* scan_getfileinfo
|
||||||
|
*
|
||||||
|
* Get information from the file headers itself -- like
|
||||||
|
* song length, bit rate, etc.
|
||||||
|
*/
|
||||||
|
int scan_getfileinfo(char *file, MP3FILE *pmp3) {
|
||||||
|
FILE *infile;
|
||||||
|
SCAN_ID3HEADER *pid3;
|
||||||
|
unsigned int size=0;
|
||||||
|
fpos_t fp_size=0;
|
||||||
|
fpos_t file_size;
|
||||||
|
unsigned char buffer[256];
|
||||||
|
int time_seconds;
|
||||||
|
|
||||||
|
int ver=0;
|
||||||
|
int layer=0;
|
||||||
|
int bitrate=0;
|
||||||
|
int samplerate=0;
|
||||||
|
|
||||||
|
if(!(infile=fopen(file,"rb"))) {
|
||||||
|
DPRINTF(ERR_WARN,"Could not open %s for reading\n",file);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
fread(buffer,1,sizeof(buffer),infile);
|
||||||
|
pid3=(SCAN_ID3HEADER*)buffer;
|
||||||
|
|
||||||
|
if(strncmp(pid3->id,"ID3",3)==0) {
|
||||||
|
/* found an ID3 header... */
|
||||||
|
size = (pid3->size[0] << 21 | pid3->size[1] << 14 |
|
||||||
|
pid3->size[2] << 7 | pid3->size[3]);
|
||||||
|
fp_size=size + sizeof(SCAN_ID3HEADER);
|
||||||
|
}
|
||||||
|
|
||||||
|
fseek(infile,0,SEEK_END);
|
||||||
|
file_size=ftell(infile);
|
||||||
|
file_size -= fp_size;
|
||||||
|
|
||||||
|
fsetpos(infile,&fp_size);
|
||||||
|
fread(buffer,1,sizeof(buffer),infile);
|
||||||
|
|
||||||
|
if((buffer[0] == 0xFF)&&(buffer[1] >= 224)) {
|
||||||
|
printf("Found sync frame\n");
|
||||||
|
|
||||||
|
ver=(buffer[1] & 0x18) >> 3;
|
||||||
|
layer=(buffer[1] & 0x6) >> 1;
|
||||||
|
if((ver==3) && (layer==1)) { /* MPEG1, Layer 3 */
|
||||||
|
bitrate=(buffer[2] & 0xF0) >> 4;
|
||||||
|
bitrate=scan_br_table[bitrate];
|
||||||
|
samplerate=(buffer[2] & 0x0C) >> 2;
|
||||||
|
switch(samplerate) {
|
||||||
|
case 0:
|
||||||
|
samplerate=44100;
|
||||||
|
break;
|
||||||
|
case 1:
|
||||||
|
samplerate=48000;
|
||||||
|
break;
|
||||||
|
case 2:
|
||||||
|
samplerate=32000;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
pmp3->bitrate=bitrate;
|
||||||
|
pmp3->samplerate=samplerate;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* guesstimate the file length */
|
||||||
|
time_seconds = ((int)(file_size * 8)) / (bitrate * 1024);
|
||||||
|
pmp3->song_length=time_seconds;
|
||||||
|
pmp3->file_size=file_size;
|
||||||
|
} else {
|
||||||
|
/* should really scan forward to next sync frame */
|
||||||
|
fclose(infile);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
fclose(infile);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
@ -30,6 +30,12 @@ typedef struct tag_mp3file {
|
|||||||
char *album;
|
char *album;
|
||||||
char *genre;
|
char *genre;
|
||||||
char *comment;
|
char *comment;
|
||||||
|
|
||||||
|
int bitrate;
|
||||||
|
int samplerate;
|
||||||
|
int song_length;
|
||||||
|
int file_size;
|
||||||
|
|
||||||
int got_id3;
|
int got_id3;
|
||||||
int id;
|
int id;
|
||||||
} MP3FILE;
|
} MP3FILE;
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
web_root ../admin-root
|
web_root ../admin-root
|
||||||
port 3689
|
port 3689
|
||||||
admin_password secret
|
admin_password secret
|
||||||
mp3_dir mp3
|
mp3_dir mp3/Type O Negative
|
||||||
|
Loading…
x
Reference in New Issue
Block a user