From c8b0ef4529ae8553162e0b66d4aea01fa1741a4a Mon Sep 17 00:00:00 2001
From: Led <led@altlinux.org>
Date: Mon, 10 Nov 2008 03:54:14 +0200
Subject: [PATCH] 0.12.0rc2

---
 config.h.in                          |  3 +++
 configure                            | 23 +++++++++++-------
 configure.ac                         |  5 ++--
 src/audioOutput.c                    |  2 +-
 src/audioOutputs/audioOutput_alsa.c  | 15 +++++++-----
 src/audioOutputs/audioOutput_osx.c   |  4 ++--
 src/audioOutputs/audioOutput_shout.c |  4 ++--
 src/conf.c                           |  2 +-
 src/decode.c                         | 10 +++-----
 src/inputPlugins/mp3_plugin.c        | 15 +++++++++---
 src/interface.c                      |  2 +-
 src/log.c                            |  3 ---
 src/log.h                            |  7 +-----
 src/ls.c                             | 10 +-------
 src/main.c                           |  4 ++--
 src/path.c                           | 18 +++++++-------
 src/path.h                           | 11 ++++++++-
 src/player.c                         |  4 ++--
 src/playerData.c                     |  5 ++++
 src/playlist.c                       | 14 ++---------
 src/tag.c                            | 35 ++++++++++++++++------------
 src/volume.c                         |  2 +-
 22 files changed, 105 insertions(+), 93 deletions(-)

diff --git a/config.h.in b/config.h.in
index 6d7116acd..08931b87d 100644
--- a/config.h.in
+++ b/config.h.in
@@ -157,6 +157,9 @@
 /* Define to the version of this package. */
 #undef PACKAGE_VERSION
 
+/* The mpd protocol version */
+#undef PROTOCOL_VERSION
+
 /* The size of a `int', as computed by sizeof. */
 #undef SIZEOF_INT
 
diff --git a/configure b/configure
index 98698d5c7..4a40413ef 100755
--- a/configure
+++ b/configure
@@ -1,6 +1,6 @@
 #! /bin/sh
 # Guess values for system-dependent variables and create Makefiles.
-# Generated by GNU Autoconf 2.59 for mpd 0.12.0.
+# Generated by GNU Autoconf 2.59 for mpd 0.12.0rc2.
 #
 # Report bugs to <warren.dukes@gmail.com>.
 #
@@ -423,8 +423,8 @@ SHELL=${CONFIG_SHELL-/bin/sh}
 # Identity of this package.
 PACKAGE_NAME='mpd'
 PACKAGE_TARNAME='mpd'
-PACKAGE_VERSION='0.12.0'
-PACKAGE_STRING='mpd 0.12.0'
+PACKAGE_VERSION='0.12.0rc2'
+PACKAGE_STRING='mpd 0.12.0rc2'
 PACKAGE_BUGREPORT='warren.dukes@gmail.com'
 
 # Factoring default headers for most tests.
@@ -965,7 +965,7 @@ if test "$ac_init_help" = "long"; then
   # Omit some internal or obsolete options to make the list less imposing.
   # This message is too long to be a string in the A/UX 3.1 sh.
   cat <<_ACEOF
