[Freeswitch-svn] [commit] r4773 - in freeswitch/trunk/src: . include mod/languages/mod_spidermonkey

Freeswitch SVN anthm at freeswitch.org
Mon Mar 26 20:40:53 EDT 2007


Author: anthm
Date: Mon Mar 26 20:40:53 2007
New Revision: 4773

Modified:
   freeswitch/trunk/src/include/switch_core.h
   freeswitch/trunk/src/include/switch_module_interfaces.h
   freeswitch/trunk/src/include/switch_types.h
   freeswitch/trunk/src/mod/languages/mod_spidermonkey/mod_spidermonkey.c
   freeswitch/trunk/src/mod/languages/mod_spidermonkey/mod_spidermonkey.h
   freeswitch/trunk/src/switch_core.c

Log:
Add state change i/o hook to the core and change some spidermonkey behaviour.

The most important thing to check is you now must create a new session with a blank constructor:
s = new Session();
then call s.originate() with all the former args that were documented to be for the constructor
this will will return true or false to indicate if the call worked.

See below this sample code demonstrates all of the changes:

////////////////////////////////////////////////////////////////////////////////
function on_hangup(hup_session)
{
    console_log("debug", "HANGUP!!!! name: " + hup_session.name + " cause: " + hup_session.cause + "\n");
	//exit here would end the script so you could cleanup and just be done
	//exit();
}

//set the on_hangup function to be called when this session is hungup
session.setHangupHook(on_hangup);

//allocate a new b_session
var b_session = new Session();

//make a call with b_session.  If this fails, all we will be able to access is the b_session.cause attr
if (b_session.originate(session, "sofia/mydomain.com/888 at conference.freeswitch.org")) {
	//Inform the scripting engine to automaticly hang this session up when the script ends
    b_session.setAutoHangup(true);
	//set the on_hangup function to be called when this session is hungup
    b_session.setHangupHook(on_hangup);	
	//bridge session with b_session
    bridge(session, b_session);
} else {
    console_log("debug", "Originate Failed.. cause: " + b_session.cause + "\n");
}
////////////////////////////////////////////////////////////////////////////////






Modified: freeswitch/trunk/src/include/switch_core.h
==============================================================================
--- freeswitch/trunk/src/include/switch_core.h	(original)
+++ freeswitch/trunk/src/include/switch_core.h	Mon Mar 26 20:40:53 2007
@@ -856,6 +856,15 @@
   \return SWITCH_STATUS_SUCCESS on suceess
 */
 SWITCH_DECLARE(switch_status_t) switch_core_session_add_event_hook_send_dtmf(switch_core_session_t *session, switch_send_dtmf_hook_t send_dtmf);
+
+/*! 
+  \brief Add an event hook to be executed when a session receives a state change signal
+  \param session session to bind hook to
+  \param state_change hook to bind
+  \return SWITCH_STATUS_SUCCESS on suceess
+*/
+SWITCH_DECLARE(switch_status_t) switch_core_session_add_event_hook_state_change(switch_core_session_t *session,
+																				switch_answer_channel_hook_t state_change);
 ///\}
 
 ///\defgroup hashf Hash Functions

Modified: freeswitch/trunk/src/include/switch_module_interfaces.h
==============================================================================
--- freeswitch/trunk/src/include/switch_module_interfaces.h	(original)
+++ freeswitch/trunk/src/include/switch_module_interfaces.h	Mon Mar 26 20:40:53 2007
@@ -145,6 +145,13 @@
 	struct switch_io_event_hook_send_dtmf *next;
 };
 
+/*! \brief Node in which to store state change callback hooks */
+struct switch_io_event_hook_state_change {
+	/*! the send dtmf channel callback hook*/
+	switch_state_change_hook_t state_change;
+	struct switch_io_event_hook_state_change *next;
+};
+
 /*! \brief A table of lists of io_event_hooks to store the event hooks associated with a session */
 struct switch_io_event_hooks {
 	/*! a list of outgoing channel hooks */
@@ -167,6 +174,8 @@
 	switch_io_event_hook_waitfor_write_t *waitfor_write;
 	/*! a list of send dtmf hooks */
 	switch_io_event_hook_send_dtmf_t *send_dtmf;
+	/*! a list of state change hooks */
+	switch_io_event_hook_state_change_t *state_change;
 };
 
 /*! \brief A table of i/o routines that an endpoint interface can implement */
@@ -191,6 +200,8 @@
 	switch_status_t (*receive_message)(switch_core_session_t *, switch_core_session_message_t *);
 	/*! queue a message for another session*/
 	switch_status_t (*receive_event)(switch_core_session_t *, switch_event_t *);
