From 4c7ab73468878ad4c9b9df2b67111df78266b50e Mon Sep 17 00:00:00 2001
From: Sam Wierema <sam@messagebird.com>
Date: Tue, 12 Jun 2018 16:30:37 +0200
Subject: [PATCH] app_mp3: remove 10 seconds of silence after mp3 playback

This patch changes the way asterisk polls output from mpg123, instead
of waiting for 10 seconds(when playing an http url) it now uses a
timeout of one second and iterates 10 times using this same timeout.

The main difference is that for every timeout asterisk receives it now
checks if mpg123 is still running before poll again.

ASTERISK-27752

Change-Id: Ib7df8462e3e380cb328011890ad9270d9e9b4620
---
 apps/app_mp3.c | 32 +++++++++++++++++++++++++-------
 1 file changed, 25 insertions(+), 7 deletions(-)

diff --git a/apps/app_mp3.c b/apps/app_mp3.c
index e48cf09a0c..8d049da07d 100644
--- a/apps/app_mp3.c
+++ b/apps/app_mp3.c
@@ -35,6 +35,7 @@
 #include "asterisk.h"
 
 #include <sys/time.h>
+#include <sys/types.h>
 #include <signal.h>
 
 #include "asterisk/lock.h"
@@ -136,17 +137,34 @@ static int mp3play(const char *filename, unsigned int sampling_rate, int fd)
 	_exit(0);
 }
 
-static int timed_read(int fd, void *data, int datalen, int timeout)
+static int timed_read(int fd, void *data, int datalen, int timeout, int pid)
 {
 	int res;
+	int i;
 	struct pollfd fds[1];
 	fds[0].fd = fd;
 	fds[0].events = POLLIN;
-	res = ast_poll(fds, 1, timeout);
-	if (res < 1) {
-		ast_log(LOG_NOTICE, "Poll timed out/errored out with %d\n", res);
+	for (i = 0; i < timeout; i++) {
+		res = ast_poll(fds, 1, 1000);
+		if (res > 0) {
+			break;
+		} else if (res == 0) {
+			/* is mpg123 still running? */
+			kill(pid, 0);
+			if (errno == ESRCH) {
+				return -1;
+			}
+		} else {
+			ast_log(LOG_NOTICE, "error polling mpg123: %s\n", strerror(errno));
+			return -1;
+		}
+	}
+
+	if (i == timeout) {
+		ast_log(LOG_NOTICE, "Poll timed out.\n");
 		return -1;
 	}
+
 	return read(fd, data, datalen);
 
 }
@@ -158,7 +176,7 @@ static int mp3_exec(struct ast_channel *chan, const char *data)
 	int ms = -1;
 	int pid = -1;
 	RAII_VAR(struct ast_format *, owriteformat, NULL, ao2_cleanup);
-	int timeout = 2000;
+	int timeout = 2;
 	struct timeval next;
 	struct ast_frame *f;
 	struct myframe {
@@ -206,7 +224,7 @@ static int mp3_exec(struct ast_channel *chan, const char *data)
 
 	res = mp3play(data, sampling_rate, fds[1]);
 	if (!strncasecmp(data, "http://", 7)) {
-		timeout = 10000;
+		timeout = 10;
 	}
 	/* Wait 1000 ms first */
 	next = ast_tvnow();
@@ -218,7 +236,7 @@ static int mp3_exec(struct ast_channel *chan, const char *data)
 		for (;;) {
 			ms = ast_tvdiff_ms(next, ast_tvnow());
 			if (ms <= 0) {
-				res = timed_read(fds[0], myf.frdata, sizeof(myf.frdata), timeout);
+				res = timed_read(fds[0], myf.frdata, sizeof(myf.frdata), timeout, pid);
 				if (res > 0) {
 					myf.f.datalen = res;
 					myf.f.samples = res / 2;
-- 
GitLab