/* * This file is part of Project DiaStar Server. * * More information about this project can be found at: * http://www.projectdiastar.org. * * Copyright (C) 2009 Dialogic Corp. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA * 02110-1301, USA. * Alternatively see . * Or see the LICENSE file included within the source tree. * */ /*! * \file ipmdevice.cxx * \brief Dialogic IPM device * \author Antony Martin * \author John Tarlton * \version 2-APR-2009 */ /*------------------------------ Dependencies --------------------------------*/ #include "logger.h" #include "string-util.h" #include "dialogicchannelmanager.h" #include "mmdevice.h" #include "gciptdevice.h" #include "ipmdevice.h" /*----------------------------------------------------------------------------*/ /* * ctor */ IpmDevice::IpmDevice( const std::string& name, DialogicChannelManager& channelMgr ) : DialogicDevice(name, channelMgr) { ipt_ = 0; /* standalone mode */ busy_ = false; /* Number of steps in the initialisation sequence, decremented by event * handlers. When zero, state is changed to IDLE. * * IPMEV_OPEN, * DMEV_GET_RX_PORT_INFO, * DMEV_GET_TX_PORT_INFO */ initStepsRemaining_ = 3; } /* * dtor */ IpmDevice::~IpmDevice() { } /* * Process a command that was queueued because an async operation was in progress * when it was initially requested. */ void IpmDevice::processPendingCommand() { if ( !pending_.empty() ) { switch( pending_.front().cmd ) { case IpmCommand::START: startMedia(); break; case IpmCommand::STOP: stop(pending_.front().operation); break; case IpmCommand::LISTEN: listen(pending_.front().other); break; case IpmCommand::UNLISTEN: unListen(); break; case IpmCommand::CONNECT: connect(pending_.front().other); break; case IpmCommand::DISCONNECT: disconnect(); break; default: break; } pending_.pop(); } } /* * Open the device. */ bool IpmDevice::open() { LOGDEBUG("IpmDevice::open() device: " << devName_); devHandle_ = ipm_Open(devName_.c_str(), NULL, EV_ASYNC); if ( devHandle_ < 0 ) { LOGERROR("ipm_Open() failed"); return false; } state_ = IPM_OPENING; return true; } /* * Close the device */ bool IpmDevice::close() { LOGDEBUG("IpmDevice::close() device: " << devName_); if ( devHandle_ > 0 ) { if ( ipm_Close(devHandle_, NULL) < 0 ) { LOGERROR("ipm_Close() failed"); return false; } devHandle_ = 0; } return true; } /* * Connect media. */ bool IpmDevice::listen( DialogicDevice* other ) { if ( listening_ != other ) { if ( busy_ ) { pending_.push(IpmCommand(IpmCommand::LISTEN, other)); return true; } LOGDEBUG("IpmDevice::listen() device: " << devName_ << " other: " << other->getDeviceName()); SC_TSINFO tsinfo; tsinfo.sc_numts = 1; tsinfo.sc_tsarrayp = other->getXmitTimeslotPtr(); if ( ipm_Listen(devHandle_, &tsinfo, EV_ASYNC) == -1 ) { LOGERROR("ipm_Listen() failed on device: " << devName_ << " " << ATDV_ERRMSGP(devHandle_)); return false; } listening_ = other; busy_ = true; } return true; } /* * Disconnect media. */ bool IpmDevice::unListen() { if ( listening_ ) { if ( busy_ ) { pending_.push(IpmCommand(IpmCommand::UNLISTEN)); return true; } LOGDEBUG("IpmDevice::unListen() device: " << devName_); if ( ipm_UnListen(devHandle_, EV_ASYNC) == -1) { LOGERROR("ipm_UnListen() failed on device: " << devName_ << " " << ATDV_ERRMSGP(devHandle_)); return false; } listening_ = 0; busy_ = true; } return true; } /* * Connect media. */ bool IpmDevice::connect( DialogicDevice* other ) { if ( listening_ != other ) { if ( busy_ ) { pending_.push(IpmCommand(IpmCommand::CONNECT, other)); return true; } LOGDEBUG("IpmDevice::connect() device: " << devName_ << " other: " << other->getDeviceName()); DM_PORT_CONNECT_INFO_LIST portConnectInfoList; INIT_DM_PORT_CONNECT_INFO_LIST(&portConnectInfoList); int count = 0; INIT_DM_PORT_CONNECT_INFO(&portConnectInfoList.port_connect_info[count]); portConnectInfoList.port_connect_info[count].unFlags = DMFL_TRANSCODE_NATIVE; //TRANSCODE_ON; portConnectInfoList.port_connect_info[count].port_info_tx = getAudioTxPortInfo(); portConnectInfoList.port_connect_info[count].port_info_rx = other->getAudioRxPortInfo(); count++; INIT_DM_PORT_CONNECT_INFO(&portConnectInfoList.port_connect_info[count]); portConnectInfoList.port_connect_info[count].unFlags = DMFL_TRANSCODE_NATIVE; //TRANSCODE_ON; portConnectInfoList.port_connect_info[count].port_info_tx = getVideoTxPortInfo(); portConnectInfoList.port_connect_info[count].port_info_rx = other->getVideoRxPortInfo(); count++; portConnectInfoList.unCount = count; if ( dev_PortConnect(devHandle_, &portConnectInfoList, NULL) != DEV_SUCCESS ) { LOGERROR("IpmDevice::connect() dev_PortConnect() failed on device: " << devName_ << " " << ATDV_ERRMSGP(devHandle_)); return false; } listening_ = other; busy_ = true; } else { LOGWARN("IpmDevice::connect() " << devName_ << " already connected to device: " << listening_->getDeviceName() << " trying to connect to device: " << other->getDeviceName()); } return true; } /* * Disconnect media. */ bool IpmDevice::disconnect() { if ( listening_ ) { if ( busy_ ) { pending_.push(IpmCommand(IpmCommand::DISCONNECT)); return true; } LOGDEBUG("IpmDevice::disconnect() device: " << devName_); DM_PORT_CONNECT_INFO_LIST portConnectInfoList; INIT_DM_PORT_CONNECT_INFO_LIST(&portConnectInfoList); int count = 0; INIT_DM_PORT_CONNECT_INFO(&portConnectInfoList.port_connect_info[count]); portConnectInfoList.port_connect_info[count].port_info_tx = getAudioTxPortInfo(); portConnectInfoList.port_connect_info[count].port_info_rx = listening_->getAudioRxPortInfo(); //XXX count++; INIT_DM_PORT_CONNECT_INFO(&portConnectInfoList.port_connect_info[count]); portConnectInfoList.port_connect_info[count].port_info_tx = getVideoTxPortInfo(); portConnectInfoList.port_connect_info[count].port_info_rx = listening_->getVideoRxPortInfo(); //XXX count++; portConnectInfoList.unCount = count; if ( dev_PortDisconnect(devHandle_, &portConnectInfoList, NULL) != DEV_SUCCESS ) { LOGERROR("IpmDevice::disconnect() dev_PortDisconnect() failed on device: " << devName_ << " " << ATDV_ERRMSGP(devHandle_)); return false; } listening_ = 0; busy_ = true; } else { LOGWARN("IpmDevice::disconnect() device: " << devName_ << " not connected"); } return true; } /* * Search localMediaInfo_ for the requested information. */ bool IpmDevice::getLocalMediaInfo( eIPM_MEDIA_TYPE type, IpInfo& rtp_media ) const { switch ( type ) { case MEDIATYPE_AUDIO_LOCAL_RTP_INFO: rtp_media = localRtpAudio_; break; case MEDIATYPE_AUDIO_LOCAL_RTCP_INFO: rtp_media = localRtcpAudio_; break; case MEDIATYPE_VIDEO_LOCAL_RTP_INFO: rtp_media = localRtpVideo_; break; case MEDIATYPE_VIDEO_LOCAL_RTCP_INFO: rtp_media = localRtcpVideo_; break; default: return false; } return true; } /* * Save the remote params. */ void IpmDevice::setRemoteMediaInfo( eIPM_MEDIA_TYPE type, const IpInfo& rtp_info ) { if ( type == MEDIATYPE_AUDIO_REMOTE_RTP_INFO ) { remoteRtpAudio_ = rtp_info; remoteRtcpAudio_ = rtp_info; remoteRtcpAudio_.setPort(remoteRtpAudio_.getPort() + 1); LOGDEBUG("IpmDevice::setRemoteMediaInfo() device: " << devName_ << " a=" << remoteRtpAudio_); } if ( type == MEDIATYPE_VIDEO_REMOTE_RTP_INFO ) { remoteRtpVideo_ = rtp_info; remoteRtcpVideo_ = rtp_info; remoteRtcpVideo_.setPort(remoteRtpVideo_.getPort() + 1); LOGDEBUG("IpmDevice::setRemoteMediaInfo() device: " << devName_ << " v=" << remoteRtpVideo_); } } /* * Stop the IPM streaming and/or digit reception */ bool IpmDevice::stop( eIPM_STOP_OPERATION operation ) { if ( state_ == IPM_IDLE ) { return true; /* already stopped */ } if ( busy_ ) { pending_.push(IpmCommand(IpmCommand::STOP, operation)); return true; } if ( ipm_Stop(devHandle_, operation, EV_ASYNC) == -1 ) { LOGERROR("ipm_Stop() on device: " << devName_ << " failed: " << ATDV_LASTERR(devHandle_)); return false; } LOGDEBUG("IpmDevice::stopMedia() stopping RTP streaming on device: " << devName_); state_ = IPM_STOPPING; busy_ = true; return true; } /* * Start RTP streaming to peer. */ bool IpmDevice::startMedia() { return startMedia(remoteRtpAudio_, remoteRtcpAudio_, remoteRtpVideo_, remoteRtcpVideo_); } /* * Start RTP streaming using G.711ulaw and local/remote port information. * XXX codecs from config */ bool IpmDevice::startMedia( const IpInfo& remote_rtp_audio, const IpInfo& remote_rtcp_audio, const IpInfo& remote_rtp_video, const IpInfo& remote_rtcp_video ) { if ( busy_ ) { pending_.push(IpmCommand(IpmCommand::START)); return true; } if ( state_ == IPM_STREAMING ) { /* already started, ignore */ LOGDEBUG("IpmDevice::startMedia() already streaming on device: " << devName_); return true; } setDtmfMode(DTMF_RFC2833); IPM_MEDIA_INFO mediaInfo; memset(&mediaInfo, 0, sizeof(IPM_MEDIA_INFO)); int mediaCnt = 0; /* limit MAX_MEDIA_INFO */ /* remote audio */ mediaInfo.MediaData[mediaCnt].eMediaType = MEDIATYPE_AUDIO_REMOTE_CODER_INFO; mediaInfo.MediaData[mediaCnt].mediaInfo.CoderInfo.eCoderType = CODER_TYPE_G711ULAW64K; mediaInfo.MediaData[mediaCnt].mediaInfo.CoderInfo.eFrameSize = CODER_FRAMESIZE_20; mediaInfo.MediaData[mediaCnt].mediaInfo.CoderInfo.unFramesPerPkt = 1; mediaInfo.MediaData[mediaCnt].mediaInfo.CoderInfo.eVadEnable = CODER_VAD_ENABLE; mediaInfo.MediaData[mediaCnt].mediaInfo.CoderInfo.unCoderPayloadType = 0; mediaInfo.MediaData[mediaCnt].mediaInfo.CoderInfo.unRedPayloadType = 0; mediaCnt++; /* local audio */ mediaInfo.MediaData[mediaCnt].eMediaType = MEDIATYPE_AUDIO_LOCAL_CODER_INFO; mediaInfo.MediaData[mediaCnt].mediaInfo.CoderInfo.eCoderType = CODER_TYPE_G711ULAW64K; mediaInfo.MediaData[mediaCnt].mediaInfo.CoderInfo.eFrameSize = CODER_FRAMESIZE_20; mediaInfo.MediaData[mediaCnt].mediaInfo.CoderInfo.unFramesPerPkt = 1; mediaInfo.MediaData[mediaCnt].mediaInfo.CoderInfo.eVadEnable = CODER_VAD_ENABLE; mediaInfo.MediaData[mediaCnt].mediaInfo.CoderInfo.unCoderPayloadType = 0; mediaInfo.MediaData[mediaCnt].mediaInfo.CoderInfo.unRedPayloadType = 0; mediaCnt++; /* remote audio ports and IP addresses */ mediaInfo.MediaData[mediaCnt].eMediaType = MEDIATYPE_AUDIO_REMOTE_RTP_INFO; copy_string_to_c_array(remote_rtp_audio.getAddress(), mediaInfo.MediaData[mediaCnt].mediaInfo.PortInfo.cIPAddress, IP_ADDR_SIZE); mediaInfo.MediaData[mediaCnt].mediaInfo.PortInfo.unPortId = remote_rtp_audio.getPort(); mediaCnt++; mediaInfo.MediaData[mediaCnt].eMediaType = MEDIATYPE_AUDIO_REMOTE_RTCP_INFO; copy_string_to_c_array(remote_rtcp_audio.getAddress(), mediaInfo.MediaData[mediaCnt].mediaInfo.PortInfo.cIPAddress, IP_ADDR_SIZE); mediaInfo.MediaData[mediaCnt].mediaInfo.PortInfo.unPortId = remote_rtcp_audio.getPort(); mediaCnt++; /* remote video */ mediaInfo.MediaData[mediaCnt].eMediaType = MEDIATYPE_VIDEO_REMOTE_CODER_INFO; INIT_IPM_VIDEO_CODER_INFO(&mediaInfo.MediaData[mediaCnt].mediaInfo.VideoCoderInfo); mediaInfo.MediaData[mediaCnt].mediaInfo.CoderInfo.eCoderType = CODER_TYPE_H263; mediaInfo.MediaData[mediaCnt].mediaInfo.CoderInfo.unCoderPayloadType = 34; IPM_VIDEO_CODER_INFO_EX remoteVideoCoderInfoEx; INIT_IPM_VIDEO_CODER_INFO_EX(&remoteVideoCoderInfoEx); remoteVideoCoderInfoEx.eProfile = VIDEO_PROFILE_0_H263; remoteVideoCoderInfoEx.eLevel = VIDEO_LEVEL_10_H263; remoteVideoCoderInfoEx.eImageWidth = VIDEO_IMAGE_WIDTH_352; //176; remoteVideoCoderInfoEx.eImageHeight = VIDEO_IMAGE_HEIGHT_288; //144; remoteVideoCoderInfoEx.eFramesPerSec = VIDEO_FRAMESPERSEC_15; remoteVideoCoderInfoEx.unBitRate = 90000; remoteVideoCoderInfoEx.eSamplingRate = VIDEO_SAMPLING_RATE_DEFAULT; remoteVideoCoderInfoEx.unVisualConfigSize = 0; remoteVideoCoderInfoEx.szVisualConfiguration = NULL; mediaInfo.MediaData[mediaCnt].mediaInfo.VideoCoderInfo.pExtraCoderInfo = &remoteVideoCoderInfoEx; mediaCnt++; /* local video */ mediaInfo.MediaData[mediaCnt].eMediaType = MEDIATYPE_VIDEO_LOCAL_CODER_INFO; INIT_IPM_VIDEO_CODER_INFO(&mediaInfo.MediaData[mediaCnt].mediaInfo.VideoCoderInfo); mediaInfo.MediaData[mediaCnt].mediaInfo.CoderInfo.eCoderType = CODER_TYPE_H263; mediaInfo.MediaData[mediaCnt].mediaInfo.CoderInfo.unCoderPayloadType = 34; IPM_VIDEO_CODER_INFO_EX localVideoCoderInfoEx; INIT_IPM_VIDEO_CODER_INFO_EX(&localVideoCoderInfoEx); localVideoCoderInfoEx.eProfile = VIDEO_PROFILE_0_H263; localVideoCoderInfoEx.eLevel = VIDEO_LEVEL_10_H263; localVideoCoderInfoEx.eImageWidth = VIDEO_IMAGE_WIDTH_352; //176; localVideoCoderInfoEx.eImageHeight = VIDEO_IMAGE_HEIGHT_288; //144; localVideoCoderInfoEx.eFramesPerSec = VIDEO_FRAMESPERSEC_15; localVideoCoderInfoEx.unBitRate = 90000; localVideoCoderInfoEx.eSamplingRate = VIDEO_SAMPLING_RATE_DEFAULT; localVideoCoderInfoEx.unVisualConfigSize = 0; localVideoCoderInfoEx.szVisualConfiguration = NULL; mediaInfo.MediaData[mediaCnt].mediaInfo.VideoCoderInfo.pExtraCoderInfo = &localVideoCoderInfoEx; mediaCnt++; /* remote video ports and IP addresses */ mediaInfo.MediaData[mediaCnt].eMediaType = MEDIATYPE_VIDEO_REMOTE_RTP_INFO; copy_string_to_c_array(remote_rtp_video.getAddress(), mediaInfo.MediaData[mediaCnt].mediaInfo.PortInfo.cIPAddress, IP_ADDR_SIZE); mediaInfo.MediaData[mediaCnt].mediaInfo.PortInfo.unPortId = remote_rtp_video.getPort(); mediaCnt++; mediaInfo.MediaData[mediaCnt].eMediaType = MEDIATYPE_VIDEO_REMOTE_RTCP_INFO; copy_string_to_c_array(remote_rtcp_video.getAddress(), mediaInfo.MediaData[mediaCnt].mediaInfo.PortInfo.cIPAddress, IP_ADDR_SIZE); mediaInfo.MediaData[mediaCnt].mediaInfo.PortInfo.unPortId = remote_rtcp_video.getPort(); mediaCnt++; /* done */ mediaInfo.unCount = mediaCnt; LOGDEBUG("IpmDevice::startMedia() starting RTP streaming on device: " << devName_ << " remote_rtp_audio: " << remote_rtp_audio << " remote_rtcp_audio: " << remote_rtcp_audio << " remote_rtp_video: " << remote_rtp_video << " remote_rtcp_video: " << remote_rtcp_video); if ( ipm_StartMedia(devHandle_, &mediaInfo, DATA_IP_TDM_BIDIRECTIONAL, EV_ASYNC) == -1 ) { LOGERROR("ipm_StartMedia failed for device: " << devName_ << " with error: " << ATDV_ERRMSGP(devHandle_)); return false; } state_ = IPM_STARTING; busy_ = true; return true; } /* * Forward to event specific handler. */ bool IpmDevice::processEvent( METAEVENT& metaevent ) { switch ( metaevent.evttype ) { case IPMEV_OPEN: onOpen(); break; case IPMEV_EVENT_ENABLED: onEventEnabled(); break; case IPMEV_GET_LOCAL_MEDIA_INFO: onLocalMediaInfo((IPM_MEDIA_INFO*)sr_getevtdatap()); break; case IPMEV_STARTMEDIA: onStartMedia(); break; case IPMEV_STOPPED: onStopped(); break; case IPMEV_LISTEN: onListen(); break; case IPMEV_UNLISTEN: onUnListen(); break; case IPMEV_ERROR: onError(); break; case IPMEV_TELEPHONY_EVENT: onTelephonyEvent((IPM_TELEPHONY_INFO*)sr_getevtdatap()); break; case DMEV_GET_TX_PORT_INFO: onGetTxPortInfo((DM_PORT_INFO_LIST*)sr_getevtdatap()); break; case DMEV_GET_RX_PORT_INFO: onGetRxPortInfo((DM_PORT_INFO_LIST*)sr_getevtdatap()); break; case DMEV_GET_TX_PORT_INFO_FAIL: onPortGetFail(); break; case DMEV_GET_RX_PORT_INFO_FAIL: onPortGetFail(); break; case DMEV_PORT_CONNECT: onPortConnect(); break; case DMEV_PORT_CONNECT_FAIL: onPortConnectFail(); break; case DMEV_PORT_DISCONNECT: onPortDisconnect(); break; case DMEV_PORT_DISCONNECT_FAIL: LOGERROR("IpmDevice::onPortDisconnectFail() device: " << devName_); break; default: LOGWARN("IpmDevice::processEvent() unhandled event: 0x" << std::hex << metaevent.evttype << " for device: " << devName_); return false; } return true; } /* * Handler for IPMEV_OPEN events. */ void IpmDevice::onOpen() { LOGINFO("IpmDevice::onOpen() device: " << devName_); listening_ = 0; /* Get and save the transmit timeslot on CTBus */ SC_TSINFO tsinfo; tsinfo.sc_numts = 1; tsinfo.sc_tsarrayp = getXmitTimeslotPtr(); if ( ipm_GetXmitSlot(devHandle_, &tsinfo, EV_SYNC) == -1 ) { LOGERROR("ipm_GetXmitSlot() failed" ); } /* Enable dtmf events. */ eIPM_EVENT event = EVT_RFC2833; if ( ipm_EnableEvents(devHandle_, &event, 1, EV_ASYNC) < 0 ) { LOGERROR("ipm_EnableEvent() failed on device:" << devHandle_); } /* Request port info */ if ( dev_GetTransmitPortInfo(devHandle_, this) == -1 ) { LOGERROR("dev_GetTransmitPortInfo() failed"); } if ( dev_GetReceivePortInfo(devHandle_, this) == -1 ) { LOGERROR("dev_GetReceivePortInfo() failed"); } /* Request the local media information. */ IPM_MEDIA_INFO media_info; memset(&media_info, 0, sizeof(IPM_MEDIA_INFO)); media_info.unCount = 2; media_info.MediaData[0].eMediaType = MEDIATYPE_AUDIO_LOCAL_RTP_INFO; media_info.MediaData[1].eMediaType = MEDIATYPE_VIDEO_LOCAL_RTP_INFO; if ( ipm_GetLocalMediaInfo(devHandle_, &media_info, EV_ASYNC) == -1 ) { LOGERROR("ipm_GetLocalMediaInfo() failed for device: " << devName_ << " with error: " << ATDV_LASTERR(devHandle_)); } /* update init state */ state_ = IPM_INITIALIZATION_START; initStepsRemaining_--; if ( initStepsRemaining_ == 0 ) { state_ = IPM_IDLE; } } /* * Handler for DMEV_GET_TX_PORT_INFO events. */ void IpmDevice::onGetTxPortInfo( DM_PORT_INFO_LIST* portInfoList ) { LOGINFO("IpmDevice::onGetTxPortInfo() device: " << devName_); txPortInfoList_ = *portInfoList; printPortInfo(&txPortInfoList_); for ( unsigned int i = 0; i < txPortInfoList_.unCount; i++ ) { switch ( txPortInfoList_.port_info[i].port_media_type ) { case DM_PORT_MEDIA_TYPE_AUDIO: memcpy(&audioPortTxInfo_, &txPortInfoList_.port_info[i], sizeof(DM_PORT_INFO)); break; case DM_PORT_MEDIA_TYPE_VIDEO: memcpy(&videoPortTxInfo_, &txPortInfoList_.port_info[i], sizeof(DM_PORT_INFO)); break; default: break; } } initStepsRemaining_--; if ( initStepsRemaining_ == 0 ) { state_ = IPM_IDLE; } } /* * Handler for DMEV_GET_RX_PORT_INFO events. */ void IpmDevice::onGetRxPortInfo( DM_PORT_INFO_LIST* portInfoList ) { LOGINFO("IpmDevice::onGetRxPortInfo() device: " << devName_); rxPortInfoList_ = *portInfoList; printPortInfo(&rxPortInfoList_); for ( unsigned int i = 0; i < rxPortInfoList_.unCount; i++ ) { switch ( rxPortInfoList_.port_info[i].port_media_type ) { case DM_PORT_MEDIA_TYPE_AUDIO: memcpy(&audioPortRxInfo_, &rxPortInfoList_.port_info[i], sizeof(DM_PORT_INFO)); break; case DM_PORT_MEDIA_TYPE_VIDEO: memcpy(&videoPortRxInfo_, &rxPortInfoList_.port_info[i], sizeof(DM_PORT_INFO)); break; default: break; } } initStepsRemaining_--; if ( initStepsRemaining_ == 0 ) { state_ = IPM_IDLE; } } /* * Handler for DMEV_GET_TX_PORT_INFO_FAIL and DMEV_GET_RX_PORT_INFO_FAIL * events. */ void IpmDevice::onPortGetFail() { LOGINFO("IpmDevice::onPortGetFail() device: " << devName_); state_ = IPM_INVALID; } /* * Handler for IPMEV_ERROR events. */ void IpmDevice::onError() { LOGERROR("IpmDevice::onError() device: " << devName_ << " error: " << ATDV_ERRMSGP(devHandle_)); state_ = IPM_INVALID; } /* * Handler for IPMEV_TELEPHONY_EVENT events. */ void IpmDevice::onTelephonyEvent( IPM_TELEPHONY_INFO* info ) { LOGINFO("IpmDevice::processEvent() IPMEV_TELEPHONY_EVENT device: " << devName_ ); const std::string dtmf = "0123456789*#"; switch ( info->eTelInfoType ) { case TEL_INFOTYPE_EVENT: { int event_id = info->TelephonyInfo.TelEvtInfo.eTelephonyEventID; LOGDEBUG("TelephonyEventID: 0x" << std::hex << event_id); if ( event_id >= 0 && event_id <= 11 ) { channelMgr_.onDtmf(ipt_, dtmf.substr(event_id, 1), 100); /* fake duration */ } break; } default: break; } } /* * Handler for IPMEV_GET_LOCAL_MEDIA_INFO events. */ void IpmDevice::onLocalMediaInfo( IPM_MEDIA_INFO* mediaInfo ) { LOGINFO("IpmDevice::onLocalMediaInfo() device: " << devName_); printMediaInfo(mediaInfo); for( unsigned int i = 0; i < mediaInfo->unCount; i++ ) { switch ( mediaInfo->MediaData[i].eMediaType ) { case MEDIATYPE_AUDIO_LOCAL_RTP_INFO: localRtpAudio_.setAddress(mediaInfo->MediaData[i].mediaInfo.PortInfo.cIPAddress); localRtpAudio_.setPort(mediaInfo->MediaData[i].mediaInfo.PortInfo.unPortId); break; case MEDIATYPE_AUDIO_LOCAL_RTCP_INFO: localRtcpAudio_.setAddress(mediaInfo->MediaData[i].mediaInfo.PortInfo.cIPAddress); localRtcpAudio_.setPort(mediaInfo->MediaData[i].mediaInfo.PortInfo.unPortId); break; case MEDIATYPE_VIDEO_LOCAL_RTP_INFO: localRtpVideo_.setAddress(mediaInfo->MediaData[i].mediaInfo.PortInfo.cIPAddress); localRtpVideo_.setPort(mediaInfo->MediaData[i].mediaInfo.PortInfo.unPortId); break; case MEDIATYPE_VIDEO_LOCAL_RTCP_INFO: localRtcpVideo_.setAddress(mediaInfo->MediaData[i].mediaInfo.PortInfo.cIPAddress); localRtcpVideo_.setPort(mediaInfo->MediaData[i].mediaInfo.PortInfo.unPortId); break; default: break; } } } /* * Handler for IPMEV_EVENT_ENABLED events */ void IpmDevice::onEventEnabled() { LOGINFO("IpmDevice::onEventEnabled() device: " << devName_); initStepsRemaining_--; if ( initStepsRemaining_ == 0 ) { state_ = IPM_IDLE; } } /* * Handler for IPMEV_STARTMEDIA events. */ void IpmDevice::onStartMedia() { LOGINFO("IpmDevice::onStartMedia() device: " << devName_); state_ = IPM_STREAMING; busy_ = false; processPendingCommand(); } /* * Handler for IPMEV_STOPPED events. */ void IpmDevice::onStopped() { LOGINFO("IpmDevice::onStopped() device: " << devName_); state_ = IPM_IDLE; busy_ = false; processPendingCommand(); } /* * Handler for IPMEV_LISTEN events. */ void IpmDevice::onListen() { LOGINFO("IpmDevice::onListen() device: " << devName_); busy_ = false; processPendingCommand(); } /* * Handler for IPMEV__UNLISTEN events. */ void IpmDevice::onUnListen() { LOGINFO("IpmDevice::onUnListen() device: " << devName_); busy_ = false; processPendingCommand(); } /* * Handler for DMEV_PORT_CONNECT events. */ void IpmDevice::onPortConnect() { LOGINFO("IpmDevice::onPortConnect() device: " << devName_); busy_ = false; processPendingCommand(); } /* * Handler for DMEV_PORT_CONNECT_FAIL events. */ void IpmDevice::onPortConnectFail() { LOGERROR("IpmDevice::onPortConnectFail() device: " << devName_); busy_ = false; processPendingCommand(); } /* * Handler for DMEV_PORT_DISCONNECT events. */ void IpmDevice::onPortDisconnect() { LOGINFO("IpmDevice::onPortDisconnect() device: " << devName_); busy_ = false; processPendingCommand(); } /* * Debug aid. */ void IpmDevice::printPortInfo( DM_PORT_INFO_LIST* portInfo ) const { std::stringstream ss; for ( unsigned int i = 0; i < portInfo->unCount; i++ ) { DM_PORT_INFO& info = portInfo->port_info[i]; ss << "Port: " << i << " MediaType: " << info.port_media_type << " "; if ( info.port_media_type == DM_PORT_MEDIA_TYPE_AUDIO ) { ss << "Audio"; } else if ( info.port_media_type == DM_PORT_MEDIA_TYPE_VIDEO ) { ss << "Video"; } else if ( info.port_media_type == DM_PORT_MEDIA_TYPE_NBUP ) { ss << "NBUP"; } else { ss << info.port_media_type; } ss << std::endl; } LOGDEBUG(ss.str()); } /* * Debug aid */ void IpmDevice::printMediaInfo( IPM_MEDIA_INFO* mediaInfo ) const { std::stringstream ss; for ( unsigned int i = 0; i < mediaInfo->unCount; i++ ) { ss << "MediaType = "; switch ( mediaInfo->MediaData[i].eMediaType ) { case MEDIATYPE_VIDEO_LOCAL_RTP_INFO: ss << "MEDIATYPE_VIDEO_LOCAL_RTP_INFO"; break; case MEDIATYPE_VIDEO_LOCAL_RTCP_INFO: ss << "MEDIATYPE_VIDEO_LOCAL_RTCP_INFO"; break; case MEDIATYPE_AUDIO_LOCAL_RTP_INFO: ss << "MEDIATYPE_AUDIO_LOCAL_RTP_INFO"; break; case MEDIATYPE_AUDIO_LOCAL_RTCP_INFO: ss << "MEDIATYPE_AUDIO_LOCAL_RTCP_INFO"; break; case MEDIATYPE_NBUP_LOCAL_RTP_INFO: ss << "MEDIATYPE_NBUP_LOCAL_RTP_INFO"; break; default: ss << "MEDIATYPE_??? " << mediaInfo->MediaData[i].eMediaType; break; } ss << " IP = " << mediaInfo->MediaData[i].mediaInfo.PortInfo.cIPAddress; ss << " Port = " << mediaInfo->MediaData[i].mediaInfo.PortInfo.unPortId; ss << std::endl; } LOGDEBUG(ss.str()); } /* * load local information into the sdp * XXX 'response' sdpS should return all 'm' (media) headers that were 'offered' * with unused/unsupported ones having their port set to 0. */ void IpmDevice::buildLocalSdp( sdpSessionDescription& sdp ) const { /* get here so it can be used for the origin address */ IpInfo audio_media; getLocalMediaInfo(MEDIATYPE_AUDIO_LOCAL_RTP_INFO, audio_media); sdp.version()->setVersion("0"); sdp.origin()->setUserName("DiaStarServer"); sdp.origin()->setNetworkType("IN"); sdp.origin()->setAddressType("IP4"); sdp.origin()->setAddress(audio_media.getAddress().c_str()); time_t t; time(&t); std::stringstream sessionIdandVersion; sessionIdandVersion << t; sdp.origin()->setSessionId(sessionIdandVersion.str().c_str()); sdp.origin()->setVersion(sessionIdandVersion.str().c_str()); sdp.sessionName()->setName("DiaStarServer"); sdpTimeDescription* timeDescription = sdp.timeDescriptionList()->addItem(); timeDescription->time()->setStart(0); timeDescription->time()->setStop(0); /* media */ sdpMediaDescriptionList* mdList = sdp.mediaDescriptionList(); mdList->clear(); /* audio */ sdpMediaDescription* audioMD = mdList->addItem(); audioMD->connection()->setNetworkType("IN"); audioMD->connection()->setAddressType("IP4"); audioMD->connection()->setAddress(audio_media.getAddress().c_str()); sdpMedia* audioMedia = audioMD->media(); audioMedia->setMedia("audio"); audioMedia->setPort(audio_media.getPort()); audioMedia->setTransport("RTP/AVP"); audioMedia->setNumPorts(1); audioMedia->addFormat("0"); /* PCMU/8000 */ audioMedia->addFormat("101"); /* telephone-event/8000 */ sdpAttributeList* audioAttrList = audioMD->attributeList(); sdpAttribute* audioAttribute = audioAttrList->addItem(); audioAttribute->setProperty("rtpmap"); audioAttribute->setPropertyValue("0 PCMU/8000"); audioAttribute = audioAttrList->addItem(); audioAttribute->setProperty("rtpmap"); audioAttribute->setPropertyValue("101 telephone-event/8000"); audioAttribute = audioAttrList->addItem(); audioAttribute->setProperty("sendrecv"); audioAttribute->setPropertyValue(""); /* video */ IpInfo video_media; if ( getLocalMediaInfo(MEDIATYPE_VIDEO_LOCAL_RTP_INFO, video_media) ) { sdpMediaDescription* videoMD = mdList->addItem(); videoMD->connection()->setNetworkType("IN"); videoMD->connection()->setAddressType("IP4"); videoMD->connection()->setAddress(video_media.getAddress().c_str()); sdpMedia* videoMedia = videoMD->media(); videoMedia->setMedia("video"); videoMedia->setPort(video_media.getPort()); videoMedia->setTransport("RTP/AVP"); videoMedia->setNumPorts(1); videoMedia->addFormat("34"); /* H263/90000 */ sdpAttributeList* videoAttrList = videoMD->attributeList(); sdpAttribute* videoAttribute = videoAttrList->addItem(); videoAttribute->setProperty("rtpmap"); videoAttribute->setPropertyValue("34 H263/90000"); videoAttribute = videoAttrList->addItem(); videoAttribute->setProperty("fmtp"); videoAttribute->setPropertyValue("34 CIF=2"); videoAttribute = videoAttrList->addItem(); videoAttribute->setProperty("sendrecv"); videoAttribute->setPropertyValue(""); videoMD->bandwidth()->setModifier("AS"); videoMD->bandwidth()->setBandwidthValue("90"); } } /* * Set the dtmf signalling mode. */ void IpmDevice::setDtmfMode( DtmfMode dtmf_mode ) { IPM_PARM_INFO parmInfo; switch ( dtmf_mode ) { case DTMF_RFC2833: { eIPM_DTMFXFERMODE value = DTMFXFERMODE_RFC2833; parmInfo.eParm = PARMCH_DTMFXFERMODE; parmInfo.pvParmValue = &value; LOGINFO("IpmDevice::setDtmfMode() using RFC2833"); if ( ipm_SetParm(devHandle_, &parmInfo, EV_SYNC) < 0 ) { LOGERROR("Error in ipm_SetParm()\n"); } int rfc2833PayloadType = 101; parmInfo.eParm = PARMCH_RFC2833EVT_TX_PLT; parmInfo.pvParmValue = &rfc2833PayloadType; if ( ipm_SetParm(devHandle_, &parmInfo, EV_SYNC) < 0 ) { LOGERROR("Error in ipm_SetParm()\n"); } parmInfo.eParm = PARMCH_RFC2833EVT_RX_PLT; parmInfo.pvParmValue = &rfc2833PayloadType; if ( ipm_SetParm(devHandle_, &parmInfo, EV_SYNC) < 0 ) { LOGERROR("Error in ipm_SetParm()\n"); } } break; case DTMF_INBAND: { eIPM_DTMFXFERMODE value = DTMFXFERMODE_INBAND; parmInfo.eParm = PARMCH_DTMFXFERMODE; parmInfo.pvParmValue = &value; LOGINFO("IpmDevice::setDtmfMode() using inband audio"); if ( ipm_SetParm(devHandle_, &parmInfo, EV_SYNC) < 0 ) { LOGERROR("Error in ipm_SetParm()\n"); } } break; } } /* vim:ts=4:set nu: * EOF */