From 7f121560fe9b28feed22ceb2080c2ec76400b17b Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Guillermo=20Bonveh=C3=AD?= <gbonvehi@gmail.com>
Date: Fri, 1 Feb 2019 12:35:26 -0300
Subject: [PATCH 01/18] Make cmus-update*.py use env python and fix pidgin with
 py3 (#857)

Changed shebang to use /usr/bin/env to get the python interpreter
updatepidgin: We simple remove the useless print without parenthesis.
---
 contrib/cmus-updategaim.py   | 2 +-
 contrib/cmus-updatepidgin.py | 9 ++-------
 2 files changed, 3 insertions(+), 8 deletions(-)

diff --git a/contrib/cmus-updategaim.py b/contrib/cmus-updategaim.py
index 515b4e28..fd013cce 100644
--- a/contrib/cmus-updategaim.py
+++ b/contrib/cmus-updategaim.py
@@ -1,4 +1,4 @@
-#!/usr/bin/python
+#!/usr/bin/env python
 # -*- coding: utf-8 -*-
 
 import dbus
diff --git a/contrib/cmus-updatepidgin.py b/contrib/cmus-updatepidgin.py
index 7d1c7ac8..84f990ab 100644
--- a/contrib/cmus-updatepidgin.py
+++ b/contrib/cmus-updatepidgin.py
@@ -1,4 +1,4 @@
-#!/usr/bin/python
+#!/usr/bin/env python
 # -*- coding: utf-8 -*-
 
 import dbus
@@ -9,11 +9,7 @@
 for n in range(1, len(sys.argv) - 1, 2):
 	args[sys.argv[n]] = sys.argv[n + 1]
 
-print args
-
-bus = dbus.SessionBus()
-
-obj = bus.get_object("im.pidgin.purple.PurpleService", "/im/pidgin/purple/PurpleObject")
+obj = dbus.SessionBus().get_object("im.pidgin.purple.PurpleService", "/im/pidgin/purple/PurpleObject")
 pidgin = dbus.Interface(obj, "im.pidgin.purple.PurpleInterface")
 
 current = pidgin.PurpleSavedstatusGetCurrent()
@@ -22,4 +18,3 @@
 pidgin.PurpleSavedstatusSetMessage(saved, "♪ %s - %s" % (args["artist"], args["title"]))
 pidgin.PurpleSavedstatusActivate(saved)
 
-

From 275df4b322bed30273f8b21d4a64878e3ca3ee05 Mon Sep 17 00:00:00 2001
From: Niko E <nefthy@users.noreply.github.com>
Date: Thu, 7 Feb 2019 15:39:55 +0100
Subject: [PATCH 02/18] Makes save -p consistent with documentation (#859)

Fixes #784
---
 command_mode.c | 5 ++++-
 1 file changed, 4 insertions(+), 1 deletion(-)

diff --git a/command_mode.c b/command_mode.c
index af54ef04..31e42839 100644
--- a/command_mode.c
+++ b/command_mode.c
@@ -212,7 +212,10 @@ void view_save(int view, char *arg, int to_stdout, int filtered, int extended)
 		do_save(lib_for_each_ti, arg, dest, save_ti);
 		break;
 	case PLAYLIST_VIEW:
-		pl_save();
+		if (arg)
+			pl_export_selected_pl(arg);
+		else
+			pl_save();
 		break;
 	case QUEUE_VIEW:
 		if (worker_has_job_by_type(JOB_TYPE_QUEUE))

From 4e12f154c663427a0d7f2c630e51efbfc147fc6f Mon Sep 17 00:00:00 2001
From: Johannes Lange <jolange@users.noreply.github.com>
Date: Fri, 8 Feb 2019 10:44:20 +0100
Subject: [PATCH 03/18] added "exiting" player status (#648)

---
 ui_curses.c | 113 +++++++++++++++++++++++++++++-----------------------
 1 file changed, 63 insertions(+), 50 deletions(-)

diff --git a/ui_curses.c b/ui_curses.c
index 4094d89f..b75f22e1 100644
--- a/ui_curses.c
+++ b/ui_curses.c
@@ -1794,67 +1794,74 @@ static void clear_error(void)
 
 /* screen updates }}} */
 
-static void spawn_status_program(void)
+static int fill_status_program_track_info_args(char **argv, int i, struct track_info *ti)
 {
-	enum player_status status;
+	/* returns first free argument index */
+
 	const char *stream_title = NULL;
-	char *argv[32];
-	int i;
+	if (player_info.status == PLAYER_STATUS_PLAYING && is_http_url(ti->filename))
+		stream_title = get_stream_title();
 
+	static const char *keys[] = {
+		"artist", "albumartist", "album", "discnumber", "tracknumber", "title",
+		"date",	"musicbrainz_trackid", NULL
+	};
+	int j;
+
+	if (is_http_url(ti->filename)) {
+		argv[i++] = xstrdup("url");
+	} else {
+		argv[i++] = xstrdup("file");
+	}
+	argv[i++] = xstrdup(ti->filename);
+
+	if (track_info_has_tag(ti)) {
+		for (j = 0; keys[j]; j++) {
+			const char *key = keys[j];
+			const char *val;
+
+			if (strcmp(key, "title") == 0 && stream_title)
+				/*
+				 * StreamTitle overrides radio station name
+				 */
+				val = stream_title;
+			else
+				val = keyvals_get_val(ti->comments, key);
+
+			if (val) {
+				argv[i++] = xstrdup(key);
+				argv[i++] = xstrdup(val);
+			}
+		}
+		if (ti->duration > 0) {
+			char buf[32];
+			snprintf(buf, sizeof(buf), "%d", ti->duration);
+			argv[i++] = xstrdup("duration");
+			argv[i++] = xstrdup(buf);
+		}
+	} else if (stream_title) {
+		argv[i++] = xstrdup("title");
+		argv[i++] = xstrdup(stream_title);
+	}
+
+	return i;
+}
+
+static void spawn_status_program_inner(const char *status_text, struct track_info *ti)
+{
 	if (status_display_program == NULL || status_display_program[0] == 0)
 		return;
 
-	status = player_info.status;
-	if (status == PLAYER_STATUS_PLAYING && player_info.ti && is_http_url(player_info.ti->filename))
-		stream_title = get_stream_title();
+	char *argv[32];
+	int i = 0;
 
-	i = 0;
 	argv[i++] = xstrdup(status_display_program);
 
 	argv[i++] = xstrdup("status");
-	argv[i++] = xstrdup(player_status_names[status]);
-	if (player_info.ti) {
-		static const char *keys[] = {
-			"artist", "albumartist", "album", "discnumber", "tracknumber", "title",
-			"date",	"musicbrainz_trackid", NULL
-		};
-		int j;
+	argv[i++] = xstrdup(status_text);
 
-		if (is_http_url(player_info.ti->filename)) {
-			argv[i++] = xstrdup("url");
-		} else {
-			argv[i++] = xstrdup("file");
-		}
-		argv[i++] = xstrdup(player_info.ti->filename);
-
-		if (track_info_has_tag(player_info.ti)) {
-			for (j = 0; keys[j]; j++) {
-				const char *key = keys[j];
-				const char *val;
-
-				if (strcmp(key, "title") == 0 && stream_title)
-					/*
-					 * StreamTitle overrides radio station name
-					 */
-					val = stream_title;
-				else
-					val = keyvals_get_val(player_info.ti->comments, key);
-
-				if (val) {
-					argv[i++] = xstrdup(key);
-					argv[i++] = xstrdup(val);
-				}
-			}
-			if (player_info.ti->duration > 0) {
-				char buf[32];
-				snprintf(buf, sizeof(buf), "%d", player_info.ti->duration);
-				argv[i++] = xstrdup("duration");
-				argv[i++] = xstrdup(buf);
-			}
-		} else if (stream_title) {
-			argv[i++] = xstrdup("title");
-			argv[i++] = xstrdup(stream_title);
-		}
+	if (ti) {
+		i = fill_status_program_track_info_args(argv, i, ti);
 	}
 	argv[i++] = NULL;
 
@@ -1864,6 +1871,11 @@ static void spawn_status_program(void)
 		free(argv[i]);
 }
 
+static void spawn_status_program(void)
+{
+	spawn_status_program_inner(player_status_names[player_info.status], player_info.ti);
+}
+
 static volatile sig_atomic_t ctrl_c_pressed = 0;
 
 static void sig_int(int sig)
@@ -2533,5 +2545,6 @@ int main(int argc, char *argv[])
 	init_all();
 	main_loop();
 	exit_all();
+	spawn_status_program_inner("exiting", NULL);
 	return 0;
 }

From 0ad71e833a04b0113622e1112c60f4b8a09ad2e6 Mon Sep 17 00:00:00 2001
From: Niko E <nefthy@users.noreply.github.com>
Date: Fri, 8 Feb 2019 14:48:06 +0100
Subject: [PATCH 04/18] Fixes various compiler warning (#862)

---
 format_print.c | 2 +-
 input.c        | 2 +-
 output.c       | 2 +-
 utils.h        | 8 ++++++--
 4 files changed, 9 insertions(+), 5 deletions(-)

diff --git a/format_print.c b/format_print.c
index 883eae5d..0fee9841 100644
--- a/format_print.c
+++ b/format_print.c
@@ -185,7 +185,7 @@ static void print_str(const char *src)
 
 			if (ws_len < 0) {
 				int w, c = -ws_len;
-				uchar u;
+				uchar u = 0;
 
 				while (c > 0) {
 					u = u_get_char(src, &s);
diff --git a/input.c b/input.c
index e544e17e..a0ac4267 100644
--- a/input.c
+++ b/input.c
@@ -504,7 +504,7 @@ void ip_load_plugins(void)
 
 	ip_wrlock();
 	while ((d = (struct dirent *) readdir(dir)) != NULL) {
-		char filename[256];
+		char filename[512];
 		struct ip *ip;
 		void *so;
 		char *ext;
diff --git a/output.c b/output.c
index 56f9d86f..a080dc2a 100644
--- a/output.c
+++ b/output.c
@@ -91,7 +91,7 @@ void op_load_plugins(void)
 		return;
 	}
 	while ((d = (struct dirent *) readdir(dir)) != NULL) {
-		char filename[256];
+		char filename[512];
 		struct output_plugin *plug;
 		void *so, *symptr;
 		char *ext;
diff --git a/utils.h b/utils.h
index 36afc0ac..5ab11916 100644
--- a/utils.h
+++ b/utils.h
@@ -321,14 +321,18 @@ static inline void init_pipes(int *out, int *in)
 static inline void notify_via_pipe(int pipe)
 {
 	char buf = 0;
-	write(pipe, &buf, 1);
+	if (write(pipe, &buf, 1) != 1) {
+		d_print("write to pipe failed. errno = %d\n", errno);
+	}
 }
 
 static inline void clear_pipe(int pipe, size_t bytes)
 {
 	char buf[128];
 	size_t bytes_to_read = min_u(sizeof(buf), bytes);
-	read(pipe, buf, bytes_to_read);
+	if (read(pipe, buf, bytes_to_read) < 0) {
+		d_print("read from pipe failed. errno = %d\n", errno);
+	}
 }
 
 static inline ssize_t strscpy(char *dst, const char *src, size_t size)

From f798dbaf249189e35b3c82c7e126bd6f2d15426d Mon Sep 17 00:00:00 2001
From: Patrick G <geek1011@outlook.com>
Date: Mon, 11 Feb 2019 03:07:53 -0500
Subject: [PATCH 05/18] Add *.lo to clean in Makefile (#864)

Without this, convert.lo doesn't get removed when running make clean.
---
 Makefile | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/Makefile b/Makefile
index 7e447ccf..7874b84a 100644
--- a/Makefile
+++ b/Makefile
@@ -264,7 +264,7 @@ quiet_cmd_ttman = MAN    $@
 
 data		= $(wildcard data/*)
 
-clean		+= *.o ip/*.lo op/*.lo ip/*.so op/*.so cmus libcmus.a cmus.def cmus.base cmus.exp cmus-remote Doc/*.o Doc/ttman Doc/*.1 Doc/*.7 .install.log
+clean		+= *.o ip/*.lo op/*.lo ip/*.so op/*.so *.lo cmus libcmus.a cmus.def cmus.base cmus.exp cmus-remote Doc/*.o Doc/ttman Doc/*.1 Doc/*.7 .install.log
 distclean	+= .version config.mk config/*.h tags
 
 main: cmus cmus-remote

From 9877eb02381fd4c57059f9c77be03127c28d8f88 Mon Sep 17 00:00:00 2001
From: Niko E <nefthy@users.noreply.github.com>
Date: Mon, 11 Feb 2019 09:09:21 +0100
Subject: [PATCH 06/18] Fixes ffmpeg deprecations (#861)

- av_register_all is no longer needed since 4.0
- AVStream::codec is deprecated since 3.1
- avcodec_decode_audio4 is deprecated since 3.1
---
 ip/ffmpeg.c | 42 ++++++++++++++++++++++++++++++++++++++++++
 1 file changed, 42 insertions(+)

diff --git a/ip/ffmpeg.c b/ip/ffmpeg.c
index eaad5c4f..418a37f8 100644
--- a/ip/ffmpeg.c
+++ b/ip/ffmpeg.c
@@ -128,9 +128,11 @@ static void ffmpeg_init(void)
 
 	av_log_set_level(AV_LOG_QUIET);
 
+#if LIBAVCODEC_VERSION_INT < AV_VERSION_INT(58, 18, 100)
 	/* We could register decoders explicitly to save memory, but we have to
 	 * be careful about compatibility. */
 	av_register_all();
+#endif
 }
 
 static int ffmpeg_open(struct input_plugin_data *ip_data)
@@ -143,6 +145,9 @@ static int ffmpeg_open(struct input_plugin_data *ip_data)
 	AVCodec *codec;
 	AVCodecContext *cc = NULL;
 	AVFormatContext *ic = NULL;
+#if LIBAVCODEC_VERSION_INT >= AV_VERSION_INT(57, 48, 101)
+	AVCodecParameters *cp = NULL;
+#endif
 	SwrContext *swr = NULL;
 
 	ffmpeg_init();
@@ -162,11 +167,20 @@ static int ffmpeg_open(struct input_plugin_data *ip_data)
 		}
 
 		for (i = 0; i < ic->nb_streams; i++) {
+
+#if LIBAVCODEC_VERSION_INT >= AV_VERSION_INT(57, 48, 101)
+			cp = ic->streams[i]->codecpar;
+			if (cp->codec_type == AVMEDIA_TYPE_AUDIO) {
+				stream_index = i;
+				break;
+			}
+#else
 			cc = ic->streams[i]->codec;
 			if (cc->codec_type == AVMEDIA_TYPE_AUDIO) {
 				stream_index = i;
 				break;
 			}
+#endif
 		}
 
 		if (stream_index == -1) {
@@ -175,7 +189,13 @@ static int ffmpeg_open(struct input_plugin_data *ip_data)
 			break;
 		}
 
+#if LIBAVCODEC_VERSION_INT >= AV_VERSION_INT(57, 48, 101)
+		codec = avcodec_find_decoder(cp->codec_id);
+		cc = avcodec_alloc_context3(codec);
+		avcodec_parameters_to_context(cc, cp);
+#else
 		codec = avcodec_find_decoder(cc->codec_id);
+#endif
 		if (!codec) {
 			d_print("codec not found: %d, %s\n", cc->codec_id, avcodec_get_name(cc->codec_id));
 			err = -IP_ERROR_UNSUPPORTED_FILE_TYPE;
@@ -196,6 +216,9 @@ static int ffmpeg_open(struct input_plugin_data *ip_data)
 
 	if (err < 0) {
 		/* Clean up.  cc is never opened at this point.  (See above assumption.) */
+#if LIBAVCODEC_VERSION_INT >= AV_VERSION_INT(57, 48, 101)
+		avcodec_free_context(&cc);
+#endif
 		avformat_close_input(&ic);
 		return err;
 	}
@@ -207,6 +230,9 @@ static int ffmpeg_open(struct input_plugin_data *ip_data)
 	priv->input = ffmpeg_input_create();
 	if (priv->input == NULL) {
 		avcodec_close(cc);
+#if LIBAVCODEC_VERSION_INT >= AV_VERSION_INT(57, 48, 101)
+		avcodec_free_context(&cc);
+#endif
 		avformat_close_input(&ic);
 		free(priv);
 		return -IP_ERROR_INTERNAL;
@@ -252,6 +278,9 @@ static int ffmpeg_close(struct input_plugin_data *ip_data)
 	struct ffmpeg_private *priv = ip_data->private;
 
 	avcodec_close(priv->codec_context);
+#if LIBAVCODEC_VERSION_INT >= AV_VERSION_INT(57, 48, 101)
+	avcodec_free_context(&priv->codec_context);
+#endif
 	avformat_close_input(&priv->input_context);
 	swr_free(&priv->swr);
 	ffmpeg_input_free(priv->input);
@@ -305,7 +334,20 @@ static int ffmpeg_fill_buffer(AVFormatContext *ic, AVCodecContext *cc, struct ff
 			AVPacket avpkt;
 			av_new_packet(&avpkt, input->curr_pkt_size);
 			memcpy(avpkt.data, input->curr_pkt_buf, input->curr_pkt_size);
+#if LIBAVCODEC_VERSION_INT >= AV_VERSION_INT(57, 48, 101)
+			if (avcodec_send_packet(cc, &avpkt) == 0) {
+				got_frame = !avcodec_receive_frame(cc, frame);
+				if (got_frame)
+					len = input->curr_pkt_size;
+				else
+					len = 0;
+			} else {
+				got_frame = 0;
+				len = 0;
+			}
+#else
 			len = avcodec_decode_audio4(cc, frame, &got_frame, &avpkt);
+#endif
 #if LIBAVCODEC_VERSION_MAJOR >= 56
 			av_packet_unref(&avpkt);
 #else

From 9a0723f7a90dc7de0898be87963d5105a999aa6c Mon Sep 17 00:00:00 2001
From: tomty89 <tom.ty89@gmail.com>
Date: Mon, 11 Feb 2019 23:31:29 +0800
Subject: [PATCH 07/18] Avoid -I$(pwd) (#820)

---
 configure         |  2 +-
 ip/aac.c          | 12 ++++++------
 ip/aac.h          |  2 +-
 ip/bass.c         | 10 +++++-----
 ip/cdio.c         | 22 +++++++++++-----------
 ip/cue.c          | 16 ++++++++--------
 ip/ffmpeg.c       | 12 ++++++------
 ip/flac.c         | 10 +++++-----
 ip/mad.c          | 16 ++++++++--------
 ip/mikmod.c       |  8 ++++----
 ip/modplug.c      | 10 +++++-----
 ip/mp4.c          | 14 +++++++-------
 ip/mpc.c          | 14 +++++++-------
 ip/nomad.c        |  8 ++++----
 ip/opus.c         | 10 +++++-----
 ip/vorbis.c       | 12 ++++++------
 ip/vtx.c          | 10 +++++-----
 ip/wav.c          | 12 ++++++------
 ip/wavpack.c      | 16 ++++++++--------
 op/alsa.c         | 10 +++++-----
 op/ao.c           | 10 +++++-----
 op/arts.c         |  6 +++---
 op/coreaudio.c    | 12 ++++++------
 op/jack.c         | 12 ++++++------
 op/mixer_alsa.c   |  8 ++++----
 op/mixer_oss.c    | 10 +++++-----
 op/mixer_sun.c    | 10 +++++-----
 op/oss.c          | 10 +++++-----
 op/pulse.c        | 10 +++++-----
 op/roar.c         | 12 ++++++------
 op/sndio.c        |  8 ++++----
 op/sun.c          |  6 +++---
 op/waveout.c      | 10 +++++-----
 scripts/checks.sh |  2 +-
 34 files changed, 176 insertions(+), 176 deletions(-)

diff --git a/configure b/configure
index e76acdd5..1f46c30a 100755
--- a/configure
+++ b/configure
@@ -447,7 +447,7 @@ check_ffmpeg()
 	topdir=`dirname "$0"`
 	ffmpeg_code=`cat "$topdir"/ip/ffmpeg.c | sed 's/\\\n//g'`
 	msg_checking "for successful build of ffmpeg.c"
-	if try_compile_link "$ffmpeg_code" $cflags $libs
+	if try_compile_link "$ffmpeg_code" $cflags -I$topdir/ip $libs
 	then
 		msg_result yes
 		return 0
diff --git a/ip/aac.c b/ip/aac.c
index d71527d0..76832eea 100644
--- a/ip/aac.c
+++ b/ip/aac.c
@@ -16,12 +16,12 @@
  * along with this program; if not, see <http://www.gnu.org/licenses/>.
  */
 
-#include "ip.h"
-#include "xmalloc.h"
-#include "debug.h"
-#include "id3.h"
-#include "comment.h"
-#include "read_wrapper.h"
+#include "../ip.h"
+#include "../xmalloc.h"
+#include "../debug.h"
+#include "../id3.h"
+#include "../comment.h"
+#include "../read_wrapper.h"
 #include "aac.h"
 
 #include <neaacdec.h>
diff --git a/ip/aac.h b/ip/aac.h
index 9430de65..7bd54bae 100644
--- a/ip/aac.h
+++ b/ip/aac.h
@@ -19,7 +19,7 @@
 #ifndef CMUS_AAC_H
 #define CMUS_AAC_H
 
-#include "channelmap.h"
+#include "../channelmap.h"
 #include <neaacdec.h>
 
 static inline channel_position_t channel_position_aac(unsigned char c)
diff --git a/ip/bass.c b/ip/bass.c
index 5adff64c..f9ecaff2 100644
--- a/ip/bass.c
+++ b/ip/bass.c
@@ -16,11 +16,11 @@
  * along with this program; if not, see <http://www.gnu.org/licenses/>.
  */
 
-#include "ip.h"
-#include "xmalloc.h"
-#include "comment.h"
-#include "bass.h"
-#include "uchar.h"
+#include "../ip.h"
+#include "../xmalloc.h"
+#include "../comment.h"
+#include "../bass.h"
+#include "../uchar.h"
 
 #define BITS (16)
 #define FREQ (44100)
diff --git a/ip/cdio.c b/ip/cdio.c
index 8a166858..134948b4 100644
--- a/ip/cdio.c
+++ b/ip/cdio.c
@@ -18,14 +18,14 @@
  * along with this program; if not, see <http://www.gnu.org/licenses/>.
  */
 
-#include "ip.h"
-#include "file.h"
-#include "xmalloc.h"
-#include "debug.h"
-#include "utils.h"
-#include "options.h"
-#include "comment.h"
-#include "discid.h"
+#include "../ip.h"
+#include "../file.h"
+#include "../xmalloc.h"
+#include "../debug.h"
+#include "../utils.h"
+#include "../options.h"
+#include "../comment.h"
+#include "../discid.h"
 
 #include <cdio/cdio.h>
 #include <cdio/logging.h>
@@ -45,12 +45,12 @@
 #undef HAVE_CDDB
 
 #ifdef HAVE_CONFIG
-#include "config/cdio.h"
+#include "../config/cdio.h"
 #endif
 
 #ifdef HAVE_CDDB
-#include "http.h"
-#include "xstrjoin.h"
+#include "../http.h"
+#include "../xstrjoin.h"
 #include <cddb/cddb.h>
 #endif
 
diff --git a/ip/cue.c b/ip/cue.c
index 93991c99..e6217fea 100644
--- a/ip/cue.c
+++ b/ip/cue.c
@@ -16,14 +16,14 @@
  * along with this program.  If not, see <http://www.gnu.org/licenses/>.
  */
 
-#include "ip.h"
-#include "debug.h"
-#include "input.h"
-#include "utils.h"
-#include "comment.h"
-#include "xmalloc.h"
-#include "cue_utils.h"
-#include "cue.h"
+#include "../ip.h"
+#include "../debug.h"
+#include "../input.h"
+#include "../utils.h"
+#include "../comment.h"
+#include "../xmalloc.h"
+#include "../cue_utils.h"
+#include "../cue.h"
 
 #include <stdio.h>
 #include <fcntl.h>
diff --git a/ip/ffmpeg.c b/ip/ffmpeg.c
index 418a37f8..04b916cc 100644
--- a/ip/ffmpeg.c
+++ b/ip/ffmpeg.c
@@ -16,13 +16,13 @@
  * along with this program; if not, see <http://www.gnu.org/licenses/>.
  */
 
-#include "ip.h"
-#include "xmalloc.h"
-#include "debug.h"
-#include "utils.h"
-#include "comment.h"
+#include "../ip.h"
+#include "../xmalloc.h"
+#include "../debug.h"
+#include "../utils.h"
+#include "../comment.h"
 #ifdef HAVE_CONFIG
-#include "config/ffmpeg.h"
+#include "../config/ffmpeg.h"
 #endif
 
 #include <stdio.h>
diff --git a/ip/flac.c b/ip/flac.c
index 90a97b6f..0153d561 100644
--- a/ip/flac.c
+++ b/ip/flac.c
@@ -16,11 +16,11 @@
  * along with this program; if not, see <http://www.gnu.org/licenses/>.
  */
 
-#include "ip.h"
-#include "comment.h"
-#include "xmalloc.h"
-#include "debug.h"
-#include "utils.h"
+#include "../ip.h"
+#include "../comment.h"
+#include "../xmalloc.h"
+#include "../debug.h"
+#include "../utils.h"
 
 #include <FLAC/export.h>
 #include <FLAC/stream_decoder.h>
diff --git a/ip/mad.c b/ip/mad.c
index b7b92ae5..0aca0743 100644
--- a/ip/mad.c
+++ b/ip/mad.c
@@ -16,15 +16,15 @@
  * along with this program; if not, see <http://www.gnu.org/licenses/>.
  */
 
-#include "ip.h"
+#include "../ip.h"
 #include "nomad.h"
-#include "id3.h"
-#include "ape.h"
-#include "xmalloc.h"
-#include "read_wrapper.h"
-#include "debug.h"
-#include "utils.h"
-#include "comment.h"
+#include "../id3.h"
+#include "../ape.h"
+#include "../xmalloc.h"
+#include "../read_wrapper.h"
+#include "../debug.h"
+#include "../utils.h"
+#include "../comment.h"
 
 #include <stdio.h>
 #include <math.h>
diff --git a/ip/mikmod.c b/ip/mikmod.c
index 4ff44791..e4ffa7a8 100644
--- a/ip/mikmod.c
+++ b/ip/mikmod.c
@@ -19,11 +19,11 @@
  * along with this program; if not, see <http://www.gnu.org/licenses/>.
  */
 
-#include "ip.h"
-#include "xmalloc.h"
+#include "../ip.h"
+#include "../xmalloc.h"
 #include <mikmod.h>
-#include "debug.h"
-#include "comment.h"
+#include "../debug.h"
+#include "../comment.h"
 
 struct mik_private {
 	MODULE *file;
diff --git a/ip/modplug.c b/ip/modplug.c
index be0bf31e..77782ef0 100644
--- a/ip/modplug.c
+++ b/ip/modplug.c
@@ -16,12 +16,12 @@
  * along with this program; if not, see <http://www.gnu.org/licenses/>.
  */
 
-#include "ip.h"
-#include "file.h"
-#include "xmalloc.h"
-#include "comment.h"
+#include "../ip.h"
+#include "../file.h"
+#include "../xmalloc.h"
+#include "../comment.h"
 #ifdef HAVE_CONFIG
-#include "config/modplug.h"
+#include "../config/modplug.h"
 #endif
 
 #include <libmodplug/modplug.h>
diff --git a/ip/mp4.c b/ip/mp4.c
index d25a24b6..475e2fa3 100644
--- a/ip/mp4.c
+++ b/ip/mp4.c
@@ -16,15 +16,15 @@
  * along with this program; if not, see <http://www.gnu.org/licenses/>.
  */
 
-#include "ip.h"
-#include "xmalloc.h"
-#include "debug.h"
-#include "id3.h"
-#include "file.h"
+#include "../ip.h"
+#include "../xmalloc.h"
+#include "../debug.h"
+#include "../id3.h"
+#include "../file.h"
 #ifdef HAVE_CONFIG
-#include "config/mp4.h"
+#include "../config/mp4.h"
 #endif
-#include "comment.h"
+#include "../comment.h"
 #include "aac.h"
 
 #if USE_MPEG4IP
diff --git a/ip/mpc.c b/ip/mpc.c
index 77361c4a..9a3ebaeb 100644
--- a/ip/mpc.c
+++ b/ip/mpc.c
@@ -18,15 +18,15 @@
  * along with this program; if not, see <http://www.gnu.org/licenses/>.
  */
 
-#include "ip.h"
-#include "ape.h"
-#include "comment.h"
-#include "file.h"
-#include "xmalloc.h"
-#include "read_wrapper.h"
+#include "../ip.h"
+#include "../ape.h"
+#include "../comment.h"
+#include "../file.h"
+#include "../xmalloc.h"
+#include "../read_wrapper.h"
 
 #ifdef HAVE_CONFIG
-#include "config/mpc.h"
+#include "../config/mpc.h"
 #endif
 
 #if MPC_SV8
diff --git a/ip/nomad.c b/ip/nomad.c
index f284d646..089cca2d 100644
--- a/ip/nomad.c
+++ b/ip/nomad.c
@@ -26,10 +26,10 @@
  */
 
 #include "nomad.h"
-#include "id3.h"
-#include "xmalloc.h"
-#include "debug.h"
-#include "misc.h"
+#include "../id3.h"
+#include "../xmalloc.h"
+#include "../debug.h"
+#include "../misc.h"
 
 #include <mad.h>
 #include <stdio.h>
diff --git a/ip/opus.c b/ip/opus.c
index 4216531b..4cdefd55 100644
--- a/ip/opus.c
+++ b/ip/opus.c
@@ -16,11 +16,11 @@
  * along with this program; if not, see <http://www.gnu.org/licenses/>.
  */
 
-#include "ip.h"
-#include "xmalloc.h"
-#include "read_wrapper.h"
-#include "debug.h"
-#include "comment.h"
+#include "../ip.h"
+#include "../xmalloc.h"
+#include "../read_wrapper.h"
+#include "../debug.h"
+#include "../comment.h"
 
 #include <opusfile.h>
 
diff --git a/ip/vorbis.c b/ip/vorbis.c
index e78e4059..ef5b5217 100644
--- a/ip/vorbis.c
+++ b/ip/vorbis.c
@@ -16,14 +16,14 @@
  * along with this program; if not, see <http://www.gnu.org/licenses/>.
  */
 
-#include "ip.h"
-#include "xmalloc.h"
-#include "read_wrapper.h"
-#include "debug.h"
+#include "../ip.h"
+#include "../xmalloc.h"
+#include "../read_wrapper.h"
+#include "../debug.h"
 #ifdef HAVE_CONFIG
-#include "config/tremor.h"
+#include "../config/tremor.h"
 #endif
-#include "comment.h"
+#include "../comment.h"
 
 #ifdef CONFIG_TREMOR
 #include <tremor/ivorbisfile.h>
diff --git a/ip/vtx.c b/ip/vtx.c
index 9e92e16f..0df6a503 100644
--- a/ip/vtx.c
+++ b/ip/vtx.c
@@ -15,11 +15,11 @@
  * along with this program; if not, see <http://www.gnu.org/licenses/>.
  */
 
-#include "comment.h"
-#include "debug.h"
-#include "ip.h"
-#include "utils.h"
-#include "xmalloc.h"
+#include "../comment.h"
+#include "../debug.h"
+#include "../ip.h"
+#include "../utils.h"
+#include "../xmalloc.h"
 #include <ayemu.h>
 #include <string.h>
 
diff --git a/ip/wav.c b/ip/wav.c
index b25db61e..9bc5f984 100644
--- a/ip/wav.c
+++ b/ip/wav.c
@@ -16,12 +16,12 @@
  * along with this program; if not, see <http://www.gnu.org/licenses/>.
  */
 
-#include "ip.h"
-#include "file.h"
-#include "xmalloc.h"
-#include "debug.h"
-#include "utils.h"
-#include "comment.h"
+#include "../ip.h"
+#include "../file.h"
+#include "../xmalloc.h"
+#include "../debug.h"
+#include "../utils.h"
+#include "../comment.h"
 
 #include <stdio.h>
 #include <string.h>
diff --git a/ip/wavpack.c b/ip/wavpack.c
index f30912ad..02fa777d 100644
--- a/ip/wavpack.c
+++ b/ip/wavpack.c
@@ -16,14 +16,14 @@
  * along with this program; if not, see <http://www.gnu.org/licenses/>.
  */
 
-#include "ip.h"
-#include "ape.h"
-#include "id3.h"
-#include "xmalloc.h"
-#include "read_wrapper.h"
-#include "debug.h"
-#include "buffer.h"
-#include "comment.h"
+#include "../ip.h"
+#include "../ape.h"
+#include "../id3.h"
+#include "../xmalloc.h"
+#include "../read_wrapper.h"
+#include "../debug.h"
+#include "../buffer.h"
+#include "../comment.h"
 
 #include <wavpack/wavpack.h>
 
diff --git a/op/alsa.c b/op/alsa.c
index 7d0e60a1..8dfaab04 100644
--- a/op/alsa.c
+++ b/op/alsa.c
@@ -48,11 +48,11 @@
  * SND_PCM_STATE_DISCONNECTED = 8,
  */
 
-#include "op.h"
-#include "utils.h"
-#include "xmalloc.h"
-#include "sf.h"
-#include "debug.h"
+#include "../op.h"
+#include "../utils.h"
+#include "../xmalloc.h"
+#include "../sf.h"
+#include "../debug.h"
 
 #define ALSA_PCM_NEW_HW_PARAMS_API
 #define ALSA_PCM_NEW_SW_PARAMS_API
diff --git a/op/ao.c b/op/ao.c
index 2187b873..4f727c67 100644
--- a/op/ao.c
+++ b/op/ao.c
@@ -16,11 +16,11 @@
  * along with this program; if not, see <http://www.gnu.org/licenses/>.
  */
 
-#include "op.h"
-#include "xmalloc.h"
-#include "utils.h"
-#include "misc.h"
-#include "debug.h"
+#include "../op.h"
+#include "../xmalloc.h"
+#include "../utils.h"
+#include "../misc.h"
+#include "../debug.h"
 
 /*
  * <ao/ao.h> uses FILE but doesn't include stdio.h.
diff --git a/op/arts.c b/op/arts.c
index d8eb693c..66e46935 100644
--- a/op/arts.c
+++ b/op/arts.c
@@ -16,9 +16,9 @@
  * along with this program; if not, see <http://www.gnu.org/licenses/>.
  */
 
-#include "op.h"
-#include "xmalloc.h"
-#include "debug.h"
+#include "../op.h"
+#include "../xmalloc.h"
+#include "../debug.h"
 
 #include <artsc.h>
 
diff --git a/op/coreaudio.c b/op/coreaudio.c
index f968eed0..ead75039 100644
--- a/op/coreaudio.c
+++ b/op/coreaudio.c
@@ -26,12 +26,12 @@
 #include <AudioUnit/AudioUnit.h>
 #include <CoreAudio/CoreAudio.h>
 
-#include "debug.h"
-#include "op.h"
-#include "mixer.h"
-#include "sf.h"
-#include "utils.h"
-#include "xmalloc.h"
+#include "../debug.h"
+#include "../op.h"
+#include "../mixer.h"
+#include "../sf.h"
+#include "../utils.h"
+#include "../xmalloc.h"
 
 
 /////////////////////////////////////////////////////////////////////////////
diff --git a/op/jack.c b/op/jack.c
index 72377244..cae52c49 100644
--- a/op/jack.c
+++ b/op/jack.c
@@ -28,17 +28,17 @@
 #include <stdbool.h>
 
 #if HAVE_CONFIG
-#include "config/samplerate.h"
+#include "../config/samplerate.h"
 #ifdef HAVE_SAMPLERATE
 #include <samplerate.h>
 #endif
 #endif
 
-#include "op.h"
-#include "utils.h"
-#include "channelmap.h"
-#include "xmalloc.h"
-#include "debug.h"
+#include "../op.h"
+#include "../utils.h"
+#include "../channelmap.h"
+#include "../xmalloc.h"
+#include "../debug.h"
 
 #define CHANNELS 2
 #define BUFFER_MULTIPLYER (sizeof(jack_default_audio_sample_t) * 16)
diff --git a/op/mixer_alsa.c b/op/mixer_alsa.c
index d91b413b..ed5d3e30 100644
--- a/op/mixer_alsa.c
+++ b/op/mixer_alsa.c
@@ -16,10 +16,10 @@
  * along with this program; if not, see <http://www.gnu.org/licenses/>.
  */
 
-#include "mixer.h"
-#include "op.h"
-#include "xmalloc.h"
-#include "debug.h"
+#include "../mixer.h"
+#include "../op.h"
+#include "../xmalloc.h"
+#include "../debug.h"
 
 #include <strings.h>
 
diff --git a/op/mixer_oss.c b/op/mixer_oss.c
index bc292da6..43378e6e 100644
--- a/op/mixer_oss.c
+++ b/op/mixer_oss.c
@@ -16,11 +16,11 @@
  * along with this program; if not, see <http://www.gnu.org/licenses/>.
  */
 
-#include "mixer.h"
-#include "op.h"
-#include "utils.h"
-#include "xmalloc.h"
-#include "debug.h"
+#include "../mixer.h"
+#include "../op.h"
+#include "../utils.h"
+#include "../xmalloc.h"
+#include "../debug.h"
 
 #include <strings.h>
 #include <unistd.h>
diff --git a/op/mixer_sun.c b/op/mixer_sun.c
index 48c689bd..825884b5 100644
--- a/op/mixer_sun.c
+++ b/op/mixer_sun.c
@@ -26,11 +26,11 @@
 #include <string.h>
 #include <unistd.h>
 
-#include "debug.h"
-#include "mixer.h"
-#include "op.h"
-#include "sf.h"
-#include "xmalloc.h"
+#include "../debug.h"
+#include "../mixer.h"
+#include "../op.h"
+#include "../sf.h"
+#include "../xmalloc.h"
 
 static int sun_mixer_device_id = -1;
 static int sun_mixer_channels = -1;
diff --git a/op/oss.c b/op/oss.c
index 9d596142..24aef6cd 100644
--- a/op/oss.c
+++ b/op/oss.c
@@ -16,11 +16,11 @@
  * along with this program; if not, see <http://www.gnu.org/licenses/>.
  */
 
-#include "op.h"
-#include "sf.h"
-#include "xmalloc.h"
-#include "debug.h"
-#include "utils.h"
+#include "../op.h"
+#include "../sf.h"
+#include "../xmalloc.h"
+#include "../debug.h"
+#include "../utils.h"
 
 #if defined(__OpenBSD__)
 #include <soundcard.h>
diff --git a/op/pulse.c b/op/pulse.c
index d753506c..a7b3f641 100644
--- a/op/pulse.c
+++ b/op/pulse.c
@@ -20,11 +20,11 @@
 
 #include <pulse/pulseaudio.h>
 
-#include "op.h"
-#include "mixer.h"
-#include "debug.h"
-#include "utils.h"
-#include "xmalloc.h"
+#include "../op.h"
+#include "../mixer.h"
+#include "../debug.h"
+#include "../utils.h"
+#include "../xmalloc.h"
 
 static pa_threaded_mainloop	*pa_ml;
 static pa_context		*pa_ctx;
diff --git a/op/roar.c b/op/roar.c
index 06ae87d3..75db0554 100644
--- a/op/roar.c
+++ b/op/roar.c
@@ -19,12 +19,12 @@
 
 #include <roaraudio.h>
 
-#include "op.h"
-#include "mixer.h"
-#include "xmalloc.h"
-#include "utils.h"
-#include "misc.h"
-#include "debug.h"
+#include "../op.h"
+#include "../mixer.h"
+#include "../xmalloc.h"
+#include "../utils.h"
+#include "../misc.h"
+#include "../debug.h"
 
 // we do not use native 2^16-1 here as they use signed ints with 16 bit
 // so we use 2^(16-1)-1 here.
diff --git a/op/sndio.c b/op/sndio.c
index c2b504fe..396eb275 100644
--- a/op/sndio.c
+++ b/op/sndio.c
@@ -27,10 +27,10 @@
 #include <unistd.h>
 #include <sndio.h>
 
-#include "op.h"
-#include "mixer.h"
-#include "sf.h"
-#include "xmalloc.h"
+#include "../op.h"
+#include "../mixer.h"
+#include "../sf.h"
+#include "../xmalloc.h"
 
 static sample_format_t sndio_sf;
 static struct sio_par par;
diff --git a/op/sun.c b/op/sun.c
index 6c9b5bdb..050b3c63 100644
--- a/op/sun.c
+++ b/op/sun.c
@@ -27,9 +27,9 @@
 #include <string.h>
 #include <unistd.h>
 
-#include "op.h"
-#include "sf.h"
-#include "xmalloc.h"
+#include "../op.h"
+#include "../sf.h"
+#include "../xmalloc.h"
 
 static sample_format_t sun_sf;
 static int sun_fd = -1;
diff --git a/op/waveout.c b/op/waveout.c
index cf92a1b2..00bf8074 100644
--- a/op/waveout.c
+++ b/op/waveout.c
@@ -18,11 +18,11 @@
  * along with this program; if not, see <http://www.gnu.org/licenses/>.
  */
 
-#include "op.h"
-#include "sf.h"
-#include "utils.h"
-#include "xmalloc.h"
-#include "debug.h"
+#include "../op.h"
+#include "../sf.h"
+#include "../utils.h"
+#include "../xmalloc.h"
+#include "../debug.h"
 
 #define WIN32_LEAN_AND_MEAN
 #include <windows.h>
diff --git a/scripts/checks.sh b/scripts/checks.sh
index 41c9f3ec..c2f048f5 100644
--- a/scripts/checks.sh
+++ b/scripts/checks.sh
@@ -172,7 +172,7 @@ check_cc()
 	check_program $CC || return 1
 
 	cc_cxx_common
-	CFLAGS="$CFLAGS -I$(pwd) $common_cf"
+	CFLAGS="$CFLAGS $common_cf"
 	LDFLAGS="$LDFLAGS $common_lf"
 
 	makefile_vars CC LD CFLAGS LDFLAGS

From ea3955d7df54c1db716a156e2a39ffc40e5480a6 Mon Sep 17 00:00:00 2001
From: Patrick G <geek1011@outlook.com>
Date: Tue, 12 Feb 2019 05:54:48 -0500
Subject: [PATCH 08/18] Add note about overriding keybindings using rc (closes
 #742) (#866)

bind -f must be used to override existing keybindings.
---
 Doc/cmus.txt | 4 ++++
 1 file changed, 4 insertions(+)

diff --git a/Doc/cmus.txt b/Doc/cmus.txt
index 46a57c69..c47c265b 100644
--- a/Doc/cmus.txt
+++ b/Doc/cmus.txt
@@ -381,6 +381,10 @@ bind [-f] <context> <key> <command>
 	example *i* selects the current track in views 1-3 but in browser it
 	is overridden to toggle showing of hidden files.
 
+	When setting custom bindings in `$XDG_CONFIG_HOME/cmus/rc`, it is
+	recommended to use the -f option, or else bind may fail due to an
+	existing binding in the autosave or system-level config files.
+
 browser-up (*backspace*)
 	Change to parent directory in browser view (5). This command only
 	makes sense to be bound to the *browser* key context although it's

From 0be981476e019e9fddb5529a73aadf004e94656b Mon Sep 17 00:00:00 2001
From: tomty89 <tom.ty89@gmail.com>
Date: Tue, 12 Feb 2019 18:55:09 +0800
Subject: [PATCH 09/18] ip/ffmpeg: enable opus support (#865)

---
 ip/ffmpeg.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/ip/ffmpeg.c b/ip/ffmpeg.c
index 04b916cc..427257c7 100644
--- a/ip/ffmpeg.c
+++ b/ip/ffmpeg.c
@@ -519,7 +519,7 @@ const int ip_priority = 30;
 const char *const ip_extensions[] = {
 	"aa", "aac", "ac3", "aif", "aifc", "aiff", "ape", "au", "fla", "flac",
 	"m4a", "m4b", "mka", "mkv", "mp+", "mp2", "mp3", "mp4", "mpc", "mpp",
-	"ogg", "shn", "tak", "tta", "wav", "webm", "wma", "wv",
+	"ogg", "opus", "shn", "tak", "tta", "wav", "webm", "wma", "wv",
 #ifdef USE_FALLBACK_IP
 	"*",
 #endif

From 483d1862ed023c3e00f2c8c4e71da40022af2f78 Mon Sep 17 00:00:00 2001
From: Shiba <3816409+shibotto@users.noreply.github.com>
Date: Tue, 12 Feb 2019 15:29:43 +0100
Subject: [PATCH 10/18] Add support for elogind (#846)

---
 configure | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/configure b/configure
index 1f46c30a..4627126e 100755
--- a/configure
+++ b/configure
@@ -289,7 +289,7 @@ check_vorbis()
 
 check_libsystemd()
 {
-	pkg_config LIBSYSTEMD "libsystemd"
+	pkg_config LIBSYSTEMD "libsystemd" || pkg_config LIBSYSTEMD "libelogind >= 239.3"
 	return $?
 }
 

From fead80b207b79ae6d10ab2b1601b11595d719908 Mon Sep 17 00:00:00 2001
From: Niko E <nefthy@users.noreply.github.com>
Date: Fri, 15 Feb 2019 08:48:28 +0100
Subject: [PATCH 11/18] Changes yes_no_query to signal error on cmus exit
 (#858)

This prevents the cmus process from zombiefying, when the Terminal is
closed while a yes/no query is displayed.

Fixes #765
---
 browser.c      |  2 +-
 command_mode.c |  9 ++++++---
 filters.c      |  2 +-
 help.c         |  2 +-
 input.c        |  2 +-
 pl.c           |  6 +++---
 ui_curses.c    | 22 ++++++++++++++++------
 ui_curses.h    |  8 +++++++-
 8 files changed, 36 insertions(+), 17 deletions(-)

diff --git a/browser.c b/browser.c
index 4ecffe67..dceeac11 100644
--- a/browser.c
+++ b/browser.c
@@ -449,7 +449,7 @@ void browser_delete(void)
 		char *name;
 
 		name = fullname(browser_dir, e->name);
-		if (yes_no_query("Delete file '%s'? [y/N]", e->name)) {
+		if (yes_no_query("Delete file '%s'? [y/N]", e->name) == UI_QUERY_ANSWER_YES) {
 			if (unlink(name) == -1) {
 				error_msg("deleting '%s': %s", e->name, strerror(errno));
 			} else {
diff --git a/command_mode.c b/command_mode.c
index 31e42839..75d3b545 100644
--- a/command_mode.c
+++ b/command_mode.c
@@ -741,11 +741,14 @@ static void cmd_showbind(char *arg)
 static void cmd_quit(char *arg)
 {
 	int flag = parse_flags((const char **)&arg, "i");
+	enum ui_query_answer answer;
 	if (!worker_has_job_by_type(JOB_TYPE_ANY)) {
-		if (flag != 'i' || yes_no_query("Quit cmus? [y/N]"))
+		answer =  yes_no_query("Quit cmus? [y/N]");
+		if (flag != 'i' || answer != UI_QUERY_ANSWER_NO)
 			cmus_running = 0;
 	} else {
-		if (yes_no_query("Tracks are being added. Quit and truncate playlist(s)? [y/N]"))
+		answer = yes_no_query("Tracks are being added. Quit and truncate playlist(s)? [y/N]");
+		if (answer != UI_QUERY_ANSWER_NO)
 			cmus_running = 0;
 	}
 }
@@ -1043,7 +1046,7 @@ static void cmd_run(char *arg)
 
 	run = 1;
 	if (confirm_run && (sel.tis_nr > 1 || strcmp(argv[0], "rm") == 0)) {
-		if (!yes_no_query("Execute %s for the %d selected files? [y/N]", arg, sel.tis_nr)) {
+		if (yes_no_query("Execute %s for the %d selected files? [y/N]", arg, sel.tis_nr) != UI_QUERY_ANSWER_YES) {
 			info_msg("Aborted");
 			run = 0;
 		}
diff --git a/filters.c b/filters.c
index b89912c3..10a190e7 100644
--- a/filters.c
+++ b/filters.c
@@ -304,7 +304,7 @@ void filters_delete_filter(void)
 		struct filter_entry *e;
 
 		e = iter_to_filter_entry(&iter);
-		if (yes_no_query("Delete filter '%s'? [y/N]", e->name)) {
+		if (yes_no_query("Delete filter '%s'? [y/N]", e->name) == UI_QUERY_ANSWER_YES) {
 			window_row_vanishes(filters_win, &iter);
 			list_del(&e->node);
 			free_filter(e);
diff --git a/help.c b/help.c
index 13248db1..53bd9eec 100644
--- a/help.c
+++ b/help.c
@@ -272,7 +272,7 @@ void help_remove(void)
 	ent = iter_to_help_entry(&sel);
 	switch (ent->type) {
 	case HE_BOUND:
-		if (yes_no_query("Remove selected binding? [y/N]"))
+		if (yes_no_query("Remove selected binding? [y/N]") == UI_QUERY_ANSWER_YES)
 			key_unbind(key_context_names[ent->binding->ctx],
 					ent->binding->key->name, 0);
 		break;
diff --git a/input.c b/input.c
index a0ac4267..12debe5b 100644
--- a/input.c
+++ b/input.c
@@ -891,7 +891,7 @@ static void set_ip_priority(void *data, const char *val)
 			static const char *msg =
 				"Metadata might become inconsistent "
 				"after this change. Continue? [y/N]";
-			if (!yes_no_query("%s", msg)) {
+			if (yes_no_query("%s", msg) != UI_QUERY_ANSWER_YES) {
 				info_msg("Aborted");
 				return;
 			}
diff --git a/pl.c b/pl.c
index 66119aa3..070c2dfd 100644
--- a/pl.c
+++ b/pl.c
@@ -423,7 +423,7 @@ static void pl_delete_selected_pl(void)
 		return;
 	}
 
-	if (!yes_no_query("Delete selected playlist? [y/N]"))
+	if (yes_no_query("Delete selected playlist? [y/N]") != UI_QUERY_ANSWER_YES)
 		return;
 
 	struct playlist *pl = pl_visible;
@@ -609,7 +609,7 @@ void pl_import(const char *path)
 void pl_export_selected_pl(const char *path)
 {
 	char *tmp = expand_filename(path);
-	if (access(tmp, F_OK) != 0 || yes_no_query("File exists. Overwrite? [y/N]"))
+	if (access(tmp, F_OK) != 0 || yes_no_query("File exists. Overwrite? [y/N]") == UI_QUERY_ANSWER_YES)
 		cmus_save(pl_save_cb, tmp, pl_visible);
 	free(tmp);
 }
@@ -826,7 +826,7 @@ void pl_win_toggle(void)
 
 void pl_win_update(void)
 {
-	if (!yes_no_query("Reload this playlist? [y/N]"))
+	if (yes_no_query("Reload this playlist? [y/N]") != UI_QUERY_ANSWER_YES)
 		return;
 
 	pl_clear_visible_pl();
diff --git a/ui_curses.c b/ui_curses.c
index b75f22e1..564b205a 100644
--- a/ui_curses.c
+++ b/ui_curses.c
@@ -1599,7 +1599,7 @@ void error_msg(const char *format, ...)
 	}
 }
 
-int yes_no_query(const char *format, ...)
+enum ui_query_answer yes_no_query(const char *format, ...)
 {
 	char buffer[512];
 	va_list ap;
@@ -1623,12 +1623,21 @@ int yes_no_query(const char *format, ...)
 
 	while (1) {
 		int ch = getch();
-
-		if (ch == ERR || ch == 0)
+		if (ch == ERR || ch == 0) {
+			if (!cmus_running) {
+				ret = UI_QUERY_ANSWER_ERROR;
+				break;
+			}
 			continue;
-		if (ch == 'y')
-			ret = 1;
-		break;
+		}
+
+		if (ch == 'y') {
+			ret = UI_QUERY_ANSWER_YES;
+			break;
+		} else {
+			ret = UI_QUERY_ANSWER_NO;
+			break;
+		}
 	}
 	update_commandline();
 	return ret;
@@ -1885,6 +1894,7 @@ static void sig_int(int sig)
 
 static void sig_shutdown(int sig)
 {
+	d_print("sig_shutdown %d\n", sig);
 	cmus_running = 0;
 }
 
diff --git a/ui_curses.h b/ui_curses.h
index 1774691e..0c7f02df 100644
--- a/ui_curses.h
+++ b/ui_curses.h
@@ -29,6 +29,12 @@ enum ui_input_mode {
 	SEARCH_MODE
 };
 
+enum ui_query_answer {
+	UI_QUERY_ANSWER_ERROR = -1,
+	UI_QUERY_ANSWER_NO = 0,
+	UI_QUERY_ANSWER_YES = 1
+};
+
 #include <signal.h>
 
 extern volatile sig_atomic_t cmus_running;
@@ -54,7 +60,7 @@ void update_colors(void);
 void update_full(void);
 void info_msg(const char *format, ...) CMUS_FORMAT(1, 2);
 void error_msg(const char *format, ...) CMUS_FORMAT(1, 2);
-int yes_no_query(const char *format, ...) CMUS_FORMAT(1, 2);
+enum ui_query_answer yes_no_query(const char *format, ...) CMUS_FORMAT(1, 2);
 void search_not_found(void);
 void set_view(int view);
 void set_client_fd(int fd);

From d14b432dc937b34b0723a69392b6415ac47d0d92 Mon Sep 17 00:00:00 2001
From: Niko E <nefthy@users.noreply.github.com>
Date: Sat, 16 Feb 2019 12:39:38 +0100
Subject: [PATCH 12/18] Fixes incorect bit rate declaration for 24bit flac
 (#867)

flac inflates the bit rate to 32bit for 24bit files, but set 24bit in
the sf structure.
---
 ip/flac.c | 2 --
 1 file changed, 2 deletions(-)

diff --git a/ip/flac.c b/ip/flac.c
index 0153d561..c31f2941 100644
--- a/ip/flac.c
+++ b/ip/flac.c
@@ -217,8 +217,6 @@ static void metadata_cb(const Dec *dec, const FLAC__StreamMetadata *metadata, vo
 				break;
 			case 20:
 			case 24:
-				bits = 24;
-				break;
 			case 32:
 				bits = 32;
 				break;

From d93f9c39b9190b2bc5eb3a2816564bdca8e945b7 Mon Sep 17 00:00:00 2001
From: tomty89 <tom.ty89@gmail.com>
Date: Tue, 19 Feb 2019 15:39:12 +0800
Subject: [PATCH 13/18] bits-per-sample fixes (#870)

---
 buffer.h  | 15 +++++++++++++--
 ip/flac.c | 24 ++++++++----------------
 2 files changed, 21 insertions(+), 18 deletions(-)

diff --git a/buffer.h b/buffer.h
index b21d57e9..e2c4d52d 100644
--- a/buffer.h
+++ b/buffer.h
@@ -19,8 +19,19 @@
 #ifndef CMUS_BUFFER_H
 #define CMUS_BUFFER_H
 
-/* must be a multiple of any supported frame size */
-#define CHUNK_SIZE (60 * 1024)
+/*
+ * must be a multiple of any supported frame size
+ *
+ * 12 is the LCM of 1, 2, 3 and 4, which corresponds to
+ * 8, 16, 24 and 32 bits respectively
+ *
+ * 840 is the LCM of 1, 2, 3, 4, 5, 6, 7 and 8, which
+ * are the numbers of supported channels
+ *
+ * we used to define the value as 60 * 1024 = 61440
+ * hence the extra 6, which makes the new value 60480
+ */
+#define CHUNK_SIZE (12 * 840 * 6)
 
 extern unsigned int buffer_nr_chunks;
 
diff --git a/ip/flac.c b/ip/flac.c
index c31f2941..39c80302 100644
--- a/ip/flac.c
+++ b/ip/flac.c
@@ -58,6 +58,7 @@ struct flac_private {
 	struct keyval *comments;
 	double duration;
 	long bitrate;
+	int bps;
 };
 
 static T(ReadStatus) read_cb(const Dec *dec, unsigned char *buf, size_t *size, void *data)
@@ -175,12 +176,12 @@ static FLAC__StreamDecoderWriteStatus write_cb(const Dec *dec, const FLAC__Frame
 
 	depth = frame->header.bits_per_sample;
 	if (!depth)
-		depth = bits;
+		depth = priv->bps;
 	nch = frame->header.channels;
 	dest = priv->buf + priv->buf_wpos;
 	for (i = 0; i < frames; i++) {
 		for (ch = 0; ch < channels; ch++) {
-			src = LE32(buf[ch % nch][i] << (bits -depth));
+			src = LE32(buf[ch % nch][i] << (bits - depth));
 			memcpy(dest, &src, bits / 8);
 			dest += bits / 8;
 		}
@@ -207,19 +208,9 @@ static void metadata_cb(const Dec *dec, const FLAC__StreamMetadata *metadata, vo
 			const FLAC__StreamMetadata_StreamInfo *si = &metadata->data.stream_info;
 			int bits = 0;
 
-			switch (si->bits_per_sample) {
-			case 8:
-				bits = 8;
-				break;
-			case 12:
-			case 16:
-				bits = 16;
-				break;
-			case 20:
-			case 24:
-			case 32:
-				bits = 32;
-				break;
+			if (si->bits_per_sample >= 4 && si->bits_per_sample <= 32) {
+				bits = priv->bps = si->bits_per_sample;
+				bits = 8 * ((bits + 7) / 8);
 			}
 
 			ip_data->sf = sf_rate(si->sample_rate) |
@@ -304,7 +295,8 @@ static int flac_open(struct input_plugin_data *ip_data)
 	const struct flac_private priv_init = {
 		.dec      = dec,
 		.duration = -1,
-		.bitrate  = -1
+		.bitrate  = -1,
+		.bps      = 0
 	};
 
 	if (!dec)

From e27e813bec7a60cca72f75ec018a3bb8b3d5326a Mon Sep 17 00:00:00 2001
From: amangrewal <5739325+amangrewal@users.noreply.github.com>
Date: Tue, 19 Feb 2019 02:40:26 -0500
Subject: [PATCH 14/18] Ensures all data sent on dbus is in utf8 (#847) (#871)

Partly addresses 847. All bytes that are invalid utf8 are converted
to <xx>, just like other areas in cmus. This is a temporary fix.
---
 mpris.c | 57 +++++++++++++++++++++++++++++++++++++++------------------
 uchar.c | 10 ++++++++++
 uchar.h | 11 +++++++++++
 3 files changed, 60 insertions(+), 18 deletions(-)

diff --git a/mpris.c b/mpris.c
index 27a8c69d..549134b6 100644
--- a/mpris.c
+++ b/mpris.c
@@ -25,6 +25,7 @@
 #include "output.h"
 #include "track_info.h"
 #include "utils.h"
+#include "uchar.h"
 
 #define CK(v) \
 do { \
@@ -374,24 +375,44 @@ static int mpris_metadata(sd_bus *_bus, const char *_path,
 		dur *= 1000 * 1000;
 		CK(mpris_msg_append_sx_dict(reply, "mpris:length", dur));
 
-		if (ti->artist)
-			CK(mpris_msg_append_sas_dict(reply, "xesam:artist",
-						ti->artist));
-		if (ti->title)
-			CK(mpris_msg_append_ss_dict(reply, "xesam:title",
-						ti->title));
-		if (ti->album)
-			CK(mpris_msg_append_ss_dict(reply, "xesam:album",
-						ti->album));
-		if (ti->albumartist)
-			CK(mpris_msg_append_sas_dict(reply, "xesam:albumArtist",
-						ti->albumartist));
-		if (ti->genre)
-			CK(mpris_msg_append_sas_dict(reply, "xesam:genre",
-						ti->genre));
-		if (ti->comment)
-			CK(mpris_msg_append_sas_dict(reply, "xesam:comment",
-						ti->comment));
+		//The dbus connection closes if invalid data is sent.
+		//As a *temporary* fix, ensure all strings are encoded in utf8.
+		if (ti->artist) {
+			char corrected[u_str_width(ti->artist)];
+			u_to_utf8(corrected, ti->artist);
+			CK(mpris_msg_append_sas_dict(reply,
+					"xesam:artist", corrected));
+		}
+		if (ti->title) {
+			char corrected[u_str_width(ti->title)];
+			u_to_utf8(corrected, ti->title);
+			CK(mpris_msg_append_sas_dict(reply,
+					"xesam:title", corrected));
+		}
+		if (ti->album) {
+			char corrected[u_str_width(ti->album)];
+			u_to_utf8(corrected, ti->album);
+			CK(mpris_msg_append_sas_dict(reply,
+					"xesam:album", corrected));
+		}
+		if (ti->albumartist) {
+			char corrected[u_str_width(ti->albumartist)];
+			u_to_utf8(corrected, ti->albumartist);
+			CK(mpris_msg_append_sas_dict(reply,
+					"xesam:albumArtist", corrected));
+		}
+		if (ti->genre) {
+			char corrected[u_str_width(ti->genre)];
+			u_to_utf8(corrected, ti->genre);
+			CK(mpris_msg_append_sas_dict(reply,
+					"xesam:genre", corrected));
+		}
+		if (ti->comment) {
+			char corrected[u_str_width(ti->comment)];
+			u_to_utf8(corrected, ti->comment);
+			CK(mpris_msg_append_sas_dict(reply,
+					"xesam:comment", corrected));
+		}
 		if (ti->bpm != -1)
 			CK(mpris_msg_append_si_dict(reply, "xesam:audioBPM",
 						ti->bpm));
diff --git a/uchar.c b/uchar.c
index b2158cc1..7b8691a6 100644
--- a/uchar.c
+++ b/uchar.c
@@ -520,6 +520,16 @@ int u_to_ascii(char *dst, const char *src, int len)
 	return i;
 }
 
+void u_to_utf8(char *dst, const char *src)
+{
+	int s = 0, d = 0;
+	uchar u;
+	do {
+		u = u_get_char(src, &s);
+		u_set_char(dst, &d, u);
+	} while (u!=0);
+}
+
 int u_skip_chars(const char *str, int *width)
 {
 	int w = *width;
diff --git a/uchar.h b/uchar.h
index 4be13381..237cd557 100644
--- a/uchar.h
+++ b/uchar.h
@@ -164,6 +164,17 @@ int u_copy_chars(char *dst, const char *src, int *width);
  */
 int u_to_ascii(char *dst, const char *src, int len);
 
+/*
+ * @dst    destination buffer
+ * @src    null-terminated string
+ *
+ * Copies src into dst, changing all invalid utf8 bytes into <xx>,
+ * where xx is the value of the byte in hex.
+ *
+ * Expects dst to be large enough to fit src + the conversions.
+ */
+void u_to_utf8(char *dst, const char *src);
+
 /*
  * @str    null-terminated UTF-8 string, must be long enough
  * @width  how much to skip

From 967a470b31ed2e6fc737ae523ba24b4dfdf81595 Mon Sep 17 00:00:00 2001
From: lennonhill <31923882+lennonhill@users.noreply.github.com>
Date: Mon, 4 Mar 2019 11:14:28 +0000
Subject: [PATCH 15/18] ip/mp4: add metadata support for bpm/tempo (#878)

---
 ip/mp4.c | 5 +++++
 1 file changed, 5 insertions(+)

diff --git a/ip/mp4.c b/ip/mp4.c
index 475e2fa3..6b275a85 100644
--- a/ip/mp4.c
+++ b/ip/mp4.c
@@ -485,6 +485,11 @@ static int mp4_read_comments(struct input_plugin_data *ip_data,
 		snprintf(buf, 6, "%u", tags->disk->index);
 		comments_add_const(&c, "discnumber", buf);
 	}
+	if (tags->tempo) {
+		char buf[6];
+		snprintf(buf, 6, "%u", *tags->tempo);
+		comments_add_const(&c, "bpm", buf);
+	}
 
 	MP4TagsFree(tags);
 

From e429ddfb3c2cfe38c89c7d62f70f86bb2665c4ca Mon Sep 17 00:00:00 2001
From: Niko E <nefthy@users.noreply.github.com>
Date: Thu, 28 Mar 2019 17:56:03 +0100
Subject: [PATCH 16/18] Makes :quit only prompt if -i is given (#888)

this is the original behaviour prior to fead80b

fixes #887
---
 command_mode.c | 3 +--
 1 file changed, 1 insertion(+), 2 deletions(-)

diff --git a/command_mode.c b/command_mode.c
index 75d3b545..0406fecc 100644
--- a/command_mode.c
+++ b/command_mode.c
@@ -743,8 +743,7 @@ static void cmd_quit(char *arg)
 	int flag = parse_flags((const char **)&arg, "i");
 	enum ui_query_answer answer;
 	if (!worker_has_job_by_type(JOB_TYPE_ANY)) {
-		answer =  yes_no_query("Quit cmus? [y/N]");
-		if (flag != 'i' || answer != UI_QUERY_ANSWER_NO)
+		if (flag != 'i' || yes_no_query("Quit cmus? [y/N]") != UI_QUERY_ANSWER_NO)
 			cmus_running = 0;
 	} else {
 		answer = yes_no_query("Tracks are being added. Quit and truncate playlist(s)? [y/N]");

From 2748d40bb670558b523d5b47b4af442e82c7ffd2 Mon Sep 17 00:00:00 2001
From: tomty89 <tom.ty89@gmail.com>
Date: Tue, 16 Apr 2019 22:26:40 +0800
Subject: [PATCH 17/18] misc_init: remove variable user_name (#898)

The variable wasn't used anywhere in cmus. Having it made cmus
unnecessarily required env var USER or USERNAME to work.
---
 misc.c | 8 --------
 misc.h | 1 -
 2 files changed, 9 deletions(-)

diff --git a/misc.c b/misc.c
index d8d4021a..f903c40c 100644
--- a/misc.c
+++ b/misc.c
@@ -41,7 +41,6 @@ const char *cmus_socket_path = NULL;
 const char *cmus_data_dir = NULL;
 const char *cmus_lib_dir = NULL;
 const char *home_dir = NULL;
-const char *user_name = NULL;
 
 char **get_words(const char *text)
 {
@@ -220,13 +219,6 @@ int misc_init(void)
 	if (home_dir == NULL)
 		die("error: environment variable HOME not set\n");
 
-	user_name = get_non_empty_env("USER");
-	if (user_name == NULL) {
-		user_name = get_non_empty_env("USERNAME");
-		if (user_name == NULL)
-			die("error: neither USER or USERNAME environment variable set\n");
-	}
-
 	cmus_config_dir = get_non_empty_env("CMUS_HOME");
 	if (cmus_config_dir == NULL) {
 		char *cmus_home = xstrjoin(home_dir, "/.cmus");
diff --git a/misc.h b/misc.h
index 48ec69e8..caccdad7 100644
--- a/misc.h
+++ b/misc.h
@@ -27,7 +27,6 @@ extern const char *cmus_socket_path;
 extern const char *cmus_data_dir;
 extern const char *cmus_lib_dir;
 extern const char *home_dir;
-extern const char *user_name;
 
 char **get_words(const char *text);
 int strptrcmp(const void *a, const void *b);

From 1ed60b5d76d2ca649c9d92699d2cf18597889c6d Mon Sep 17 00:00:00 2001
From: Jinwoo Park <jwparkau@gmail.com>
Date: Fri, 21 Jun 2019 22:16:08 +1000
Subject: [PATCH 18/18] fixed playlist name searching (#906)

Fixes #905.
---
 pl.c | 8 ++++++--
 1 file changed, 6 insertions(+), 2 deletions(-)

diff --git a/pl.c b/pl.c
index 070c2dfd..fc5cfddf 100644
--- a/pl.c
+++ b/pl.c
@@ -132,8 +132,12 @@ static int pl_search_matches(void *data, struct iter *iter, const char *text)
 
 	char **words = get_words(text);
 	for (size_t i = 0; words[i]; i++) {
-		if (u_strcasestr_base(pl->name, words[i])) {
-			matched = 1;
+
+		/* set in the loop to deal with empty search string */
+		matched = 1;
+
+		if (!u_strcasestr_base(pl->name, words[i])) {
+			matched = 0;
 			break;
 		}
 	}
