[server] / trunk / server / src / ipmdevice.cxx Repository:
ViewVC logotype

View of /trunk/server/src/ipmdevice.cxx

Parent Directory Parent Directory | Revision Log Revision Log


Revision 275 - (download) (annotate)
Tue Jun 16 15:50:49 2009 UTC (3 years, 11 months ago) by jtarlton
File size: 13858 byte(s)
ensure streaming always gets started even if some states get skipped
    1 /*
    2  * This file is part of Dialogic Woomera Server project.
    3  *
    4  * More information about this project can be found at:
    5  * http://www.opendialogic.org.
    6  *
    7  * Copyright (C) 2009 Dialogic Corp.
    8  *
    9  * This program is free software; you can redistribute it and/or
   10  * modify it under the terms of the GNU General Public License
   11  * as published by the Free Software Foundation; either version 2
   12  * of the License, or (at your option) any later version.
   13  *
   14  * This program is distributed in the hope that it will be useful,
   15  * but WITHOUT ANY WARRANTY; without even the implied warranty of
   16  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
   17  * GNU General Public License for more details.
   18  *
   19  * You should have received a copy of the GNU General Public License
   20  * along with this program; if not, write to the Free Software
   21  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
   22  * 02110-1301, USA.
   23  * Alternatively see <http://www.gnu.org/licenses/>.
   24  * Or see the LICENSE file included within the source tree.
   25  *
   26  */
   27 
   28 /*!
   29  * \file        ipmdevice.cxx
   30  * \brief       Dialogic IPM device
   31  * \author      Antony Martin <antony.martin@dialogic.com>
   32  * \author      John Tarlton <john.tarlton@dialogic.com>
   33  * \version     2-APR-2009
   34  */
   35 
   36 /*------------------------------ Dependencies --------------------------------*/
   37 
   38 #include "logger.h"
   39 #include "string-util.h"
   40 
   41 #include "ipmdevice.h"
   42 
   43 /*----------------------------------------------------------------------------*/
   44 
   45 /*
   46  * ctor
   47  */
   48 IpmDevice::IpmDevice( const std::string& name,
   49                     DialogicChannelManager& channelMgr )
   50   : DialogicDevice(name, channelMgr)
   51 {
   52   memset(&localMediaInfo_, 0, sizeof(IPM_MEDIA_INFO));
   53 
   54   /* Number of steps in the initialisation sequence, decremented by event
   55    * handlers. When zero state is changed to IDLE.
   56    *
   57    *  IPMEV_OPEN,
   58    *  DMEV_GET_RX_PORT_INFO,
   59    *  DMEV_GET_TX_PORT_INFO
   60    */
   61   initStepsRemaining_ = 3;
   62 }
   63 
   64 
   65 /*
   66  * dtor
   67  */
   68 IpmDevice::~IpmDevice()
   69 {
   70 }
   71 
   72 
   73 /*
   74  * Open the device.
   75  */
   76 bool IpmDevice::open()
   77 {
   78   LOGDEBUG("IpmDevice::open() device: " << devName_);
   79 
   80   devHandle_ = ipm_Open(devName_.c_str(), NULL, EV_ASYNC);
   81   if ( devHandle_ < 0 )
   82   {
   83     LOGERROR("ipm_Open() failed");
   84     return false;
   85   }
   86   state_ = IPM_OPENING;
   87   return true;
   88 }
   89 
   90 
   91 /*
   92  * Close the device
   93  */
   94 bool IpmDevice::close()
   95 {
   96   LOGDEBUG("IpmDevice::close() device: " << devName_);
   97 
   98   if ( devHandle_ > 0 )
   99   {
  100     if ( ipm_Close(devHandle_, NULL) < 0 )
  101     {
  102       LOGERROR("ipm_Close() failed");
  103       return false;
  104     }
  105     devHandle_ = 0;
  106   }
  107   return true;
  108 }
  109 
  110 
  111 /*
  112  * Connect media.
  113  */
  114 bool IpmDevice::listen( DialogicDevice* other )
  115 {
  116   LOGDEBUG("IpmDevice::listen() device: " << devName_ <<
  117            " other: " << other->getDeviceName());
  118 
  119   SC_TSINFO tsinfo;
  120   tsinfo.sc_numts = 1;
  121   tsinfo.sc_tsarrayp = other->getXmitTimeslotPtr();
  122 
  123   if ( ipm_Listen(devHandle_, &tsinfo, EV_SYNC) == -1 )
  124   {
  125     LOGERROR("ipm_Listen() failed on device: " << devName_ <<
  126              " " << ATDV_ERRMSGP(devHandle_));
  127     return false;
  128   }
  129   return true;
  130 }
  131 
  132 
  133 /*
  134  * Disconnect media.
  135  */
  136 bool IpmDevice::unListen()
  137 {
  138   LOGDEBUG("IpmDevice::unListen() device: " << devName_);
  139 
  140   if ( ipm_UnListen(devHandle_, EV_SYNC) == -1)
  141   {
  142     LOGERROR("ipm_UnListen() failed on device: " << devName_ <<
  143              " " << ATDV_ERRMSGP(devHandle_));
  144     return false;
  145   }
  146   return true;
  147 }
  148 
  149 
  150 /*
  151  * Search localMediaInfo_ for the requested information.
  152  */
  153 void IpmDevice::getLocalMediaInfo( eIPM_MEDIA_TYPE type,
  154                                    IpInfo& rtp_media ) const
  155 {
  156   for ( unsigned int i = 0; i < localMediaInfo_.unCount; i++ )
  157   {
  158     if ( type == localMediaInfo_.MediaData[i].eMediaType )
  159     {
  160       rtp_media.setAddress(localMediaInfo_.MediaData[i].mediaInfo.PortInfo.cIPAddress);
  161       rtp_media.setPort(localMediaInfo_.MediaData[i].mediaInfo.PortInfo.unPortId);
  162       break;
  163     }
  164   }
  165 }
  166 
  167 
  168 /*
  169  * Save the remote params.
  170  */
  171 void IpmDevice::setRemoteMediaInfo( eIPM_MEDIA_TYPE type,
  172                                     const IpInfo& rtp_info )
  173 {
  174   if ( type == MEDIATYPE_AUDIO_LOCAL_RTP_INFO )
  175   {
  176     remoteRtpAudio_ = rtp_info;
  177     remoteRtcpAudio_ = rtp_info;
  178     remoteRtcpAudio_.setPort(remoteRtpAudio_.getPort() + 1); // XXXXXXXXXx
  179   }
  180 }
  181 
  182 
  183 /*
  184  * Stop the IPM streaming and/or digit reception
  185  */
  186 bool IpmDevice::stop( eIPM_STOP_OPERATION operation )
  187 {
  188   if ( state_ == IPM_IDLE )
  189   {
  190     return false;
  191   }
  192 
  193   if ( ipm_Stop(devHandle_, operation, EV_ASYNC) == -1 )
  194   {
  195     LOGERROR("ipm_Stop() on device: " << devName_ << " failed: " <<
  196              ATDV_LASTERR(devHandle_));
  197     return false;
  198   }
  199   state_ = IPM_STOPPING;
  200   return true;
  201 }
  202 
  203 
  204 /*
  205  * Start RTP streaming to peer.
  206  */
  207 bool IpmDevice::startMedia()
  208 {
  209   return startMedia(remoteRtpAudio_, remoteRtcpAudio_);
  210 }
  211 
  212 
  213 /*
  214  * Start RTP streaming using G.711 and local/remote port information.
  215  * Will use G.711 - choose ALaw Ulaw from woomera msg?
  216  * Mu hardwired in for now.
  217  */
  218 bool IpmDevice::startMedia( const IpInfo& remote_rtp_audio,
  219                             const IpInfo& remote_rtcp_audio )
  220 {
  221   if ( state_ != IPM_IDLE )
  222   {
  223     LOGINFO("IpmDevice::startMedia() device: " << devName_ << " already started");
  224     return false;
  225   }
  226 
  227   IPM_MEDIA_INFO mediaInfo;
  228   memset(&mediaInfo, 0, sizeof(IPM_MEDIA_INFO));
  229 
  230   int mediaCnt = 0; /* limit MAX_MEDIA_INFO */
  231 
  232   /* remote audio
  233    */
  234   mediaInfo.MediaData[mediaCnt].eMediaType =  MEDIATYPE_AUDIO_REMOTE_CODER_INFO;
  235   mediaInfo.MediaData[mediaCnt].mediaInfo.CoderInfo.eCoderType = CODER_TYPE_G711ULAW64K;
  236   mediaInfo.MediaData[mediaCnt].mediaInfo.CoderInfo.eFrameSize = CODER_FRAMESIZE_20;
  237   mediaInfo.MediaData[mediaCnt].mediaInfo.CoderInfo.unFramesPerPkt = 1;
  238   mediaInfo.MediaData[mediaCnt].mediaInfo.CoderInfo.eVadEnable = CODER_VAD_ENABLE;
  239   mediaInfo.MediaData[mediaCnt].mediaInfo.CoderInfo.unCoderPayloadType = 0;
  240   mediaInfo.MediaData[mediaCnt].mediaInfo.CoderInfo.unRedPayloadType = 0;
  241   mediaCnt++;
  242 
  243   /* local audio
  244    */
  245   mediaInfo.MediaData[mediaCnt].eMediaType =  MEDIATYPE_AUDIO_LOCAL_CODER_INFO;
  246   mediaInfo.MediaData[mediaCnt].mediaInfo.CoderInfo.eCoderType = CODER_TYPE_G711ULAW64K;
  247   mediaInfo.MediaData[mediaCnt].mediaInfo.CoderInfo.eFrameSize = CODER_FRAMESIZE_20;
  248   mediaInfo.MediaData[mediaCnt].mediaInfo.CoderInfo.unFramesPerPkt = 1;
  249   mediaInfo.MediaData[mediaCnt].mediaInfo.CoderInfo.eVadEnable = CODER_VAD_ENABLE;
  250   mediaInfo.MediaData[mediaCnt].mediaInfo.CoderInfo.unCoderPayloadType = 0;
  251   mediaInfo.MediaData[mediaCnt].mediaInfo.CoderInfo.unRedPayloadType = 0;
  252   mediaCnt++;
  253 
  254   /* remote audio ports and IP addresses
  255    */
  256   mediaInfo.MediaData[mediaCnt].eMediaType = MEDIATYPE_AUDIO_REMOTE_RTP_INFO;
  257   copy_string_to_c_array(remote_rtp_audio.getAddress(),
  258                          mediaInfo.MediaData[mediaCnt].mediaInfo.PortInfo.cIPAddress,
  259                          IP_ADDR_SIZE);
  260   mediaInfo.MediaData[mediaCnt].mediaInfo.PortInfo.unPortId = remote_rtp_audio.getPort();
  261   mediaCnt++;
  262 
  263   mediaInfo.MediaData[mediaCnt].eMediaType =  MEDIATYPE_AUDIO_REMOTE_RTCP_INFO;
  264   copy_string_to_c_array(remote_rtcp_audio.getAddress(),
  265                          mediaInfo.MediaData[mediaCnt].mediaInfo.PortInfo.cIPAddress,
  266                          IP_ADDR_SIZE);
  267   mediaInfo.MediaData[mediaCnt].mediaInfo.PortInfo.unPortId = remote_rtcp_audio.getPort();
  268   mediaCnt++;
  269 
  270   mediaInfo.unCount = mediaCnt;
  271 
  272   LOGDEBUG("IpmDevice::startMedia() starting RTP streaming on device: " <<
  273            devName_ << " remote_rtp_audio: " << remote_rtp_audio <<
  274            " remote_rtcp_audio: " << remote_rtcp_audio);
  275 
  276   if ( ipm_StartMedia(devHandle_, &mediaInfo, DATA_IP_TDM_BIDIRECTIONAL, EV_ASYNC) == -1 )
  277   {
  278     LOGERROR("ipm_StartMedia failed for device: " << devName_ <<
  279              " with error: " << ATDV_ERRMSGP(devHandle_));
  280     return false;
  281   }
  282 
  283   state_ = IPM_STARTING;
  284   return true;
  285 }
  286 
  287 
  288 /*
  289  * Forward to event specific handler.
  290  */
  291 bool IpmDevice::processEvent( METAEVENT& metaevent )
  292 {
  293   switch ( metaevent.evttype )
  294   {
  295     case IPMEV_OPEN:
  296       onOpen();
  297       break;
  298 
  299     case IPMEV_EVENT_ENABLED:
  300       onEventEnabled();
  301       break;
  302 
  303     case IPMEV_GET_LOCAL_MEDIA_INFO:
  304       onLocalMediaInfo((IPM_MEDIA_INFO*)sr_getevtdatap());
  305       break;
  306 
  307     case IPMEV_STARTMEDIA:
  308       onStartMedia();
  309       break;
  310 
  311     case IPMEV_STOPPED:
  312       onStopped();
  313       break;
  314 
  315     case IPMEV_ERROR:
  316       onError();
  317       break;
  318 
  319     case DMEV_GET_TX_PORT_INFO:
  320       onGetTxPortInfo((DM_PORT_INFO_LIST*)sr_getevtdatap());
  321       break;
  322 
  323     case DMEV_GET_RX_PORT_INFO:
  324       onGetRxPortInfo((DM_PORT_INFO_LIST*)sr_getevtdatap());
  325       break;
  326 
  327     case DMEV_GET_TX_PORT_INFO_FAIL:
  328       onPortGetFail();
  329       break;
  330 
  331     case DMEV_GET_RX_PORT_INFO_FAIL:
  332       onPortGetFail();
  333       break;
  334 
  335     case DMEV_PORT_CONNECT:
  336       onPortConnect();
  337       break;
  338 
  339     default:
  340       LOGWARN("IpmDevice::processEvent() unhandled event: 0x" <<
  341               std::hex << metaevent.evttype << " for device: " << devName_);
  342       return false;
  343   }
  344   return true;
  345 }
  346 
  347 
  348 /*
  349  * Handler for IPMEV_OPEN events.
  350  */
  351 void IpmDevice::onOpen()
  352 {
  353   LOGINFO("IpmDevice::onOpen() device: " << devName_);
  354 
  355   /* Get and save the transmit timeslot on CTBus
  356    */
  357   SC_TSINFO tsinfo;
  358   tsinfo.sc_numts = 1;
  359   tsinfo.sc_tsarrayp = getXmitTimeslotPtr();
  360   if ( ipm_GetXmitSlot(devHandle_, &tsinfo, EV_SYNC) == -1 )
  361   {
  362     LOGERROR("ipm_GetXmitSlot() failed" );
  363   }
  364 
  365   /* Request port info
  366    */
  367   if ( dev_GetTransmitPortInfo(devHandle_, this) == -1 )
  368   {
  369     LOGERROR("dev_GetTransmitPortInfo() failed");
  370   }
  371   if ( dev_GetReceivePortInfo(devHandle_, this) == -1 )
  372   {
  373     LOGERROR("dev_GetReceivePortInfo() failed");
  374   }
  375 
  376   /* Request the local media information and save it in localMediaInfo_
  377    */
  378   localMediaInfo_.unCount = 3;
  379   localMediaInfo_.MediaData[0].eMediaType = MEDIATYPE_AUDIO_LOCAL_RTP_INFO;
  380   localMediaInfo_.MediaData[1].eMediaType = MEDIATYPE_VIDEO_LOCAL_RTP_INFO;
  381   localMediaInfo_.MediaData[2].eMediaType = MEDIATYPE_NBUP_LOCAL_RTP_INFO;
  382 
  383   if ( ipm_GetLocalMediaInfo (devHandle_, &localMediaInfo_, EV_ASYNC) == -1 )
  384   {
  385     LOGERROR("ipm_GetLocalMediaInfo() failed for device: " <<
  386              devName_ << " with error: " << ATDV_LASTERR(devHandle_));
  387   }
  388 
  389   /* update init state
  390    */
  391   state_ = IPM_INITIALIZATION_START;
  392   initStepsRemaining_--;
  393   if ( initStepsRemaining_ == 0 )
  394   {
  395     state_ = IPM_IDLE;
  396   }
  397 }
  398 
  399 
  400 /*
  401  * Handler for DMEV_GET_TX_PORT_INFO events.
  402  */
  403 void IpmDevice::onGetTxPortInfo( DM_PORT_INFO_LIST* portInfo )
  404 {
  405   LOGINFO("IpmDevice::onGetTxPortInfo() device: " << devName_);
  406 
  407   memcpy(&txPortInfoList_, portInfo, sizeof(DM_PORT_INFO_LIST));
  408   printPortInfo(portInfo);
  409 
  410   initStepsRemaining_--;
  411   if ( initStepsRemaining_ == 0 )
  412   {
  413     state_ = IPM_IDLE;
  414   }
  415 }
  416 
  417 
  418 /*
  419  * Handler for DMEV_GET_RX_PORT_INFO events.
  420  */
  421 void IpmDevice::onGetRxPortInfo( DM_PORT_INFO_LIST* portInfo )
  422 {
  423   LOGINFO("IpmDevice::onGetRxPortInfo() device: " << devName_);
  424 
  425   memcpy(&rxPortInfoList_, portInfo, sizeof(DM_PORT_INFO_LIST));
  426   printPortInfo(portInfo);
  427 
  428   initStepsRemaining_--;
  429   if ( initStepsRemaining_ == 0 )
  430   {
  431     state_ = IPM_IDLE;
  432   }
  433 }
  434 
  435 
  436 /*
  437  * Handler for DMEV_PORT_CONNECT events.
  438  */
  439 void IpmDevice::onPortConnect()
  440 {
  441   LOGINFO("IpmDevice::onPortConnect() device: " << devName_);
  442 }
  443 
  444 
  445 /*
  446  * Handler for DMEV_GET_TX_PORT_INFO_FAIL and DMEV_GET_RX_PORT_INFO_FAIL
  447  * events.
  448  */
  449 void IpmDevice::onPortGetFail()
  450 {
  451   LOGINFO("IpmDevice::onPortGetFail() device: " << devName_);
  452 
  453   state_ = IPM_INVALID;
  454 }
  455 
  456 
  457 /*
  458  * Handler for IPMEV_ERROR events.
  459  */
  460 void IpmDevice::onError()
  461 {
  462   LOGERROR("IpmDevice::onError() device: " << devName_ <<
  463            " error: " << ATDV_ERRMSGP(devHandle_));
  464 
  465   state_ = IPM_INVALID;
  466 }
  467 
  468 
  469 /*
  470  * Handler for IPMEV_EVENT_ENABLED events
  471  */
  472 void IpmDevice::onEventEnabled()
  473 {
  474   LOGINFO("IpmDevice::onEventEnabled() device: " << devName_);
  475 
  476   initStepsRemaining_--;
  477   if ( initStepsRemaining_ == 0 )
  478   {
  479     state_ = IPM_IDLE;
  480   }
  481 }
  482 
  483 
  484 /*
  485  * Handler for IPMEV_STARTMEDIA events.
  486  */
  487 void IpmDevice::onStartMedia()
  488 {
  489   LOGINFO("IpmDevice::onStartMedia() device: " << devName_);
  490 
  491   state_ = IPM_STREAMING;
  492 }
  493 
  494 
  495 /*
  496  * Handler for IPMEV_STOPPED events.
  497  */
  498 void IpmDevice::onStopped()
  499 {
  500   LOGINFO("IpmDevice::onStopped() device: " << devName_);
  501 
  502   state_ = IPM_IDLE;
  503 }
  504 
  505 
  506 /*
  507  * Handler for IPMEV_GET_LOCAL_MEDIA_INFO events.
  508  */
  509 void IpmDevice::onLocalMediaInfo( IPM_MEDIA_INFO* mediaInfo )
  510 {
  511   LOGINFO("IpmDevice::onLocalMediaInfo() device: " << devName_);
  512 
  513   memcpy(&localMediaInfo_, mediaInfo, sizeof(IPM_MEDIA_INFO));
  514   printMediaInfo(&localMediaInfo_);
  515 }
  516 
  517 
  518 
  519 /*
  520  * Debug aid.
  521  */
  522 void IpmDevice::printPortInfo( DM_PORT_INFO_LIST* portInfo ) const
  523 {
  524   std::stringstream ss;
  525 
  526   for ( unsigned int i = 0; i < portInfo->unCount; i++ )
  527   {
  528     DM_PORT_INFO& info = portInfo->port_info[i];
  529     ss << "Port: " << i << " MediaType: " << info.port_media_type << " ";
  530     if ( info.port_media_type == DM_PORT_MEDIA_TYPE_AUDIO )
  531     {
  532       ss << "Audio";
  533     }
  534     else if ( info.port_media_type == DM_PORT_MEDIA_TYPE_VIDEO )
  535     {
  536       ss << "Video";
  537     }
  538     else if ( info.port_media_type == DM_PORT_MEDIA_TYPE_NBUP )
  539     {
  540       ss << "NBUP";
  541     }
  542     else
  543     {
  544       ss << info.port_media_type;
  545     }
  546     ss << std::endl;
  547   }
  548   LOGDEBUG(ss.str());
  549 }
  550 
  551 
  552 /*
  553  * Debug aid
  554  */
  555 void IpmDevice::printMediaInfo( IPM_MEDIA_INFO* mediaInfo ) const
  556 {
  557   std::stringstream ss;
  558   for ( unsigned int i = 0; i < mediaInfo->unCount; i++ )
  559   {
  560     ss << "MediaType = ";
  561     switch ( mediaInfo->MediaData[i].eMediaType )
  562     {
  563       case MEDIATYPE_VIDEO_LOCAL_RTP_INFO:
  564         ss << "MEDIATYPE_VIDEO_LOCAL_RTP_INFO";
  565         break;
  566 
  567       case MEDIATYPE_VIDEO_LOCAL_RTCP_INFO:
  568         ss << "MEDIATYPE_VIDEO_LOCAL_RTCP_INFO";
  569         break;
  570 
  571       case MEDIATYPE_AUDIO_LOCAL_RTP_INFO:
  572         ss << "MEDIATYPE_AUDIO_LOCAL_RTP_INFO";
  573         break;
  574 
  575       case MEDIATYPE_AUDIO_LOCAL_RTCP_INFO:
  576         ss << "MEDIATYPE_AUDIO_LOCAL_RTCP_INFO";
  577         break;
  578 
  579       case MEDIATYPE_NBUP_LOCAL_RTP_INFO:
  580         ss << "MEDIATYPE_NBUP_LOCAL_RTP_INFO";
  581         break;
  582 
  583       default:
  584         ss << "MEDIATYPE_??? " << mediaInfo->MediaData[i].eMediaType;
  585         break;
  586     }
  587     ss << " IP = " << mediaInfo->MediaData[i].mediaInfo.PortInfo.cIPAddress;
  588     ss << " Port = " << mediaInfo->MediaData[i].mediaInfo.PortInfo.unPortId;
  589     ss << std::endl;
  590   }
  591   LOGDEBUG(ss.str());
  592 }
  593 
  594 
  595 /* vim:ts=4:set nu:
  596  * EOF
  597  */

No admin address has been configured
ViewVC Help
Powered by ViewVC 1.0.8