/*
* 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
*/