From ce015904865928342e35eba732efeb4469574965 Mon Sep 17 00:00:00 2001
From: Anthony Minessale <anthm@freeswitch.org>
Date: Mon, 7 Nov 2016 12:17:56 -0600
Subject: [PATCH] FS-9706 #resolve [Add loops param to file playback in
 conference]

---
 .../mod_conference/conference_file.c          |  9 ++++++
 .../mod_conference/mod_conference.c           | 31 +++++++++++++++++--
 .../mod_conference/mod_conference.h           |  1 +
 3 files changed, 39 insertions(+), 2 deletions(-)

diff --git a/src/mod/applications/mod_conference/conference_file.c b/src/mod/applications/mod_conference/conference_file.c
index eceff51148..801aab168a 100644
--- a/src/mod/applications/mod_conference/conference_file.c
+++ b/src/mod/applications/mod_conference/conference_file.c
@@ -275,7 +275,16 @@ switch_status_t conference_file_play(conference_obj_t *conference, char *file, u
 		const char *vol = switch_event_get_header(fnode->fh.params, "vol");
 		const char *position = switch_event_get_header(fnode->fh.params, "position");
 		const char *canvasstr = switch_event_get_header(fnode->fh.params, "canvas");
+		const char *loopsstr = switch_event_get_header(fnode->fh.params, "loops");
 		int canvas_id = -1;
+		
+		if (loopsstr) {
+			fnode->loops = atoi(loopsstr);
+
+			if (!strcasecmp(loopsstr, "inf") || !strcasecmp(loopsstr, "infinite")) {
+				fnode->loops = -1;
+			}
+		}
 
 		if (canvasstr) {
 			canvas_id = atoi(canvasstr) - 1;
diff --git a/src/mod/applications/mod_conference/mod_conference.c b/src/mod/applications/mod_conference/mod_conference.c
index 75b2e3b27e..5d8961dd06 100644
--- a/src/mod/applications/mod_conference/mod_conference.c
+++ b/src/mod/applications/mod_conference/mod_conference.c
@@ -446,6 +446,7 @@ void *SWITCH_THREAD_FUNC conference_thread_run(switch_thread_t *thread, void *ob
 					}
 				} else if (conference->fnode->type == NODE_TYPE_FILE) {
 					switch_core_file_read(&conference->fnode->fh, file_frame, &file_sample_len);
+					
 					if (conference->fnode->fh.vol) {
 						switch_change_sln_volume_granular((void *)file_frame, (uint32_t)file_sample_len * conference->fnode->fh.channels,
 														  conference->fnode->fh.vol);
@@ -456,7 +457,20 @@ void *SWITCH_THREAD_FUNC conference_thread_run(switch_thread_t *thread, void *ob
 				}
 
 				if (file_sample_len <= 0) {
-					conference->fnode->done++;
+					if (conference->fnode->loops) {
+						if (--conference->fnode->loops < 0) {
+							conference->fnode->loops = -1;
+						}
+						
+						if (conference->fnode->loops) {
+							uint32_t pos = 0;
+							switch_core_file_seek(&conference->fnode->fh, &pos, 0, SEEK_SET);
+						}
+					}
+					
+					if (!conference->fnode->loops) {
+						conference->fnode->done++;
+					}
 				} else {
 					has_file_data = 1;
 				}
@@ -474,7 +488,20 @@ void *SWITCH_THREAD_FUNC conference_thread_run(switch_thread_t *thread, void *ob
 					conference_al_process(conference->async_fnode->al, file_frame, file_sample_len * 2, conference->async_fnode->fh.samplerate);
 				}
 				if (file_sample_len <= 0) {
-					conference->async_fnode->done++;
+					if (conference->async_fnode->loops) {
+						if (--conference->async_fnode->loops < 0) {
+							conference->async_fnode->loops = -1;
+						}
+						
+						if (conference->async_fnode->loops) {
+							uint32_t pos = 0;
+							switch_core_file_seek(&conference->async_fnode->fh, &pos, 0, SEEK_SET);
+						}
+					}
+					
+					if (!conference->async_fnode->loops) {
+						conference->async_fnode->done++;
+					}
 				} else {
 					if (has_file_data) {
 						switch_size_t x;
diff --git a/src/mod/applications/mod_conference/mod_conference.h b/src/mod/applications/mod_conference/mod_conference.h
index a4aca869fc..cc8d36b4fd 100644
--- a/src/mod/applications/mod_conference/mod_conference.h
+++ b/src/mod/applications/mod_conference/mod_conference.h
@@ -386,6 +386,7 @@ typedef struct conference_file_node {
 	int canvas_id;
 	struct conference_obj *conference;
 	char *res_id;
+	int loops;
 } conference_file_node_t;
 
 typedef enum {