+	/*! change a sessions channel state */
+	switch_status_t (*state_change)(switch_core_session_t *);
 };
 
 /*! \brief Abstraction of an module endpoint interface

Modified: freeswitch/trunk/src/include/switch_types.h
==============================================================================
--- freeswitch/trunk/src/include/switch_types.h	(original)
+++ freeswitch/trunk/src/include/switch_types.h	Mon Mar 26 20:40:53 2007
@@ -954,6 +954,7 @@
 typedef struct switch_io_event_hook_waitfor_read switch_io_event_hook_waitfor_read_t;
 typedef struct switch_io_event_hook_waitfor_write switch_io_event_hook_waitfor_write_t;
 typedef struct switch_io_event_hook_send_dtmf switch_io_event_hook_send_dtmf_t;
+typedef struct switch_io_event_hook_state_change switch_io_event_hook_state_change_t;
 typedef struct switch_io_routines switch_io_routines_t;
 typedef struct switch_io_event_hooks switch_io_event_hooks_t;
 typedef struct switch_speech_handle switch_speech_handle_t;
@@ -989,6 +990,7 @@
 typedef switch_status_t (*switch_waitfor_read_hook_t)(switch_core_session_t *, int, int);
 typedef switch_status_t (*switch_waitfor_write_hook_t)(switch_core_session_t *, int, int);
 typedef switch_status_t (*switch_send_dtmf_hook_t)(switch_core_session_t *, char *);
+typedef switch_status_t (*switch_state_change_hook_t)(switch_core_session_t *);
 typedef struct switch_stream_handle switch_stream_handle_t;
 typedef switch_status_t (*switch_stream_handle_write_function_t)(switch_stream_handle_t *handle, const char *fmt, ...);
 typedef switch_status_t (*switch_api_function_t)(char *in, switch_core_session_t *session, switch_stream_handle_t *stream);

Modified: freeswitch/trunk/src/mod/languages/mod_spidermonkey/mod_spidermonkey.c
==============================================================================
--- freeswitch/trunk/src/mod/languages/mod_spidermonkey/mod_spidermonkey.c	(original)
+++ freeswitch/trunk/src/mod/languages/mod_spidermonkey/mod_spidermonkey.c	Mon Mar 26 20:40:53 2007
@@ -43,6 +43,7 @@
 
 static void session_destroy(JSContext *cx, JSObject *obj);
 static JSBool session_construct(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval);
+static JSBool session_originate(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval);
 static switch_api_interface_t js_run_interface;
 
 static struct {
@@ -79,7 +80,8 @@
 typedef struct sm_loadable_module sm_loadable_module_t;
 
 typedef enum {
-	S_HUP = (1 << 0)
+	S_HUP = (1 << 0),
+	S_FREE = (1 << 1)
 } session_flag_t;
 
 struct input_callback_state {
@@ -640,7 +642,8 @@
 	jsval argv[4];
 	JSObject *Event = NULL;
 
-	if (!jss) {
+	if (!jss || !jss->session) {
+		switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_WARNING, "You must call the session.originate method before calling this method!\n");
 		return SWITCH_STATUS_FALSE;
 	}
 
@@ -822,15 +825,15 @@
 	switch_size_t has;
 	switch_channel_t *channel;
 
+	if (!jss || !jss->session) {
+		switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_WARNING, "You must call the session.originate method before calling this method!\n");
+		*rval = BOOLEAN_TO_JSVAL( JS_FALSE );
+		return JS_TRUE;
+	}
+
 	channel = switch_core_session_get_channel(jss->session);
     assert(channel != NULL);
 
-    if (!switch_channel_ready(channel)) {
-        switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Session is not active!\n");
-        *rval = BOOLEAN_TO_JSVAL( JS_FALSE );
-        return JS_TRUE;
-    }
-
 	while ((has = switch_channel_has_dtmf(channel))) {
 		switch_channel_dequeue_dtmf(channel, buf, sizeof(buf));
 	}
@@ -845,14 +848,14 @@
 	switch_event_t *event;
     switch_channel_t *channel;
 
+	if (!jss || !jss->session) {
+		*rval = BOOLEAN_TO_JSVAL( JS_FALSE );
+		return JS_TRUE;
+	}
+
     channel = switch_core_session_get_channel(jss->session);
     assert(channel != NULL);
 
-    if (!switch_channel_ready(channel)) {
-        switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Session is not active!\n");
-        *rval = BOOLEAN_TO_JSVAL( JS_FALSE );
-        return JS_TRUE;
-    }
 
 	while (switch_core_session_dequeue_event(jss->session, &event) == SWITCH_STATUS_SUCCESS) {
 		switch_event_destroy(&event);
@@ -877,6 +880,12 @@
     int32 limit = 0;
     switch_input_args_t args = {0};
 
+	if (!jss || !jss->session) {
+		switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_WARNING, "You must call the session.originate method before calling this method!\n");
+		*rval = BOOLEAN_TO_JSVAL( JS_FALSE );
+		return JS_TRUE;
+	}
+
 	channel = switch_core_session_get_channel(jss->session);
 	assert(channel != NULL);
 
@@ -953,6 +962,13 @@
 	JSFunction *function;
     switch_input_args_t args = {0};
 
+
+	if (!jss || !jss->session) {
+		switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_WARNING, "You must call the session.originate method before calling this method!\n");
+		*rval = BOOLEAN_TO_JSVAL( JS_FALSE );
+		return JS_TRUE;
+	}
+
 	channel = switch_core_session_get_channel(jss->session);
 	assert(channel != NULL);
 
@@ -1014,6 +1030,12 @@
 	JSFunction *function;
     switch_input_args_t args = {0};
 
+	if (!jss || !jss->session) {
+		switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_WARNING, "You must call the session.originate method before calling this method!\n");
+		*rval = BOOLEAN_TO_JSVAL( JS_FALSE );
+		return JS_TRUE;
+	}
+
 	channel = switch_core_session_get_channel(jss->session);
 	assert(channel != NULL);
 
@@ -1074,6 +1096,55 @@
 	return JS_TRUE;
 }
 
+static void check_hangup_hook(struct js_session *jss)
+{
+	jsval argv[2] = {0};
+	int argc = 0;
+	jsval ret;
+	if (jss->on_hangup ) {
+		argv[argc++] = OBJECT_TO_JSVAL(jss->obj);			
+		JS_CallFunction(jss->cx, jss->obj, jss->on_hangup, argc, argv, &ret);
+	}
+}
+
+static switch_status_t hanguphook(switch_core_session_t *session)
+{
+	switch_channel_t *channel;
+	struct js_session *jss = NULL;
+
+	channel = switch_core_session_get_channel(session);
+	assert(channel != NULL);
+	if (switch_channel_get_state(channel) == CS_HANGUP) {
+		if ((jss = switch_channel_get_private(channel, "jss"))) {
+			check_hangup_hook(jss);
+		}
+	}
+
+	return SWITCH_STATUS_SUCCESS;
+}
+
+static JSBool session_hanguphook(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval)
+{
+	JSFunction *function;
+	struct js_session *jss;
+	*rval = BOOLEAN_TO_JSVAL( JS_FALSE );
+
+	if ((jss = JS_GetPrivate(cx, obj)) && jss->session) {
+		if (argc > 0) {
+			if ((function = JS_ValueToFunction(cx, argv[0]))) {
+				switch_channel_t *channel = switch_core_session_get_channel(jss->session);
+				assert(channel != NULL);
+				jss->on_hangup = function;
+				switch_channel_set_private(channel, "jss", jss);
+				switch_core_session_add_event_hook_state_change(jss->session, hanguphook);
+				*rval = BOOLEAN_TO_JSVAL( JS_FALSE );
+			}
+		}
+	}
+
+	return JS_TRUE;
+}
+
 static JSBool session_streamfile(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval)
 {
 	struct js_session *jss = JS_GetPrivate(cx, obj);
@@ -1088,6 +1159,12 @@
 	JSFunction *function;
     switch_input_args_t args = {0};
 
+	if (!jss || !jss->session) {
+		switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_WARNING, "You must call the session.originate method before calling this method!\n");
+		*rval = BOOLEAN_TO_JSVAL( JS_FALSE );
+		return JS_TRUE;
+	}
+
 	channel = switch_core_session_get_channel(jss->session);
 	assert(channel != NULL);
 
@@ -1147,16 +1224,15 @@
 	struct js_session *jss = JS_GetPrivate(cx, obj);
     switch_channel_t *channel;
 
+	if (!jss || !jss->session) {
+		switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_WARNING, "You must call the session.originate method before calling this method!\n");
+		*rval = BOOLEAN_TO_JSVAL( JS_FALSE );
+		return JS_TRUE;
+	}
+
 	channel = switch_core_session_get_channel(jss->session);
     assert(channel != NULL);
 
-    if (!switch_channel_ready(channel)) {
-        switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Session is not active!\n");
-        *rval = BOOLEAN_TO_JSVAL( JS_FALSE );
-        return JS_TRUE;
-    }
-
-
 	if (argc > 1) {
 		char *var, *val;
 
@@ -1176,16 +1252,14 @@
 	struct js_session *jss = JS_GetPrivate(cx, obj);
     switch_channel_t *channel;
 
+	if (!jss || !jss->session) {
+		*rval = BOOLEAN_TO_JSVAL( JS_FALSE );
+		return JS_TRUE;
+	}
+
 	channel = switch_core_session_get_channel(jss->session);
     assert(channel != NULL);
 
-    if (!switch_channel_ready(channel)) {
-        switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Session is not active!\n");
-        *rval = BOOLEAN_TO_JSVAL( JS_FALSE );
-        return JS_TRUE;
-    }
-
-
 	if (argc > 0) {
 		char *var, *val;
 		
@@ -1220,6 +1294,12 @@
 	JSFunction *function;
     switch_input_args_t args = {0};
 
+	if (!jss || !jss->session) {
+		switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_WARNING, "You must call the session.originate method before calling this method!\n");
+		*rval = BOOLEAN_TO_JSVAL( JS_FALSE );
+		return JS_TRUE;
+	}
+
 	channel = switch_core_session_get_channel(jss->session);
 	assert(channel != NULL);
 
@@ -1286,6 +1366,12 @@
 	int32 digits = 0, timeout = 5000;
 	switch_channel_t *channel;
 
+	if (!jss || !jss->session) {
+		switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_WARNING, "You must call the session.originate method before calling this method!\n");
+		*rval = BOOLEAN_TO_JSVAL( JS_FALSE );
+		return JS_TRUE;
+	}
+
 	channel = switch_core_session_get_channel(jss->session);
     assert(channel != NULL);
 
@@ -1321,11 +1407,42 @@
 	return JS_FALSE;
 }
 
+static JSBool session_autohangup(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval)
+{
+	struct js_session *jss = JS_GetPrivate(cx, obj);
+	*rval = BOOLEAN_TO_JSVAL(JS_FALSE);
+
+	if (!jss || !jss->session) {
+		switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_WARNING, "You must call the session.originate method before calling this method!\n");
+		*rval = BOOLEAN_TO_JSVAL( JS_FALSE );
+		return JS_TRUE;
+	}
+	
+	if (argv[0]) {
+		JSBool tf;
+		JS_ValueToBoolean(cx, argv[0], &tf);
+		if (tf == JS_TRUE) {
+			switch_set_flag(jss, S_HUP);
+		} else {
+			switch_clear_flag(jss, S_HUP);
+		}
+		*rval = BOOLEAN_TO_JSVAL(tf);
+	}
+
+	return JS_TRUE;
+}
+
 static JSBool session_answer(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval)
 {
 	struct js_session *jss = JS_GetPrivate(cx, obj);
 	switch_channel_t *channel;
 
+	if (!jss || !jss->session) {
+		switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_WARNING, "You must call the session.originate method before calling this method!\n");
+		*rval = BOOLEAN_TO_JSVAL( JS_FALSE );
+		return JS_TRUE;
+	}
+
 	channel = switch_core_session_get_channel(jss->session);
 	assert(channel != NULL);
 
@@ -1349,6 +1466,11 @@
 	/*Always a pessimist... sheesh!*/
 	*rval = BOOLEAN_TO_JSVAL( JS_FALSE );
 
