Index: configs/extconfig.conf.sample
===================================================================
--- configs/extconfig.conf.sample	(revision 89114)
+++ configs/extconfig.conf.sample	(working copy)
@@ -58,4 +58,5 @@
 ;extensions => odbc,asterisk
 ;queues => odbc,asterisk
 ;queue_members => odbc,asterisk
+;musiconhold => mysql,asterisk
 
Index: res/res_musiconhold.c
===================================================================
--- res/res_musiconhold.c	(revision 89114)
+++ res/res_musiconhold.c	(working copy)
@@ -152,6 +152,8 @@
 	int pseudofd;
 	/*! Number of users */
 	int inuse;
+	/*! Created on the fly, from RT engine */
+	int realtime;
 	unsigned int delete:1;
 	AST_LIST_HEAD_NOLOCK(, mohdata) members;
 	AST_LIST_ENTRY(mohclass) list;
@@ -836,7 +838,7 @@
 	struct stat statbuf;
 	int dirnamelen;
 	int i;
-	
+
 	files_DIR = opendir(class->dir);
 	if (!files_DIR) {
 		ast_log(LOG_WARNING, "Cannot open dir %s or dir does not exist\n", class->dir);
@@ -993,9 +995,26 @@
 	}
 }
 
+static struct mohclass *moh_class_malloc(void)
+{
+	struct mohclass *class;
+
+	if ((class = ast_calloc(1, sizeof(*class)))) {
+		class->format = AST_FORMAT_SLINEAR;
+		class->realtime = 0;
+	}
+
+	return class;
+}
+
 static int local_ast_moh_start(struct ast_channel *chan, const char *mclass, const char *interpclass)
 {
 	struct mohclass *mohclass = NULL;
+	struct ast_variable *var = NULL;
+	struct ast_variable *tmp = NULL;
+#ifdef HAVE_ZAPTEL
+	int x;
+#endif
 
 	/* The following is the order of preference for which class to use:
 	 * 1) The channels explicitly set musicclass, which should *only* be
@@ -1008,19 +1027,131 @@
 	 *    option.
 	 * 4) The default class.
 	 */
-	AST_RWLIST_RDLOCK(&mohclasses);
-	if (!ast_strlen_zero(chan->musicclass))
-		mohclass = get_mohbyname(chan->musicclass, 1);
-	if (!mohclass && !ast_strlen_zero(mclass))
-		mohclass = get_mohbyname(mclass, 1);
-	if (!mohclass && !ast_strlen_zero(interpclass))
-		mohclass = get_mohbyname(interpclass, 1);
-	if (!mohclass)	
-		mohclass = get_mohbyname("default", 1);
-	if (mohclass)
-		ast_atomic_fetchadd_int(&mohclass->inuse, +1);
-	AST_RWLIST_UNLOCK(&mohclasses);
 
+	/* First, let's check RT storage for MOH records */
+	if (ast_check_realtime("musiconhold")) {
+		if (!ast_strlen_zero(chan->musicclass)) {
+			var = ast_load_realtime("musiconhold", "name", chan->musicclass, NULL);
+		}
+		if (!var && !ast_strlen_zero(mclass))
+			var = ast_load_realtime("musiconhold", "name", mclass, NULL);
+		if (!var && !ast_strlen_zero(interpclass))
+			var = ast_load_realtime("musiconhold", "name", interpclass, NULL);
+		if (!var)
+			var = ast_load_realtime("musiconhold", "name", "default", NULL);
+		if (var && (mohclass = moh_class_malloc())) {
+			mohclass->realtime = 1;
+			for (tmp = var; tmp; tmp = tmp->next) {
+				if (!strcasecmp(tmp->name, "name"))
+					ast_copy_string(mohclass->name, tmp->value, sizeof(mohclass->name));
+				else if (!strcasecmp(tmp->name, "mode"))
+					ast_copy_string(mohclass->mode, tmp->value, sizeof(mohclass->mode)); 
+				else if (!strcasecmp(tmp->name, "directory"))
+					ast_copy_string(mohclass->dir, tmp->value, sizeof(mohclass->dir));
+				else if (!strcasecmp(tmp->name, "application"))
+					ast_copy_string(mohclass->args, tmp->value, sizeof(mohclass->args));
+				else if (!strcasecmp(tmp->name, "digit") && (isdigit(*tmp->value) || strchr("*#", *tmp->value)))
+					mohclass->digit = *tmp->value;
+				else if (!strcasecmp(tmp->name, "random"))
+					ast_set2_flag(mohclass, ast_true(tmp->value), MOH_RANDOMIZE);
+				else if (!strcasecmp(tmp->name, "sort") && !strcasecmp(tmp->value, "random"))
+					ast_set_flag(mohclass, MOH_RANDOMIZE);
+				else if (!strcasecmp(tmp->name, "sort") && !strcasecmp(tmp->value, "alpha")) 
+					ast_set_flag(mohclass, MOH_SORTALPHA);
+				else if (!strcasecmp(tmp->name, "format")) {
+					mohclass->format = ast_getformatbyname(tmp->value);
+					if (!mohclass->format) {
+						ast_log(LOG_WARNING, "Unknown format '%s' -- defaulting to SLIN\n", tmp->value);
+						mohclass->format = AST_FORMAT_SLINEAR;
+					}
+				}
+			}
+			if (ast_strlen_zero(mohclass->dir)) {
+				if (!strcasecmp(mohclass->mode, "custom")) {
+					strcpy(mohclass->dir, "nodir");
+				} else {
+					ast_log(LOG_WARNING, "A directory must be specified for class '%s'!\n", mohclass->name);
+					ast_free(mohclass);
+				}
+			}
+			if (ast_strlen_zero(mohclass->mode)) {
+				ast_log(LOG_WARNING, "A mode must be specified for class '%s'!\n", mohclass->name);
+				ast_free(mohclass);
+			}
+			if (ast_strlen_zero(mohclass->args) && !strcasecmp(mohclass->mode, "custom")) {
+				ast_log(LOG_WARNING, "An application must be specified for class '%s'!\n", mohclass->name);
+				ast_free(mohclass);
+			}
+
+			/* We don't register RT moh class, so let's init it manualy */
+
+			time(&mohclass->start);
+			mohclass->start -= respawn_time;
+	
+			if (!strcasecmp(mohclass->mode, "files")) {
+				if (!moh_scan_files(mohclass)) {
+					ast_moh_free_class(&mohclass);
+					return -1;
+				}
+				if (strchr(mohclass->args, 'r'))
+					ast_set_flag(mohclass, MOH_RANDOMIZE);
+			} else if (!strcasecmp(mohclass->mode, "mp3") || !strcasecmp(mohclass->mode, "mp3nb") || !strcasecmp(mohclass->mode, "quietmp3") || !strcasecmp(mohclass->mode, "quietmp3nb") || !strcasecmp(mohclass->mode, "httpmp3") || !strcasecmp(mohclass->mode, "custom")) {
+
+				if (!strcasecmp(mohclass->mode, "custom"))
+					ast_set_flag(mohclass, MOH_CUSTOM);
+				else if (!strcasecmp(mohclass->mode, "mp3nb"))
+					ast_set_flag(mohclass, MOH_SINGLE);
+				else if (!strcasecmp(mohclass->mode, "quietmp3nb"))
+					ast_set_flag(mohclass, MOH_SINGLE | MOH_QUIET);
+				else if (!strcasecmp(mohclass->mode, "quietmp3"))
+					ast_set_flag(mohclass, MOH_QUIET);
+		
+				mohclass->srcfd = -1;
+#ifdef HAVE_ZAPTEL
+				/* Open /dev/zap/pseudo for timing...  Is
+				   there a better, yet reliable way to do this? */
+				mohclass->pseudofd = open("/dev/zap/pseudo", O_RDONLY);
+				if (mohclass->pseudofd < 0) {
+					ast_log(LOG_WARNING, "Unable to open pseudo channel for timing...  Sound may be choppy.\n");
+				} else {
+					x = 320;
+					ioctl(mohclass->pseudofd, ZT_SET_BLOCKSIZE, &x);
+				}
+#else
+				mohclass->pseudofd = -1;
+#endif
+				if (ast_pthread_create_background(&mohclass->thread, NULL, monmp3thread, mohclass)) {
+					ast_log(LOG_WARNING, "Unable to create moh...\n");
+					if (mohclass->pseudofd > -1)
+						close(mohclass->pseudofd);
+					ast_moh_free_class(&mohclass);
+					return -1;
+				}
+			} else {
+				ast_log(LOG_WARNING, "Don't know how to do a mode '%s' music on hold\n", mohclass->mode);
+				ast_moh_free_class(&mohclass);
+				return -1;
+			}
+
+
+
+		}
+	}
+	if (!mohclass) {
+		AST_RWLIST_RDLOCK(&mohclasses);
+		if (!ast_strlen_zero(chan->musicclass)) 
+			mohclass = get_mohbyname(chan->musicclass, 1);
+		if (!mohclass && !ast_strlen_zero(mclass))
+			mohclass = get_mohbyname(mclass, 1);
+		if (!mohclass && !ast_strlen_zero(interpclass))
+			mohclass = get_mohbyname(interpclass, 1);
+		if (!mohclass)	
+			mohclass = get_mohbyname("default", 1);
+		if (mohclass)
+			ast_atomic_fetchadd_int(&mohclass->inuse, +1);
+		AST_RWLIST_UNLOCK(&mohclasses);
+	}
+
 	if (!mohclass)
 		return -1;
 
@@ -1033,6 +1164,7 @@
 
 static void local_ast_moh_stop(struct ast_channel *chan)
 {
+	struct moh_files_state *state = chan->music_state;
 	ast_clear_flag(chan, AST_FLAG_MOH);
 	ast_deactivate_generator(chan);
 
@@ -1041,19 +1173,12 @@
 			ast_closestream(chan->stream);
 			chan->stream = NULL;
 		}
+		if (state->class->realtime) {
+			ast_moh_destroy_one(state->class);
+		}
 	}
 }
 
-static struct mohclass *moh_class_malloc(void)
-{
-	struct mohclass *class;
-
-	if ((class = ast_calloc(1, sizeof(*class))))
-		class->format = AST_FORMAT_SLINEAR;
-
-	return class;
-}
-
 static int load_moh_classes(int reload)
 {
 	struct ast_config *cfg;
@@ -1079,7 +1204,7 @@
 	cat = ast_category_browse(cfg, NULL);
 	for (; cat; cat = ast_category_browse(cfg, cat)) {
 		/* These names were deprecated in 1.4 and should not be used until after the next major release. */
-		if (strcasecmp(cat, "classes") && strcasecmp(cat, "moh_files")) {			
+		if (strcasecmp(cat, "classes") && strcasecmp(cat, "moh_files")) {
 			if (!(class = moh_class_malloc()))
 				break;
 
