[xiph-commits] r12680 - in trunk/ezstream: . src
moritz at svn.xiph.org
moritz at svn.xiph.org
Thu Mar 8 06:39:05 PST 2007
Author: moritz
Date: 2007-03-08 06:39:00 -0800 (Thu, 08 Mar 2007)
New Revision: 12680
Added:
trunk/ezstream/src/metadata.c
trunk/ezstream/src/metadata.h
Modified:
trunk/ezstream/configure.in
trunk/ezstream/src/Makefile.am
trunk/ezstream/src/ezstream.c
Log:
Iterate towards optional TagLib support, as well as scripted metadata support.
This is just the first step and equivalent to current functionality.
Modified: trunk/ezstream/configure.in
===================================================================
--- trunk/ezstream/configure.in 2007-03-08 14:36:00 UTC (rev 12679)
+++ trunk/ezstream/configure.in 2007-03-08 14:39:00 UTC (rev 12680)
@@ -64,7 +64,7 @@
dnl USEFUL HEADERS
-AC_CHECK_HEADERS(sys/time.h paths.h signal.h)
+AC_CHECK_HEADERS(sys/time.h paths.h signal.h libgen.h)
dnl LIBRARY FUNCTIONS
Modified: trunk/ezstream/src/Makefile.am
===================================================================
--- trunk/ezstream/src/Makefile.am 2007-03-08 14:36:00 UTC (rev 12679)
+++ trunk/ezstream/src/Makefile.am 2007-03-08 14:39:00 UTC (rev 12680)
@@ -2,12 +2,14 @@
bin_PROGRAMS = ezstream
-ezstream_SOURCES = ezstream.c compat.c configfile.c playlist.c util.c
+ezstream_SOURCES = compat.c configfile.c ezstream.c metadata.c playlist.c \
+ util.c
ezstream_LDADD = @LIBOBJS@ @XIPH_LIBS@
AM_CFLAGS = @XIPH_CFLAGS@
AM_CPPFLAGS = @XIPH_CPPFLAGS@
-EXTRA_DIST = compat.h configfile.h getopt.h playlist.h strfctns.h util.h
+EXTRA_DIST = compat.h configfile.h getopt.h metadata.h playlist.h \
+ strfctns.h util.h
CLEANFILES = core *.core *~ .*~
Modified: trunk/ezstream/src/ezstream.c
===================================================================
--- trunk/ezstream/src/ezstream.c 2007-03-08 14:36:00 UTC (rev 12679)
+++ trunk/ezstream/src/ezstream.c 2007-03-08 14:39:00 UTC (rev 12680)
@@ -33,6 +33,10 @@
#include <ctype.h>
#include <errno.h>
#include <fcntl.h>
+#ifdef HAVE_LIBGEN_H
+# include <libgen.h>
+#endif
+#include <limits.h>
#ifdef HAVE_PATHS_H
# include <paths.h>
#endif
@@ -42,22 +46,21 @@
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
-#include <limits.h>
#ifdef WIN32
# include <io.h>
# include <windows.h>
-#else
-# include <libgen.h>
-# include <unistd.h>
#endif /* WIN32 */
+#ifdef HAVE_UNISTD_H
+# include <unistd.h>
+#endif
#include <shout/shout.h>
-#include <vorbis/vorbisfile.h>
#include "compat.h"
#include "configfile.h"
#ifndef HAVE_GETOPT
# include "getopt.h"
#endif
+#include "metadata.h"
#include "playlist.h"
#include "strfctns.h"
#include "util.h"
@@ -105,9 +108,8 @@
int urlParse(const char *, char **, int *, char **);
void replaceString(const char *, char *, size_t, const char *, const char *);
-void setMetadata(shout_t *, const char *);
char * buildCommandString(const char *, const char *, const char *);
-char * processMetadata(shout_t *, const char *, const char *);
+char * processMetadata(shout_t *, const char *);
FILE * openResource(shout_t *, const char *, int *, char **, int *);
int reconnectServer(shout_t *, int);
int sendStream(shout_t *, FILE *, const char *, int, void *);
@@ -214,17 +216,7 @@
strlcat(dest, p1, size);
}
-void
-setMetadata(shout_t *shout, const char *metadata)
-{
- shout_metadata_t *shoutMetadata = shout_metadata_new();
-
- shout_metadata_add(shoutMetadata, "song", metadata);
- shout_set_metadata(shout, shoutMetadata);
- shout_metadata_free(shoutMetadata);
-}
-
-char*
+char *
buildCommandString(const char *extension, const char *fileName,
const char *metadata)
{
@@ -293,154 +285,33 @@
}
char *
-processMetadata(shout_t *shout, const char *extension, const char *fileName)
+processMetadata(shout_t *shout, const char *fileName)
{
- FILE *filepstream = NULL;
char *songInfo = NULL;
- size_t songLen = 0;
- ID3Tag id3tag;
- shout_metadata_t *pmetadata = NULL;
+ shout_metadata_t *shout_mdata = NULL;
+ metadata_t *mdata = NULL;
- if ((filepstream = fopen(fileName, "rb")) == NULL) {
- printf("%s: processMetadata(): %s: %s\n",
- __progname, fileName, strerror(errno));
- return (xstrdup(blankString));
+ if ((mdata = metadata_file(fileName)) == NULL) {
+ songInfo = xstrdup(blankString);
+ return (songInfo);
}
- if (strcmp(extension, ".mp3") == 0) {
- /* Look for the ID3 tag */
- memset(&id3tag, '\000', sizeof(id3tag));
- fseek(filepstream, -128L, SEEK_END);
- fread(&id3tag, 1, 127, filepstream);
- if (strncmp(id3tag.tag, "TAG", strlen("TAG")) == 0) {
- char tempTrackName[31];
- char tempArtistName[31];
-
- snprintf(tempTrackName, sizeof(tempTrackName), "%s",
- id3tag.trackName);
- snprintf(tempArtistName, sizeof(tempArtistName), "%s",
- id3tag.artistName);
-
- if (strlen(tempTrackName) > 0 ||
- strlen(tempArtistName) > 0) {
- songLen = strlen(tempArtistName) +
- strlen(" - ") + strlen(tempTrackName)
- + 1;
- songInfo = xmalloc(songLen);
- strlcpy(songInfo, tempArtistName, songLen);
- if (strlen(songInfo) > 0 &&
- strlen(tempTrackName) > 0)
- strlcat(songInfo, " - ", songLen);
- strlcat(songInfo, tempTrackName, songLen);
- }
- }
- } else if (strcmp(extension, ".ogg") == 0) {
- OggVorbis_File vf;
- int ret;
-
- if ((ret = ov_open(filepstream, &vf, NULL, 0)) != 0) {
- switch (ret) {
- case OV_EREAD:
- printf("%s: No metadata support: %s: Media read error\n",
- __progname, fileName);
- break;
- case OV_ENOTVORBIS:
- printf("%s: No metadata support: %s: Invalid Vorbis bitstream\n",
- __progname, fileName);
- break;
- case OV_EVERSION:
- printf("%s: No metadata support: %s: Vorbis version mismatch\n",
- __progname, fileName);
- break;
- case OV_EBADHEADER:
- printf("%s: No metadata support: %s: Invalid Vorbis bitstream header\n",
- __progname, fileName);
- break;
- case OV_EFAULT:
- printf("%s: Fatal: Internal libvorbisfile fault\n",
- __progname);
- abort();
- default:
- printf("%s: No metadata support: %s: ov_read() returned unknown error\n",
- __progname, fileName);
- break;
- }
- } else {
- char **ptr = ov_comment(&vf, -1)->user_comments;
- char *artist = NULL;
- char *title = NULL;
-
- while(*ptr){
- if (artist == NULL &&
- strncasecmp(*ptr, "ARTIST", strlen("ARTIST")) == 0)
- artist = xstrdup(*ptr + strlen("ARTIST="));
- if (title == NULL &&
- strncasecmp(*ptr, "TITLE", strlen("TITLE")) == 0)
- title = xstrdup(*ptr + strlen("TITLE="));
- ++ptr;
- }
-
- if (artist != NULL || title != NULL) {
- songLen = 0;
- if (artist != NULL)
- songLen += strlen(artist);
- if (title != NULL)
- songLen += strlen(title);
- songLen += strlen(" - ") + 1;
- songInfo = xcalloc(1, songLen);
-
- if (artist != NULL)
- strlcpy(songInfo, artist, songLen);
- if (title != NULL) {
- if (artist != NULL)
- strlcat(songInfo, " - ", songLen);
- strlcat(songInfo, title, songLen);
- xfree(title);
- }
- if (artist != NULL)
- xfree(artist);
- }
-
- ov_clear(&vf);
- filepstream = NULL;
- }
+ if (!metadata_file_update(mdata)) {
+ metadata_free(mdata);
+ songInfo = xstrdup(blankString);
+ return (songInfo);
}
+ songInfo = xstrdup(metadata_get_string(mdata));
+ metadata_free(mdata);
- if (filepstream != NULL)
- fclose(filepstream);
-
- if (songInfo == NULL) {
- /*
- * If we didn't get any song info via tags or comments, then
- * let's just use the filename.
- */
- char *p1 = NULL;
- char *p2 = NULL;
- char *filename_copy = NULL;
-
- filename_copy = xstrdup(fileName);
- p2 = basename(filename_copy);
- if (p2 == NULL) {
- /* Assert that basename() cannot fail. */
- printf("%s: Internal error: basename() failed with '%s'\n",
- __progname, filename_copy);
- exit(1);
- }
- songInfo = xstrdup(p2);
- xfree(filename_copy);
- p1 = strrchr(songInfo, '.');
- if (p1 != NULL)
- *p1 = '\000';
- }
-
- if ((pmetadata = shout_metadata_new()) == NULL) {
+ if ((shout_mdata = shout_metadata_new()) == NULL) {
printf("%s: shout_metadata_new(): %s\n", __progname,
strerror(ENOMEM));
exit(1);
}
- shout_metadata_add(pmetadata, "song", songInfo);
- shout_set_metadata(shout, pmetadata);
- shout_metadata_free(pmetadata);
+ shout_metadata_add(shout_mdata, "song", songInfo);
+ shout_set_metadata(shout, shout_mdata);
+ shout_metadata_free(shout_mdata);
return (songInfo);
}
@@ -451,7 +322,7 @@
{
FILE *filep = NULL;
char extension[25];
- char *p1 = NULL;
+ char *p = NULL;
char *pMetadata = NULL;
char *pCommandString = NULL;
@@ -471,62 +342,65 @@
*isStdin = 0;
extension[0] = '\0';
- p1 = strrchr(fileName, '.');
- if (p1 != NULL)
- strlcpy(extension, p1, sizeof(extension));
- for (p1 = extension; *p1 != '\0'; p1++)
- *p1 = tolower((int)*p1);
- pMetadata = processMetadata(shout, extension, fileName);
+ p = strrchr(fileName, '.');
+ if (p != NULL)
+ strlcpy(extension, p, sizeof(extension));
+ for (p = extension; *p != '\0'; p++)
+ *p = tolower((int)*p);
+
+ if (strlen(extension) == 0) {
+ printf("%s: Error: Cannot determine file type of '%s'\n",
+ __progname, fileName);
+ return (filep);
+ }
+
+ pMetadata = processMetadata(shout, fileName);
if (metaCopy != NULL)
*metaCopy = xstrdup(pMetadata);
*popenFlag = 0;
if (pezConfig->reencode) {
- if (strlen(extension) > 0) {
- int stderr_fd = dup(fileno(stderr));
+ int stderr_fd = dup(fileno(stderr));
- pCommandString = buildCommandString(extension, fileName, pMetadata);
- if (vFlag > 1)
- printf("%s: Running command `%s`\n", __progname,
- pCommandString);
+ pCommandString = buildCommandString(extension, fileName, pMetadata);
+ if (vFlag > 1)
+ printf("%s: Running command `%s`\n", __progname,
+ pCommandString);
- if (qFlag) {
- int fd;
+ if (qFlag) {
+ int fd;
- if ((fd = open(_PATH_DEVNULL, O_RDWR, 0)) == -1) {
- printf("%s: Cannot open %s for redirecting STDERR output: %s\n",
- __progname, _PATH_DEVNULL, strerror(errno));
- exit(1);
- }
-
- dup2(fd, fileno(stderr));
- if (fd > 2)
- close(fd);
+ if ((fd = open(_PATH_DEVNULL, O_RDWR, 0)) == -1) {
+ printf("%s: Cannot open %s for redirecting STDERR output: %s\n",
+ __progname, _PATH_DEVNULL, strerror(errno));
+ exit(1);
}
- fflush(NULL);
- errno = 0;
- if ((filep = popen(pCommandString, "r")) == NULL) {
- printf("%s: popen(): Error while executing '%s'",
- __progname, pCommandString);
- /* popen() does not set errno reliably ... */
- if (errno)
- printf(": %s\n", strerror(errno));
- else
- printf("\n");
- } else {
- *popenFlag = 1;
+ dup2(fd, fileno(stderr));
+ if (fd > 2)
+ close(fd);
+ }
+
+ fflush(NULL);
+ errno = 0;
+ if ((filep = popen(pCommandString, "r")) == NULL) {
+ printf("%s: popen(): Error while executing '%s'",
+ __progname, pCommandString);
+ /* popen() does not set errno reliably ... */
+ if (errno)
+ printf(": %s\n", strerror(errno));
+ else
+ printf("\n");
+ } else {
+ *popenFlag = 1;
#ifdef WIN32
- _setmode(_fileno(filep), _O_BINARY );
+ _setmode(_fileno(filep), _O_BINARY );
#endif
- }
- xfree(pCommandString);
+ }
+ xfree(pCommandString);
- if (qFlag)
- dup2(stderr_fd, fileno(stderr));
- } else
- printf("%s: Error: Cannot determine file type of '%s'\n",
- __progname, fileName);
+ if (qFlag)
+ dup2(stderr_fd, fileno(stderr));
xfree(pMetadata);
return (filep);
Added: trunk/ezstream/src/metadata.c
===================================================================
--- trunk/ezstream/src/metadata.c 2007-03-08 14:36:00 UTC (rev 12679)
+++ trunk/ezstream/src/metadata.c 2007-03-08 14:39:00 UTC (rev 12680)
@@ -0,0 +1,457 @@
+/*
+ * Copyright (c) 2007 Moritz Grimm <gtgbr at gmx.net>
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#ifdef HAVE_CONFIG_H
+# include "config.h"
+#endif
+
+#ifdef HAVE_SYS_TYPES_H
+# include <sys/types.h>
+#endif
+#ifdef HAVE_SYS_STAT_H
+# include <sys/stat.h>
+#endif
+#include <ctype.h>
+#include <errno.h>
+#ifdef HAVE_LIBGEN_H
+# include <libgen.h>
+#endif
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include <vorbis/vorbisfile.h>
+
+#include "compat.h"
+#include "metadata.h"
+#include "strfctns.h"
+#include "util.h"
+
+extern char *__progname;
+
+struct metadata {
+ char *filename;
+ char *string;
+ char *artist;
+ char *title;
+ int program;
+};
+
+struct ID3Tag {
+ char tag[3];
+ char trackName[30];
+ char artistName[30];
+ char albumName[30];
+ char year[3];
+ char comment[30];
+ char genre;
+};
+
+metadata_t * metadata_create(const char *);
+void metadata_use_taglib(metadata_t *, FILE **);
+void metadata_use_self(metadata_t *, FILE **);
+void metadata_clean_md(metadata_t *);
+void metadata_get_extension(char *, size_t, const char *);
+char * metadata_get_name(const char *);
+void metadata_process_md(metadata_t *);
+
+metadata_t *
+metadata_create(const char *filename)
+{
+ metadata_t *md;
+
+ md = xcalloc(1, sizeof(metadata_t));
+ md->filename = xstrdup(filename);
+
+ return (md);
+}
+
+void
+metadata_use_taglib(metadata_t *md, FILE **filep)
+#ifdef HAVE_TAG_C
+{
+ TagLib_File *tf;
+ TagLib_Tag *tt;
+ char *str;
+
+ if (md == NULL || md->filename == NULL) {
+ printf("%s: metadata_use_taglib(): Internal error: Bad arguments\n",
+ __progname);
+ abort();
+ }
+
+ if (filep != NULL)
+ fclose(*filep);
+
+ metadata_clean_md(md);
+ taglib_set_string_management_enabled(0);
+
+ if (md->string != NULL)
+ xfree(md->string);
+
+ if ((tf = taglib_file_new(md->filename)) == NULL) {
+ md->string = metadata_get_name(md->filename);
+ return;
+ }
+ tt = taglib_file_tag(tf);
+
+ str = taglib_tag_artist(tt);
+ if (str != NULL) {
+ if (strlen(str) > 0)
+ md->artist = xstrdup(str);
+ xfree(str);
+ }
+
+ str = taglib_tag_title(tt);
+ if (str != NULL) {
+ if (strlen(str) > 0)
+ md->title = xstrdup(str);
+ xfree(str);
+ }
+
+ taglib_file_free(tf);
+}
+#else
+{
+ printf("%s: Internal error: metadata_use_taglib() called without TagLib support\n",
+ __progname);
+ abort();
+}
+#endif /* HAVE_TAG_C */
+
+void
+metadata_use_self(metadata_t *md, FILE **filep)
+#ifdef HAVE_TAG_C
+{
+ printf("%s: Internal error: metadata_use_self() called with TagLib support\n",
+ __progname);
+ abort();
+}
+#else
+{
+ char extension[25];
+ struct ID3Tag id3tag;
+
+ if (md == NULL || filep == NULL || *filep == NULL ||
+ md->filename == NULL) {
+ printf("%s: metadata_use_self(): Internal error: Bad arguments\n",
+ __progname);
+ abort();
+ }
+
+ metadata_clean_md(md);
+ metadata_get_extension(extension, sizeof(extension), md->filename);
+
+ if (strcmp(extension, ".mp3") == 0) {
+ memset(&id3tag, 0, sizeof(id3tag));
+ fseek(*filep, -128L, SEEK_END);
+ fread(&id3tag, 1, 127, *filep);
+ if (strncmp(id3tag.tag, "TAG", strlen("TAG")) == 0) {
+ if (strlen(id3tag.artistName) > 0)
+ md->artist = xstrdup(id3tag.artistName);
+ if (strlen(id3tag.trackName) > 0)
+ md->title = xstrdup(id3tag.trackName);
+ }
+ } else if (strcmp(extension, ".ogg") == 0) {
+ OggVorbis_File vf;
+ int ret;
+
+ if ((ret = ov_open(*filep, &vf, NULL, 0)) != 0) {
+ switch (ret) {
+ case OV_EREAD:
+ printf("%s: ov_open(): %s: Media read error\n",
+ __progname, md->filename);
+ break;
+ case OV_ENOTVORBIS:
+ printf("%s: ov_open(): %s: Invalid Vorbis bitstream\n",
+ __progname, md->filename);
+ break;
+ case OV_EVERSION:
+ printf("%s: ov_open(): %s: Vorbis version mismatch\n",
+ __progname, md->filename);
+ break;
+ case OV_EBADHEADER:
+ printf("%s: ov_open(): %s: Invalid Vorbis bitstream header\n",
+ __progname, md->filename);
+ break;
+ case OV_EFAULT:
+ printf("%s: Fatal: Internal libvorbisfile fault\n",
+ __progname);
+ abort();
+ default:
+ printf("%s: ov_open(): %s: ov_read() returned unknown error\n",
+ __progname, md->filename);
+ break;
+ }
+ } else {
+ char **ptr;
+
+ for (ptr = ov_comment(&vf, -1)->user_comments; *ptr != NULL; ptr++) {
+ if (md->artist == NULL &&
+ strncasecmp(*ptr, "ARTIST", strlen("ARTIST")) == 0) {
+ if (strlen(*ptr + strlen("ARTIST=")) > 0)
+ md->artist = xstrdup(*ptr + strlen("ARTIST="));
+ }
+ if (md->title == NULL &&
+ strncasecmp(*ptr, "TITLE", strlen("TITLE")) == 0) {
+ if (strlen(*ptr + strlen("TITLE=")) > 0)
+ md->title = xstrdup(*ptr + strlen("TITLE="));
+ }
+ }
+
+ ov_clear(&vf);
+ *filep = NULL;
+ }
+ }
+
+ if (*filep != NULL)
+ fclose(*filep);
+
+ if (md->artist == NULL && md->title == NULL)
+ md->string = metadata_get_name(md->filename);
+}
+#endif /* HAVE_TAG_C */
+
+void
+metadata_clean_md(metadata_t *md)
+{
+ if (md == NULL) {
+ printf("%s: Internal error: metadata_clean_md(): NULL argument\n",
+ __progname);
+ abort();
+ }
+
+ if (md->string != NULL)
+ xfree(md->string);
+ if (md->artist != NULL)
+ xfree(md->artist);
+ if (md->title != NULL)
+ xfree(md->title);
+}
+
+void
+metadata_get_extension(char *buf, size_t siz, const char *filename)
+{
+ char *p;
+
+ if (buf == NULL || siz == 0 || filename == NULL) {
+ printf("%s: metadata_get_extension(): Internal error: Bad arguments\n",
+ __progname);
+ abort();
+ }
+
+ if ((p = strrchr(filename, '.')) != NULL)
+ strlcpy(buf, p, siz);
+ else
+ buf[0] = '\0';
+ for (p = buf; *p != '\0'; p++)
+ *p = tolower((int)*p);
+}
+
+char *
+metadata_get_name(const char *file)
+{
+ char *filename = xstrdup(file);
+ char *p1, *p2, *name;
+
+ if (file == NULL) {
+ printf("%s: metadata_get_name(): Internal error: Bad arguments\n",
+ __progname);
+ abort();
+ }
+
+ if ((p1 = basename(filename)) == NULL) {
+ printf("%s: Internal error: basename() failed with '%s'\n",
+ __progname, filename);
+ exit(1);
+ }
+
+ if ((p2 = strrchr(p1, '.')) != NULL)
+ *p2 = '\0';
+
+ if (strlen(p1) == 0)
+ name = xstrdup("[unknown]");
+ else
+ name = xstrdup(p1);
+
+ xfree(filename);
+ return (name);
+}
+
+void
+metadata_process_md(metadata_t *md)
+{
+ size_t siz = 0;
+
+ if (md == NULL) {
+ printf("%s: metadata_process_md(): Internal error: Bad arguments\n",
+ __progname);
+ abort();
+ }
+
+ if (md->string != NULL)
+ return;
+
+ if (md->artist != NULL)
+ siz += strlen(md->artist);
+ if (md->title != NULL) {
+ if (siz > 0)
+ siz += strlen(" - ");
+ siz += strlen(md->title);
+ }
+ siz++;
+ md->string = xcalloc(1, siz);
+
+ if (md->artist != NULL)
+ strlcpy(md->string, md->artist, siz);
+ if (md->title != NULL) {
+ if (md->artist != NULL)
+ strlcat(md->string, " - ", siz);
+ strlcat(md->string, md->title, siz);
+ }
+}
+
+metadata_t *
+metadata_file(const char *filename)
+{
+ metadata_t *md;
+
+ if (filename == NULL || strlen(filename) == 0) {
+ printf("%s: metadata_file(): Internal error: Bad arguments\n",
+ __progname);
+ abort();
+ }
+
+ md = metadata_create(filename);
+ if (!metadata_file_update(md)) {
+ metadata_free(md);
+ return (NULL);
+ }
+
+ return (md);
+}
+
+metadata_t *
+metadata_program(const char *program)
+{
+ metadata_t *md;
+
+ if (program == NULL || strlen(program) == 0) {
+ printf("%s: metadata_program(): Internal error: Bad arguments\n",
+ __progname);
+ abort();
+ }
+
+ md = metadata_create(program);
+ md->program = 1;
+
+ return (md);
+}
+
+void
+metadata_free(metadata_t *md)
+{
+ if (md == NULL)
+ return;
+
+ if (md->filename != NULL)
+ xfree(md->filename);
+ metadata_clean_md(md);
+ xfree(md);
+}
+
+
+int
+metadata_file_update(metadata_t *md)
+{
+ FILE *filep;
+
+ if (md == NULL) {
+ printf("%s: metadata_file_update(): Internal error: NULL argument\n",
+ __progname);
+ abort();
+ }
+
+ if (md->program) {
+ printf("%s: metadata_file_update(): Internal error: Called with program handle\n",
+ __progname);
+ abort();
+ }
+
+ if ((filep = fopen(md->filename, "rb")) == NULL) {
+ printf("%s: %s: %s\n", __progname, md->filename, strerror(errno));
+ return (0);
+ }
+
+#ifdef HAVE_TAG_C
+ metadata_use_taglib(md, &filep);
+#else
+ metadata_use_self(md, &filep);
+#endif /* HAVE_TAG_C */
+
+ metadata_process_md(md);
+
+ return (1);
+}
+
+int
+metadata_program_update(metadata_t *md, enum metadata_request md_req)
+{
+ /* XXX not implemented */
+ return (0);
+}
+
+const char *
+metadata_get_string(metadata_t *md)
+{
+ if (md == NULL) {
+ printf("%s: metadata_get_string(): Internal error: Bad arguments\n",
+ __progname);
+ abort();
+ }
+
+ if (md->string == NULL) {
+ printf("%s: metadata_get_string(): Internal error: md->string cannot be NULL\n",
+ __progname);
+ abort();
+ }
+
+ return (md->string);
+}
+
+const char *
+metadata_get_artist(metadata_t *md)
+{
+ if (md == NULL) {
+ printf("%s: metadata_get_artist(): Internal error: Bad arguments\n",
+ __progname);
+ abort();
+ }
+
+ return (md->artist);
+}
+
+const char *
+metadata_get_title(metadata_t *md)
+{
+ if (md == NULL) {
+ printf("%s: metadata_get_title(): Internal error: Bad arguments\n",
+ __progname);
+ abort();
+ }
+
+ return (md->title);
+}
Added: trunk/ezstream/src/metadata.h
===================================================================
--- trunk/ezstream/src/metadata.h 2007-03-08 14:36:00 UTC (rev 12679)
+++ trunk/ezstream/src/metadata.h 2007-03-08 14:39:00 UTC (rev 12680)
@@ -0,0 +1,96 @@
+/*
+ * Copyright (c) 2007 Moritz Grimm <gtgbr at gmx.net>
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#ifndef __METADATA_H__
+#define __METADATA_H__
+
+#define METADATA_MAX 1023
+
+enum metadata_request {
+ METADATA_ALL = 0,
+ METADATA_STRING,
+ METADATA_ARTIST,
+ METADATA_TITLE
+};
+
+typedef struct metadata metadata_t;
+
+/*
+ * Read the metadata of a media file and return a new metadata handle on
+ * success, or NULL on failure. The returned handle is "branded" for reading
+ * metadata from media files.
+ */
+metadata_t * metadata_file(const char * /* filename */);
+
+/*
+ * Create a metadata handle that is "branded" for acquiring metadata from an
+ * external program. The handle is returned on success, or NULL on failure.
+ * The program is NOT YET being queried, use metadata_program_update() for
+ * that. Also, the program (or script) needs to follow these rules:
+ *
+ * - Print one line to standard output and exit.
+ * - Accept no command line parameter and return a complete metadata string
+ * (for metadata_get_string()). The program *should* always return
+ * something in this case (e.g. something based on the filename in case no
+ * metadata is available.) This string will default to "[unknown]"
+ * otherwise.
+ * - Accept the command line parameter "artist" and return only the artist
+ * metadata, or an empty string if no artist information is available.
+ * - Accept the command line parameter "title" and return only the song title
+ * metadata, or an empty string if no artist information is available.
+ * - Return at most METADATA_MAX characters, or the result will be truncated.
+ */
+metadata_t * metadata_program(const char * /* program name */);
+
+/*
+ * Free all memory used by a metadata handle that has been created with
+ * metadata_file() or metadata_program().
+ */
+void metadata_free(metadata_t *);
+
+/*
+ * Update/read the metadata for the given handle. Returns 1 on success, and 0
+ * on failure.
+ */
+int metadata_file_update(metadata_t *);
+
+/*
+ * Update/read the specified metadata for the given program-handle. Returns 1
+ * on success, and 0 on failure.
+ */
+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.
+ */
+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.
+ */
+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.
+ */
+const char * metadata_get_title(metadata_t *);
+
+#endif /* __METADATA_H__ */
More information about the commits
mailing list