[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