+	if (!jss || !jss->session) {
+		switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_WARNING, "You must call the session.originate method before calling this method!\n");
+		return JS_TRUE;
+	}
+
     if (switch_ivr_generate_xml_cdr(jss->session, &cdr) == SWITCH_STATUS_SUCCESS) {
 		char *xml_text;
 		if ((xml_text = switch_xml_toxml(cdr))) {
@@ -1366,6 +1488,12 @@
 	struct js_session *jss = JS_GetPrivate(cx, obj);
 	switch_channel_t *channel;
 
+	if (!jss || !jss->session) {
+		switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_WARNING, "You must call the session.originate method before calling this method!\n");
+		*rval = BOOLEAN_TO_JSVAL( JS_FALSE );
+		return JS_TRUE;
+	}
+
 	channel = switch_core_session_get_channel(jss->session);
 	assert(channel != NULL);
 
@@ -1384,6 +1512,12 @@
 	unsigned int elapsed;
 	int32 timeout = 60;
 
+	if (!jss || !jss->session) {
+		switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_WARNING, "You must call the session.originate method before calling this method!\n");
+		*rval = BOOLEAN_TO_JSVAL( JS_FALSE );
+		return JS_TRUE;
+	}
+
 	channel = switch_core_session_get_channel(jss->session);
 	assert(channel != NULL);
 
