--- res_musiconhold.c.old	2004-01-11 10:23:26.000000000 +0100
+++ res_musiconhold.c	2004-01-25 19:01:12.000000000 +0100
@@ -43,6 +43,7 @@
 
 #include <pthread.h>
 
+static char *appconf = NULL;
 static char *app0 = "MusicOnHold";
 static char *app1 = "WaitMusicOnHold";
 static char *app2 = "SetMusicOnHold";
@@ -82,6 +83,8 @@
 	/* FD for timing source */
 	int pseudofd;
 	struct mohclass *next;
+
+	int privatemp3;
 };
 
 struct mohdata {
@@ -186,6 +189,11 @@
 			close(x);
 		/* Child */
 		chdir(class->dir);
+
+		/* Custom path */		
+		if (appconf != NULL)
+		    execv(appconf, argv);
+		
 		/* Default install is /usr/local/bin */
 		execv(LOCAL_MPG_123, argv);
 		/* Many places have it in /usr/bin */
@@ -337,11 +345,49 @@
 
 static struct mohclass *get_mohbyname(char *name)
 {
-	struct mohclass *moh;
+	struct mohclass *moh, *newmoh;
 	moh = mohclasses;
 	while(moh) {
 		if (!strcasecmp(name, moh->class))
-			return moh;
+		{
+			if (!moh->privatemp3)
+			    return moh;
+			    
+			/* Alloc private class */
+			newmoh = malloc(sizeof(struct mohclass));
+    			if (!newmoh)
+			    return NULL;
+    			memcpy(newmoh, moh, sizeof(struct mohclass));
+				
+			/* Set moh for private class */
+			newmoh->class[0] = '\0'; 
+
+#ifdef ZAPATA_MOH
+    			/* It's an MP3 Moh -- Open /dev/zap/pseudo for timing...  Is
+			there a better, yet reliable way to do this? */
+			newmoh->pseudofd = open("/dev/zap/pseudo", O_RDONLY);
+			if (newmoh->pseudofd < 0) {
+				ast_log(LOG_WARNING, "Unable to open pseudo channel for timing...  Sound may be choppy.\n");
+			} else {
+				int x = 320;
+				ioctl(newmoh->pseudofd, ZT_SET_BLOCKSIZE, &x);
+			}
+#endif
+
+			/* Create thread */
+			if (pthread_create(&newmoh->thread, NULL, monmp3thread, newmoh)) 
+			{
+			    ast_log(LOG_WARNING, "Unable to create private moh...\n");
+			    free(newmoh);
+    			    return NULL;
+			}
+
+			/* Add new private mohclass */
+			newmoh->next = mohclasses;
+			mohclasses = newmoh;
+		
+			return newmoh;
+		}
 		moh = moh->next;
 	}
 	return NULL;
@@ -374,17 +420,18 @@
 static void moh_release(struct ast_channel *chan, void *data)
 {
 	struct mohdata *moh = data, *prev, *cur;
+	struct mohclass* class = moh->parent, *searchmoh, *prevmoh;
 	int oldwfmt;
 	ast_mutex_lock(&moh_lock);
 	/* Unlink */
 	prev = NULL;
-	cur = moh->parent->members;
+	cur = class->members;
 	while(cur) {
 		if (cur == moh) {
 			if (prev)
 				prev->next = cur->next;
 			else
-				moh->parent->members = cur->next;
+				class->members = cur->next;
 			break;
 		}
 		prev = cur;
@@ -401,6 +448,45 @@
 		if (option_verbose > 2)
 			ast_verbose(VERBOSE_PREFIX_3 "Stopped music on hold on %s\n", chan->name);
 	}
+	
+	/* Close class if private moh */
+	if (class->privatemp3)
+	{
+	    ast_mutex_lock(&moh_lock);
+	    prevmoh = NULL;
+	    searchmoh = mohclasses;
+	    while(searchmoh) 
+	    {
+		    if (searchmoh == class) 
+		    {
+			    if (class->pid > 0)
+			    {
+				    char buff[8192];
+				    int bytes, tbytes = 0;
+				    int stime = time(NULL);
+				    ast_log(LOG_DEBUG, "killing %d!\n", class->pid);
+				    kill(class->pid, SIGKILL);
+				    while ((bytes = read(class->srcfd, buff, 8192)) && time(NULL) < stime + 5) {
+					    tbytes = tbytes + bytes;
+				    }
+				    ast_log(LOG_DEBUG, "mpg123 pid %d and child died after %d bytes read\n", class->pid, tbytes);
+				    close(class->srcfd);
+				    class->pid = 0;
+		    	    }
+			    
+			    if (prev)
+				prevmoh->next = class->next;
+			    else
+				mohclasses = class->next;
+		
+			    free(class);
+			    break;
+		    }	
+		    prevmoh = searchmoh;
+		    searchmoh = searchmoh->next;
+	    }
+	    ast_mutex_unlock(&moh_lock);
+	}
 }
 
 static void *moh_alloc(struct ast_channel *chan, void *params)
@@ -497,30 +583,37 @@
 	strncpy(moh->class, classname, sizeof(moh->class) - 1);
 	if (miscargs)
 		strncpy(moh->miscargs, miscargs, sizeof(moh->miscargs) - 1);
-	if (!strcasecmp(mode, "mp3") || !strcasecmp(mode, "quietmp3") || !strcasecmp(mode, "httpmp3")) {
+	if (!strcasecmp(mode, "mp3") || !strcasecmp(mode, "quietmp3") || !strcasecmp(mode, "httpmp3") || !strcasecmp(mode, "privatemp3")) {
 		if (!strcasecmp(mode, "quietmp3"))
 			moh->quiet = 1;
+		else if (!strcasecmp(mode, "privatemp3"))
+			moh->privatemp3 = 1;
+		
 		strncpy(moh->dir, param, sizeof(moh->dir) - 1);
 		moh->srcfd = -1;
-#ifdef ZAPATA_MOH
-		/* It's an MP3 Moh -- Open /dev/zap/pseudo for timing...  Is
-		   there a better, yet reliable way to do this? */
-		moh->pseudofd = open("/dev/zap/pseudo", O_RDONLY);
-		if (moh->pseudofd < 0) {
-			ast_log(LOG_WARNING, "Unable to open pseudo channel for timing...  Sound may be choppy.\n");
-		} else {
-			x = 320;
-			ioctl(moh->pseudofd, ZT_SET_BLOCKSIZE, &x);
-		}
-#else
 		moh->pseudofd = -1;
+		
+		if (!moh->privatemp3)
+		{
+#ifdef ZAPATA_MOH
+    			/* It's an MP3 Moh -- Open /dev/zap/pseudo for timing...  Is
+			there a better, yet reliable way to do this? */
+			moh->pseudofd = open("/dev/zap/pseudo", O_RDONLY);
+			if (moh->pseudofd < 0) {
+				ast_log(LOG_WARNING, "Unable to open pseudo channel for timing...  Sound may be choppy.\n");
+			} else {
+				x = 320;
+				ioctl(moh->pseudofd, ZT_SET_BLOCKSIZE, &x);
+			}
 #endif
-		if (pthread_create(&moh->thread, NULL, monmp3thread, moh)) {
-			ast_log(LOG_WARNING, "Unable to create moh...\n");
-			if (moh->pseudofd > -1)
-				close(moh->pseudofd);
-			free(moh);
-			return -1;
+
+    			if (pthread_create(&moh->thread, NULL, monmp3thread, moh)) {
+				ast_log(LOG_WARNING, "Unable to create moh...\n");
+				if (moh->pseudofd > -1)
+					close(moh->pseudofd);
+				free(moh);
+				return -1;
+			}
 		}
 	} else {
 		ast_log(LOG_WARNING, "Don't know how to do a mode '%s' music on hold\n", mode);
@@ -556,6 +649,21 @@
 	char *args;
 	cfg = ast_load("musiconhold.conf");
 	if (cfg) {
+		data = ast_variable_retrieve(cfg, "global", "application");
+		if (data)
+		{
+		    appconf = malloc(strlen(data) + 1);
+		    if (appconf != NULL)
+			strcpy(appconf, data);
+		    else
+		    {
+			ast_log(LOG_ERROR, "Out of memory error.\n");
+			return;
+		    }
+		}
+		
+		ast_log(LOG_NOTICE, "%s\n", appconf);
+
 		var = ast_variable_browse(cfg, "classes");
 		while(var) {
 			data = strchr(var->value, ':');
@@ -577,7 +685,7 @@
 
 static void ast_moh_destroy(void)
 {
-	struct mohclass *moh;
+	struct mohclass *moh, *prevmoh;;
 	char buff[8192];
 	int bytes, tbytes=0, stime = 0;
 	if (option_verbose > 1)
@@ -596,7 +704,10 @@
 			close(moh->srcfd);
 			moh->pid = 0;
 			}
+
+		prevmoh = moh;
 		moh = moh->next;
+		free(prevmoh);
 	}
 	ast_mutex_unlock(&moh_lock);
 }
@@ -616,6 +727,9 @@
 
 int unload_module(void)
 {
+	if (appconf != NULL)
+		free(appconf);
+
 	return -1;
 }
 
