mirror of
https://gitlab.xiph.org/xiph/ezstream.git
synced 2024-12-04 14:46:31 -05:00
More metadata featuritis, add <metadata_format/> and implement support for
'@a@', '@t@' and '@s@'. git-svn-id: https://svn.xiph.org/trunk/ezstream@12707 0101bb08-14d6-0310-b084-bc0e0c8e3800
This commit is contained in:
parent
6f779c21f3
commit
c5aaa28594
4
NEWS
4
NEWS
@ -25,6 +25,10 @@ Changes in 0.4.0, (SVN trunk):
|
||||
- [ADD] New runtime control via the SIGUSR2 signal, which triggers reading
|
||||
of fresh metadata information from <metadata_progname> (metadata
|
||||
is always read at song changes.)
|
||||
- [ADD] New <metadata_format> configuration option, to customize metadata
|
||||
strings when used with the new <metadata_progname> feature.
|
||||
- [ADD] New '@a@' and '@t@' placeholders for separate artist and title
|
||||
metadata in de-/encoder commands.
|
||||
|
||||
|
||||
|
||||
|
@ -215,6 +215,17 @@ configuration file.
|
||||
See the
|
||||
.Sy SCRIPTING
|
||||
section for details on how the metadata program must behave.
|
||||
.It Sy \&<metadata_format\ /\&>
|
||||
.Pq Optional.
|
||||
Set the format of the string that should be used for the
|
||||
.Sq @M@
|
||||
placeholder when setting metadata with an external program or script via
|
||||
\&<metadata_progname/\&>.
|
||||
.Pp
|
||||
See the
|
||||
.Sy METADATA
|
||||
section for details on how metadata is handled by
|
||||
.Nm .
|
||||
.It Sy \&<stream_once\ /\&>
|
||||
Set to
|
||||
.Sy 1
|
||||
@ -339,16 +350,17 @@ Set the command to decode the specified media file format to raw data and send
|
||||
it to standard output.
|
||||
During runtime, the placeholder
|
||||
.Sq Li @T@
|
||||
is replaced with the fully qualified name of the media file, as specified in
|
||||
the \&<filename/\&> element or a playlist file.
|
||||
is replaced with the name of the media file, as it is specified in the
|
||||
\&<filename/\&> element or contained in a playlist file.
|
||||
It should always be enclosed in quotes, to prevent problems with filenames that
|
||||
contain whitespaces.
|
||||
.Pp
|
||||
The metadata placeholder,
|
||||
.Sq @M@ ,
|
||||
is also available in the \&<decode/\&> element.
|
||||
That way it can be used for combined de-/encoder programs that produce readily
|
||||
streamable data.
|
||||
Metadata placeholders can be used in the \&<decode/\&> element as well, for
|
||||
combined de-/encoder programs that produce streamable data.
|
||||
See the
|
||||
.Sy METADATA
|
||||
section for details on how metadata is handled by
|
||||
.Nm .
|
||||
.Pp
|
||||
For example, to decode Ogg Vorbis files using the
|
||||
.Cm oggdec
|
||||
@ -358,15 +370,13 @@ utility:
|
||||
.It Sy \&<encode\ /\&>
|
||||
Set the command to encode raw data, received from standard input, to the
|
||||
specified stream format.
|
||||
During runtime, the placeholder
|
||||
.Sq Li @M@
|
||||
is replaced with the metadata
|
||||
.Po
|
||||
e.g.
|
||||
.Dq Artist - Title
|
||||
.Pc
|
||||
for the current track.
|
||||
It also should be enclosed in quotes at all times.
|
||||
.Pp
|
||||
Metadata placeholders can be used in the \&<encode/\&> element.
|
||||
For details about using metadata in
|
||||
.Nm ,
|
||||
see below in the
|
||||
.Sy METADATA
|
||||
section.
|
||||
.Pp
|
||||
For example, to encode an Ogg Vorbis stream using the quality setting 1.5 with
|
||||
the
|
||||
@ -423,11 +433,89 @@ When called with the command line parameter
|
||||
the program should return only the title information of the metadata.
|
||||
.Pq Optional.
|
||||
.El
|
||||
.Sh METADATA
|
||||
The main tool for handling metadata with
|
||||
.Nm
|
||||
is placeholders in decoder and encoder commands that are replaced with real
|
||||
content during runtime.
|
||||
The tricky part about is that one placeholders has to be handled differently
|
||||
depending on where the metadata comes from.
|
||||
This section will explain each possible scenario.
|
||||
.Ss Metadata Placeholders
|
||||
.Bl -tag -width -Ds
|
||||
.It Sy @T@
|
||||
Replaced with the media file name.
|
||||
Required in \&<decode/\&> and is available in \&<metadata_format/\&>.
|
||||
.It Sy @M@
|
||||
Replaced with a metadata string.
|
||||
See below for a detailed explanation.
|
||||
Available in \&<decode/\&> and \&<encode/\&>.
|
||||
.It Sy @a@
|
||||
Replaced with the artist information.
|
||||
Available in \&<decode/\&>, \&<encode/\&> and \&<metadata_format/\&>.
|
||||
.It Sy @t@
|
||||
Replaced with the title information.
|
||||
Available in \&<decode/\&>, \&<encode/\&> and \&<metadata_format/\&>.
|
||||
.It Sy @s@
|
||||
Replaced with the string returned by \&<metadata_progname/\&> when called
|
||||
without any command line parameters.
|
||||
Available only in \&<metadata_format/\&>.
|
||||
.El
|
||||
.Ss The @M@ Placeholder
|
||||
While all other placeholders are simply replaced with whatever data they are
|
||||
associated with,
|
||||
.Sq @M@
|
||||
is context-sensitive.
|
||||
The logic used by
|
||||
.Nm
|
||||
is the following:
|
||||
.Bd -literal -offset indent
|
||||
If ('@M@ is present')
|
||||
If ('\&<metadata_progname/\&>' AND '\&<metadata_format/\&>')
|
||||
Replace with format string result.
|
||||
Else
|
||||
If (NOT '\&<metadata_progname/\&>' AND '@t@ is present')
|
||||
Replace with empty string.
|
||||
else
|
||||
Replace with generated metadata string.
|
||||
Endif
|
||||
Endif
|
||||
Endif
|
||||
.Ed
|
||||
.Pp
|
||||
The generated metadata string for
|
||||
.Sq @M@
|
||||
is of the format
|
||||
.Dq Artist - Title ,
|
||||
if both artist and title information is available.
|
||||
If one of the two is missing, the available one is displayed without a leading
|
||||
or trailing dash, e.g. just
|
||||
.Dq Artist .
|
||||
If neither artist nor title are available, the name of the media file, without
|
||||
its file extension, is used.
|
||||
.Ss Metadata Caveats
|
||||
It is possible to generate strange results with odd combinations of
|
||||
placeholders, external metadata programs and updates during runtime via
|
||||
.Sy SIGUSR2 .
|
||||
If things start to become just confusing, simplify.
|
||||
.Pp
|
||||
Metadata updates during runtime are done with a relatively broken feature of
|
||||
libshout.
|
||||
Additional metadata information that is already present in the stream sent via
|
||||
.Nm
|
||||
is usually destroyed and replaced with the new data.
|
||||
It is not possible to properly discern between artist and title information,
|
||||
which means that anything set with the
|
||||
.Sy SIGUSR2
|
||||
feature will continue to end up entirely in the
|
||||
.Qq Title
|
||||
field of a stream.
|
||||
.Sh FILES
|
||||
.Bl -tag -width "!!EXAMPLES_DIR!!" -compact
|
||||
.It Pa !!EXAMPLES_DIR!!
|
||||
Directory containing example configuration files for various uses of
|
||||
.Nm .
|
||||
.Nm ,
|
||||
as well as example playlist and metadata scripts.
|
||||
.El
|
||||
.Sh AUTHORS
|
||||
.Nm
|
||||
|
@ -39,6 +39,7 @@ static const char *blankString = "";
|
||||
void freeConfig(EZCONFIG *);
|
||||
unsigned int checkDecoderLine(const char *, const char *, long);
|
||||
unsigned int checkEncoderLine(const char *, const char *, long);
|
||||
unsigned int checkFormatLine(const char *, const char *, long);
|
||||
|
||||
EZCONFIG *
|
||||
getEZConfig(void)
|
||||
@ -198,6 +199,27 @@ parseConfig(const char *fileName)
|
||||
xmlFree(ls_xmlContentPtr);
|
||||
}
|
||||
}
|
||||
if (!xmlStrcmp(cur->name, BAD_CAST "metadata_format")) {
|
||||
if (ezConfig.metadataFormat != NULL) {
|
||||
printf("%s[%ld]: Error: Cannot have multiple <metadata_format> elements\n",
|
||||
fileName, xmlGetLineNo(cur));
|
||||
config_error++;
|
||||
continue;
|
||||
}
|
||||
if (cur->xmlChildrenNode != NULL) {
|
||||
unsigned int ret;
|
||||
|
||||
ls_xmlContentPtr = (char *)xmlNodeListGetString(doc, cur->xmlChildrenNode, 1);
|
||||
ezConfig.metadataFormat = xstrdup(ls_xmlContentPtr);
|
||||
xmlFree(ls_xmlContentPtr);
|
||||
if ((ret = checkFormatLine(ezConfig.metadataFormat,
|
||||
fileName, xmlGetLineNo(cur)))
|
||||
> 0) {
|
||||
config_error += ret;
|
||||
continue;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (!xmlStrcmp(cur->name, BAD_CAST "playlist_program")) {
|
||||
if (program_set) {
|
||||
printf("%s[%ld]: Error: Cannot have multiple <playlist_program> elements\n",
|
||||
@ -564,6 +586,8 @@ freeConfig(EZCONFIG *cfg)
|
||||
xfree(cfg->fileName);
|
||||
if (cfg->metadataProgram != NULL)
|
||||
xfree(cfg->metadataProgram);
|
||||
if (cfg->metadataFormat != NULL)
|
||||
xfree(cfg->metadataFormat);
|
||||
if (cfg->serverName != NULL)
|
||||
xfree(cfg->serverName);
|
||||
if (cfg->serverURL != NULL)
|
||||
@ -604,15 +628,22 @@ checkDecoderLine(const char *str, const char *file, long line)
|
||||
{
|
||||
unsigned int errors;
|
||||
char *p;
|
||||
int have_track = 0;
|
||||
|
||||
errors = 0;
|
||||
if ((p = strstr(str, STRING_PLACEHOLDER)) != NULL) {
|
||||
printf("%s[%ld]: Error: `%s' placeholder not allowed in decoder command\n",
|
||||
file, line, STRING_PLACEHOLDER);
|
||||
errors++;
|
||||
}
|
||||
if ((p = strstr(str, TRACK_PLACEHOLDER)) != NULL) {
|
||||
p += strlen(TRACK_PLACEHOLDER);
|
||||
if ((p = strstr(p, TRACK_PLACEHOLDER)) != NULL) {
|
||||
printf("%s[%ld]: Error: Multiple `%s' placeholders in decoder command\n",
|
||||
file, line, TRACK_PLACEHOLDER);
|
||||
errors++;
|
||||
}
|
||||
} else
|
||||
have_track = 1;
|
||||
}
|
||||
if ((p = strstr(str, METADATA_PLACEHOLDER)) != NULL) {
|
||||
p += strlen(METADATA_PLACEHOLDER);
|
||||
@ -639,6 +670,12 @@ checkDecoderLine(const char *str, const char *file, long line)
|
||||
}
|
||||
}
|
||||
|
||||
if (!have_track) {
|
||||
printf("%s[%ld]: Error: The decoder command requires the '%s' track placeholder\n",
|
||||
file, line, TRACK_PLACEHOLDER);
|
||||
errors++;
|
||||
}
|
||||
|
||||
return (errors);
|
||||
}
|
||||
|
||||
@ -654,6 +691,11 @@ checkEncoderLine(const char *str, const char *file, long line)
|
||||
file, line, TRACK_PLACEHOLDER);
|
||||
errors++;
|
||||
}
|
||||
if ((p = strstr(str, STRING_PLACEHOLDER)) != NULL) {
|
||||
printf("%s[%ld]: Error: `%s' placeholder not allowed in encoder command\n",
|
||||
file, line, STRING_PLACEHOLDER);
|
||||
errors++;
|
||||
}
|
||||
if ((p = strstr(str, METADATA_PLACEHOLDER)) != NULL) {
|
||||
p += strlen(METADATA_PLACEHOLDER);
|
||||
if ((p = strstr(p, METADATA_PLACEHOLDER)) != NULL) {
|
||||
@ -681,3 +723,51 @@ checkEncoderLine(const char *str, const char *file, long line)
|
||||
|
||||
return (errors);
|
||||
}
|
||||
|
||||
unsigned int
|
||||
checkFormatLine(const char *str, const char *file, long line)
|
||||
{
|
||||
unsigned int errors;
|
||||
char *p;
|
||||
|
||||
errors = 0;
|
||||
if ((p = strstr(str, METADATA_PLACEHOLDER)) != NULL) {
|
||||
printf("%s[%ld]: Error: `%s' placeholder not allowed in <metadata_format>\n",
|
||||
file, line, METADATA_PLACEHOLDER);
|
||||
errors++;
|
||||
}
|
||||
if ((p = strstr(str, TRACK_PLACEHOLDER)) != NULL) {
|
||||
p += strlen(TRACK_PLACEHOLDER);
|
||||
if ((p = strstr(p, TRACK_PLACEHOLDER)) != NULL) {
|
||||
printf("%s[%ld]: Error: Multiple `%s' placeholders in <metadata_format>\n",
|
||||
file, line, TRACK_PLACEHOLDER);
|
||||
errors++;
|
||||
}
|
||||
}
|
||||
if ((p = strstr(str, STRING_PLACEHOLDER)) != NULL) {
|
||||
p += strlen(STRING_PLACEHOLDER);
|
||||
if ((p = strstr(p, STRING_PLACEHOLDER)) != NULL) {
|
||||
printf("%s[%ld]: Error: Multiple `%s' placeholders in <metadata_format>\n",
|
||||
file, line, STRING_PLACEHOLDER);
|
||||
errors++;
|
||||
}
|
||||
}
|
||||
if ((p = strstr(str, ARTIST_PLACEHOLDER)) != NULL) {
|
||||
p += strlen(ARTIST_PLACEHOLDER);
|
||||
if ((p = strstr(p, ARTIST_PLACEHOLDER)) != NULL) {
|
||||
printf("%s[%ld]: Error: Multiple `%s' placeholders in <metadata_format>\n",
|
||||
file, line, ARTIST_PLACEHOLDER);
|
||||
errors++;
|
||||
}
|
||||
}
|
||||
if ((p = strstr(str, TITLE_PLACEHOLDER)) != NULL) {
|
||||
p += strlen(TITLE_PLACEHOLDER);
|
||||
if ((p = strstr(p, TITLE_PLACEHOLDER)) != NULL) {
|
||||
printf("%s[%ld]: Error: Multiple `%s' placeholders in <metadata_format>\n",
|
||||
file, line, TITLE_PLACEHOLDER);
|
||||
errors++;
|
||||
}
|
||||
}
|
||||
|
||||
return (errors);
|
||||
}
|
||||
|
@ -33,6 +33,7 @@
|
||||
#define METADATA_PLACEHOLDER "@M@"
|
||||
#define ARTIST_PLACEHOLDER "@a@"
|
||||
#define TITLE_PLACEHOLDER "@t@"
|
||||
#define STRING_PLACEHOLDER "@s@"
|
||||
|
||||
typedef struct tag_FORMAT_ENCDEC {
|
||||
char *format;
|
||||
@ -47,6 +48,7 @@ typedef struct tag_EZCONFIG {
|
||||
char *format;
|
||||
char *fileName;
|
||||
char *metadataProgram;
|
||||
char *metadataFormat;
|
||||
char *serverName;
|
||||
char *serverURL;
|
||||
char *serverGenre;
|
||||
|
149
src/ezstream.c
149
src/ezstream.c
@ -112,6 +112,7 @@ typedef struct tag_ID3Tag {
|
||||
int urlParse(const char *, char **, int *, char **);
|
||||
void replaceString(const char *, char *, size_t, const char *, const char *);
|
||||
char * buildCommandString(const char *, const char *, metadata_t *);
|
||||
char * getMetadataString(const char *, metadata_t *);
|
||||
metadata_t * getMetadata(const char *);
|
||||
int setMetadata(shout_t *, metadata_t *, char **);
|
||||
FILE * openResource(shout_t *, const char *, int *, char **, int *);
|
||||
@ -247,14 +248,61 @@ buildCommandString(const char *extension, const char *fileName,
|
||||
newDecoder = xcalloc(1, newDecoderLen);
|
||||
replaceString(decoder, newDecoder, newDecoderLen, TRACK_PLACEHOLDER,
|
||||
fileName);
|
||||
if (strstr(decoder, ARTIST_PLACEHOLDER) != NULL) {
|
||||
size_t tmpLen = strlen(newDecoder) + strlen(metadata_get_artist(mdata)) + 1;
|
||||
char *tmpStr = xcalloc(1, tmpLen);
|
||||
replaceString(newDecoder, tmpStr, tmpLen, ARTIST_PLACEHOLDER,
|
||||
metadata_get_artist(mdata));
|
||||
xfree(newDecoder);
|
||||
newDecoder = tmpStr;
|
||||
}
|
||||
if (strstr(decoder, TITLE_PLACEHOLDER) != NULL) {
|
||||
size_t tmpLen = strlen(newDecoder) + strlen(metadata_get_title(mdata)) + 1;
|
||||
char *tmpStr = xcalloc(1, tmpLen);
|
||||
replaceString(newDecoder, tmpStr, tmpLen, TITLE_PLACEHOLDER,
|
||||
metadata_get_title(mdata));
|
||||
xfree(newDecoder);
|
||||
newDecoder = tmpStr;
|
||||
}
|
||||
/*
|
||||
* if meta
|
||||
* if (prog && format)
|
||||
* metatoformat
|
||||
* else
|
||||
* if (!prog && title)
|
||||
* emptymeta
|
||||
* else
|
||||
* replacemeta
|
||||
*/
|
||||
if (strstr(decoder, METADATA_PLACEHOLDER) != NULL) {
|
||||
if (metadataFromProgram && pezConfig->metadataFormat != NULL) {
|
||||
char *mdataString = getMetadataString(pezConfig->metadataFormat, mdata);
|
||||
size_t tmpLen = strlen(newDecoder) + strlen(mdataString) + 1;
|
||||
char *tmpStr = xcalloc(1, tmpLen);
|
||||
replaceString(newDecoder, tmpStr, tmpLen,
|
||||
METADATA_PLACEHOLDER, mdataString);
|
||||
xfree(newDecoder);
|
||||
xfree(mdataString);
|
||||
newDecoder = tmpStr;
|
||||
} else {
|
||||
if (!metadataFromProgram && strstr(decoder, TITLE_PLACEHOLDER) != NULL) {
|
||||
size_t tmpLen = strlen(newDecoder) + 1;
|
||||
char *tmpStr = xcalloc(1, tmpLen);
|
||||
replaceString(newDecoder, tmpStr, tmpLen,
|
||||
METADATA_PLACEHOLDER, "");
|
||||
xfree(newDecoder);
|
||||
newDecoder = tmpStr;
|
||||
} else {
|
||||
size_t tmpLen = strlen(newDecoder) + strlen(metadata_get_string(mdata)) + 1;
|
||||
char *tmpStr = xcalloc(1, tmpLen);
|
||||
replaceString(newDecoder, tmpStr, tmpLen, METADATA_PLACEHOLDER,
|
||||
replaceString(newDecoder, tmpStr, tmpLen,
|
||||
METADATA_PLACEHOLDER,
|
||||
metadata_get_string(mdata));
|
||||
xfree(newDecoder);
|
||||
newDecoder = tmpStr;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
encoder = xstrdup(getFormatEncoder(pezConfig->format));
|
||||
if (strlen(encoder) == 0) {
|
||||
@ -272,10 +320,47 @@ buildCommandString(const char *extension, const char *fileName,
|
||||
return (commandString);
|
||||
}
|
||||
|
||||
newEncoderLen = strlen(encoder) + strlen(metadata_get_string(mdata)) + 1;
|
||||
newEncoderLen = strlen(encoder) + strlen(metadata_get_artist(mdata)) + 1;
|
||||
newEncoder = xcalloc(1, newEncoderLen);
|
||||
replaceString(encoder, newEncoder, newEncoderLen, METADATA_PLACEHOLDER,
|
||||
replaceString(encoder, newEncoder, newEncoderLen, ARTIST_PLACEHOLDER,
|
||||
metadata_get_artist(mdata));
|
||||
if (strstr(encoder, TITLE_PLACEHOLDER) != NULL) {
|
||||
size_t tmpLen = strlen(newEncoder) + strlen(metadata_get_title(mdata)) + 1;
|
||||
char *tmpStr = xcalloc(1, tmpLen);
|
||||
replaceString(newEncoder, tmpStr, tmpLen, TITLE_PLACEHOLDER,
|
||||
metadata_get_title(mdata));
|
||||
xfree(newEncoder);
|
||||
newEncoder = tmpStr;
|
||||
}
|
||||
if (strstr(encoder, METADATA_PLACEHOLDER) != NULL) {
|
||||
if (metadataFromProgram && pezConfig->metadataFormat != NULL) {
|
||||
char *mdataString = getMetadataString(pezConfig->metadataFormat, mdata);
|
||||
size_t tmpLen = strlen(newEncoder) + strlen(mdataString) + 1;
|
||||
char *tmpStr = xcalloc(1, tmpLen);
|
||||
replaceString(newEncoder, tmpStr, tmpLen,
|
||||
METADATA_PLACEHOLDER, mdataString);
|
||||
xfree(newEncoder);
|
||||
xfree(mdataString);
|
||||
newEncoder = tmpStr;
|
||||
} else {
|
||||
if (!metadataFromProgram && strstr(encoder, TITLE_PLACEHOLDER) != NULL) {
|
||||
size_t tmpLen = strlen(newEncoder) + 1;
|
||||
char *tmpStr = xcalloc(1, tmpLen);
|
||||
replaceString(newEncoder, tmpStr, tmpLen,
|
||||
METADATA_PLACEHOLDER, "");
|
||||
xfree(newEncoder);
|
||||
newEncoder = tmpStr;
|
||||
} else {
|
||||
size_t tmpLen = strlen(newEncoder) + strlen(metadata_get_string(mdata)) + 1;
|
||||
char *tmpStr = xcalloc(1, tmpLen);
|
||||
replaceString(newEncoder, tmpStr, tmpLen,
|
||||
METADATA_PLACEHOLDER,
|
||||
metadata_get_string(mdata));
|
||||
xfree(newEncoder);
|
||||
newEncoder = tmpStr;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
commandStringLen = strlen(newDecoder) + strlen(" | ") +
|
||||
strlen(newEncoder) + 1;
|
||||
@ -291,6 +376,59 @@ buildCommandString(const char *extension, const char *fileName,
|
||||
return (commandString);
|
||||
}
|
||||
|
||||
char *
|
||||
getMetadataString(const char *format, metadata_t *mdata)
|
||||
{
|
||||
char *tmp, *str;
|
||||
size_t siz;
|
||||
|
||||
if (mdata == NULL) {
|
||||
printf("%s: getMetadataString(): Internal error: NULL metadata_t\n",
|
||||
__progname);
|
||||
abort();
|
||||
}
|
||||
|
||||
if (format == NULL)
|
||||
return (NULL);
|
||||
|
||||
str = xstrdup(format);
|
||||
|
||||
if (strstr(format, ARTIST_PLACEHOLDER) != NULL) {
|
||||
siz = strlen(str) + strlen(metadata_get_artist(mdata)) + 1;
|
||||
tmp = xcalloc(1, siz);
|
||||
replaceString(str, tmp, siz, ARTIST_PLACEHOLDER,
|
||||
metadata_get_artist(mdata));
|
||||
xfree(str);
|
||||
str = tmp;
|
||||
}
|
||||
if (strstr(format, TITLE_PLACEHOLDER) != NULL) {
|
||||
siz = strlen(str) + strlen(metadata_get_title(mdata)) + 1;
|
||||
tmp = xcalloc(1, siz);
|
||||
replaceString(str, tmp, siz, TITLE_PLACEHOLDER,
|
||||
metadata_get_title(mdata));
|
||||
xfree(str);
|
||||
str = tmp;
|
||||
}
|
||||
if (strstr(format, STRING_PLACEHOLDER) != NULL) {
|
||||
siz = strlen(str) + strlen(metadata_get_string(mdata)) + 1;
|
||||
tmp = xcalloc(1, siz);
|
||||
replaceString(str, tmp, siz, STRING_PLACEHOLDER,
|
||||
metadata_get_string(mdata));
|
||||
xfree(str);
|
||||
str = tmp;
|
||||
}
|
||||
if (strstr(format, TRACK_PLACEHOLDER) != NULL) {
|
||||
siz = strlen(str) + strlen(metadata_get_filename(mdata)) + 1;
|
||||
tmp = xcalloc(1, siz);
|
||||
replaceString(str, tmp, siz, TRACK_PLACEHOLDER,
|
||||
metadata_get_filename(mdata));
|
||||
xfree(str);
|
||||
str = tmp;
|
||||
}
|
||||
|
||||
return (str);
|
||||
}
|
||||
|
||||
metadata_t *
|
||||
getMetadata(const char *fileName)
|
||||
{
|
||||
@ -339,10 +477,13 @@ setMetadata(shout_t *shout, metadata_t *mdata, char **mdata_copy)
|
||||
exit(1);
|
||||
}
|
||||
|
||||
if (metadata_get_artist(mdata) == NULL && metadata_get_title(mdata) == NULL)
|
||||
if ((songInfo = getMetadataString(pezConfig->metadataFormat, mdata)) == NULL) {
|
||||
if (strlen(metadata_get_artist(mdata)) == 0 &&
|
||||
strlen(metadata_get_title(mdata)) == 0)
|
||||
songInfo = xstrdup(metadata_get_string(mdata));
|
||||
else
|
||||
songInfo = metadata_assemble_string(mdata);
|
||||
}
|
||||
|
||||
if (shout_metadata_add(shout_mdata, "song", songInfo) != SHOUTERR_SUCCESS) {
|
||||
/* Assume SHOUTERR_MALLOC */
|
||||
|
@ -46,6 +46,8 @@
|
||||
extern char *__progname;
|
||||
extern int vFlag;
|
||||
|
||||
static const char *blankString = "";
|
||||
|
||||
struct metadata {
|
||||
char *filename;
|
||||
char *string;
|
||||
@ -563,6 +565,9 @@ metadata_get_artist(metadata_t *md)
|
||||
abort();
|
||||
}
|
||||
|
||||
if (md->artist == NULL)
|
||||
return (blankString);
|
||||
else
|
||||
return (md->artist);
|
||||
}
|
||||
|
||||
@ -575,9 +580,28 @@ metadata_get_title(metadata_t *md)
|
||||
abort();
|
||||
}
|
||||
|
||||
if (md->title == NULL)
|
||||
return (blankString);
|
||||
else
|
||||
return (md->title);
|
||||
}
|
||||
|
||||
const char *
|
||||
metadata_get_filename(metadata_t *md)
|
||||
{
|
||||
if (md == NULL) {
|
||||
printf("%s: metadata_get_filename(): Internal error: Bad arguments\n",
|
||||
__progname);
|
||||
abort();
|
||||
}
|
||||
|
||||
if (md->filename == NULL)
|
||||
/* Should never happen: */
|
||||
return (blankString);
|
||||
else
|
||||
return (md->filename);
|
||||
}
|
||||
|
||||
char *
|
||||
metadata_assemble_string(metadata_t *md)
|
||||
{
|
||||
|
@ -75,23 +75,27 @@ int metadata_program_update(metadata_t *, enum metadata_request);
|
||||
/*
|
||||
* Returns a pointer to a metadata string ``artist - title'', or just
|
||||
* ``artist'' or ``title'' if one of the two is not available. If neither
|
||||
* are present, it usually returns the filename without the extension.
|
||||
* This function never returns NULL.
|
||||
* are present, it returns the filename without the extension. An empty string
|
||||
* is returned for metadata_program() handles that didn't supply any generic
|
||||
* information.
|
||||
*/
|
||||
const char * metadata_get_string(metadata_t *);
|
||||
|
||||
/*
|
||||
* Returns a pointer to the artist string, or NULL if the file did not
|
||||
* contain any artist information.
|
||||
* Returns a pointer to the artist string, which may be empty.
|
||||
*/
|
||||
const char * metadata_get_artist(metadata_t *);
|
||||
|
||||
/*
|
||||
* Returns a pointer to the title string, or NULL if the file did not
|
||||
* contain any title information.
|
||||
* Returns a pointer to the title string, which may be empty.
|
||||
*/
|
||||
const char * metadata_get_title(metadata_t *);
|
||||
|
||||
/*
|
||||
* Returns a pointer to the filename used in the metadata handle.
|
||||
*/
|
||||
const char * metadata_get_filename(metadata_t *);
|
||||
|
||||
/*
|
||||
* 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
|
||||
|
Loading…
Reference in New Issue
Block a user