All pastes #982833 Raw Edit

Anonymous

public text v1 · immutable
·published 2008-04-12 21:20 UTC
rendered paste body
SWITCH_DECLARE(switch_status_t) switch_ivr_eavesdrop_session(switch_core_session_t *session, const char *uuid, switch_eavesdrop_flag_t flags)
{
	switch_core_session_t *tsession;
	switch_status_t status = SWITCH_STATUS_FALSE;
	switch_channel_t *channel = switch_core_session_get_channel(session);
	switch_codec_t *read_codec = switch_core_session_get_read_codec(session);

	if ((tsession = switch_core_session_locate(uuid))) {
		struct eavesdrop_pvt *ep;
		switch_media_bug_t *bug = NULL;
		switch_channel_t *tchannel = switch_core_session_get_channel(tsession);
		switch_frame_t *read_frame, write_frame = { 0 };
		switch_codec_t codec = {0};
		int16_t buf[SWITCH_RECOMMENDED_BUFFER_SIZE/2];
		switch_codec_t *tread_codec = switch_core_session_get_read_codec(tsession);
		uint32_t tlen = tread_codec->implementation->bytes_per_frame;

		ep = switch_core_session_alloc(session, sizeof(*ep));

		switch_channel_pre_answer(channel);
		
		if (switch_core_codec_init(&codec,
								   "L16",
								   NULL, 
								   tread_codec->implementation->actual_samples_per_second,
								   tread_codec->implementation->microseconds_per_frame / 1000,
								   tread_codec->implementation->number_of_channels, 
								   SWITCH_CODEC_FLAG_ENCODE | SWITCH_CODEC_FLAG_DECODE, 
								   NULL, switch_core_session_get_pool(session)) != SWITCH_STATUS_SUCCESS) {
			switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Cannot init codec\n");
			switch_core_session_rwunlock(tsession);
			return status;
		}
		
		switch_core_session_set_read_codec(session, &codec);
		write_frame.codec = &codec;
		write_frame.data = buf;
		write_frame.buflen = sizeof(buf);
		write_frame.rate = read_codec->implementation->actual_samples_per_second;
		
		ep->flags = flags;
		switch_mutex_init(&ep->mutex, SWITCH_MUTEX_NESTED, switch_core_session_get_pool(tsession));
		switch_buffer_create_dynamic(&ep->buffer, 2048, 2048, 8192);
		switch_buffer_add_mutex(ep->buffer, ep->mutex);

		switch_mutex_init(&ep->w_mutex, SWITCH_MUTEX_NESTED, switch_core_session_get_pool(tsession));
		switch_buffer_create_dynamic(&ep->w_buffer, 2048, 2048, 8192);
		switch_buffer_add_mutex(ep->w_buffer, ep->w_mutex);

		switch_mutex_init(&ep->r_mutex, SWITCH_MUTEX_NESTED, switch_core_session_get_pool(tsession));
		switch_buffer_create_dynamic(&ep->r_buffer, 2048, 2048, 8192);
		switch_buffer_add_mutex(ep->r_buffer, ep->r_mutex);

		
		if (switch_core_media_bug_add(tsession, eavesdrop_callback, ep, 0, 
									  SMBF_READ_STREAM | SMBF_WRITE_STREAM | SMBF_READ_REPLACE | SMBF_WRITE_REPLACE | SMBF_READ_PING | SMBF_THREAD_LOCK,
									  &bug) != SWITCH_STATUS_SUCCESS) {
			switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Cannot attach bug\n");
			goto end;
		}
		
        while(switch_channel_ready(tchannel) && switch_channel_ready(channel)) {
			uint32_t len = sizeof(buf);
			switch_event_t *event = NULL;
			char *fcommand = NULL;
			char db[2] = "";

			status = switch_core_session_read_frame(session, &read_frame, 1000, 0);
			
			if (!SWITCH_READ_ACCEPTABLE(status)) {
				goto end;
			}

			if (switch_core_session_dequeue_event(session, &event) == SWITCH_STATUS_SUCCESS) {
				char *command = switch_event_get_header(event, "eavesdrop-command");
				if (command) {
					fcommand = command;
				}
				switch_event_destroy(&event);
			}

			if ((flags & ED_DTMF) && switch_channel_has_dtmf(channel)) {
				switch_dtmf_t dtmf = {0};
				switch_channel_dequeue_dtmf(channel, &dtmf);
				db[0] = dtmf.digit;
				fcommand = db;
			}

			if (fcommand) {
				char *d;
				for(d = fcommand; *d; d++) {
					int z = 1;
					
					switch (*d) {
					case '1':
						switch_set_flag(ep, ED_MUX_READ);
						switch_clear_flag(ep, ED_MUX_WRITE);
						break;
					case '2':
						switch_set_flag(ep, ED_MUX_WRITE);
						switch_clear_flag(ep, ED_MUX_READ);
						break;
					case '3':
						switch_set_flag(ep, ED_MUX_READ);
						switch_set_flag(ep, ED_MUX_WRITE);
						break;
                    case '*':
                        switch_core_codec_destroy(&codec);
                        return status;
					case '0':
						switch_clear_flag(ep, ED_MUX_READ);
						switch_clear_flag(ep, ED_MUX_WRITE);
						break;
					default:
						z = 0;
						break;

					}
					
					if (z) {
						if (ep->r_buffer) {
							switch_buffer_lock(ep->r_buffer);
							switch_buffer_zero(ep->r_buffer);
							switch_buffer_unlock(ep->r_buffer);
						}
						
						if (ep->w_buffer) {
							switch_buffer_lock(ep->w_buffer);
							switch_buffer_zero(ep->w_buffer);
							switch_buffer_unlock(ep->w_buffer);
						}
					}
				}
			}

			if (!switch_test_flag(read_frame, SFF_CNG)) {
				switch_buffer_lock(ep->r_buffer);
				switch_buffer_zwrite(ep->r_buffer, read_frame->data, read_frame->datalen);
				switch_buffer_unlock(ep->r_buffer);

				switch_buffer_lock(ep->w_buffer);
				switch_buffer_zwrite(ep->w_buffer, read_frame->data, read_frame->datalen);
				switch_buffer_unlock(ep->w_buffer);
			}

			if (len > tlen) {
				len = tlen;
			}

            if (switch_buffer_inuse(ep->buffer) >= len) {
                switch_buffer_lock(ep->buffer);				
				while (switch_buffer_inuse(ep->buffer) >= len) {
					write_frame.datalen = (uint32_t)switch_buffer_read(ep->buffer, buf, len);
					write_frame.samples = write_frame.datalen / 2;
					if ((status = switch_core_session_write_frame(session, &write_frame, 1000, 0)) != SWITCH_STATUS_SUCCESS) {
						break;
					}
				}
                switch_buffer_unlock(ep->buffer);
            }
			
        }

    end:

		switch_core_codec_destroy(&codec);

        if (bug) {
            switch_core_media_bug_remove(tsession, &bug);
        }

        if (ep->buffer) {
            switch_buffer_destroy(&ep->buffer);
        }

        if (ep->r_buffer) {
            switch_buffer_destroy(&ep->r_buffer);
        }

        if (ep->w_buffer) {
            switch_buffer_destroy(&ep->w_buffer);
        }

        switch_core_session_rwunlock(tsession);
		status = SWITCH_STATUS_SUCCESS;

		switch_core_session_set_read_codec(session, read_codec);
		switch_core_session_reset(session, SWITCH_TRUE);
    }
	
	return status;
}