@@ -1419,6 +1553,12 @@
 	unsigned int elapsed;
 	int32 timeout = 60;
 
+	if (!jss || !jss->session) {
+		switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_WARNING, "You must call the session.originate method before calling this method!\n");
+		*rval = BOOLEAN_TO_JSVAL( JS_FALSE );
+		return JS_TRUE;
+	}
+
 	channel = switch_core_session_get_channel(jss->session);
 	assert(channel != NULL);
 
@@ -1451,6 +1591,12 @@
 	switch_channel_t *channel;
     struct js_session *jss = JS_GetPrivate(cx, obj);
 
+	if (!jss || !jss->session) {
+		switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_WARNING, "You must call the session.originate method before calling this method!\n");
+		*rval = BOOLEAN_TO_JSVAL( JS_FALSE );
+		return JS_TRUE;
+	}
+
 	channel = switch_core_session_get_channel(jss->session);
     assert(channel != NULL);
 
@@ -1468,6 +1614,12 @@
 		struct js_session *jss = JS_GetPrivate(cx, obj);
 		jsrefcount saveDepth;
 
+		if (!jss || !jss->session) {
+			switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_WARNING, "You must call the session.originate method before calling this method!\n");
+			*rval = BOOLEAN_TO_JSVAL( JS_FALSE );
+			return JS_TRUE;
+		}
+
 		if ((application_interface = switch_loadable_module_get_application_interface(app_name))) {
 			if (application_interface->application_function) {
 				saveDepth = JS_SuspendRequest(cx);
@@ -1486,17 +1638,12 @@
 {
 	struct js_session *jss = JS_GetPrivate(cx, obj);
 	switch_event_t *event;
-	switch_channel_t *channel;
-
-	channel = switch_core_session_get_channel(jss->session);
-    assert(channel != NULL);
-
-    if (!switch_channel_ready(channel)) {
-        switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Session is not active!\n");
-        *rval = BOOLEAN_TO_JSVAL( JS_FALSE );
-        return JS_TRUE;
-    }
 
+	if (!jss || !jss->session) {
+		switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_WARNING, "You must call the session.originate method before calling this method!\n");
+		*rval = BOOLEAN_TO_JSVAL( JS_FALSE );
+		return JS_TRUE;
+	}
 
 	if (switch_core_session_dequeue_event(jss->session, &event) == SWITCH_STATUS_SUCCESS) {
 		JSObject *Event;
@@ -1528,6 +1675,12 @@
 	JSObject *Event;
 	struct event_obj *eo;
 
+	if (!jss || !jss->session) {
+		switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_WARNING, "You must call the session.originate method before calling this method!\n");
+		*rval = BOOLEAN_TO_JSVAL( JS_FALSE );
+		return JS_TRUE;
+	}
+
 	if (argc > 0) {
 		if (JS_ValueToObject(cx, argv[0], &Event)) {
 			if ((eo = JS_GetPrivate(cx, Event))) {
@@ -1554,6 +1707,12 @@
 	char *cause_name = NULL;
 	switch_call_cause_t cause = SWITCH_CAUSE_NORMAL_CLEARING;
 
+	if (!jss || !jss->session) {
+		switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_WARNING, "You must call the session.originate method before calling this method!\n");
+		*rval = BOOLEAN_TO_JSVAL( JS_FALSE );
+		return JS_TRUE;
+	}
+
 	channel = switch_core_session_get_channel(jss->session);
 	assert(channel != NULL);
 
@@ -1722,10 +1881,13 @@
 /*********************************************************************************/
 enum session_tinyid {
 	SESSION_NAME, SESSION_STATE,
-	PROFILE_DIALPLAN, PROFILE_CID_NAME, PROFILE_CID_NUM, PROFILE_IP, PROFILE_ANI, PROFILE_ANI_II, PROFILE_DEST, SESSION_UUID
+	PROFILE_DIALPLAN, PROFILE_CID_NAME, PROFILE_CID_NUM, PROFILE_IP, PROFILE_ANI, PROFILE_ANI_II, PROFILE_DEST, SESSION_UUID, SESSION_CAUSE
 };
 
 static JSFunctionSpec session_methods[] = {
+	{"originate", session_originate, 2}, 
+	{"setHangupHook", session_hanguphook, 1}, 
+	{"setAutoHangup", session_autohangup, 1}, 
     {"sayPhrase", session_sayphrase, 1}, 
     {"streamFile", session_streamfile, 1}, 
 	{"collectInput", session_collect_input, 1}, 
@@ -1760,6 +1922,7 @@
 	{"aniii", PROFILE_ANI_II, JSPROP_READONLY|JSPROP_PERMANENT}, 
 	{"destination", PROFILE_DEST, JSPROP_READONLY|JSPROP_PERMANENT}, 
 	{"uuid", SESSION_UUID, JSPROP_READONLY|JSPROP_PERMANENT}, 
+	{"cause", SESSION_CAUSE, JSPROP_READONLY|JSPROP_PERMANENT}, 
 	{0}
 };
 
@@ -1767,29 +1930,40 @@
 {
 	struct js_session *jss = JS_GetPrivate(cx, obj);
 	int param = 0;
-	JSBool res = JS_TRUE;
-	switch_channel_t *channel;
-	switch_caller_profile_t *caller_profile;
-	char *name;
-	
-	if (!jss || !jss->session) {
-		return JS_FALSE;
+	switch_channel_t *channel = NULL;
+	switch_caller_profile_t *caller_profile = NULL;
+	char *name = NULL;
+
+	if (jss && jss->session) {
+		channel = switch_core_session_get_channel(jss->session);
+		assert(channel != NULL);
+		caller_profile = switch_channel_get_caller_profile(channel);
 	}
 
-	channel = switch_core_session_get_channel(jss->session);
-	assert(channel != NULL);
-
-	caller_profile = switch_channel_get_caller_profile(channel);
-
 	name = JS_GetStringBytes(JS_ValueToString(cx, id));
+
 	/* numbers are our props anything else is a method */
 	if (name[0] >= 48 && name[0] <= 57) {
 		param = atoi(name);
 	} else {
 		return JS_TRUE;
 	}
-	
+
+	if (!channel) {
+		switch(param) {
+		case SESSION_CAUSE:
+			*vp = STRING_TO_JSVAL (JS_NewStringCopyZ(cx, switch_channel_cause2str(jss->cause)));
+			break;
+		default:
+			*vp = BOOLEAN_TO_JSVAL(JS_FALSE);
+		}
+		return JS_TRUE;
+	}
+
 	switch(param) {
+	case SESSION_CAUSE:
+		*vp = STRING_TO_JSVAL (JS_NewStringCopyZ(cx, switch_channel_cause2str(switch_channel_get_cause(channel))));
+		break;
 	case SESSION_NAME:
 		*vp = STRING_TO_JSVAL(JS_NewStringCopyZ(cx, switch_channel_get_name(channel)));
 		break;
@@ -1835,12 +2009,12 @@
 		}
 		break;
 	default:
-		res = JS_FALSE;
+		*vp = BOOLEAN_TO_JSVAL(JS_FALSE);
 		break;
-
+		
 	}
 
-	return res;
+	return JS_TRUE;
 }
 
 JSClass session_class = {
@@ -1859,7 +2033,7 @@
 		jss->session = session;
 		jss->flags = flags;
 		jss->cx = cx;
-		jss->obj = obj;
+		jss->obj = session_obj;
 		if ((JS_SetPrivate(cx, session_obj, jss) &&
 			 JS_DefineProperties(cx, session_obj, session_props) &&
 			 JS_DefineFunctions(cx, session_obj, session_methods))) {
@@ -1870,18 +2044,36 @@
 	return NULL;
 }
 
-
 /* Session Object */
 /*********************************************************************************/
+
 static JSBool session_construct(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval)
 {
+	struct js_session *jss = NULL;
+
+	assert((jss = malloc(sizeof(*jss))));
+	memset(jss, 0, sizeof(*jss));
+	jss->cx = cx;
+	jss->obj = obj;
+	switch_set_flag(jss, S_FREE);
+
+	JS_SetPrivate(cx, obj, jss);
+
+	return JS_TRUE;
+}
+
+static JSBool session_originate(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval)
+{
+	struct js_session *jss = NULL;
 	switch_memory_pool_t *pool = NULL;
+
+	jss = JS_GetPrivate(cx, obj);
+	jss->cause = SWITCH_CAUSE_DESTINATION_OUT_OF_ORDER;
+
 	if (argc > 1) {
-		switch_call_cause_t cause = SWITCH_CAUSE_NORMAL_CLEARING;
-		struct js_session *jss = NULL;
 		JSObject *session_obj;
 		switch_core_session_t *session = NULL, *peer_session = NULL;
-		switch_caller_profile_t *caller_profile = NULL;
+		switch_caller_profile_t *caller_profile = NULL, *orig_caller_profile = NULL;
 		char *dest = NULL;
 		char *dialplan = NULL;
 		char *cid_name = "";
@@ -1893,12 +2085,22 @@
 		char *context = "";
 		char *username = NULL;
 		char *to = NULL;
-		*rval = BOOLEAN_TO_JSVAL( JS_FALSE );
+
+		*rval = BOOLEAN_TO_JSVAL(JS_FALSE);
 
 		if (JS_ValueToObject(cx, argv[0], &session_obj)) {
 			struct js_session *old_jss = NULL;
 			if ((old_jss = JS_GetPrivate(cx, session_obj))) {
 				session = old_jss->session;
+				orig_caller_profile = switch_channel_get_caller_profile(switch_core_session_get_channel(session));
+				dialplan = orig_caller_profile->dialplan;
+				cid_name = orig_caller_profile->caller_id_name;
+				cid_num = orig_caller_profile->caller_id_number;
+				ani = orig_caller_profile->ani;
+				aniii = orig_caller_profile->aniii;
+				rdnis = orig_caller_profile->rdnis;
+				context = orig_caller_profile->context;
+				username = orig_caller_profile->username;
 			}
 		}
 
@@ -1906,7 +2108,7 @@
 
 		if (!strchr(dest, '/')) {
 			switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_WARNING, "Invalid Channel String\n");
-			return JS_TRUE;
+			goto done;
 		}
 
 		if (argc > 2) {
@@ -1940,7 +2142,6 @@
 			to = JS_GetStringBytes(JS_ValueToString(cx, argv[11]));
 		}
 		
-		
 		if (switch_core_new_memory_pool(&pool) != SWITCH_STATUS_SUCCESS) {
 			switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_CRIT, "OH OH no pool\n");
 			return JS_FALSE;
@@ -1959,41 +2160,45 @@
 												   context,
 												   dest);
 		
-		if (switch_ivr_originate(session, &peer_session, &cause, dest, to ? atoi(to) : 60, NULL, NULL, NULL, caller_profile) != SWITCH_STATUS_SUCCESS) {
+		if (switch_ivr_originate(session, &peer_session, &jss->cause, dest, to ? atoi(to) : 60, NULL, NULL, NULL, caller_profile) != SWITCH_STATUS_SUCCESS) {
 			switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_WARNING, "Cannot Create Outgoing Channel! [%s]\n", dest);
-			return JS_TRUE;
+			goto done;
 		}
 
-		*rval = STRING_TO_JSVAL (JS_NewStringCopyZ(cx, switch_channel_cause2str(cause)));
-
-		jss = switch_core_session_alloc(peer_session, sizeof(*jss));
 		jss->session = peer_session;
 		jss->flags = 0;
-		jss->cx = cx;
-		jss->obj = obj;
-		JS_SetPrivate(cx, obj, jss);
-		switch_set_flag(jss, S_HUP);
+
+		*rval = BOOLEAN_TO_JSVAL(JS_TRUE);
 
 	} else {
 		switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_WARNING, "Missing Args\n");
 	}
 
+ done:
 	return JS_TRUE;
 }
 
+
+
+
 static void session_destroy(JSContext *cx, JSObject *obj)
 {
 	struct js_session *jss;
+	switch_channel_t *channel = NULL;
 	
 	if (cx && obj) {
 		if ((jss = JS_GetPrivate(cx, obj))) {
-			if (switch_test_flag(jss, S_HUP)) {
-				switch_channel_t *channel;
+			if (jss->session) {
+				channel = switch_core_session_get_channel(jss->session);
+				switch_channel_set_private(channel, "jss", NULL);
+			}
 
-				if (jss->session) {
-					channel = switch_core_session_get_channel(jss->session);
-					switch_channel_hangup(channel, SWITCH_CAUSE_NORMAL_CLEARING);
-				}
+			if (channel && switch_test_flag(jss, S_HUP)) {
+				switch_channel_hangup(channel, SWITCH_CAUSE_NORMAL_CLEARING);
+			}
+
+			if (switch_test_flag(jss, S_FREE)) {
+				free(jss);
 			}
 		}
 	}
@@ -2073,8 +2278,9 @@
 	switch_size_t read = 0;
 
 	*rval = BOOLEAN_TO_JSVAL( JS_FALSE );
-
-	if (fio) {
+	
+	if (!fio) {
+		*rval = BOOLEAN_TO_JSVAL( JS_FALSE );
 		return JS_TRUE;
 	}
 

Modified: freeswitch/trunk/src/mod/languages/mod_spidermonkey/mod_spidermonkey.h
==============================================================================
--- freeswitch/trunk/src/mod/languages/mod_spidermonkey/mod_spidermonkey.h	(original)
+++ freeswitch/trunk/src/mod/languages/mod_spidermonkey/mod_spidermonkey.h	Mon Mar 26 20:40:53 2007
@@ -132,6 +132,8 @@
 	JSContext *cx;
 	JSObject *obj;
 	unsigned int flags;
+	switch_call_cause_t cause;
+	JSFunction *on_hangup;
 };
 
 

Modified: freeswitch/trunk/src/switch_core.c
==============================================================================
--- freeswitch/trunk/src/switch_core.c	(original)
+++ freeswitch/trunk/src/switch_core.c	Mon Mar 26 20:40:53 2007
@@ -185,7 +185,6 @@
 /* The main runtime obj we keep this hidden for ourselves */
 static struct switch_core_runtime runtime;
 
-
 static void db_pick_path(char *dbname, char *buf, switch_size_t size)
 {
 
@@ -1835,20 +1834,22 @@
 SWITCH_DECLARE(switch_status_t) switch_core_session_answer_channel(switch_core_session_t *session)
 {
 	switch_io_event_hook_answer_channel_t *ptr;
-	switch_status_t status = SWITCH_STATUS_FALSE;
+	switch_status_t status = SWITCH_STATUS_SUCCESS;
 
 	assert(session != NULL);
+
 	if (session->endpoint_interface->io_routines->answer_channel) {
-		if ((status = session->endpoint_interface->io_routines->answer_channel(session)) == SWITCH_STATUS_SUCCESS) {
-			for (ptr = session->event_hooks.answer_channel; ptr; ptr = ptr->next) {
-				if ((status = ptr->answer_channel(session)) != SWITCH_STATUS_SUCCESS) {
-					break;
-				}
+		status = session->endpoint_interface->io_routines->answer_channel(session);
+	}
+
+	if (status == SWITCH_STATUS_SUCCESS) {
+		for (ptr = session->event_hooks.answer_channel; ptr; ptr = ptr->next) {
+			if ((status = ptr->answer_channel(session)) != SWITCH_STATUS_SUCCESS) {
+				break;
 			}
 		}
-	} else {
-		status = SWITCH_STATUS_SUCCESS;
 	}
+	 
 
 	return status;
 }
@@ -1856,19 +1857,23 @@
 SWITCH_DECLARE(switch_status_t) switch_core_session_receive_message(switch_core_session_t *session, switch_core_session_message_t *message)
 {
 	switch_io_event_hook_receive_message_t *ptr;
-	switch_status_t status = SWITCH_STATUS_FALSE;
+	switch_status_t status = SWITCH_STATUS_SUCCESS;
 
 	assert(session != NULL);
+
 	if (session->endpoint_interface->io_routines->receive_message) {
-		if ((status =
-			 session->endpoint_interface->io_routines->receive_message(session, message)) == SWITCH_STATUS_SUCCESS) {
-			for (ptr = session->event_hooks.receive_message; ptr; ptr = ptr->next) {
-				if ((status = ptr->receive_message(session, message)) != SWITCH_STATUS_SUCCESS) {
-					break;
-				}
+		status = session->endpoint_interface->io_routines->receive_message(session, message);
+		
+	}
+
+	if (status == SWITCH_STATUS_SUCCESS) {
+		for (ptr = session->event_hooks.receive_message; ptr; ptr = ptr->next) {
+			if ((status = ptr->receive_message(session, message)) != SWITCH_STATUS_SUCCESS) {
+				break;
 			}
 		}
 	}
+
 	switch_core_session_kill_channel(session, SWITCH_SIG_BREAK);
 	return status;
 }
@@ -2874,6 +2879,31 @@
 
 }
 
+SWITCH_DECLARE(switch_status_t) switch_core_session_add_event_hook_state_change(switch_core_session_t *session,
+																				switch_answer_channel_hook_t state_change)
+																				  
+
+{
+	switch_io_event_hook_state_change_t *hook, *ptr;
+
+	assert(state_change != NULL);
+	if ((hook = switch_core_session_alloc(session, sizeof(*hook))) != 0) {
+		hook->state_change = state_change;
+		if (!session->event_hooks.state_change) {
+			session->event_hooks.state_change = hook;
+		} else {
+			for (ptr = session->event_hooks.state_change; ptr && ptr->next; ptr = ptr->next);
+			ptr->next = hook;
+
+		}
+
+		return SWITCH_STATUS_SUCCESS;
+	}
+
+	return SWITCH_STATUS_MEMERR;
+
+}
+
 SWITCH_DECLARE(switch_status_t) switch_core_session_add_event_hook_read_frame(switch_core_session_t *session,
 																			switch_read_frame_hook_t read_frame)
 {
@@ -3216,13 +3246,26 @@
 
 SWITCH_DECLARE(void) switch_core_session_signal_state_change(switch_core_session_t *session)
 {
+	switch_status_t status = SWITCH_STATUS_SUCCESS;
+	switch_io_event_hook_state_change_t *ptr;
 
 	/* If trylock fails the signal is already awake so we needn't bother */
 	if (switch_mutex_trylock(session->mutex) == SWITCH_STATUS_SUCCESS) {
 		switch_thread_cond_signal(session->cond);
 		switch_mutex_unlock(session->mutex);
 	} 
-	
+
+	if (session->endpoint_interface->io_routines->state_change) {
+		status = session->endpoint_interface->io_routines->state_change(session);
+	}
+
+	if (status == SWITCH_STATUS_SUCCESS) {
+		for (ptr = session->event_hooks.state_change; ptr; ptr = ptr->next) {
+			if ((status = ptr->state_change(session)) != SWITCH_STATUS_SUCCESS) {
+				break;
+			}
+		}
+	}
 }
 
 SWITCH_DECLARE(unsigned int) switch_core_session_running(switch_core_session_t *session)



More information about the Freeswitch-svn mailing list