Index: apps/app_dial.c
===================================================================
RCS file: /usr/src/asterisk-1.0.7/apps/app_dial.c,v
retrieving revision 1.1.1.1
diff -u -r1.1.1.1 app_dial.c
--- apps/app_dial.c	22 Feb 2005 21:36:10 -0000	1.1.1.1
+++ apps/app_dial.c	23 Feb 2005 03:02:33 -0000
@@ -135,7 +135,7 @@
 
 #define AST_MAX_WATCHERS 256
 
-static struct ast_channel *wait_for_answer(struct ast_channel *in, struct localuser *outgoing, int *to, int *allowredir_in, int *allowredir_out, int *allowdisconnect_in, int *allowdisconnect_out, int *noforwardhtml, int *sentringing, char *status, size_t statussize)
+static struct ast_channel *wait_for_answer(struct ast_channel *in, struct localuser *outgoing, int *to, int *allowredir_in, int *allowredir_out, int *allowdisconnect_in, int *allowdisconnect_out, int *noforwardhtml, int *sentringing, char *status, size_t statussize, int *go_on)
 {
 	struct localuser *o;
 	int found;
@@ -396,8 +396,17 @@
 				strncpy(status, "CANCEL", statussize - 1);
 				if (f)
 					ast_frfree(f);
 				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 */
+				*go_on = 1;
+ 				ast_frfree(f);
+ 				return NULL;
+ 			}
+
 			if (f && (f->frametype == AST_FRAME_DTMF) && *allowdisconnect_out &&
 				(f->subclass == '*')) {
 			    if (option_verbose > 3)
@@ -902,7 +902,7 @@
 		strncpy(status, "CHANUNAVAIL", sizeof(status) - 1);
 
 	time(&start_time);
-	peer = wait_for_answer(chan, outgoing, &to, &allowredir_in, &allowredir_out, &allowdisconnect_in, &allowdisconnect_out, &sentringing, &noforwardhtml, status, sizeof(status));
+	peer = wait_for_answer(chan, outgoing, &to, &allowredir_in, &allowredir_out, &allowdisconnect_in, &allowdisconnect_out, &sentringing, &noforwardhtml, status, sizeof(status), &go_on);
 
 	if (!peer) {
 		if (to) 
Index: channels/chan_sip.c
===================================================================
RCS file: /usr/src/asterisk-1.0.7/channels/chan_sip.c,v
retrieving revision 1.1.1.1
diff -u -r1.1.1.1 chan_sip.c
--- channels/chan_sip.c	22 Feb 2005 21:36:10 -0000	1.1.1.1
+++ channels/chan_sip.c	23 Feb 2005 03:02:33 -0000
@@ -7422,14 +7422,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);
-						p->alreadygone = 1;
+					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);
+							p->alreadygone = 1;
+						}
 						/* 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/src/asterisk-1.0.7/configs/features.conf.sample,v
retrieving revision 1.1.1.1
diff -u -r1.1.1.1 features.conf.sample
--- configs/features.conf.sample	22 Feb 2005 21:36:11 -0000	1.1.1.1
+++ configs/features.conf.sample	23 Feb 2005 03:02:33 -0000
@@ -13,3 +13,8 @@
 				; when someone dials a parked call
 ;adsipark = yes			; if you want ADSI parking announcements
 ;pickupexten = *8		; Configure the pickup extension.  Default is *8
+
+;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
+
Index: include/asterisk/frame.h
===================================================================
RCS file: /usr/src/asterisk-1.0.7/include/asterisk/frame.h,v
retrieving revision 1.1.1.1
diff -u -r1.1.1.1 frame.h
--- include/asterisk/frame.h	22 Feb 2005 21:36:11 -0000	1.1.1.1
+++ include/asterisk/frame.h	23 Feb 2005 03:02:33 -0000
@@ -222,6 +222,9 @@
 #define AST_CONTROL_PROGRESS            14
 /*! Indicate CALL PROCEEDING */
 #define AST_CONTROL_PROCEEDING		15
+/*! 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/src/asterisk-1.0.7/res/res_features.c,v
retrieving revision 1.1.1.1
diff -u -r1.1.1.1 res_features.c
--- res/res_features.c	22 Feb 2005 21:36:11 -0000	1.1.1.1
+++ res/res_features.c	23 Feb 2005 03:02:33 -0000
@@ -76,6 +76,11 @@
 
 static int transferdigittimeout = DEFAULT_TRANSFER_DIGIT_TIMEOUT;
 
+/* the alternative pickup code is off by default */
+static int alternative_pickup = 0;
+/* by default wait 4 seconds before bringing back the call */
+static char alternative_pickup_wait[10] = "3";
+
 /* Default courtesy tone played when party joins conference */
 static char courtesytone[256] = "";
 
@@ -969,6 +972,12 @@
 				strncpy(courtesytone, var->value, sizeof(courtesytone) - 1);
 			} else if (!strcasecmp(var->name, "pickupexten")) {
 				strncpy(pickup_ext, var->value, sizeof(pickup_ext) - 1);
+			} 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)) {
+					strncpy(alternative_pickup_wait, var->value, sizeof(alternative_pickup_wait) - 1);
+				}
 			}
 			var = var->next;
 		}
@@ -993,11 +1004,89 @@
 	return res;
 }
 
+/* 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;
 	int res = -1;
 	cur = ast_channel_walk_locked(NULL);
+	if (alternative_pickup) {
+		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) {
+			int callerid_ok = 0;
+			char cid[256];
+			char *l = NULL, *n=NULL;
+
+			/* change the pbx info for this call */
+			if (!ast_exists_extension(cur, PICKUP_WAIT_CONTEXT, PICKUP_WAIT_EXTEN, 1, cur->callerid)) {
+				/* 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, PICKUP_WAIT_APP1, strdup(PICKUP_WAIT_ARG1), free, registrar);
+				ast_add_extension2(con, 1, PICKUP_WAIT_EXTEN, 2, NULL, PICKUP_WAIT_APP2, strdup(PICKUP_WAIT_ARG2), free, registrar);
+			}
+			if (chan->callerid && strlen(chan->callerid)) {
+				strncpy(cid, chan->callerid, sizeof(cid) - 1);
+				ast_callerid_parse(cid, &n, &l);
+				if (l) 
+					ast_shrink_phone_number(l);
+				if (l && strlen(l))
+					callerid_ok = 1;
+			}
+			if (!callerid_ok) {
+				ast_mutex_unlock(&cur->lock);
+				cur = ast_channel_walk_locked(NULL);
+				goto regular_method;
+			}
+			pbx_builtin_setvar_helper(cur, PICKUP_EXTEN, l);
+			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:
+
 	while(cur) {
 		if (!cur->pbx && 
 			(cur != chan) &&
