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

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

Parent Directory Parent Directory | Revision Log Revision Log


Revision 1218 - (download) (annotate)
Wed Jun 6 13:16:07 2012 UTC (11 months, 1 week ago) by jtarlton
File size: 43914 byte(s)
Pass/store rtp information in RtpIpInfo objects. These include the media direction in addition to the ip address and port number.
    1 /*
    2  * This file is part of Project DiaStar Server.
    3  *
    4  * More information about this project can be found at:
    5  * http://www.projectdiastar.org.
    6  *
    7  * Copyright (C) 2009,2010  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        dialogicchannel.cxx
   30  * \brief       Manages the resources for a single call channel.
   31  * \author      Antony Martin <antony.martin@dialogic.com>
   32  * \author      John Tarlton <john.tarlton@dialogic.com>
   33  * \version     15-MAR-2010 extracted from DialogicChannelManager
   34  */
   35 
   36 
   37 /*-------------------------------- Dependencies ------------------------------*/
   38 
   39 #include <climits>
   40 #include <sys/stat.h>
   41 #include <unistd.h>
   42 
   43 #include "logger.h"
   44 
   45 #include "dialogicchannelmanager.h"
   46 
   47 
   48 /*----------------------------------------------------------------------------*/
   49 
   50 /*
   51  * ctor. ISDN
   52  */
   53 DialogicChannel::DialogicChannel( DialogicChannelManager& channelMgr,
   54                                   GcIsdnDevice* gc,
   55                                   IpmDevice* ipm )
   56   : channelMgr_ (channelMgr),
   57     context_ (0),
   58     gcDevice_ (gc),
   59     m3gDevice_ (0),
   60     ipmDevice_ (ipm),
   61     mmDevice_ (0),
   62     confDevice_ (0),
   63     confParty_ (0),
   64     rtspIpmDevice_ (0),
   65     protocol_ (gc->getProtocol()),  /* ISDN | SS7 */
   66     other_channel_ (0)
   67 {
   68   gcDevice_->bindChannel(this);
   69   ipmDevice_->bindChannel(this);
   70 
   71   VoxDevice* vox = gcDevice_->getVox();
   72   vox->bindChannel(this);
   73 }
   74 
   75 
   76 /*
   77  * ctor. H324 (using ISDN)
   78  */
   79 DialogicChannel::DialogicChannel( DialogicChannelManager& channelMgr,
   80                                 StateMachine& sm,
   81                                 GcIsdnDevice* gc,
   82                                 M3gDevice* m3g,
   83                                 IpmDevice* ipm )
   84   : channelMgr_ (channelMgr),
   85     context_ (0),
   86     gcDevice_ (gc),
   87     m3gDevice_ (m3g),
   88     ipmDevice_ (ipm),
   89     mmDevice_ (0),
   90     confDevice_ (0),
   91     confParty_ (0),
   92     rtspIpmDevice_ (0),
   93     protocol_ (PROTOCOL_H324),
   94     other_channel_ (0)
   95 {
   96   gcDevice_->bindChannel(this);
   97   m3gDevice_->bindChannel(this);
   98   ipmDevice_->bindChannel(this);
   99 
  100   context_ = sm.createContext(this);
  101 }
  102 
  103 
  104 /*
  105  * ctor. SIP
  106  */
  107 DialogicChannel::DialogicChannel( DialogicChannelManager& channelMgr,
  108                                   StateMachine& sm,
  109                                   GcIptDevice* gc,
  110                                   IpmDevice* ipm )
  111   : channelMgr_ (channelMgr),
  112     context_ (0),
  113     gcDevice_ (gc),
  114     m3gDevice_ (0),
  115     ipmDevice_ (ipm),
  116     mmDevice_ (0),
  117     confDevice_ (0),
  118     confParty_ (0),
  119     rtspIpmDevice_ (0),
  120     protocol_ (PROTOCOL_SIP),
  121     other_channel_ (0)
  122 {
  123   gcDevice_->bindChannel(this);
  124 
  125   IpmDevice* ipt_ipm = static_cast<GcIptDevice*>(gcDevice_)->getIpmDevice();
  126   ipt_ipm->bindChannel(this);
  127 
  128   ipmDevice_->bindChannel(this);
  129 
  130   VoxDevice* vox = gcDevice_->getVox();
  131   vox->bindChannel(this);
  132 
  133   context_ = sm.createContext(this);
  134 }
  135 
  136 
  137 /*
  138  * ctor. CONF
  139  */
  140 DialogicChannel::DialogicChannel( DialogicChannelManager& channelMgr,
  141                                   StateMachine& sm,
  142                                   ConfDevice* confDevice,
  143                                   ConfPartyDevice* confParty,
  144                                   IpmDevice* ipm )
  145   : channelMgr_ (channelMgr),
  146     context_ (0),
  147     gcDevice_ (0),
  148     m3gDevice_ (0),
  149     ipmDevice_ (ipm),
  150     mmDevice_ (0),
  151     confDevice_ (confDevice),
  152     confParty_ (confParty),
  153     rtspIpmDevice_ (0),
  154     protocol_ (PROTOCOL_CONF),
  155     other_channel_ (0)
  156 {
  157   confDevice_->bindChannel(this);
  158   confParty_->bindChannel(this);
  159   ipmDevice_->bindChannel(this);
  160 
  161   context_ = sm.createContext(this);
  162 }
  163 
  164 
  165 /*
  166  * dtor, release resources.
  167  */
  168 DialogicChannel::~DialogicChannel()
  169 {
  170   if ( gcDevice_ )
  171   {
  172     if ( getProtocol() == PROTOCOL_SIP )
  173     {
  174       IpmDevice* ipt_ipm = static_cast<GcIptDevice*>(gcDevice_)->getIpmDevice();
  175       ipt_ipm->unBindChannel();
  176     }
  177 
  178     VoxDevice* vox = gcDevice_->getVox();
  179     if ( vox  )
  180     {
  181       vox->unBindChannel();
  182     }
  183     gcDevice_->unBindChannel();
  184   }
  185   if ( m3gDevice_ )
  186   {
  187     m3gDevice_->unBindChannel();
  188   }
  189   if ( ipmDevice_ )
  190   {
  191     ipmDevice_->unBindChannel();
  192   }
  193   if ( mmDevice_ )
  194   {
  195     if ( mmDevice_->isPlaying() )
  196     {
  197       mmDevice_->stopPlay(PLAY_STOPPED);
  198       mmDevice_->disconnect();
  199     }
  200     if ( mmDevice_->isRecording() )
  201     {
  202       mmDevice_->stopRecord(RECORD_STOPPED);
  203       mmDevice_->disconnect();
  204     }
  205     mmDevice_->unBindChannel();
  206     channelMgr_.freeMmDevice(mmDevice_);
  207   }
  208   if ( confDevice_ )
  209   {
  210     confDevice_->unBindChannel();
  211   }
  212   if ( confParty_ )
  213   {
  214     confParty_->unBindChannel();
  215   }
  216   if ( rtspIpmDevice_ )
  217   {
  218     rtspIpmDevice_->unBindChannel();
  219     channelMgr_.freeIpmDevice(rtspIpmDevice_);
  220   }
  221   delete context_;
  222 }
  223 
  224 
  225 /*
  226  * Forward to channel manager.
  227  */
  228 RtspConnector& DialogicChannel::getRtspConnector()
  229 {
  230   return channelMgr_.getRtspConnector();
  231 }
  232 
  233 
  234 /*
  235  * Make an outbound call on the dti or ipt device.
  236  */
  237 bool DialogicChannel::makeCall( const std::string& local_number,
  238                                 const std::string& local_name,
  239                                 const std::string& remote_number,
  240                                 bool cpa )
  241 {
  242   if ( !gcDevice_ )
  243   {
  244     return false;
  245   }
  246   direction_ = DIRECTION_OUTBOUND;
  247   return gcDevice_->makeCall(local_number, local_name, remote_number, cpa);
  248 }
  249 
  250 
  251 /*
  252  * Hangup the current call.
  253  */
  254 bool DialogicChannel::hangup( int cause )
  255 {
  256   if ( !gcDevice_ )
  257   {
  258     return false;
  259   }
  260   if ( getProtocol() == PROTOCOL_H324 )
  261   {
  262     m3gDevice_->endSession();
  263     return true;
  264   }
  265   return gcDevice_->dropCall(cause);
  266 }
  267 
  268 
  269 /*
  270  * Accept the current call.
  271  */
  272 bool DialogicChannel::accept()
  273 {
  274   if ( !gcDevice_ || (direction_ != DIRECTION_INBOUND) )
  275   {
  276     return false;
  277   }
  278   return gcDevice_->acceptCall();
  279 }
  280 
  281 
  282 /*
  283  * Answer the current call.
  284  */
  285 bool DialogicChannel::answer()
  286 {
  287   if ( !gcDevice_ || (direction_ != DIRECTION_INBOUND) )
  288   {
  289     return false;
  290   }
  291 
  292   /* Stop any multi-media ringback. SIP only */
  293   if ( mmDevice_ && mmDevice_->isPlaying() )
  294   {
  295     IpmDevice* ipt_ipm = static_cast<GcIptDevice*>(gcDevice_)->getIpmDevice();
  296     ipt_ipm->removeOverlay();
  297 
  298     mmDevice_->stopPlay(PLAY_STOPPED);
  299   }
  300   return gcDevice_->answerCall();
  301 }
  302 
  303 
  304 /*
  305  * Send dtmf digits.
  306  */
  307 bool DialogicChannel::sendDtmf( const std::string& dtmf )
  308 {
  309   if ( (protocol_ == PROTOCOL_ISDN) || (protocol_ == PROTOCOL_SS7) )
  310   {
  311     /* Inband using the vox device. */
  312     VoxDevice* vox = gcDevice_->getVox();
  313     if ( !vox )
  314     {
  315       return false;
  316     }
  317     gcDevice_->listen(vox);
  318     return vox->sendDtmf(dtmf);
  319   }
  320   else if ( protocol_ == PROTOCOL_H324 )
  321   {
  322     m3gDevice_->sendDtmf(dtmf);
  323     return true;
  324   }
  325   return false;
  326 }
  327 
  328 
  329 /*
  330  * Enable tone event notifications.
  331  */
  332 bool DialogicChannel::enableToneEvents()
  333 {
  334   if ( !gcDevice_ )
  335   {
  336     return false;
  337   }
  338   VoxDevice* vox = gcDevice_->getVox();
  339   if ( !vox )
  340   {
  341     return false;
  342   }
  343   vox->enableToneNotifications();
  344   return true;
  345 }
  346 
  347 
  348 /*
  349  * Disable tone event notifications.
  350  */
  351 bool DialogicChannel::disableToneEvents()
  352 {
  353   if ( !gcDevice_ )
  354   {
  355     return false;
  356   }
  357   VoxDevice* vox = gcDevice_->getVox();
  358   if ( !vox )
  359   {
  360     return false;
  361   }
  362   vox->disableToneNotifications();
  363   return true;
  364 }
  365 
  366 
  367 /*
  368  * Enable info event notifications.
  369  */
  370 bool DialogicChannel::enableInfoEvents()
  371 {
  372   if ( getProtocol() != PROTOCOL_SIP )
  373   {
  374     return false;
  375   }
  376   GcIptDevice* ipt = static_cast<GcIptDevice*>(gcDevice_);
  377   ipt->enableInfoEvents();
  378   return true;
  379 }
  380 
  381 
  382 /*
  383  * Disable info event notifications.
  384  */
  385 bool DialogicChannel::disableInfoEvents()
  386 {
  387   if ( getProtocol() != PROTOCOL_SIP )
  388   {
  389     return false;
  390   }
  391   GcIptDevice* ipt = static_cast<GcIptDevice*>(gcDevice_);
  392   ipt->disableInfoEvents();
  393   return true;
  394 }
  395 
  396 
  397 /*
  398  * Play media to an established call.
  399  */
  400 bool DialogicChannel::play( const std::string& audio_uri,
  401                             const std::string& video_uri,
  402                             const std::string& overlay,
  403                             const std::string& stop_digits,
  404                             const std::string& lang,
  405                             int repeat_count )
  406 {
  407   if ( mmDevice_ || rtspIpmDevice_ )
  408   {
  409     return false;   /* Busy! */
  410   }
  411 
  412   player_.audioFile.clear();
  413   player_.audioEncoding.clear();
  414 
  415   player_.videoFile.clear();
  416   player_.videoEncoding.clear();
  417 
  418   player_.overlay = overlay;
  419 
  420   stop_digits_ = stop_digits;
  421   collected_digits_.clear();
  422 
  423   player_.repeatCount = repeat_count;
  424   player_.duration = 0;
  425   player_.rtspSessionId = 0;
  426 
  427 
  428   /* Check scheme.
  429    */
  430   bool play_rtsp = false;
  431 
  432   if ( !audio_uri.empty() )
  433   {
  434     if ( audio_uri.find("rtsp://") == 0 )
  435     {
  436       play_rtsp = true;
  437     }
  438   }
  439   if ( !video_uri.empty() )
  440   {
  441     if ( video_uri.find("rtsp://") == 0 )
  442     {
  443       play_rtsp = true;
  444     }
  445   }
  446 
  447   if ( play_rtsp )
  448   {
  449     rtspIpmDevice_ = channelMgr_.allocIpmDevice();
  450     if ( !rtspIpmDevice_ )
  451     {
  452       LOGERROR("DialogicChannel::play() no ipm device available");
  453       return false;
  454     }
  455     rtspIpmDevice_->bindChannel(this);
  456 
  457     /* Extract and strip username and password from the uri string to avoid
  458      * passing authentication information in clear text to the rtsp server.
  459      * "rtsp://" username ":" password "@" host ...
  460      */
  461     std::string username;
  462     std::string password;
  463     std::string uri = audio_uri.empty() ? video_uri : audio_uri;
  464 
  465     std::string::size_type at = uri.find("@");
  466     if ( at != std::string::npos )
  467     {
  468       std::string::size_type colon = uri.find(":", 7);
  469       if ( colon != std::string::npos )
  470       {
  471         username = uri.substr(7, colon - 7);
  472         password = uri.substr(colon + 1, at - colon - 1);
  473       }
  474       uri.erase(7, at + 1 - 7);
  475     }
  476 
  477     /* Use same uri for both a+v, these may be modified once the session
  478      * details have been received from the rtsp server.
  479      */
  480     player_.audioFile = uri;
  481     player_.videoFile = uri;
  482 
  483     /* Set remote rtp.
  484      */
  485     RtpIpInfo remote_rtp;
  486     remote_rtp.setDirection(RtpIpInfo::SENDONLY);
  487     rtspIpmDevice_->setRemoteMediaInfo(MEDIATYPE_AUDIO_LOCAL_RTP_INFO, remote_rtp);
  488     rtspIpmDevice_->setRemoteMediaInfo(MEDIATYPE_VIDEO_LOCAL_RTP_INFO, remote_rtp);
  489 
  490     /* Get local rtp details so that they can be passed to the rtsp server.
  491      */
  492     RtpIpInfo audio_rtp;
  493     RtpIpInfo video_rtp;
  494     rtspIpmDevice_->getLocalMediaInfo(MEDIATYPE_AUDIO_LOCAL_RTP_INFO, audio_rtp);
  495     rtspIpmDevice_->getLocalMediaInfo(MEDIATYPE_VIDEO_LOCAL_RTP_INFO, video_rtp);
  496 
  497     channelMgr_.getRtspConnector().open(uri,
  498                                         username,
  499                                         password,
  500                                         audio_rtp.getPort(),
  501                                         video_rtp.getPort(),
  502                                         reinterpret_cast<void*>(rtspIpmDevice_->getDeviceHandle()));
  503 
  504     LOGINFO("DialogicChannel::play() rtsp ipmdevice: " << rtspIpmDevice_->getDeviceName());
  505   }
  506   else /* Local filesystem. */
  507   {
  508     AudioCoderInfo audioCoder;
  509     VideoCoderInfo videoCoder;
  510     if ( getProtocol() == PROTOCOL_SIP )
  511     {
  512       IpmDevice* ipt_ipm = static_cast<GcIptDevice*>(gcDevice_)->getIpmDevice();
  513       audioCoder = ipt_ipm->getLocalAudioCoder();
  514       videoCoder = ipt_ipm->getLocalVideoCoder();
  515     }
  516     else if ( getProtocol() == PROTOCOL_CONF )
  517     {
  518       audioCoder = ipmDevice_->getLocalAudioCoder();
  519       videoCoder = ipmDevice_->getLocalVideoCoder();
  520     }
  521     else if ( getProtocol() == PROTOCOL_H324 )
  522     {
  523       audioCoder = m3gDevice_->getLocalAudioCoder();
  524       videoCoder = m3gDevice_->getLocalVideoCoder();
  525     }
  526     else
  527     {
  528       return false;
  529     }
  530 
  531     if ( !audio_uri.empty() )
  532     {
  533       if ( !channelMgr_.getMediaFinder().find(audio_uri,
  534                                               audioCoder.encoding,
  535                                               lang,
  536                                               player_.audioFile,
  537                                               player_.audioEncoding) )
  538       {
  539         LOGERROR("DialogicChannel::play() " <<
  540                  " audio file not found: \"" << audio_uri << "\"");
  541         return false;
  542       }
  543     }
  544 
  545     if ( !video_uri.empty() )
  546     {
  547       if ( !channelMgr_.getMediaFinder().find(video_uri,
  548                                               videoCoder.encoding,
  549                                               videoCoder.active_fmt.imageWidth,
  550                                               lang,
  551                                               player_.videoFile,
  552                                               player_.videoEncoding,
  553                                               player_.videoSize,
  554                                               player_.videoFps) )
  555       {
  556         LOGERROR("DialogicChannel::play() " <<
  557                   " video file not found: \"" << video_uri << "\"");
  558         return false;
  559       }
  560     }
  561 
  562     if ( !audio_uri.empty() || !video_uri.empty() )
  563     {
  564       if ( !mmDevice_ )
  565       {
  566         mmDevice_ = channelMgr_.allocMmDevice();
  567         if ( !mmDevice_ )
  568         {
  569           LOGERROR("DialogicChannel::play() no mm device available");
  570           return false;
  571         }
  572         mmDevice_->bindChannel(this);
  573       }
  574     }
  575 
  576     onMediaEvent(new Event(EVT_PLAY));
  577   }
  578   return true;
  579 }
  580 
  581 
  582 /*
  583  * Record media from an established call using the mm device.
  584  * The recording will be made using the active coders.
  585  */
  586 bool DialogicChannel::record( const std::string& audio_uri,
  587                               const std::string& video_uri,
  588                               const std::string& stop_digits,
  589                               const std::string& lang,
  590                               bool beep,
  591                               unsigned int maxTime )
  592 {
  593   recorder_.audioFile.clear();
  594   recorder_.videoFile.clear();
  595   recorder_.duration = 0;
  596 
  597   AudioCoderInfo audioCoder;
  598   VideoCoderInfo videoCoder;
  599   if ( getProtocol() == PROTOCOL_SIP )
  600   {
  601     IpmDevice* ipt_ipm = static_cast<GcIptDevice*>(gcDevice_)->getIpmDevice();
  602     audioCoder = ipt_ipm->getLocalAudioCoder();
  603     videoCoder = ipt_ipm->getLocalVideoCoder();
  604   }
  605   else if ( getProtocol() == PROTOCOL_CONF )
  606   {
  607     audioCoder = ipmDevice_->getLocalAudioCoder();
  608     videoCoder = ipmDevice_->getLocalVideoCoder();
  609   }
  610   else if ( getProtocol() == PROTOCOL_H324 )
  611   {
  612     audioCoder = m3gDevice_->getLocalAudioCoder();
  613     videoCoder = m3gDevice_->getLocalVideoCoder();
  614   }
  615   else
  616   {
  617     return false;
  618   }
  619 
  620   /* Build audio file path, fail if the directory does not exist.
  621    */
  622   if ( !audio_uri.empty() )
  623   {
  624     recorder_.audioFile = channelMgr_.getMediaFinder().getMediaDir();
  625     recorder_.audioFile  += '/';
  626 
  627     if ( !lang.empty() )
  628     {
  629       recorder_.audioFile  += lang;
  630     }
  631     else
  632     {
  633       recorder_.audioFile  += channelMgr_.getMediaFinder().getLanguage();
  634     }
  635     recorder_.audioFile  += '/';
  636 
  637     const std::string& audio_format = channelMgr_.getConfig().getRecordAudioFormat();
  638     if ( !audio_format.empty() )
  639     {
  640       recorder_.audioFile  += audio_format;
  641       recorder_.audioEncoding = audio_format;
  642     }
  643     else /* use native format */
  644     {
  645       recorder_.audioFile  += audioCoder.encoding;
  646       recorder_.audioEncoding = audioCoder.encoding;
  647     }
  648     recorder_.audioFile  += '/';
  649     recorder_.audioFile  += audio_uri;
  650 
  651     std::string dirPath = recorder_.audioFile.substr(0, recorder_.audioFile.rfind('/'));
  652     struct stat st;
  653     if ( lstat(dirPath.c_str(), &st) != 0 )
  654     {
  655       LOGERROR(" DialogicChannel::record() bad path: " << dirPath);
  656       return false;
  657     }
  658   }
  659 
  660   /* build video file path, fail if the directory does not exist.
  661    */
  662   if ( !video_uri.empty() )
  663   {
  664     recorder_.videoFile = channelMgr_.getMediaFinder().getMediaDir();
  665     recorder_.videoFile += '/';
  666 
  667     if ( !lang.empty() )
  668     {
  669       recorder_.videoFile += lang;
  670     }
  671     else
  672     {
  673       recorder_.videoFile += channelMgr_.getMediaFinder().getLanguage();
  674     }
  675     recorder_.videoFile += '/';
  676 
  677     const std::string& video_format = channelMgr_.getConfig().getRecordVideoFormat();
  678     if ( !video_format.empty() )
  679     {
  680       recorder_.videoFile  += video_format;
  681       recorder_.videoEncoding = video_format;
  682     }
  683     else /* use native format */
  684     {
  685       recorder_.videoFile += videoCoder.encoding;
  686       recorder_.videoEncoding = videoCoder.encoding;
  687     }
  688     recorder_.videoFile += '/';
  689 
  690     const std::string& video_format_size = channelMgr_.getConfig().getRecordVideoSize();
  691     if ( !video_format_size.empty() )
  692     {
  693       recorder_.videoFile += video_format_size;
  694       recorder_.videoFile += '/';
  695 
  696       if ( video_format_size == "VGA" )
  697       {
  698         recorder_.videoSize = VIDEO_IMAGE_WIDTH_VGA;
  699       }
  700       else if ( video_format_size == "CIF" )
  701       {
  702         recorder_.videoSize = VIDEO_IMAGE_WIDTH_352;
  703       }
  704       else /* "QCIF" */
  705       {
  706         recorder_.videoSize = VIDEO_IMAGE_WIDTH_176;
  707       }
  708     }
  709     else
  710     {
  711       if ( videoCoder.active_fmt.imageWidth == VIDEO_IMAGE_WIDTH_VGA )
  712       {
  713         recorder_.videoFile += "VGA/";
  714       }
  715       else if ( videoCoder.active_fmt.imageWidth == VIDEO_IMAGE_WIDTH_352 )
  716       {
  717         recorder_.videoFile += "CIF/";
  718       }
  719       else
  720       {
  721         recorder_.videoFile += "QCIF/";
  722       }
  723       recorder_.videoSize = videoCoder.active_fmt.imageWidth;
  724     }
  725     recorder_.videoFile += video_uri;
  726 
  727     std::string dirPath = recorder_.videoFile.substr(0, recorder_.videoFile.rfind('/'));
  728     struct stat st;
  729     if ( lstat(dirPath.c_str(), &st) != 0 )
  730     {
  731       LOGERROR(" DialogicChannel::record() bad path: " << dirPath);
  732       return false;
  733     }
  734   }
  735 
  736   if ( !mmDevice_ )
  737   {
  738     mmDevice_ = channelMgr_.allocMmDevice();
  739     if ( !mmDevice_ )
  740     {
  741       LOGERROR(" DialogicChannel::record() no mm device available");
  742       return false;
  743     }
  744     mmDevice_->bindChannel(this);
  745   }
  746 
  747   recorder_.videoFps = videoCoder.active_fmt.framesPerSec,
  748   recorder_.beep = beep;
  749   recorder_.maxTime = maxTime;
  750 
  751   stop_digits_ = stop_digits;
  752 
  753   onMediaEvent(new Event(EVT_RECORD));
  754 
  755   return true;
  756 }
  757 
  758 
  759 /*
  760  * Post a stop event into the media statemachine.
  761  */
  762 bool DialogicChannel::stop()
  763 {
  764   onMediaEvent(new Event(EVT_STOP));
  765   return true;
  766 }
  767 
  768 
  769 /*
  770  * Request an overlay to be generated.
  771  */
  772 bool DialogicChannel::requestOverlay( const std::string& overlay )
  773 {
  774   if ( overlay.empty() )
  775   {
  776     return false;
  777   }
  778 
  779   std::string basename;
  780 
  781   /* The imageMakerEvent object will be deleted by the response callback. */
  782   ImageMakerEvent* imageMakerEvent = new ImageMakerEvent;
  783   imageMakerEvent->duration_ms = INT_MAX;
  784 
  785   unsigned int width, height;  /* For scaling. */
  786 
  787   if ( getProtocol() == PROTOCOL_SIP )
  788   {
  789     IpmDevice* ipt_ipm = static_cast<GcIptDevice*>(gcDevice_)->getIpmDevice();
  790     imageMakerEvent->dev_handle = ipt_ipm->getDeviceHandle();
  791     imageMakerEvent->direction = eSM_OVERLAY_DIRECTION_NETWORK;
  792     basename = ipt_ipm->getDeviceName();
  793     width = ipt_ipm->getLocalVideoCoder().active_fmt.imageWidth;
  794     height = ipt_ipm->getLocalVideoCoder().active_fmt.imageHeight;
  795   }
  796   else if ( (getProtocol() == PROTOCOL_CONF) || (getProtocol() == PROTOCOL_H324) )
  797   {
  798     if ( rtspIpmDevice_ )
  799     {
  800       imageMakerEvent->dev_handle = rtspIpmDevice_->getDeviceHandle();
  801       basename = rtspIpmDevice_->getDeviceName();
  802       width = rtspIpmDevice_->getLocalVideoCoder().active_fmt.imageWidth;
  803       height = rtspIpmDevice_->getLocalVideoCoder().active_fmt.imageHeight;
  804     }
  805     else
  806     {
  807       imageMakerEvent->dev_handle = ipmDevice_->getDeviceHandle();
  808       basename = ipmDevice_->getDeviceName();
  809       width = ipmDevice_->getLocalVideoCoder().active_fmt.imageWidth;
  810       height = ipmDevice_->getLocalVideoCoder().active_fmt.imageHeight;
  811     }
  812     imageMakerEvent->direction = eSM_OVERLAY_DIRECTION_DEVICE;
  813   }
  814   else
  815   {
  816     LOGERROR("DialogicChannel::requestOverlay() Unsupported protocol");
  817     delete imageMakerEvent;
  818     return false;
  819   }
  820 
  821   LOGDEBUG("DialogicChannel::requestOverlay() overlay: \"" << overlay << "\"" <<
  822            ", width: " << width << ", height: " << height);
  823   std::string filename = "/tmp/" + basename + ".jpeg";
  824   truncate(filename.c_str(), 0);
  825   channelMgr_.getImageMakerThread().create(overlay,
  826                                            filename,
  827                                            width,
  828                                            height,
  829                                            imageMakerEvent);
  830   return true;
  831 }
  832 
  833 
  834 /*
  835  * Create an optimised media connection between this channel and another. This
  836  * will disconnect the current ipm connection and replace it with a half-duplex
  837  * connection to a device in 'other_channel'.
  838  * Note, 3G is not supported here, as conference parties they need an ipm device
  839  * in the media path in order to display captions, and clearing of a call that is
  840  * bridged to 3G can cause issues when clearing the 3G call as its media is only
  841  * half connected.
  842  */
  843 bool DialogicChannel::bridge( Channel* other_channel )
  844 {
  845   if ( getProtocol() == PROTOCOL_SIP )
  846   {
  847     if ( (other_channel->getProtocol() == PROTOCOL_SIP) ||
  848          (other_channel->getProtocol() == PROTOCOL_CONF) )
  849     {
  850       other_channel_ = static_cast<DialogicChannel*>(other_channel);
  851       /* The media state machine only handles actions on a single channel,
  852        * this code is to ensure that new connections initiated will not
  853        * conflict with those of the other channel.
  854        */
  855       IpmDevice* other_ipm = other_channel_->getIpmDevice();
  856       other_ipm->disconnect();
  857 
  858       onMediaEvent(new Event(EVT_CONNECT_OTHER));
  859       return true;
  860     }
  861   }
  862   else if ( getProtocol() == PROTOCOL_CONF )
  863   {
  864     if ( (other_channel->getProtocol() == PROTOCOL_SIP) ||
  865          (other_channel->getProtocol() == PROTOCOL_CONF) )
  866     {
  867       other_channel_ = static_cast<DialogicChannel*>(other_channel);
  868 
  869       /* The media state machine only handles actions on a single channel,
  870        * this code is to ensure that new connections initiated will not
  871        * conflict with those of the other channel.
  872        */
  873       IpmDevice* other_ipm = other_channel_->getIpmDevice();
  874       other_ipm->disconnect();
  875 
  876       onMediaEvent(new Event(EVT_CONNECT_OTHER));
  877       return true;
  878     }
  879   }
  880   return false;
  881 }
  882 
  883 
  884 /*
  885  * Remove optimised media bridge and restore the normal media path.
  886  */
  887 bool DialogicChannel::unbridge()
  888 {
  889   if ( other_channel_ )
  890   {
  891     if ( getProtocol() == PROTOCOL_SIP )
  892     {
  893       onMediaEvent(new Event(EVT_CONNECT_SIP_GW));
  894       other_channel_ = 0;
  895       return true;
  896     }
  897     else if ( getProtocol() == PROTOCOL_CONF )
  898     {
  899       onMediaEvent(new Event(EVT_CONNECT_CONF));
  900       other_channel_ = 0;
  901       return true;
  902     }
  903     else if ( getProtocol() == PROTOCOL_H324 )
  904     {
  905       onMediaEvent(new Event(EVT_CONNECT_3G_GW));
  906       other_channel_ = 0;
  907       return true;
  908     }
  909   }
  910   return false;
  911 }
  912 
  913 
  914 /*
  915  * Test if a dtmf digit is a stop digit for the current play/record operation.
  916  */
  917 bool DialogicChannel::isStopDigit( char dtmf ) const
  918 {
  919   return (stop_digits_.find(dtmf) != std::string::npos);
  920 }
  921 
  922 
  923 /*
  924  * Start streaming media to the client.
  925  */
  926 bool DialogicChannel::startMedia()
  927 {
  928   if ( !ipmDevice_ )
  929   {
  930     return false;
  931   }
  932   return ipmDevice_->startMedia();
  933 }
  934 
  935 
  936 /*
  937  * Stop streaming media to the client.
  938  */
  939 bool DialogicChannel::stopMedia()
  940 {
  941   if ( !ipmDevice_ )
  942   {
  943     return false;
  944   }
  945   return ipmDevice_->stopMedia();
  946 }
  947 
  948 
  949 /*
  950  * Test if this is a video call.
  951  */
  952 bool DialogicChannel::isVideo() const
  953 {
  954   if ( getProtocol() == PROTOCOL_SIP )
  955   {
  956     IpmDevice* ipt_ipm = static_cast<GcIptDevice*>(gcDevice_)->getIpmDevice();
  957     RtpIpInfo rtp_video;
  958     ipt_ipm->getRemoteMediaInfo(MEDIATYPE_VIDEO_REMOTE_RTP_INFO, rtp_video);
  959     return rtp_video.isValid();
  960   }
  961   if ( getProtocol() == PROTOCOL_CONF )
  962   {
  963     RtpIpInfo rtp_video;
  964     ipmDevice_->getRemoteMediaInfo(MEDIATYPE_VIDEO_REMOTE_RTP_INFO, rtp_video);
  965     return rtp_video.isValid();
  966   }
  967   if ( getProtocol() == PROTOCOL_H324 )
  968   {
  969     return true;
  970   }
  971   return false;
  972 }
  973 
  974 
  975 /*
  976  * Get the local ip-address and port number for the rtp audio media.
  977  */
  978 void DialogicChannel::getLocalRtpAudioInfo( RtpIpInfo& rtp_audio ) const
  979 {
  980   if ( ipmDevice_ )
  981   {
  982     ipmDevice_->getLocalMediaInfo(MEDIATYPE_AUDIO_LOCAL_RTP_INFO, rtp_audio);
  983   }
  984 }
  985 
  986 
  987 /*
  988  * Get the local ip-address and port number for the rtp video media.
  989  */
  990 void DialogicChannel::getLocalRtpVideoInfo( RtpIpInfo& rtp_video ) const
  991 {
  992   if ( ipmDevice_ )
  993   {
  994     ipmDevice_->getLocalMediaInfo(MEDIATYPE_VIDEO_LOCAL_RTP_INFO, rtp_video);
  995   }
  996 }
  997 
  998 
  999 /*
 1000  * Save the ip-address and port of the remote party's rtp audio.
 1001  */
 1002 void DialogicChannel::setRemoteRtpAudioInfo( const RtpIpInfo& rtp_audio )
 1003 {
 1004   if ( ipmDevice_ )
 1005   {
 1006     ipmDevice_->setRemoteMediaInfo(MEDIATYPE_AUDIO_REMOTE_RTP_INFO, rtp_audio);
 1007   }
 1008 }
 1009 
 1010 
 1011 /*
 1012  * Get the remote ip-address and port number for the rtp audio media.
 1013  */
 1014 void DialogicChannel::getRemoteRtpAudioInfo( RtpIpInfo& rtp_audio ) const
 1015 {
 1016   if ( ipmDevice_ )
 1017   {
 1018     ipmDevice_->getRemoteMediaInfo(MEDIATYPE_AUDIO_LOCAL_RTP_INFO, rtp_audio);
 1019   }
 1020 }
 1021 
 1022 
 1023 /*
 1024  * Save the ip-address and port of the remote party's rtp video.
 1025  */
 1026 void DialogicChannel::setRemoteRtpVideoInfo( const RtpIpInfo& rtp_video )
 1027 {
 1028   if ( ipmDevice_ )
 1029   {
 1030     ipmDevice_->setRemoteMediaInfo(MEDIATYPE_VIDEO_REMOTE_RTP_INFO, rtp_video);
 1031   }
 1032 }
 1033 
 1034 
 1035 /*
 1036  * Get the remote ip-address and port number for the rtp video media.
 1037  */
 1038 void DialogicChannel::getRemoteRtpVideoInfo( RtpIpInfo& rtp_video ) const
 1039 {
 1040   if ( ipmDevice_ )
 1041   {
 1042     ipmDevice_->getRemoteMediaInfo(MEDIATYPE_VIDEO_REMOTE_RTP_INFO, rtp_video);
 1043   }
 1044 }
 1045 
 1046 
 1047 /*
 1048  * Forward the event to the media state machine.
 1049  */
 1050 void DialogicChannel::onMediaEvent( Event* event )
 1051 {
 1052   if ( context_ )
 1053   {
 1054     LOGINFO("DialogicChannel::onMediaEvent() event: " << event->getId());
 1055     context_->onEvent(event);
 1056   }
 1057   else
 1058   {
 1059     LOGERROR("DialogicChannel::onMediaEvent() no context");
 1060   }
 1061 }
 1062 
 1063 
 1064 /*
 1065  * Tell the client there's an incoming call.
 1066  */
 1067 void DialogicChannel::onIncoming( const std::string& local_number,
 1068                                   const std::string& local_uri,
 1069                                   const std::string& remote_number,
 1070                                   const std::string& remote_name )
 1071 {
 1072   direction_ = DIRECTION_INBOUND;
 1073   channelMgr_.getClient().onIncoming(this,
 1074                                      local_number,
 1075                                      local_uri,
 1076                                      remote_number,
 1077                                      remote_name);
 1078 }
 1079 
 1080 
 1081 /*
 1082  * Handle a call accept completion event.
 1083  */
 1084 void DialogicChannel::onAccepted()
 1085 {
 1086   if ( getProtocol() == PROTOCOL_SIP )
 1087   {
 1088     /* Use the state machine to connect the media, notifying the client
 1089      * when complete.
 1090      */
 1091     onMediaEvent(new Event(EVT_CONNECT_SIP_GW));
 1092     ipmDevice_->startMedia();
 1093   }
 1094   else if ( (getProtocol() == PROTOCOL_ISDN) || (getProtocol() == PROTOCOL_SS7) )
 1095   {
 1096     /* Connect the media and notify the client.
 1097      */
 1098     GcIsdnDevice* dti = static_cast<GcIsdnDevice*>(gcDevice_);
 1099 
 1100     dti->listen(ipmDevice_);
 1101     ipmDevice_->listen(dti);
 1102     ipmDevice_->startMedia();
 1103     channelMgr_.getClient().onAccepted(this);
 1104   }
 1105   else /* H324 */
 1106   {
 1107     /* Notify the client. The media will be connected when the call has
 1108      * been answered.
 1109      */
 1110     channelMgr_.getClient().onAccepted(this);
 1111   }
 1112 }
 1113 
 1114 
 1115 /*
 1116  * Handle a call answer completion event.
 1117  */
 1118 void DialogicChannel::onAnswered()
 1119 {
 1120   if ( getProtocol() == PROTOCOL_H324 )
 1121   {
 1122     /* Use the state machine to connect the media. Notify the client
 1123      * when this has completed and the h245 session has been established.
 1124      */
 1125     onMediaEvent(new Event(EVT_CONNECT_3G_GW));
 1126     ipmDevice_->startMedia();
 1127   }
 1128   else
 1129   {
 1130     channelMgr_.getClient().onAnswered(this);
 1131   }
 1132 }
 1133 
 1134 
 1135 /*
 1136  * Handle a call proceeding event (outbound).
 1137  */
 1138 void DialogicChannel::onProceeding()
 1139 {
 1140   if ( (getProtocol() == PROTOCOL_ISDN) || (getProtocol() == PROTOCOL_SS7) )
 1141   {
 1142     GcIsdnDevice* dti = static_cast<GcIsdnDevice*>(gcDevice_);
 1143     dti->listen(ipmDevice_);
 1144     ipmDevice_->listen(dti);
 1145     ipmDevice_->startMedia();
 1146   }
 1147   channelMgr_.getClient().onProceeding(this);
 1148 }
 1149 
 1150 
 1151 /*
 1152  * Handle a remote-party ringing event (outbound).
 1153  */
 1154 void DialogicChannel::onRinging()
 1155 {
 1156   if ( (getProtocol() == PROTOCOL_ISDN) || (getProtocol() == PROTOCOL_SS7) )
 1157   {
 1158     GcIsdnDevice* dti = static_cast<GcIsdnDevice*>(gcDevice_);
 1159     dti->listen(ipmDevice_);
 1160     ipmDevice_->listen(dti);
 1161   }
 1162   channelMgr_.getClient().onRinging(this);
 1163 }
 1164 
 1165 
 1166 /*
 1167  * Handle an 'outbound' call connected event from a dti, ipt, confparty or m3g
 1168  * device. Now connected the media.
 1169  */
 1170 void DialogicChannel::onConnect( const std::string& conn_type )
 1171 {
 1172   conn_type_ = conn_type;
 1173 
 1174   if ( getProtocol() == PROTOCOL_SIP )
 1175   {
 1176     /* Use the state machine to connect the media, notifying the client
 1177      * when complete.
 1178      */
 1179     onMediaEvent(new Event(EVT_CONNECT_SIP_GW));
 1180   }
 1181   else if ( (getProtocol() == PROTOCOL_ISDN) || (getProtocol() == PROTOCOL_SS7) )
 1182   {
 1183     /* Connect the media and notify the client.
 1184      */
 1185     GcIsdnDevice* dti = static_cast<GcIsdnDevice*>(gcDevice_);
 1186     dti->listen(ipmDevice_);
 1187     ipmDevice_->listen(dti);
 1188     channelMgr_.getClient().onConnect(this, conn_type_);
 1189   }
 1190   else if ( getProtocol() == PROTOCOL_CONF )
 1191   {
 1192     /* Use the state machine to connect the media, notifying the client
 1193      * when complete.
 1194      */
 1195     onMediaEvent(new Event(EVT_CONNECT_CONF));
 1196   }
 1197   else  /* H324 */
 1198   {
 1199     /* Use the state machine to connect the media. Notify the client
 1200      * when this has completed and the h245 session has been established.
 1201      */
 1202     onMediaEvent(new Event(EVT_CONNECT_3G_GW));
 1203   }
 1204   ipmDevice_->startMedia();
 1205 }
 1206 
 1207 
 1208 /*
 1209  * Gateway media connections have been established. For sip/conf calls, tell the
 1210  * client that the call is connected; for H324 calls, defer telling the client
 1211  * until after the h245 session has been established and its media started.
 1212  */
 1213 void DialogicChannel::onGatewayConnected()
 1214 {
 1215   if ( getProtocol() == PROTOCOL_H324 )
 1216   {
 1217     h324_connected_ = false;
 1218     m3gDevice_->startH245();
 1219   }
 1220   else
 1221   {
 1222     if ( direction_ == DIRECTION_OUTBOUND )
 1223     {
 1224       channelMgr_.getClient().onConnect(this, conn_type_);
 1225     }
 1226     else
 1227     {
 1228       channelMgr_.getClient().onAccepted(this);
 1229     }
 1230   }
 1231 }
 1232 
 1233 
 1234 /*
 1235  * Conference media connections have been established, tell the client that the
 1236  * call is connected.
 1237  */
 1238 void DialogicChannel::onConfConnected()
 1239 {
 1240   channelMgr_.getClient().onConnect(this, CONN_CONFERENCE);
 1241 }
 1242 
 1243 
 1244 /*
 1245  * Handle a hangup from a dti or an ipt device.
 1246  * If a play or record is active fake their completion event so that it will be
 1247  * handled before the hangup event.
 1248  */
 1249 void DialogicChannel::onHangup( GcDevice* gc,
 1250                                 int cause,
 1251                                 const std::string& cause_text,
 1252                                 const std::string& conn_type )
 1253 {
 1254   if ( mmDevice_ )
 1255   {
 1256     if ( mmDevice_->isPlaying() )
 1257     {
 1258       mmDevice_->stopPlay(PLAY_STOPPED);
 1259       channelMgr_.getClient().onPlayCompleted(this, PLAY_STOPPED, 0);
 1260       mmDevice_->disconnect();
 1261     }
 1262     if ( mmDevice_->isRecording() )
 1263     {
 1264       mmDevice_->stopRecord(RECORD_STOPPED);
 1265       channelMgr_.getClient().onRecordCompleted(this, RECORD_STOPPED, 0);
 1266       mmDevice_->disconnect();
 1267     }
 1268   }
 1269   if ( rtspIpmDevice_ )
 1270   {
 1271     channelMgr_.getRtspConnector().stop(player_.rtspSessionId);
 1272   }
 1273 
 1274   if ( getProtocol() == PROTOCOL_H324 )
 1275   {
 1276     m3gDevice_->endSession();
 1277   }
 1278 
 1279   channelMgr_.getClient().onHangup(this, cause, cause_text, conn_type);
 1280 }
 1281 
 1282 
 1283 /*
 1284  * H.324 session has ended, clear its isdn call.
 1285  */
 1286 void DialogicChannel::onHangup( M3gDevice* m3g )
 1287 {
 1288   if ( mmDevice_ )
 1289   {
 1290     if ( mmDevice_->isPlaying() )
 1291     {
 1292       mmDevice_->stopPlay(PLAY_STOPPED);
 1293       channelMgr_.getClient().onPlayCompleted(this, PLAY_STOPPED, 0);
 1294       mmDevice_->disconnect();
 1295     }
 1296     if ( mmDevice_->isRecording() )
 1297     {
 1298       mmDevice_->stopRecord(RECORD_STOPPED);
 1299       channelMgr_.getClient().onRecordCompleted(this, RECORD_STOPPED, 0);
 1300       mmDevice_->disconnect();
 1301     }
 1302   }
 1303   if ( rtspIpmDevice_ )
 1304   {
 1305     channelMgr_.getRtspConnector().stop(player_.rtspSessionId);
 1306   }
 1307 
 1308   if ( !player_.overlay.empty() )
 1309   {
 1310     if ( getProtocol() == PROTOCOL_SIP )
 1311     {
 1312       IpmDevice* ipt_ipm = static_cast<GcIptDevice*>(gcDevice_)->getIpmDevice();
 1313       ipt_ipm->removeOverlay();
 1314     }
 1315     else  /* PROTOCOL_CONF, PROTOCOL_H324 */
 1316     {
 1317       if ( rtspIpmDevice_ )
 1318       {
 1319         rtspIpmDevice_->removeOverlay();
 1320       }
 1321       else
 1322       {
 1323         ipmDevice_->removeOverlay();
 1324       }
 1325     }
 1326     if ( !mmDevice_  && !rtspIpmDevice_ ) /* Playing overlay only? */
 1327     {
 1328       channelMgr_.getClient().onPlayCompleted(this, PLAY_STOPPED, 0);
 1329     }
 1330   }
 1331 
 1332   gcDevice_->dropCall(GC_NORMAL_CLEARING);
 1333 
 1334   int cause = GC_NORMAL_CLEARING;
 1335   std::string cause_text = "Normal Clearing";
 1336   channelMgr_.getClient().onHangup(this, cause, cause_text);
 1337 }
 1338 
 1339 
 1340 /*
 1341  * Handle a hangup from a conference party device.
 1342  * If a play or record is active fake a completion event so that it will be
 1343  * handled before the hangup event.
 1344  */
 1345 void DialogicChannel::onHangup( ConfPartyDevice* confParty )
 1346 {
 1347   if ( mmDevice_ )
 1348   {
 1349     if ( mmDevice_->isPlaying() )
 1350     {
 1351       mmDevice_->stopPlay(PLAY_STOPPED);
 1352       channelMgr_.getClient().onPlayCompleted(this, PLAY_STOPPED, 0);
 1353       mmDevice_->disconnect();
 1354     }
 1355     if ( mmDevice_->isRecording() )
 1356     {
 1357       mmDevice_->stopRecord(RECORD_STOPPED);
 1358       channelMgr_.getClient().onRecordCompleted(this, RECORD_STOPPED, 0);
 1359       mmDevice_->disconnect();
 1360     }
 1361   }
 1362 
 1363   if ( rtspIpmDevice_ )
 1364   {
 1365     channelMgr_.getRtspConnector().stop(player_.rtspSessionId);
 1366   }
 1367 
 1368   if ( !player_.overlay.empty() )
 1369   {
 1370     ipmDevice_->removeOverlay();
 1371 
 1372     if ( !mmDevice_  && !rtspIpmDevice_ ) /* Playing overlay only? */
 1373     {
 1374       channelMgr_.getClient().onPlayCompleted(this, PLAY_STOPPED, 0);
 1375     }
 1376   }
 1377   channelMgr_.getClient().onHangup(this, 16, "Normal clearing", std::string());
 1378 }
 1379 
 1380 
 1381 /*
 1382  * Handle a dtmf digit received event.
 1383  * The behaviour is modified when either a play or record operation is active.
 1384  * If playing, buffer the digit until the play completes and if the digit matches
 1385  * a 'stop' digit, terminate the play /record.
 1386  * If neither playing nor recording, forward the digit to the client.
 1387  */
 1388 void DialogicChannel::onDtmf( char dtmf )
 1389 {
 1390   LOGDEBUG("DialogicChannel::onDtmf() digit: " << dtmf);
 1391   if ( mmDevice_  || rtspIpmDevice_ || !player_.overlay.empty() )
 1392   {
 1393     collectDigit(dtmf);
 1394     if ( isStopDigit(dtmf) )
 1395     {
 1396       onMediaEvent(new Event(EVT_STOP));
 1397     }
 1398   }
 1399   else
 1400   {
 1401     std::string digits;
 1402     digits.push_back(dtmf);
 1403     channelMgr_.getClient().onDtmf(this, digits);
 1404   }
 1405 }
 1406 
 1407 
 1408 /*
 1409  * Handle a tone detection event.
 1410  */
 1411 void DialogicChannel::onTone( const std::string& name )
 1412 {
 1413   channelMgr_.getClient().onTone(this, name);
 1414 }
 1415 
 1416 
 1417 /*
 1418  * Handle a user info event.
 1419  */
 1420 void DialogicChannel::onInfo( const std::string& mimetype,
 1421                               const std::string& content )
 1422 {
 1423   channelMgr_.getClient().onInfo(this, mimetype, content);
 1424 }
 1425 
 1426 
 1427 /*
 1428  * Handle a dtmf send-completion event.
 1429  */
 1430 void DialogicChannel::onSendDtmfCompleted()
 1431 {
 1432   if ( (protocol_ == PROTOCOL_ISDN) || (protocol_ == PROTOCOL_SS7) )
 1433   {
 1434     gcDevice_->listen(ipmDevice_);
 1435     channelMgr_.getClient().onSendDtmfCompleted(this);
 1436   }
 1437   else if ( protocol_ == PROTOCOL_H324 )
 1438   {
 1439     channelMgr_.getClient().onSendDtmfCompleted(this);
 1440   }
 1441 }
 1442 
 1443 
 1444 /*
 1445  * Handle a media connect completion event from an ipm device.
 1446  */
 1447 void DialogicChannel::onConnectCompleted( IpmDevice* ipm )
 1448 {
 1449   LOGDEBUG("DialogicChannel::onConnectCompleted() device: " << ipm->getDeviceName());
 1450 
 1451   GcIptDevice* ipt = ipm->getIptDevice();
 1452   if ( ipt )
 1453   {
 1454     onMediaEvent(new Event(EVT_IPTIPM_CONNECTED));
 1455 
 1456     /* If this connection was made to as part of an optimised bridge to
 1457      * a conference channel, the original caption will no longer been seen
 1458      * (conf's ipm disconnected) so its regenerated here and overlayed on
 1459      * this ipm device. Note, this does not take into account the amount
 1460      * of time that the original caption has been shown.
 1461      */
 1462     if ( other_channel_ && (other_channel_->getProtocol() == PROTOCOL_CONF) )
 1463     {
 1464       ConfPartyDevice* confParty = other_channel_->getConfPartyDevice();
 1465       ConfDevice* confDevice = other_channel_->getConfDevice();
 1466       if ( confDevice && confParty )
 1467       {
 1468         if ( (confDevice->getCaptionDuration() > 0) && (!confParty->getCaption().empty()) )
 1469         {
 1470           confDevice->displayCaption(ipm, confParty->getCaption());
 1471         }
 1472       }
 1473     }
 1474   }
 1475   else
 1476   {
 1477     onMediaEvent(new Event(EVT_IPM_CONNECTED));
 1478   }
 1479 }
 1480 
 1481 
 1482 /*
 1483  * Handle a media disconnect completion event from an ipm device.
 1484  */
 1485 void DialogicChannel::onDisconnectCompleted( IpmDevice* ipm )
 1486 {
 1487   LOGDEBUG("DialogicChannel::onDisconnectCompleted() device: " << ipm->getDeviceName());
 1488 
 1489   GcIptDevice* ipt = ipm->getIptDevice();
 1490   if ( ipt )
 1491   {
 1492     onMediaEvent(new Event(EVT_IPTIPM_DISCONNECTED));
 1493   }
 1494   else
 1495   {
 1496     onMediaEvent(new Event(EVT_IPM_DISCONNECTED));
 1497   }
 1498 }
 1499 
 1500 
 1501 /*
 1502  * Handle a media connect completion event from a mm device.
 1503  */
 1504 void DialogicChannel::onConnectCompleted( MmDevice* mm )
 1505 {
 1506   LOGDEBUG("DialogicChannel::onConnectCompleted() device: " << mm->getDeviceName());
 1507 
 1508   onMediaEvent(new Event(EVT_MM_CONNECTED));
 1509 }
 1510 
 1511 
 1512 /*
 1513  * Handle a media disconnect completion event from a mm device.
 1514  */
 1515 void DialogicChannel::onDisconnectCompleted( MmDevice* mm )
 1516 {
 1517   LOGDEBUG("DialogicChannel::onDisconnectCompleted() device: " << mm->getDeviceName());
 1518   onMediaEvent(new Event(EVT_MM_DISCONNECTED));
 1519 }
 1520 
 1521 
 1522 /*
 1523  * Handle a media connect completion event from a m3g device.
 1524  */
 1525 void DialogicChannel::onConnectCompleted( M3gDevice* m3g )
 1526 {
 1527   LOGDEBUG("DialogicChannel::onConnectCompleted() device: " << m3g->getDeviceName());
 1528   onMediaEvent(new Event(EVT_M3G_CONNECTED));
 1529 }
 1530 
 1531 
 1532 /*
 1533  * Handle a media disconnect completion event from a m3g device.
 1534  */
 1535 void DialogicChannel::onDisconnectCompleted( M3gDevice* m3g )
 1536 {
 1537   LOGDEBUG("DialogicChannel::onDisconnectCompleted() device: " << m3g->getDeviceName());
 1538   onMediaEvent(new Event(EVT_M3G_DISCONNECTED));
 1539 }
 1540 
 1541 
 1542 /*
 1543  * Handle a media streaming started event from a m3g device.
 1544  */
 1545 void DialogicChannel::onMediaStarted( M3gDevice* m3g )
 1546 {
 1547   LOGDEBUG("DialogicChannel::onMediaStarted() device: " << m3g->getDeviceName());
 1548 
 1549   /* The first time that this event occurs is when the h245 session has been
 1550    * established, use it to tell the client the call is now fully connected.
 1551    */
 1552   if ( !h324_connected_ )
 1553   {
 1554     if ( direction_ == DIRECTION_OUTBOUND )
 1555     {
 1556       channelMgr_.getClient().onConnect(this, conn_type_);
 1557     }
 1558     else
 1559     {
 1560       channelMgr_.getClient().onAnswered(this);
 1561     }
 1562     h324_connected_ = true;
 1563   }
 1564 
 1565   onMediaEvent(new Event(EVT_M3G_STARTED));
 1566 }
 1567 
 1568 
 1569 /*
 1570  * Handle a media streaming stopped event from a m3g device.
 1571  */
 1572 void DialogicChannel::onMediaStopped( M3gDevice* m3g )
 1573 {
 1574   LOGDEBUG("DialogicChannel::onMediaStopped() device: " << m3g->getDeviceName());
 1575   onMediaEvent(new Event(EVT_M3G_STOPPED));
 1576 }
 1577 
 1578 
 1579 /*
 1580  * Handle a media connect completion event from a conference party device.
 1581  */
 1582 void DialogicChannel::onConnectCompleted( ConfPartyDevice* confparty )
 1583 {
 1584   LOGDEBUG("DialogicChannel::onConnectCompleted() device: " << confparty->getDeviceName());
 1585   onMediaEvent(new Event(EVT_CONF_CONNECTED));
 1586 }
 1587 
 1588 
 1589 /*
 1590  * Handle a media disconnect completion event from a conference party device.
 1591  */
 1592 void DialogicChannel::onDisconnectCompleted( ConfPartyDevice* confparty )
 1593 {
 1594   LOGDEBUG("DialogicChannel::onDisconnectCompleted() device: " << confparty->getDeviceName());
 1595   onMediaEvent(new Event(EVT_CONF_DISCONNECTED));
 1596 }
 1597 
 1598 
 1599 /*
 1600  * Handle a play started event from a media device.
 1601  */
 1602 void DialogicChannel::onPlayStarted( DialogicDevice* media_device )
 1603 {
 1604   if ( getProtocol() == PROTOCOL_SIP )
 1605   {
 1606     IpmDevice* ipt_ipm = static_cast<GcIptDevice*>(gcDevice_)->getIpmDevice();
 1607     if ( !player_.videoFile.empty() )
 1608     {
 1609       ipt_ipm->generateIFrame(media_device->isVideoTranscodeOn());
 1610     }
 1611   }
 1612 
 1613   channelMgr_.getClient().onPlayOk(this);
 1614 
 1615   /* Check if a stop digit was collected during the play setup.
 1616    */
 1617   if ( collected_digits_.find_first_of(stop_digits_) != std::string::npos )
 1618   {
 1619     onMediaEvent(new Event(EVT_STOP));
 1620   }
 1621 }
 1622 
 1623 
 1624 /*
 1625  * Handle a play failed event from an mm or rtsp(ipm) device.
 1626  */
 1627 void DialogicChannel::onPlayFailed( DialogicDevice* media_device  )
 1628 {
 1629   LOGDEBUG("DialogicChannel::onPlayFailed() device: " << media_device->getDeviceName());
 1630 
 1631   if ( media_device == mmDevice_ )
 1632   {
 1633     channelMgr_.freeMmDevice(mmDevice_);
 1634     mmDevice_->unBindChannel();
 1635     mmDevice_ = 0;
 1636   }
 1637   else if ( media_device == rtspIpmDevice_ )
 1638   {
 1639     channelMgr_.freeIpmDevice(rtspIpmDevice_);
 1640     rtspIpmDevice_->unBindChannel();
 1641     rtspIpmDevice_ = 0;
 1642   }
 1643   else
 1644   {
 1645     if ( media_device )
 1646     {
 1647       LOGERROR("DialogicChannel::onPlayFailed() bad device: " << media_device->getDeviceName());
 1648     }
 1649     return;
 1650   }
 1651   player_.overlay.clear();
 1652   channelMgr_.getClient().onPlayFail(this);
 1653 }
 1654 
 1655 
 1656 /*
 1657  * Handle a play completion event from an mm or ipm(rtsp) device.
 1658  */
 1659 void DialogicChannel::onPlayCompleted( const std::string& reason,
 1660                                        unsigned int duration )
 1661 {
 1662   if ( collected_digits_.find_first_of(stop_digits_) != std::string::npos )
 1663   {
 1664     player_.reason = PLAY_END_DIGIT;
 1665   }
 1666   else
 1667   {
 1668     player_.reason = reason;
 1669   }
 1670   player_.duration = duration;
 1671 
 1672   onMediaEvent(new Event(EVT_PLAY_COMPLETED));
 1673 }
 1674 
 1675 
 1676 /*
 1677  * Handle a play completion event from the state machine.
 1678  */
 1679 void DialogicChannel::onPlayCompleted()
 1680 {
 1681   if ( mmDevice_ )
 1682   {
 1683     channelMgr_.freeMmDevice(mmDevice_);
 1684     mmDevice_->unBindChannel();
 1685     mmDevice_ = 0;
 1686   }
 1687 
 1688   if ( rtspIpmDevice_ )
 1689   {
 1690     channelMgr_.freeIpmDevice(rtspIpmDevice_);
 1691     rtspIpmDevice_->unBindChannel();
 1692     rtspIpmDevice_ = 0;
 1693   }
 1694 
 1695   channelMgr_.getClient().onPlayCompleted(this,
 1696                                           player_.reason,
 1697                                           player_.duration);
 1698 
 1699   std::string::size_type pos = collected_digits_.find_first_of(stop_digits_);
 1700   if ( pos != std::string::npos )
 1701   {
 1702     channelMgr_.getClient().onDtmf(this, collected_digits_.substr(0, pos + 1));
 1703     channelMgr_.getClient().onDtmf(this, collected_digits_.substr(pos + 1));
 1704   }
 1705   clearDigits();
 1706   player_.overlay.clear();
 1707 }
 1708 
 1709 
 1710 /*
 1711  * Handle a record started event from an mm device.
 1712  */
 1713 void DialogicChannel::onRecordStarted( DialogicDevice* media_device )
 1714 {
 1715   channelMgr_.getClient().onRecordOk(this);
 1716 }
 1717 
 1718 
 1719 /*
 1720  * Handle a record failed event from an mm device.
 1721  */
 1722 void DialogicChannel::onRecordFailed( DialogicDevice* media_device )
 1723 {
 1724   if ( mmDevice_ )
 1725   {
 1726     channelMgr_.freeMmDevice(mmDevice_);
 1727     mmDevice_->unBindChannel();
 1728     mmDevice_ = 0;
 1729   }
 1730   channelMgr_.getClient().onRecordFail(this);
 1731 }
 1732 
 1733 
 1734 /*
 1735  * Handle a record completion event from an mm device.
 1736  */
 1737 void DialogicChannel::onRecordCompleted( const std::string& reason,
 1738                                          unsigned int duration )
 1739 {
 1740   recorder_.reason = reason;
 1741   recorder_.duration = duration;
 1742 
 1743   onMediaEvent(new Event(EVT_RECORD_COMPLETED));
 1744 }
 1745 
 1746 
 1747 /*
 1748  * Handle a record completion event from the state machine.
 1749  */
 1750 void DialogicChannel::onRecordCompleted()
 1751 {
 1752   if ( mmDevice_ )
 1753   {
 1754     channelMgr_.freeMmDevice(mmDevice_);
 1755     mmDevice_->unBindChannel();
 1756     mmDevice_ = 0;
 1757   }
 1758   channelMgr_.getClient().onRecordCompleted(this,
 1759                                             recorder_.reason,
 1760                                             recorder_.duration);
 1761 }
 1762 
 1763 
 1764 /*
 1765  * Handle a record completion event from the state machine.
 1766  */
 1767 void DialogicChannel::onBridgeCompleted()
 1768 {
 1769   channelMgr_.getClient().onBridgeCompleted(this);
 1770 }
 1771 
 1772 
 1773 /*
 1774  * Handle a rtsp session open event.
 1775  */
 1776 void DialogicChannel::onRtspSession( int session_id,
 1777                                      std::string audio_encoding,
 1778                                      std::string video_encoding,
 1779                                      unsigned int width,
 1780                                      unsigned int height,
 1781                                      unsigned int fps )
 1782 {
 1783   LOGDEBUG("DialogicChannel::onRtspSession() device: " << rtspIpmDevice_->getDeviceName());
 1784 
 1785   player_.rtspSessionId = session_id;
 1786 
 1787   if ( !audio_encoding.empty() )
 1788   {
 1789     player_.audioEncoding = audio_encoding;
 1790   }
 1791   else /* No audio */
 1792   {
 1793     player_.audioFile.clear();
 1794   }
 1795 
 1796   if ( !video_encoding.empty() )
 1797   {
 1798     player_.videoEncoding = video_encoding;
 1799     player_.videoSize = width;
 1800     player_.videoFps = fps;
 1801   }
 1802   else /* No video. */
 1803   {
 1804     player_.videoFile.clear();
 1805   }
 1806 
 1807   /* Now that the formats are known start the ipm device.
 1808    */
 1809   rtspIpmDevice_->startMedia();
 1810 
 1811   onMediaEvent(new Event(EVT_PLAY));
 1812 }
 1813 
 1814 
 1815 /*
 1816  * Handle a overlay added event.
 1817  */
 1818 void DialogicChannel::onOverlayAdded()
 1819 {
 1820   onMediaEvent(new Event(EVT_OVERLAY_ADDED));
 1821 }
 1822 
 1823 
 1824 /*
 1825  * Handle a overlay removed event.
 1826  */
 1827 void DialogicChannel::onOverlayRemoved()
 1828 {
 1829   onMediaEvent(new Event(EVT_OVERLAY_REMOVED));
 1830 }
 1831 
 1832 /* vim:ts=4:set nu:
 1833  * EOF
 1834  */

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