Index: apps/app_dial.c
===================================================================
RCS file: /usr/cvsroot/asterisk-1.2.0/apps/app_dial.c,v
retrieving revision 1.1.1.1
diff -u -r1.1.1.1 app_dial.c
--- apps/app_dial.c	5 Dec 2005 02:56:37 -0000	1.1.1.1
+++ apps/app_dial.c	5 Dec 2005 02:58:17 -0000
@@ -671,6 +671,15 @@
 				return NULL;
 			}
 
+  			if (f && (f->frametype == AST_FRAME_CONTROL) && (f->subclass == AST_CONTROL_EXIT_APP_DIAL)) {
+  				/* Received the exit app dial frame */
+  				/* make is so that dial exits without hanging up */
+				ast_set_flag(peerflags, OPT_GO_ON);
+  				ast_frfree(f);
+				ast_verbose("status is %s\n", status);
+  				return NULL;
+  			}
+ 
 			if (f && (f->frametype == AST_FRAME_DTMF)) {
 				if (ast_test_flag(peerflags, OPT_DTMF_EXIT)) {
 					context = pbx_builtin_getvar_helper(in, "EXITCONTEXT");
Index: channels/chan_sip.c
===================================================================
RCS file: /usr/cvsroot/asterisk-1.2.0/channels/chan_sip.c,v
retrieving revision 1.1.1.1
diff -u -r1.1.1.1 chan_sip.c
--- channels/chan_sip.c	5 Dec 2005 02:56:37 -0000	1.1.1.1
+++ channels/chan_sip.c	5 Dec 2005 02:58:17 -0000
@@ -10419,14 +10419,19 @@
 					c = NULL;
 				}
 			} else {
+				int result = 0;
 				ast_mutex_unlock(&c->lock);
-				if (ast_pickup_call(c)) {
-					ast_log(LOG_NOTICE, "Nothing to pick up\n");
-					if (ignore)
-						transmit_response(p, "503 Unavailable", req);
-					else
-						transmit_response_reliable(p, "503 Unavailable", req, 1);
-					ast_set_flag(p, SIP_ALREADYGONE);	
+				if ((result = ast_pickup_call(c))) {
+					if (result == -2) {
+						sip_answer(c);
+					} else {
+						ast_log(LOG_NOTICE, "Nothing to pick up\n");
+						if (ignore)
+							transmit_response(p, "503 Unavailable", req);
+						else
+							transmit_response_reliable(p, "503 Unavailable", req, 1);
+						ast_set_flag(p, SIP_ALREADYGONE);	
+					}
 					/* Unlock locks so ast_hangup can do its magic */
 					ast_mutex_unlock(&p->lock);
 					ast_hangup(c);
Index: configs/features.conf.sample
===================================================================
RCS file: /usr/cvsroot/asterisk-1.2.0/configs/features.conf.sample,v
retrieving revision 1.1.1.1
diff -u -r1.1.1.1 features.conf.sample
--- configs/features.conf.sample	5 Dec 2005 02:56:37 -0000	1.1.1.1
+++ configs/features.conf.sample	5 Dec 2005 02:58:17 -0000
@@ -19,6 +19,9 @@
 ;featuredigittimeout = 500	; Max time (ms) between digits for 
 				; feature activation.  Default is 500
 
+;alternative_pickup = yes	; Use alternative way to pickup the calls
+;alternative_pickup_wait = 4	; Wait that many seconds before bringing
+ 				; the call to your interface
 
 [featuremap]
 ;blindxfer => #1		; Blind transfer
Index: include/asterisk/frame.h
===================================================================
RCS file: /usr/cvsroot/asterisk-1.2.0/include/asterisk/frame.h,v
retrieving revision 1.1.1.1
diff -u -r1.1.1.1 frame.h
--- include/asterisk/frame.h	5 Dec 2005 02:56:37 -0000	1.1.1.1
+++ include/asterisk/frame.h	5 Dec 2005 02:58:18 -0000
@@ -243,6 +243,9 @@
 #define AST_CONTROL_UNHOLD			17
 /*! Indicate video frame update */
 #define AST_CONTROL_VIDUPDATE		18
+/*! Exit app_dial and continue pbx */
+#define AST_CONTROL_EXIT_APP_DIAL	30
+
 
 #define AST_SMOOTHER_FLAG_G729		(1 << 0)
 
Index: res/res_features.c
===================================================================
RCS file: /usr/cvsroot/asterisk-1.2.0/res/res_features.c,v
retrieving revision 1.1.1.1
diff -u -r1.1.1.1 res_features.c
--- res/res_features.c	5 Dec 2005 02:56:37 -0000	1.1.1.1
+++ res/res_features.c	5 Dec 2005 02:58:18 -0000
@@ -108,6 +108,11 @@
 static int transferdigittimeout;
 static int featuredigittimeout;
 
+/* the alternative pickup code is off by default */
+static int alternative_pickup = 0;
+/* by default wait 3 seconds before bringing back the call */
+static char alternative_pickup_wait[10] = "3";
+
 /* Default courtesy tone played when party joins conference */
 
 /* Registrar for operations */
@@ -1906,12 +1911,79 @@
         return RESULT_SUCCESS;
 }
 
+/* Alternative pickup code implemented by	*/
+/* Martin Pycko (m78pl@yahoo.com)		*/
+/* ************					*/
+/* Enjoy!					*/
+
+#define PICKUP_CONTEXT		"PICKUP_CONTEXT"
+#define PICKUP_EXTEN		"PICKUP_EXTEN"
+#define PICKUP_WAIT_CONTEXT	"pickup_wait_context"
+#define PICKUP_WAIT_EXTEN	"s"
+#define PICKUP_WAIT_APP1	"Wait"
+#define PICKUP_WAIT_ARG1	alternative_pickup_wait
+#define PICKUP_WAIT_APP2	"Goto"
+#define PICKUP_WAIT_ARG2	"${" PICKUP_CONTEXT "}|${" PICKUP_EXTEN "}|1"
 
 int ast_pickup_call(struct ast_channel *chan)
 {
 	struct ast_channel *cur = NULL;
 	int res = -1;
 
+	if (alternative_pickup) {
+		cur = ast_channel_walk_locked(NULL);
+		while(cur) {
+			if (cur->pbx && 
+				(cur != chan) &&
+				(cur->callgroup ? chan->pickupgroup & cur->callgroup : 1) &&
+				((cur->_state == AST_STATE_RINGING) ||
+				 (cur->_state == AST_STATE_RING))) {
+					break;
+			}
+			ast_mutex_unlock(&cur->lock);
+			cur = ast_channel_walk_locked(cur);
+		}
+		if (cur) {
+			/* change the pbx info for this call */
+			if (!ast_exists_extension(cur, PICKUP_WAIT_CONTEXT, PICKUP_WAIT_EXTEN, 1, cur->cid.cid_num)) {
+				/* add our extensions to the dialplan */
+				struct ast_context *con = ast_context_find(PICKUP_WAIT_CONTEXT);
+				if (!con) {
+					con = ast_context_create(NULL, PICKUP_WAIT_CONTEXT, registrar);
+					if (!con) {
+						ast_log(LOG_ERROR, "New pickup logic can't create the '%s' context for channel %s\n", PICKUP_WAIT_CONTEXT, chan->name);
+						ast_mutex_unlock(&cur->lock);
+						cur = ast_channel_walk_locked(NULL);
+						goto regular_method;
+					}
+				}
+				ast_add_extension2(con, 1, PICKUP_WAIT_EXTEN, 1, NULL, NULL, PICKUP_WAIT_APP1, strdup(PICKUP_WAIT_ARG1), free, registrar);
+				ast_add_extension2(con, 1, PICKUP_WAIT_EXTEN, 2, NULL, NULL, PICKUP_WAIT_APP2, strdup(PICKUP_WAIT_ARG2), free, registrar);
+			}
+			/* no callerid ... won't be able to insert a pickup extension */
+			if (!(chan->cid.cid_num && strlen(chan->cid.cid_num))) {
+				ast_mutex_unlock(&cur->lock);
+				goto regular_method;
+			}
+			pbx_builtin_setvar_helper(cur, PICKUP_EXTEN, chan->cid.cid_num);
+			pbx_builtin_setvar_helper(cur, PICKUP_CONTEXT, chan->context);
+			strcpy(cur->context, PICKUP_WAIT_CONTEXT);
+			strcpy(cur->exten, PICKUP_WAIT_EXTEN);
+			cur->priority = 0;
+
+			/* exit app dial -> stop ringing any phones */
+			ast_queue_control(cur, AST_CONTROL_EXIT_APP_DIAL);
+			ast_mutex_unlock(&cur->lock);
+			ast_verbose(VERBOSE_PREFIX_3 "Channel %s will receive a call from channel %s in %s seconds.\n", chan->name, cur->name, alternative_pickup_wait);
+			/* hangup the calling channel as though there would not be pick_ext defined */
+			/* make it so that the SIP channel driver doesn't write 'Nothing to pick up' */
+			return -2;
+		}
+	}
+
+regular_method:
+	cur = NULL;
+
 	while ( (cur = ast_channel_walk_locked(cur)) != NULL) {
 		if (!cur->pbx && 
 			(cur != chan) &&
@@ -2020,6 +2092,12 @@
 				ast_copy_string(xferfailsound, var->value, sizeof(xferfailsound));
 			} else if (!strcasecmp(var->name, "pickupexten")) {
 				ast_copy_string(pickup_ext, var->value, sizeof(pickup_ext));
+ 			} else if (!strcasecmp(var->name, "alternative_pickup")) {
+ 				alternative_pickup = ast_true(var->value);
+ 			} else if (!strcasecmp(var->name, "alternative_pickup_wait")) {
+ 				if (atoi(var->value)) {
+ 					ast_copy_string(alternative_pickup_wait, var->value, sizeof(alternative_pickup_wait));
+ 				}
 			}
 			var = var->next;
 		}

