diff --git a/src/include/switch_types.h b/src/include/switch_types.h
index 37fd18c022..3312ebd497 100644
--- a/src/include/switch_types.h
+++ b/src/include/switch_types.h
@@ -917,6 +917,8 @@ typedef enum {
 	CF_XFER_ZOMBIE,
 	CF_MEDIA_ACK,
 	CF_THREAD_SLEEPING,
+	CF_DISABLE_RINGBACK,
+	CF_NOT_READY,
 	/* WARNING: DO NOT ADD ANY FLAGS BELOW THIS LINE */
 	CF_FLAG_MAX
 } switch_channel_flag_t;
diff --git a/src/mod/applications/mod_dptools/mod_dptools.c b/src/mod/applications/mod_dptools/mod_dptools.c
index 8aa72bd553..3d2791a43b 100644
--- a/src/mod/applications/mod_dptools/mod_dptools.c
+++ b/src/mod/applications/mod_dptools/mod_dptools.c
@@ -2054,13 +2054,47 @@ SWITCH_STANDARD_APP(stop_record_session_function)
 /*								Bridge Functions								*/
 /********************************************************************************/
 
+struct camping_stake {
+	switch_core_session_t *session;
+	int running;
+	const char *moh;
+};
+
+static void *SWITCH_THREAD_FUNC camp_music_thread(switch_thread_t *thread, void *obj)
+{
+	struct camping_stake *stake = (struct camping_stake *) obj;
+	switch_core_session_t *session = stake->session;
+	switch_channel_t *channel = switch_core_session_get_channel(stake->session);
+	const char *moh = stake->moh;
+
+	switch_core_session_read_lock(session);
+	while(stake->running && switch_channel_ready(channel)) {
+		if (!strcasecmp(moh, "silence")) {
+			switch_ivr_collect_digits_callback(session, NULL, 0, 0);
+		} else {
+			switch_ivr_play_file(session, NULL, stake->moh, NULL);
+		}
+	}
+	switch_core_session_rwunlock(session);
+
+	return NULL;
+}
+
 SWITCH_STANDARD_APP(audio_bridge_function)
 {
 	switch_channel_t *caller_channel = switch_core_session_get_channel(session);
 	switch_core_session_t *peer_session = NULL;
-	const char *continue_on_fail = NULL, *failure_causes = NULL;
+	const char *continue_on_fail = NULL, *failure_causes = NULL, 
+		*v_campon = NULL, *v_campon_retries, *v_campon_sleep, *v_campon_timeout, *v_campon_fallback_exten = NULL;
 	switch_call_cause_t cause = SWITCH_CAUSE_NORMAL_CLEARING;
-
+	int campon_retries = 100, campon_timeout = 10, campon_sleep = 10, tmp, do_xfer = 0, camping = 0, fail = 0, thread_started = 0;
+	struct camping_stake stake = { 0 };
+	const char *moh = NULL;
+	switch_thread_t *thread = NULL;
+	switch_threadattr_t *thd_attr = NULL;
+	char *camp_data = NULL;
+	switch_status_t status;
+	
 	if (switch_strlen_zero(data)) {
 		return;
 	}
@@ -2068,7 +2102,133 @@ SWITCH_STANDARD_APP(audio_bridge_function)
 	continue_on_fail = switch_channel_get_variable(caller_channel, "continue_on_fail");
 	failure_causes = switch_channel_get_variable(caller_channel, "failure_causes");
 
-	if (switch_ivr_originate(session, &peer_session, &cause, data, 0, NULL, NULL, NULL, NULL, NULL, SOF_NONE) != SWITCH_STATUS_SUCCESS) {
+	if ((v_campon = switch_channel_get_variable(caller_channel, "campon")) && switch_true(v_campon)) {
+		const char *cid_name = NULL;
+		const char *cid_number = NULL;
+		
+		if (!(cid_name = switch_channel_get_variable(caller_channel, "effective_caller_id_name"))) {
+			cid_name = switch_channel_get_variable(caller_channel, "caller_id_name");
+		}
+
+		if (!(cid_number = switch_channel_get_variable(caller_channel, "effective_caller_id_number"))) {
+			cid_number = switch_channel_get_variable(caller_channel, "caller_id_number");
+		}
+
+		if (cid_name && !cid_number) {
+			cid_number = cid_name;
+		}
+
+		if (cid_number && !cid_name) {
+			cid_name = cid_number;
+		}
+
+		v_campon_retries = switch_channel_get_variable(caller_channel, "campon_retries");
+		v_campon_timeout = switch_channel_get_variable(caller_channel, "campon_timeout");
+		v_campon_sleep = switch_channel_get_variable(caller_channel, "campon_sleep");
+		v_campon_fallback_exten = switch_channel_get_variable(caller_channel, "campon_fallback_exten");
+		
+		if (v_campon_retries) {
+			if ((tmp = atoi(v_campon_retries)) > 0) {
+				campon_retries = tmp;
+			}
+		}
+
+		if (v_campon_timeout) {
+			if ((tmp = atoi(v_campon_timeout)) > 0) {
+				campon_timeout = tmp;
+			}
+		}
+
+		if (v_campon_sleep) {
+			if ((tmp = atoi(v_campon_sleep)) > 0) {
+				campon_sleep = tmp;
+			}
+		}
+
+		switch_channel_answer(caller_channel);
+		camping = 1;
+
+		if (cid_name && cid_number) {
+			camp_data = switch_core_session_sprintf(session, "{origination_caller_id_name='%s',origination_caller_id_number='%s'}%s", 
+													cid_name, cid_number, data);
+		} else {
+			camp_data = (char *)data;
+		}
+
+		if (!(moh = switch_channel_get_variable(caller_channel, "hold_music"))) {
+			moh = switch_channel_get_variable(caller_channel, "campon_hold_music");
+		}
+
+		do {
+			fail = 0;
+			status = switch_ivr_originate(NULL, &peer_session, &cause, camp_data, campon_timeout, NULL, NULL, NULL, NULL, NULL, SOF_NONE);
+			
+			if (!switch_channel_ready(caller_channel)) {
+				fail = 1;
+				break;
+			}
+			
+			if (status == SWITCH_STATUS_SUCCESS) {
+				camping = 0;
+				break;
+			} else {
+				fail = 1;
+			}
+			
+			if (camping) {
+				
+				if (!thread_started && fail && moh && !switch_channel_test_flag(caller_channel, CF_PROXY_MODE) && 
+					!switch_channel_test_flag(caller_channel, CF_PROXY_MEDIA) &&
+					!switch_true(switch_channel_get_variable(caller_channel, "bypass_media"))) {
+					switch_threadattr_create(&thd_attr, switch_core_session_get_pool(session));
+					switch_threadattr_stacksize_set(thd_attr, SWITCH_THREAD_STACKSIZE);
+					stake.running = 1;
+					stake.moh = moh;
+					stake.session = session;
+					switch_thread_create(&thread, thd_attr, camp_music_thread, &stake, switch_core_session_get_pool(session));
+					thread_started = 1;
+				}
+
+
+				if (--campon_retries <= 0) {
+					camping = 0;
+					do_xfer = 1;
+					break;
+				}
+
+				if (fail) {
+					int64_t wait = campon_sleep * 1000000;
+					
+					while(wait > 0 && switch_channel_ready(caller_channel)) {
+						switch_yield(100000);
+						wait -= 100000;
+					}
+				}
+			}
+		} while (camping);
+		
+		if (thread) {
+			stake.running = 0;
+			switch_channel_set_flag(caller_channel, CF_NOT_READY);
+			switch_thread_join(&status, thread);
+			switch_channel_clear_flag(caller_channel, CF_NOT_READY);
+		}
+		
+		if (do_xfer && !switch_strlen_zero(v_campon_fallback_exten)) {
+			switch_ivr_session_transfer(session, 
+										v_campon_fallback_exten, 
+										switch_channel_get_variable(caller_channel, "campon_fallback_dialplan"),
+										switch_channel_get_variable(caller_channel, "campon_fallback_context"));
+			return;
+		}
+
+	} else {
+		if ((status = switch_ivr_originate(session, &peer_session, &cause, data, 0, NULL, NULL, NULL, NULL, NULL, SOF_NONE)) != SWITCH_STATUS_SUCCESS) {
+			fail = 1;
+		}
+	}
+
+	if (fail) {
 		switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_INFO, "Originate Failed.  Cause: %s\n", switch_channel_cause2str(cause));
 
 		/* 
diff --git a/src/switch_channel.c b/src/switch_channel.c
index 7bb78be23f..1e2af783d4 100644
--- a/src/switch_channel.c
+++ b/src/switch_channel.c
@@ -1080,7 +1080,7 @@ SWITCH_DECLARE(int) switch_channel_test_ready(switch_channel_t *channel, switch_
 	ret = 0;
 
 	if (!channel->hangup_cause && channel->state > CS_ROUTING && channel->state < CS_HANGUP && channel->state != CS_RESET &&
-		!switch_channel_test_flag(channel, CF_TRANSFER)) {
+		!switch_channel_test_flag(channel, CF_TRANSFER) && !switch_channel_test_flag(channel, CF_NOT_READY)) {
 		ret++;
 	}
 
diff --git a/src/switch_ivr_originate.c b/src/switch_ivr_originate.c
index 7407f5d4c8..2f9cbafbff 100644
--- a/src/switch_ivr_originate.c
+++ b/src/switch_ivr_originate.c
@@ -395,6 +395,12 @@ static uint8_t check_channel_status(originate_global_t *oglobals, originate_stat
 		}
 
 		if (switch_channel_test_flag(originate_status[i].peer_channel, CF_EARLY_MEDIA)) {
+			if (oglobals->ignore_early_media == 2 && len == 1 && caller_channel && !oglobals->ignore_ring_ready) {
+				switch_channel_pass_callee_id(originate_status[0].peer_channel, caller_channel);
+				switch_channel_ring_ready(caller_channel);
+				oglobals->sent_ring = 1;
+			}
+
 			if (!originate_status[i].early_media) {
 				originate_status[i].early_media = 1;
 				if (oglobals->early_ok) {
@@ -765,6 +771,10 @@ SWITCH_DECLARE(switch_status_t) switch_ivr_wait_for_answer(switch_core_session_t
 			}
 		}
 		
+		if (switch_channel_test_flag(caller_channel, CF_DISABLE_RINGBACK)) {
+			ringback_data = NULL;
+		}
+
 		if (ringback_data) {
 			char *tmp_data = NULL;
 
@@ -1301,9 +1311,14 @@ SWITCH_DECLARE(switch_status_t) switch_ivr_originate(switch_core_session_t *sess
 		*oglobals.file = '\0';
 	}
 
-	if ((var_val = switch_event_get_header(var_event, "ignore_early_media")) && switch_true(var_val)) {
-		oglobals.early_ok = 0;
-		oglobals.ignore_early_media = 1;
+	if ((var_val = switch_event_get_header(var_event, "ignore_early_media"))) {
+		if (switch_true(var_val)) {
+			oglobals.early_ok = 0;
+			oglobals.ignore_early_media = 1;
+		} else if (!strcmp(var_val, "ring_ready")) {
+			oglobals.early_ok = 0;
+			oglobals.ignore_early_media = 2;
+		}
 	}
 
 	if ((var_val = switch_event_get_header(var_event, "originate_continue_on_timeout")) && switch_true(var_val)) {
@@ -1855,7 +1870,8 @@ SWITCH_DECLARE(switch_status_t) switch_ivr_originate(switch_core_session_t *sess
 		endfor1:
 
 			if (caller_channel) {
-				if (switch_channel_test_flag(caller_channel, CF_PROXY_MODE) || switch_channel_test_flag(caller_channel, CF_PROXY_MEDIA)) {
+				if (switch_channel_test_flag(caller_channel, CF_PROXY_MODE) || 
+					switch_channel_test_flag(caller_channel, CF_PROXY_MEDIA) || switch_channel_test_flag(caller_channel, CF_DISABLE_RINGBACK)) {
 					ringback_data = NULL;
 				}
 			}