[Asterisk-Dev] Fix for Music on Hold

Michael Manousos manousos at inaccessnetworks.com
Mon Jul 21 02:51:12 MST 2003


This patch fixes the playback of music on hold for
machines that do not have any zaptel hardware.

Michael.


-------------- next part --------------
Index: res/res_musiconhold.c
===================================================================
RCS file: /usr/cvsroot/asterisk/res/res_musiconhold.c,v
retrieving revision 1.1.1.5
diff -u -r1.1.1.5 res_musiconhold.c
--- res/res_musiconhold.c	18 Mar 2003 06:00:18 -0000	1.1.1.5
+++ res/res_musiconhold.c	21 Jul 2003 10:11:48 -0000
@@ -201,11 +201,24 @@
 
 static void *monmp3thread(void *data)
 {
+#define	MOH_MS_INTERVAL		100
+
 	struct mohclass *class = data;
 	struct mohdata *moh;
 	char buf[8192];
 	short sbuf[8192];
 	int res, res2;
+	struct timeval tv;
+	struct timeval tv_tmp;
+	long error_sec, error_usec;
+	long delay;
+
+	tv_tmp.tv_sec = 0;
+	tv_tmp.tv_usec = 0;
+	tv.tv_sec = 0;
+	tv.tv_usec = 0;
+	error_sec = 0;
+	error_usec = 0;
 	signal(SIGCHLD, child_handler);
 	for(;/* ever */;) {
 		/* Spawn mp3 player if it's not there */
@@ -220,8 +233,39 @@
 			/* Pause some amount of time */
 			res = read(class->pseudofd, buf, sizeof(buf));
 		} else {
-			/* otherwise just sleep (unreliable) */
-			usleep(100000);	/* Sleep 100 ms */
+			/* Reliable sleep */
+			if (gettimeofday(&tv_tmp, NULL) < 0) {
+				ast_log(LOG_NOTICE, "gettimeofday() failed!\n");
+				return NULL;
+			}
+			if (((unsigned long)(tv.tv_sec) > 0)&&((unsigned long)(tv.tv_usec) > 0)) {
+				if ((unsigned long)(tv_tmp.tv_usec) < (unsigned long)(tv.tv_usec)) {
+					tv_tmp.tv_usec += 1000000;
+					tv_tmp.tv_sec -= 1;
+				}
+				error_sec = (unsigned long)(tv_tmp.tv_sec) - (unsigned long)(tv.tv_sec);
+				error_usec = (unsigned long)(tv_tmp.tv_usec) - (unsigned long)(tv.tv_usec);
+			} else {
+				error_sec = 0;
+				error_usec = 0;
+			}
+			if (error_sec * 1000 + error_usec / 1000 < MOH_MS_INTERVAL) {
+				tv.tv_sec = tv_tmp.tv_sec + (MOH_MS_INTERVAL/1000 - error_sec);
+				tv.tv_usec = tv_tmp.tv_usec + ((MOH_MS_INTERVAL % 1000) * 1000 - error_usec);
+				delay = (MOH_MS_INTERVAL/1000 - error_sec) * 1000 +
+							((MOH_MS_INTERVAL % 1000) * 1000 - error_usec) / 1000;
+			} else {
+				ast_log(LOG_NOTICE, "Request to schedule in the past?!?!\n");
+				tv.tv_sec = tv_tmp.tv_sec;
+				tv.tv_usec = tv_tmp.tv_usec;
+				delay = 0;
+			}
+			if (tv.tv_usec > 1000000) {
+				tv.tv_sec++;
+				tv.tv_usec-= 1000000;
+			}
+			if (delay > 0)
+				usleep(delay * 1000);
 			res = 800;		/* 800 samples */
 		}
 		if (!class->members)
@@ -400,7 +444,8 @@
 		ast_log(LOG_WARNING, "Only doing %d of %d requested bytes on %s\n", sizeof(buf), len, chan->name);
 		len = sizeof(buf);
 	}
-	res = read(moh->pipe[0], buf + AST_FRIENDLY_OFFSET/2, len);
+	/* XXX SEGFAULT res = read(moh->pipe[0], buf + AST_FRIENDLY_OFFSET/2, len);*/
+	res = read(moh->pipe[0], buf, len);
 #if 0
 	if (res != len) {
 		ast_log(LOG_WARNING, "Read only %d of %d bytes: %s\n", res, len, strerror(errno));
@@ -413,7 +458,8 @@
 		f.mallocd = 0;
 		f.datalen = res;
 		f.samples = res / 2;
-		f.data = buf + AST_FRIENDLY_OFFSET / 2;
+		/* XXX SEGFAULT f.data = buf + AST_FRIENDLY_OFFSET / 2;*/
+		f.data = buf;
 		f.offset = AST_FRIENDLY_OFFSET;
 		if (ast_write(chan, &f)< 0) {
 			ast_log(LOG_WARNING, "Failed to write frame to '%s': %s\n", chan->name, strerror(errno));


More information about the asterisk-dev mailing list