mirror of
https://gitlab.xiph.org/xiph/ezstream.git
synced 2024-11-03 04:17:18 -05:00
Include the total playing time of a song in the "real-time" output, if TagLib
supplies it. git-svn-id: https://svn.xiph.org/trunk/ezstream@12711 0101bb08-14d6-0310-b084-bc0e0c8e3800
This commit is contained in:
parent
5125437d3f
commit
6eb5d8f557
2
NEWS
2
NEWS
@ -19,6 +19,8 @@ Changes in 0.4.0, (SVN trunk):
|
|||||||
* various:
|
* various:
|
||||||
- [ADD] Allow ezstream to use TagLib for reading metadata from media
|
- [ADD] Allow ezstream to use TagLib for reading metadata from media
|
||||||
files. TagLib (libtag_c) is now an optional dependency.
|
files. TagLib (libtag_c) is now an optional dependency.
|
||||||
|
- [ADD] When built with TagLib support, include the song length in the
|
||||||
|
"real-time" information line, if available.
|
||||||
- [ADD] New <metadata_progname> configuration option, which causes
|
- [ADD] New <metadata_progname> configuration option, which causes
|
||||||
metadata to be read from the output of an external program or
|
metadata to be read from the output of an external program or
|
||||||
script.
|
script.
|
||||||
|
@ -110,14 +110,18 @@ typedef struct tag_ID3Tag {
|
|||||||
} ID3Tag;
|
} ID3Tag;
|
||||||
|
|
||||||
int urlParse(const char *, char **, int *, char **);
|
int urlParse(const char *, char **, int *, char **);
|
||||||
void replaceString(const char *, char *, size_t, const char *, const char *);
|
void replaceString(const char *, char *, size_t, const char *,
|
||||||
|
const char *);
|
||||||
char * buildCommandString(const char *, const char *, metadata_t *);
|
char * buildCommandString(const char *, const char *, metadata_t *);
|
||||||
char * getMetadataString(const char *, metadata_t *);
|
char * getMetadataString(const char *, metadata_t *);
|
||||||
metadata_t * getMetadata(const char *);
|
metadata_t * getMetadata(const char *);
|
||||||
int setMetadata(shout_t *, metadata_t *, char **);
|
int setMetadata(shout_t *, metadata_t *, char **);
|
||||||
FILE * openResource(shout_t *, const char *, int *, char **, int *);
|
FILE * openResource(shout_t *, const char *, int *, char **, int *,
|
||||||
|
int *);
|
||||||
int reconnectServer(shout_t *, int);
|
int reconnectServer(shout_t *, int);
|
||||||
int sendStream(shout_t *, FILE *, const char *, int, void *);
|
const char * getTimeString(int);
|
||||||
|
int sendStream(shout_t *, FILE *, const char *, int, const char *,
|
||||||
|
void *);
|
||||||
int streamFile(shout_t *, const char *);
|
int streamFile(shout_t *, const char *);
|
||||||
int streamPlaylist(shout_t *, const char *);
|
int streamPlaylist(shout_t *, const char *);
|
||||||
char * getProgname(const char *);
|
char * getProgname(const char *);
|
||||||
@ -505,7 +509,7 @@ setMetadata(shout_t *shout, metadata_t *mdata, char **mdata_copy)
|
|||||||
|
|
||||||
FILE *
|
FILE *
|
||||||
openResource(shout_t *shout, const char *fileName, int *popenFlag,
|
openResource(shout_t *shout, const char *fileName, int *popenFlag,
|
||||||
char **metaCopy, int *isStdin)
|
char **metaCopy, int *isStdin, int *songLen)
|
||||||
{
|
{
|
||||||
FILE *filep = NULL;
|
FILE *filep = NULL;
|
||||||
char extension[25];
|
char extension[25];
|
||||||
@ -561,6 +565,8 @@ openResource(shout_t *shout, const char *fileName, int *popenFlag,
|
|||||||
}
|
}
|
||||||
if (metaCopy != NULL)
|
if (metaCopy != NULL)
|
||||||
*metaCopy = metadata_assemble_string(mdata);
|
*metaCopy = metadata_assemble_string(mdata);
|
||||||
|
if (songLen != NULL)
|
||||||
|
*songLen = metadata_get_length(mdata);
|
||||||
|
|
||||||
*popenFlag = 0;
|
*popenFlag = 0;
|
||||||
if (pezConfig->reencode) {
|
if (pezConfig->reencode) {
|
||||||
@ -661,9 +667,28 @@ reconnectServer(shout_t *shout, int closeConn)
|
|||||||
return (0);
|
return (0);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const char *
|
||||||
|
getTimeString(int seconds)
|
||||||
|
{
|
||||||
|
static char str[20];
|
||||||
|
int secs, mins, hours;
|
||||||
|
|
||||||
|
if (seconds < 0)
|
||||||
|
return (NULL);
|
||||||
|
|
||||||
|
secs = seconds;
|
||||||
|
hours = secs / 3600;
|
||||||
|
secs %= 3600;
|
||||||
|
mins = secs / 60;
|
||||||
|
secs %= 60;
|
||||||
|
|
||||||
|
snprintf(str, sizeof(str), "%uh%02um%02us", hours, mins, secs);
|
||||||
|
return ((const char *)str);
|
||||||
|
}
|
||||||
|
|
||||||
int
|
int
|
||||||
sendStream(shout_t *shout, FILE *filepstream, const char *fileName,
|
sendStream(shout_t *shout, FILE *filepstream, const char *fileName,
|
||||||
int isStdin, void *tv)
|
int isStdin, const char *songLenStr, void *tv)
|
||||||
{
|
{
|
||||||
unsigned char buff[4096];
|
unsigned char buff[4096];
|
||||||
size_t read, total, oldTotal;
|
size_t read, total, oldTotal;
|
||||||
@ -728,7 +753,6 @@ sendStream(shout_t *shout, FILE *filepstream, const char *fileName,
|
|||||||
#ifdef HAVE_GETTIMEOFDAY
|
#ifdef HAVE_GETTIMEOFDAY
|
||||||
struct timeval tv;
|
struct timeval tv;
|
||||||
double oldTime, newTime;
|
double oldTime, newTime;
|
||||||
unsigned int hrs, mins, secs;
|
|
||||||
#endif /* HAVE_GETTIMEOFDAY */
|
#endif /* HAVE_GETTIMEOFDAY */
|
||||||
|
|
||||||
if (!isStdin && playlistMode) {
|
if (!isStdin && playlistMode) {
|
||||||
@ -749,18 +773,19 @@ sendStream(shout_t *shout, FILE *filepstream, const char *fileName,
|
|||||||
gettimeofday(&tv, NULL);
|
gettimeofday(&tv, NULL);
|
||||||
newTime = (double)tv.tv_sec
|
newTime = (double)tv.tv_sec
|
||||||
+ (double)tv.tv_usec / 1000000.0;
|
+ (double)tv.tv_usec / 1000000.0;
|
||||||
secs = tv.tv_sec - startTime->tv_sec;
|
if (songLenStr == NULL)
|
||||||
hrs = secs / 3600;
|
printf(" [ %s]",
|
||||||
secs %= 3600;
|
getTimeString(tv.tv_sec - startTime->tv_sec));
|
||||||
mins = secs / 60;
|
else
|
||||||
secs %= 60;
|
printf(" [ %s/%s]",
|
||||||
|
getTimeString(tv.tv_sec - startTime->tv_sec),
|
||||||
|
songLenStr);
|
||||||
if (newTime - oldTime >= 1.0) {
|
if (newTime - oldTime >= 1.0) {
|
||||||
kbps = (((double)(total - oldTotal) / (newTime - oldTime)) * 8.0) / 1000.0;
|
kbps = (((double)(total - oldTotal) / (newTime - oldTime)) * 8.0) / 1000.0;
|
||||||
timeStamp.tv_sec = tv.tv_sec;
|
timeStamp.tv_sec = tv.tv_sec;
|
||||||
timeStamp.tv_usec = tv.tv_usec;
|
timeStamp.tv_usec = tv.tv_usec;
|
||||||
oldTotal = total;
|
oldTotal = total;
|
||||||
}
|
}
|
||||||
printf(" [ %uh%02um%02us]", hrs, mins, secs);
|
|
||||||
if (kbps < 0)
|
if (kbps < 0)
|
||||||
printf(" ");
|
printf(" ");
|
||||||
else
|
else
|
||||||
@ -788,15 +813,15 @@ streamFile(shout_t *shout, const char *fileName)
|
|||||||
{
|
{
|
||||||
FILE *filepstream = NULL;
|
FILE *filepstream = NULL;
|
||||||
int popenFlag = 0;
|
int popenFlag = 0;
|
||||||
char *metaData = NULL;
|
char *metaData = NULL, *songLenStr = NULL;
|
||||||
int isStdin = 0;
|
int isStdin = 0;
|
||||||
int ret, retval = 0;
|
int ret, retval = 0, songLen;
|
||||||
#ifdef HAVE_GETTIMEOFDAY
|
#ifdef HAVE_GETTIMEOFDAY
|
||||||
struct timeval startTime;
|
struct timeval startTime;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
if ((filepstream = openResource(shout, fileName, &popenFlag,
|
if ((filepstream = openResource(shout, fileName, &popenFlag,
|
||||||
&metaData, &isStdin))
|
&metaData, &isStdin, &songLen))
|
||||||
== NULL) {
|
== NULL) {
|
||||||
return (retval);
|
return (retval);
|
||||||
}
|
}
|
||||||
@ -811,13 +836,15 @@ streamFile(shout_t *shout, const char *fileName)
|
|||||||
}
|
}
|
||||||
|
|
||||||
#ifdef HAVE_GETTIMEOFDAY
|
#ifdef HAVE_GETTIMEOFDAY
|
||||||
|
if (songLen >= 0)
|
||||||
|
songLenStr = xstrdup(getTimeString(songLen));
|
||||||
gettimeofday(&startTime, NULL);
|
gettimeofday(&startTime, NULL);
|
||||||
do {
|
do {
|
||||||
ret = sendStream(shout, filepstream, fileName, isStdin,
|
ret = sendStream(shout, filepstream, fileName, isStdin,
|
||||||
(void *)&startTime);
|
songLenStr, (void *)&startTime);
|
||||||
#else
|
#else
|
||||||
do {
|
do {
|
||||||
ret = sendStream(shout, filepstream, fileName, isStdin, NULL);
|
ret = sendStream(shout, filepstream, fileName, isStdin, NULL, NULL);
|
||||||
#endif
|
#endif
|
||||||
if (ret != STREAM_DONE) {
|
if (ret != STREAM_DONE) {
|
||||||
if ((skipTrack && rereadPlaylist) ||
|
if ((skipTrack && rereadPlaylist) ||
|
||||||
@ -875,6 +902,9 @@ streamFile(shout_t *shout, const char *fileName)
|
|||||||
else
|
else
|
||||||
fclose(filepstream);
|
fclose(filepstream);
|
||||||
|
|
||||||
|
if (songLenStr != NULL)
|
||||||
|
xfree(songLenStr);
|
||||||
|
|
||||||
return (retval);
|
return (retval);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -53,6 +53,7 @@ struct metadata {
|
|||||||
char *string;
|
char *string;
|
||||||
char *artist;
|
char *artist;
|
||||||
char *title;
|
char *title;
|
||||||
|
int songLen;
|
||||||
int program;
|
int program;
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -81,6 +82,7 @@ metadata_create(const char *filename)
|
|||||||
|
|
||||||
md = xcalloc(1, sizeof(metadata_t));
|
md = xcalloc(1, sizeof(metadata_t));
|
||||||
md->filename = xstrdup(filename);
|
md->filename = xstrdup(filename);
|
||||||
|
md->songLen = -1;
|
||||||
|
|
||||||
return (md);
|
return (md);
|
||||||
}
|
}
|
||||||
@ -91,6 +93,7 @@ metadata_use_taglib(metadata_t *md, FILE **filep)
|
|||||||
{
|
{
|
||||||
TagLib_File *tf;
|
TagLib_File *tf;
|
||||||
TagLib_Tag *tt;
|
TagLib_Tag *tt;
|
||||||
|
TagLib_AudioProperties *ta;
|
||||||
char *str;
|
char *str;
|
||||||
|
|
||||||
if (md == NULL || md->filename == NULL) {
|
if (md == NULL || md->filename == NULL) {
|
||||||
@ -113,7 +116,9 @@ metadata_use_taglib(metadata_t *md, FILE **filep)
|
|||||||
md->string = metadata_get_name(md->filename);
|
md->string = metadata_get_name(md->filename);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
tt = taglib_file_tag(tf);
|
tt = taglib_file_tag(tf);
|
||||||
|
ta = taglib_file_audioproperties(tf);
|
||||||
|
|
||||||
str = taglib_tag_artist(tt);
|
str = taglib_tag_artist(tt);
|
||||||
if (str != NULL) {
|
if (str != NULL) {
|
||||||
@ -129,6 +134,8 @@ metadata_use_taglib(metadata_t *md, FILE **filep)
|
|||||||
xfree(str);
|
xfree(str);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
md->songLen = taglib_audioproperties_length(ta);
|
||||||
|
|
||||||
taglib_file_free(tf);
|
taglib_file_free(tf);
|
||||||
}
|
}
|
||||||
#else
|
#else
|
||||||
@ -602,6 +609,18 @@ metadata_get_filename(metadata_t *md)
|
|||||||
return (md->filename);
|
return (md->filename);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int
|
||||||
|
metadata_get_length(metadata_t *md)
|
||||||
|
{
|
||||||
|
if (md == NULL) {
|
||||||
|
printf("%s: metadata_get_length(): Internal error: Bad arguments\n",
|
||||||
|
__progname);
|
||||||
|
abort();
|
||||||
|
}
|
||||||
|
|
||||||
|
return (md->songLen);
|
||||||
|
}
|
||||||
|
|
||||||
char *
|
char *
|
||||||
metadata_assemble_string(metadata_t *md)
|
metadata_assemble_string(metadata_t *md)
|
||||||
{
|
{
|
||||||
|
@ -96,6 +96,12 @@ const char * metadata_get_title(metadata_t *);
|
|||||||
*/
|
*/
|
||||||
const char * metadata_get_filename(metadata_t *);
|
const char * metadata_get_filename(metadata_t *);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Returns the length of the song, in seconds, or -1 if the information is not
|
||||||
|
* available.
|
||||||
|
*/
|
||||||
|
int metadata_get_length(metadata_t *);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Allocates and returns a meaningful string based on a metadata handle's
|
* Allocates and returns a meaningful string based on a metadata handle's
|
||||||
* content. The result is what metadata_get_string() defaults to if an external
|
* content. The result is what metadata_get_string() defaults to if an external
|
||||||
|
Loading…
Reference in New Issue
Block a user