-\`configure' configures mpd 0.12.0 to adapt to many kinds of systems.
+\`configure' configures mpd 0.12.0rc2 to adapt to many kinds of systems.
 
 Usage: $0 [OPTION]... [VAR=VALUE]...
 
@@ -1031,7 +1031,7 @@ fi
 
 if test -n "$ac_init_help"; then
   case $ac_init_help in
-     short | recursive ) echo "Configuration of mpd 0.12.0:";;
+     short | recursive ) echo "Configuration of mpd 0.12.0rc2:";;
    esac
   cat <<\_ACEOF
 
@@ -1236,7 +1236,7 @@ fi
 test -n "$ac_init_help" && exit 0
 if $ac_init_version; then
   cat <<\_ACEOF
-mpd configure 0.12.0
+mpd configure 0.12.0rc2
 generated by GNU Autoconf 2.59
 
 Copyright (C) 2003 Free Software Foundation, Inc.
@@ -1250,7 +1250,7 @@ cat >&5 <<_ACEOF
 This file contains any messages produced by compilers while
 running configure, to aid debugging if configure makes a mistake.
 
-It was created by mpd $as_me 0.12.0, which was
+It was created by mpd $as_me 0.12.0rc2, which was
 generated by GNU Autoconf 2.59.  Invocation command line was
 
   $ $0 $@
@@ -18790,6 +18790,11 @@ fi
 
 
 
+cat >>confdefs.h <<\_ACEOF
+#define PROTOCOL_VERSION "0.12.0"
+_ACEOF
+
+
 MPD_LIBS=""
 MPD_CFLAGS=""
 case "$CC" in
@@ -27477,7 +27482,7 @@ _ASBOX
 } >&5
 cat >&5 <<_CSEOF
 
-This file was extended by mpd $as_me 0.12.0, which was
+This file was extended by mpd $as_me 0.12.0rc2, which was
 generated by GNU Autoconf 2.59.  Invocation command line was
 
   CONFIG_FILES    = $CONFIG_FILES
@@ -27540,7 +27545,7 @@ _ACEOF
 
 cat >>$CONFIG_STATUS <<_ACEOF
 ac_cs_version="\\
-mpd config.status 0.12.0
+mpd config.status 0.12.0rc2
 configured by $0, generated by GNU Autoconf 2.59,
   with options \\"`echo "$ac_configure_args" | sed 's/[\\""\`\$]/\\\\&/g'`\\"
 
diff --git a/configure.ac b/configure.ac
index a8b827850..1de0c7b9e 100644
--- a/configure.ac
+++ b/configure.ac
@@ -1,8 +1,8 @@
 dnl AC_INIT(src/main.c)
-dnl AM_INIT_AUTOMAKE(mpd, 0.12.0)
+dnl AM_INIT_AUTOMAKE(mpd, 0.12.0rc2)
 
 AC_PREREQ(2.58)
-AC_INIT(mpd, 0.12.0, warren.dukes@gmail.com)
+AC_INIT(mpd, 0.12.0rc2, warren.dukes@gmail.com)
 AM_INIT_AUTOMAKE($PACKAGE_NAME, $PACKAGE_VERSION)
 
 AC_SUBST(MPD_LIBS)
@@ -16,6 +16,7 @@ AC_PROG_LIBTOOL
 AC_PROG_MAKE_SET
 
 AM_CONFIG_HEADER(config.h)
+AC_DEFINE(PROTOCOL_VERSION, "0.12.0", [The mpd protocol version])
 
 MPD_LIBS=""
 MPD_CFLAGS=""
diff --git a/src/audioOutput.c b/src/audioOutput.c
index 358947695..60ae9b772 100644
--- a/src/audioOutput.c
+++ b/src/audioOutput.c
@@ -59,7 +59,7 @@ void finishAudioOutputPlugins(void)
 	bp = getBlockParam(param, name); \
 	if(force && bp == NULL) { \
 		ERROR("couldn't find parameter \"%s\" in audio output " \
-				"definition begining at %i\n", \
+				"definition beginning at %i\n", \
 				name, param->line); \
 		exit(EXIT_FAILURE); \
 	} \
diff --git a/src/audioOutputs/audioOutput_alsa.c b/src/audioOutputs/audioOutput_alsa.c
index c129e2d6e..9aefb4be8 100644
--- a/src/audioOutputs/audioOutput_alsa.c
+++ b/src/audioOutputs/audioOutput_alsa.c
@@ -140,8 +140,9 @@ static int alsa_openDevice(AudioOutput * audioOutput)
 	snd_pcm_uframes_t alsa_period_size;
 	int err;
 	const char *cmd = NULL;
-	unsigned int period_time;
 	int retry = MPD_ALSA_RETRY_NR;
+	unsigned int period_time, period_time_ro;
+	unsigned int buffer_time;
 
 	switch (audioFormat->bits) {
 	case 8:
@@ -175,6 +176,7 @@ static int alsa_openDevice(AudioOutput * audioOutput)
 	if (err < 0)
 		goto error;
 
+	period_time_ro = period_time = ad->period_time;
 configure_hw:
 	/* configure HW params */
 	snd_pcm_hw_params_alloca(&hwparams);
@@ -231,28 +233,29 @@ configure_hw:
 	}
 	audioFormat->sampleRate = sampleRate;
 
+	buffer_time = ad->buffer_time;
 	cmd = "snd_pcm_hw_params_set_buffer_time_near";
 	err = snd_pcm_hw_params_set_buffer_time_near(ad->pcmHandle, hwparams,
-						     &ad->buffer_time, NULL);
+						     &buffer_time, NULL);
 	if (err < 0)
 		goto error;
 
-	period_time = ad->period_time;
+	period_time = period_time_ro;
 	cmd = "snd_pcm_hw_params_set_period_time_near";
 	err = snd_pcm_hw_params_set_period_time_near(ad->pcmHandle, hwparams,
-						     &ad->period_time, NULL);
+						     &period_time, NULL);
 	if (err < 0)
 		goto error;
 
 	cmd = "snd_pcm_hw_params";
 	err = snd_pcm_hw_params(ad->pcmHandle, hwparams);
 	if (err == -EPIPE && --retry > 0) {
-		ad->period_time = period_time >> 1;
+		period_time_ro = period_time_ro >> 1;
 		goto configure_hw;
 	} else if (err < 0)
 		goto error;
 	if (retry != MPD_ALSA_RETRY_NR)
-		DEBUG("ALSA period_time set to %d\n", ad->period_time);
+		DEBUG("ALSA period_time set to %d\n", period_time);
 
 	cmd = "snd_pcm_hw_params_get_buffer_size";
 	err = snd_pcm_hw_params_get_buffer_size(hwparams, &alsa_buffer_size);
diff --git a/src/audioOutputs/audioOutput_osx.c b/src/audioOutputs/audioOutput_osx.c
index 6f03c7cf7..d386bcbfc 100644
--- a/src/audioOutputs/audioOutput_osx.c
+++ b/src/audioOutputs/audioOutput_osx.c
@@ -245,7 +245,7 @@ static int osx_openDevice(AudioOutput * audioOutput)
 
 	if (AudioUnitInitialize(od->au) != 0) {
 		CloseComponent(od->au);
-		ERROR("Unable to initialuze OS X audio unit\n");
+		ERROR("Unable to initialize OS X audio unit\n");
 		return -1;
 	}
 
@@ -257,7 +257,7 @@ static int osx_openDevice(AudioOutput * audioOutput)
 				 &callback, sizeof(callback)) != 0) {
 		AudioUnitUninitialize(od->au);
 		CloseComponent(od->au);
-		ERROR("unable to set callbak for OS X audio unit\n");
+		ERROR("unable to set callback for OS X audio unit\n");
 		return -1;
 	}
 
diff --git a/src/audioOutputs/audioOutput_shout.c b/src/audioOutputs/audioOutput_shout.c
index ab5a9b54c..5c268930a 100644
--- a/src/audioOutputs/audioOutput_shout.c
+++ b/src/audioOutputs/audioOutput_shout.c
@@ -423,7 +423,7 @@ static int initEncoder(ShoutData * sd)
 						sd->audioFormat->channels,
 						sd->audioFormat->sampleRate,
 						sd->quality * 0.1)) {
-			ERROR("problem seting up vorbis encoder for shout\n");
+			ERROR("problem setting up vorbis encoder for shout\n");
 			vorbis_info_clear(&(sd->vi));
 			return -1;
 		}
@@ -432,7 +432,7 @@ static int initEncoder(ShoutData * sd)
 					    sd->audioFormat->channels,
 					    sd->audioFormat->sampleRate, -1.0,
 					    sd->bitrate * 1000, -1.0)) {
-			ERROR("problem seting up vorbis encoder for shout\n");
+			ERROR("problem setting up vorbis encoder for shout\n");
 			vorbis_info_clear(&(sd->vi));
 			return -1;
 		}
diff --git a/src/conf.c b/src/conf.c
index 54cb560b4..03680de82 100644
--- a/src/conf.c
+++ b/src/conf.c
@@ -233,7 +233,7 @@ static ConfigParam *readConfigBlock(FILE * fp, int *count, char *string)
 		    0 == strcmp(array[1], CONF_BLOCK_END)) {
 			ERROR("improperly formatted config file at line %i:"
 			      " %s\n", *count, string);
-			ERROR("in block begining at line %i\n", ret->line);
+			ERROR("in block beginning at line %i\n", ret->line);
 			exit(EXIT_FAILURE);
 		}
 
diff --git a/src/decode.c b/src/decode.c
index c07da9907..158727f6f 100644
--- a/src/decode.c
+++ b/src/decode.c
@@ -260,15 +260,11 @@ static void decodeStart(PlayerControl * pc, OutputBuffer * cb,
 	InputStream inStream;
 	InputPlugin *plugin = NULL;
 	char *path;
-	char *relativePath;
 
-	if (isRemoteUrl(pc->utf8url)) {
+	if (isRemoteUrl(pc->utf8url))
 		path = utf8StrToLatin1Dup(pc->utf8url);
-	} else {
-		relativePath = utf8ToFsCharset(pc->utf8url);
-		path = strdup(rmp2amp(relativePath));
-		free(relativePath);
-	}
+	else
+		path = strdup(rmp2amp(utf8ToFsCharset(pc->utf8url)));
 
 	if (!path) {
 		dc->error = DECODE_ERROR_FILE;
diff --git a/src/inputPlugins/mp3_plugin.c b/src/inputPlugins/mp3_plugin.c
index 29a0c43d9..f2329d25a 100644
--- a/src/inputPlugins/mp3_plugin.c
+++ b/src/inputPlugins/mp3_plugin.c
@@ -138,6 +138,7 @@ typedef struct _mp3DecodeData {
 	int dropFramesAtEnd;
 	int dropSamplesAtStart;
 	int dropSamplesAtEnd;
+	int foundXing;
 	int foundFirstFrame;
 	int decodedFirstFrame;
 	int flush;
@@ -161,6 +162,7 @@ static void initMp3DecodeData(mp3DecodeData * data, InputStream * inStream)
 	data->dropFramesAtEnd = 0;
 	data->dropSamplesAtStart = 0;
 	data->dropSamplesAtEnd = 0;
+	data->foundXing = 0;
 	data->foundFirstFrame = 0;
 	data->decodedFirstFrame = 0;
 	data->flush = 1;
@@ -640,6 +642,7 @@ static int decodeFirstFrame(mp3DecodeData * data, DecoderControl * dc,
 	bitlen = data->stream.anc_bitlen;
 
 	if (parse_xing(&xing, &ptr, &bitlen)) {
+		data->foundXing = 1;
 		data->muteFrame = MUTEFRAME_SKIP;
 
 		if (parse_lame(&lame, &ptr, &bitlen)) {
@@ -737,9 +740,12 @@ static int mp3Read(mp3DecodeData * data, OutputBuffer * cb, DecoderControl * dc,
 		mad_timer_add(&data->timer, (data->frame).header.duration);
 		data->bitRate = (data->frame).header.bitrate;
 		if (data->currentFrame >= data->maxFrames) {
+			/* stop decoding, since Xing maxFrames is accurate */
+			if (data->foundXing) return DECODE_BREAK;
 			data->currentFrame = data->maxFrames - 1;
-		} else
+		} else {
 			data->highestFrame++;
+		}
 		data->frameOffset[data->currentFrame] = data->inStream->offset;
 		if (data->stream.this_frame != NULL) {
 			data->frameOffset[data->currentFrame] -=
@@ -749,8 +755,9 @@ static int mp3Read(mp3DecodeData * data, OutputBuffer * cb, DecoderControl * dc,
 			    data->stream.bufend - data->stream.buffer;
 		}
 		data->times[data->currentFrame] = data->timer;
-	} else
+	} else {
 		data->timer = data->times[data->currentFrame];
+	}
 	data->currentFrame++;
 	data->elapsedTime =
 	    ((float)mad_timer_count(data->timer, MAD_UNITS_MILLISECONDS)) /
@@ -815,7 +822,9 @@ static int mp3Read(mp3DecodeData * data, OutputBuffer * cb, DecoderControl * dc,
 			} else if (data->dropSamplesAtEnd &&
 			           (data->currentFrame == (data->maxFrames - data->dropFramesAtEnd))) {
 				samplesLeft--;
-				if (samplesLeft < data->dropSamplesAtEnd) break;
+				/* stop decoding, since samples were dropped */
+				if (samplesLeft < data->dropSamplesAtEnd)
+					return DECODE_BREAK;
 			}
 
 			sample = (mpd_sint16 *) data->outputPtr;
diff --git a/src/interface.c b/src/interface.c
index 99d891bee..0381404bf 100644
--- a/src/interface.c
+++ b/src/interface.c
@@ -42,7 +42,7 @@
 #include <errno.h>
 #include <signal.h>
 
-#define GREETING					"OK MPD " VERSION "\n"
+#define GREETING				"OK MPD " PROTOCOL_VERSION "\n"
 
 #define INTERFACE_MAX_BUFFER_LENGTH			(40960)
 #define INTERFACE_LIST_MODE_BEGIN			"command_list_begin"
diff --git a/src/log.c b/src/log.c
index 6d88ea575..3f05b4d07 100644
--- a/src/log.c
+++ b/src/log.c
@@ -188,10 +188,7 @@ mpd_printf void func(const char *fmt, ...) \
 log_func(ERROR, 0, stderr)
 log_func(LOG, 0, stdout)
 log_func(SECURE, LOG_LEVEL_SECURE, stdout)
-
-#ifndef NDEBUG
 log_func(DEBUG, LOG_LEVEL_DEBUG, stdout)
-#endif /* NDEBUG */
 
 #undef log_func
 
diff --git a/src/log.h b/src/log.h
index 0fb69ac7a..e0adf80fa 100644
--- a/src/log.h
+++ b/src/log.h
@@ -29,15 +29,10 @@
 #define LOG_LEVEL_SECURE	1
 #define LOG_LEVEL_DEBUG		2
 
-#ifndef NDEBUG
-  mpd_printf void DEBUG(const char *fmt, ...);
-#else
-  static inline void DEBUG(const char *fmt, ...) { }
-#endif
-
 mpd_printf void ERROR(const char *fmt, ...);
 mpd_printf void LOG(const char *fmt, ...);
 mpd_printf void SECURE(const char *fmt, ...);
+mpd_printf void DEBUG(const char *fmt, ...);
 mpd_printf void WARNING(const char *fmt, ...);
 mpd_printf void FATAL(const char *fmt, ...);
 
diff --git a/src/ls.c b/src/ls.c
index 376ebb058..427d01b43 100644
--- a/src/ls.c
+++ b/src/ls.c
@@ -118,7 +118,6 @@ int lsPlaylists(int fd, char *utf8path)
 	int suff;
 
 	if (actlen > MAXPATHLEN - 1 || (dir = opendir(actualPath)) == NULL) {
-		free(path);
 		return 0;
 	}
 
@@ -143,7 +142,6 @@ int lsPlaylists(int fd, char *utf8path)
 					dup[suff] = '\0';
 					if ((utf8 = fsCharsetToUtf8(dup))) {
 						insertInList(list, utf8, NULL);
-						free(utf8);
 					}
 				}
 			}
@@ -151,7 +149,6 @@ int lsPlaylists(int fd, char *utf8path)
 	}
 
 	closedir(dir);
-	free(path);
 
 	if (list) {
 		int i;
@@ -185,16 +182,11 @@ int myStat(char *utf8file, struct stat *st)
 {
 	char *file = utf8ToFsCharset(utf8file);
 	char *actualFile = file;
-	int ret;
 
 	if (actualFile[0] != '/')
 		actualFile = rmp2amp(file);
 
-	ret = stat(actualFile, st);
-
-	free(file);
-
-	return ret;
+	return stat(actualFile, st);
 }
 
 static int isFile(char *utf8file, time_t * mtime)
diff --git a/src/main.c b/src/main.c
index 43311b3a7..6c175fbd7 100644
--- a/src/main.c
+++ b/src/main.c
@@ -477,14 +477,13 @@ int main(int argc, char *argv[])
 	playerKill();
 	freeAllInterfaces();
 	closeAllListenSockets();
+	finishPlaylist();
 
 	start = clock();
 	closeMp3Directory();
 	DEBUG("closeMp3Directory took %f seconds\n", 
 	      ((float)(clock()-start))/CLOCKS_PER_SEC);
 
-	finishPlaylist();
-	freePlayerData();
 	finishNormalization();
 	finishAudioDriver();
 	finishAudioConfig();
@@ -495,6 +494,7 @@ int main(int argc, char *argv[])
 	finishInputPlugins();
 	cleanUpPidFile();
 	finishConf();
+	freePlayerData();
 
 	close_log_files();
 	return EXIT_SUCCESS;
diff --git a/src/path.c b/src/path.c
index 69c86391b..b05843514 100644
--- a/src/path.c
+++ b/src/path.c
@@ -41,18 +41,18 @@ const char *musicDir;
 static const char *playlistDir;
 static char *fsCharset = NULL;
 
-static char *pathConvCharset(char *to, char *from, char *str)
+static char *pathConvCharset(char *to, char *from, char *str, char *ret)
 {
-	if (setCharSetConversion(to, from) == 0) {
-		return convStrDup(str);
-	}
-
-	return NULL;
+	if (ret)
+		free(ret);
+	return setCharSetConversion(to, from) ? NULL : convStrDup(str);
 }
 
 char *fsCharsetToUtf8(char *str)
 {
-	char *ret = pathConvCharset("UTF-8", fsCharset, str);
+	static char *ret = NULL;
+
+	ret = pathConvCharset("UTF-8", fsCharset, str, ret);
 
 	if (ret && !validUtf8String(ret)) {
 		free(ret);
@@ -64,7 +64,9 @@ char *fsCharsetToUtf8(char *str)
 
 char *utf8ToFsCharset(char *str)
 {
-	char *ret = pathConvCharset(fsCharset, "UTF-8", str);
+	static char *ret = NULL;
+
+	ret = pathConvCharset(fsCharset, "UTF-8", str, ret);
 
 	if (!ret)
 		ret = strdup(str);
diff --git a/src/path.h b/src/path.h
index 222e145a5..e9fd36fa0 100644
--- a/src/path.h
+++ b/src/path.h
@@ -29,8 +29,17 @@ void initPaths();
 
 void finishPaths();
 
+/* utf8ToFsCharset() and fsCharsetToUtf8()
+ * Each returns a static pointer to a dynamically allocated buffer
+ * which means:
+ * - Do not manually free the return value of these functions, it'll be
+ *   automatically freed the next time it is called.
+ * - They are not reentrant, strdup the return value immediately if
+ *   you expect to call one of these functions again, but still need the
+ *   previous result.
+ * - The static pointer is unique to each function.
+ */
 char *utf8ToFsCharset(char *str);
-
 char *fsCharsetToUtf8(char *str);
 
 void setFsCharset(char *charset);
diff --git a/src/player.c b/src/player.c
index faa05a32a..c24424c44 100644
--- a/src/player.c
+++ b/src/player.c
@@ -124,8 +124,8 @@ int playerInit(void)
 
 		closeAllListenSockets();
 		freeAllInterfaces();
-		closeMp3Directory();
 		finishPlaylist();
+		closeMp3Directory();
 		finishPermissions();
 		finishCommands();
 		finishVolume();
@@ -307,7 +307,7 @@ char *getPlayerErrorStr(void)
 	switch (pc->error) {
 	case PLAYER_ERROR_FILENOTFOUND:
 		snprintf(error, errorlen,
-			 "file \"%s\" does not exist or is inaccesible",
+			 "file \"%s\" does not exist or is inaccessible",
 			 pc->erroredUrl);
 		break;
 	case PLAYER_ERROR_FILE:
diff --git a/src/playerData.c b/src/playerData.c
index df928acc4..3feb46e45 100644
--- a/src/playerData.c
+++ b/src/playerData.c
@@ -21,6 +21,7 @@
 #include "log.h"
 
 #include <sys/types.h>
+#include <sys/wait.h>
 #include <sys/ipc.h>
 #include <sys/shm.h>
 #include <stdio.h>
@@ -164,5 +165,9 @@ PlayerData *getPlayerData(void)
 
 void freePlayerData(void)
 {
+	/* We don't want to release this memory until we know our player and
+	 * decoder have exited.  Otherwise, their signal handlers will want to
+	 * access playerData_pd and we need to keep it available for them */
+	waitpid(-1, NULL, 0);
 	shmdt(playerData_pd);
 }
diff --git a/src/playlist.c b/src/playlist.c
index 359e3ac24..80c50f5b5 100644
--- a/src/playlist.c
+++ b/src/playlist.c
@@ -1272,8 +1272,6 @@ int deletePlaylist(int fd, char *utf8file)
 	strcat(rfile, ".");
 	strcat(rfile, PLAYLIST_FILE_SUFFIX);
 
-	free(file);
-
 	if ((actualFile = rpp2app(rfile)) && isPlaylist(actualFile))
 		free(rfile);
 	else {
@@ -1300,7 +1298,6 @@ int savePlaylist(int fd, char *utf8file)
 	char *file;
 	char *rfile;
 	char *actualFile;
-	char *url;
 
 	if (strstr(utf8file, "/")) {
 		commandError(fd, ACK_ERROR_ARG,
@@ -1318,8 +1315,6 @@ int savePlaylist(int fd, char *utf8file)
 	strcat(rfile, ".");
 	strcat(rfile, PLAYLIST_FILE_SUFFIX);
 
-	free(file);
-
 	actualFile = rpp2app(rfile);
 
 	free(rfile);
@@ -1343,10 +1338,8 @@ int savePlaylist(int fd, char *utf8file)
 				  rmp2amp(utf8ToFsCharset
 					  ((getSongUrl(playlist.songs[i])))));
 		} else {
-			url = utf8ToFsCharset(getSongUrl(playlist.songs[i]));
-			fprintf(fileP, "%s\n", url);
-			free(url);
-
+			fprintf(fileP, "%s\n",
+			        utf8ToFsCharset(getSongUrl(playlist.songs[i])));
 		}
 	}
 
@@ -1441,8 +1434,6 @@ static int PlaylistIterFunc(int fd, char *utf8file,
 	strcat(rfile, ".");
 	strcat(rfile, PLAYLIST_FILE_SUFFIX);
 
-	free(temp);
-
 	if ((actualFile = rpp2app(rfile)) && isPlaylist(actualFile))
 		free(rfile);
 	else {
@@ -1499,7 +1490,6 @@ static int PlaylistIterFunc(int fd, char *utf8file,
 				strcpy(s, temp);
 				IterFunc(fd, s, &erroredFile);
 			}
-			free(temp);
 		} else if (slength == MAXPATHLEN) {
 			s[slength] = '\0';
 			commandError(fd, ACK_ERROR_PLAYLIST_LOAD,
diff --git a/src/tag.c b/src/tag.c
index b4707d487..68fd2dbab 100644
--- a/src/tag.c
+++ b/src/tag.c
@@ -27,6 +27,7 @@
 #include "charConv.h"
 #include "tagTracker.h"
 #include "mpd_types.h"
+#include "gcc.h"
 
 #include <sys/stat.h>
 #include <stdlib.h>
@@ -132,15 +133,15 @@ void printMpdTag(int fd, MpdTag * tag)
 }
 
 #ifdef HAVE_ID3TAG
-MpdTag *getID3Info(struct id3_tag *tag, char *id, int type, MpdTag * mpdTag)
+static MpdTag *getID3Info(struct id3_tag *tag, char *id, int type, MpdTag * mpdTag)
 {
 	struct id3_frame const *frame;
 	id3_ucs4_t const *ucs4;
 	id3_utf8_t *utf8;
+	id3_latin1_t *isostr;
 	union id3_field const *field;
 	unsigned int nstrings;
 	int i;
-	char *isostr;
 	char *encoding;
 
 	frame = id3_tag_findframe(tag, id, 0);
@@ -158,20 +159,24 @@ MpdTag *getID3Info(struct id3_tag *tag, char *id, int type, MpdTag * mpdTag)
 		if (type == TAG_ITEM_GENRE)
 			ucs4 = id3_genre_name(ucs4);
 
-		utf8 = id3_ucs4_utf8duplicate(ucs4);
-		if (!utf8)
-			continue;
-
-		if (isId3v1(tag)) {
-			encoding = getConfigParamValue(CONF_ID3V1_ENCODING);
-			if (encoding) {
-				setCharSetConversion("ISO-8859-1", "UTF-8");
-				isostr = convStrDup((char *)utf8);
-				free(utf8);
-				setCharSetConversion("UTF-8", encoding);
-				utf8 = (id3_utf8_t *)convStrDup(isostr);
+		if (isId3v1(tag) &&
+		    (encoding = getConfigParamValue(CONF_ID3V1_ENCODING))) {
+			isostr = id3_ucs4_latin1duplicate(ucs4);
+			if (mpd_unlikely(!isostr))
+				continue;
+			setCharSetConversion("UTF-8", encoding);
+			utf8 = (id3_utf8_t *)convStrDup((char *)isostr);
+			if (!utf8) {
+				DEBUG("Unable to convert %s string to UTF-8: "
+				      "'%s'\n", encoding, isostr);
 				free(isostr);
+				continue;
 			}
+			free(isostr);
+		} else {
+			utf8 = id3_ucs4_utf8duplicate(ucs4);
+			if (mpd_unlikely(!utf8))
+				continue;
 		}
 
 		if (mpdTag == NULL)
@@ -414,7 +419,7 @@ MpdTag *apeDup(char *file)
 	if (readLEuint32(footer.version) != 2000)
 		goto fail;
 
-	/* find begining of ape tag */
+	/* find beginning of ape tag */
 	tagLen = readLEuint32(footer.length);
 	if (tagLen < sizeof(footer))
 		goto fail;
diff --git a/src/volume.c b/src/volume.c
index 52ea571a5..ea9d1dd71 100644
--- a/src/volume.c
+++ b/src/volume.c
@@ -233,7 +233,7 @@ static int prepAlsaMixer(char *card)
 
 	if ((err = snd_mixer_attach(volume_alsaMixerHandle, card)) < 0) {
 		closeAlsaMixer();
-		WARNING("problems problems attaching alsa mixer: %s\n",
+		WARNING("problems attaching alsa mixer: %s\n",
 			snd_strerror(err));
 		return -1;
 	}
-- 
2.24.1