[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 959 - (download) (annotate)
Tue Oct 26 16:20:50 2010 UTC (2 years, 6 months ago) by jtarlton
File size: 33336 byte(s)
Regenerate caption after bridging external ipm device to a conf channel.
    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 
   42 #include "logger.h"
   43 
   44 #include "dialogicchannelmanager.h"
   45 
   46 
   47 /*----------------------------------------------------------------------------*/
   48 
   49 /*
   50  * ctor. ISDN
   51  */
   52 DialogicChannel::DialogicChannel( DialogicChannelManager& channelMgr,
   53                                   GcIsdnDevice* gc,
   54                                   IpmDevice* ipm )
   55   : channelMgr_ (channelMgr),
   56     context_ (0),
   57     gcDevice_ (gc),
   58     m3gDevice_ (0),
   59     ipmDevice_ (ipm),
   60     mmDevice_ (0),
   61     confDevice_ (0),
   62     confParty_ (0),
   63     protocol_ (gc->getProtocol()),  /* ISDN | SS7 */
   64     other_channel_ (0)
   65 {
   66   gcDevice_->bindChannel(this);
   67   ipmDevice_->bindChannel(this);
   68 
   69   VoxDevice* vox = gcDevice_->getVox();
   70   vox->bindChannel(this);
   71 }
   72 
   73 
   74 /*
   75  * ctor. H324 (using ISDN)
   76  */
   77 DialogicChannel::DialogicChannel( DialogicChannelManager& channelMgr,
   78                                 StateMachine& sm,
   79                                 GcIsdnDevice* gc,
   80                                 M3gDevice* m3g,
   81                                 IpmDevice* ipm )
   82   : channelMgr_ (channelMgr),
   83     context_ (0),
   84     gcDevice_ (gc),
   85     m3gDevice_ (m3g),
   86     ipmDevice_ (ipm),
   87     mmDevice_ (0),
   88     confDevice_ (0),
   89     confParty_ (0),
   90     protocol_ (PROTOCOL_H324),
   91     other_channel_ (0)
   92 {
   93   gcDevice_->bindChannel(this);
   94   m3gDevice_->bindChannel(this);
   95   ipmDevice_->bindChannel(this);
   96 
   97   context_ = sm.createContext(this);
   98 }
   99 
  100 
  101 /*
  102  * ctor. SIP
  103  */
  104 DialogicChannel::DialogicChannel( DialogicChannelManager& channelMgr,
  105                                   StateMachine& sm,
  106                                   GcIptDevice* gc,
  107                                   IpmDevice* ipm )
  108   : channelMgr_ (channelMgr),
  109     context_ (0),
  110     gcDevice_ (gc),
  111     m3gDevice_ (0),
  112     ipmDevice_ (ipm),
  113     mmDevice_ (0),
  114     confDevice_ (0),
  115     confParty_ (0),
  116     protocol_ (PROTOCOL_SIP),
  117     other_channel_ (0)
  118 {
  119   gcDevice_->bindChannel(this);
  120 
  121   IpmDevice* ipt_ipm = static_cast<GcIptDevice*>(gcDevice_)->getIpmDevice();
  122   ipt_ipm->bindChannel(this);
  123 
  124   ipmDevice_->bindChannel(this);
  125 
  126   VoxDevice* vox = gcDevice_->getVox();
  127   vox->bindChannel(this);
  128 
  129   context_ = sm.createContext(this);
  130 }
  131 
  132 
  133 /*
  134  * ctor. CONF
  135  */
  136 DialogicChannel::DialogicChannel( DialogicChannelManager& channelMgr,
  137                                   StateMachine& sm,
  138                                   ConfDevice* confDevice,
  139                                   ConfPartyDevice* confParty,
  140                                   IpmDevice* ipm )
  141   : channelMgr_ (channelMgr),
  142     context_ (0),
  143     gcDevice_ (0),
  144     m3gDevice_ (0),
  145     ipmDevice_ (ipm),
  146     mmDevice_ (0),
  147     confDevice_ (confDevice),
  148     confParty_ (confParty),
  149     protocol_ (PROTOCOL_CONF),
  150     other_channel_ (0)
  151 {
  152   confDevice_->bindChannel(this);
  153   confParty_->bindChannel(this);
  154   ipmDevice_->bindChannel(this);
  155 
  156   context_ = sm.createContext(this);
  157 }
  158 
  159 
  160 /*
  161  * dtor, release resources.
  162  */
  163 DialogicChannel::~DialogicChannel()
  164 {
  165   if ( gcDevice_ )
  166   {
  167     if ( getProtocol() == PROTOCOL_SIP )
  168     {
  169       IpmDevice* ipt_ipm = static_cast<GcIptDevice*>(gcDevice_)->getIpmDevice();
  170       ipt_ipm->unBindChannel();
  171     }
  172 
  173     VoxDevice* vox = gcDevice_->getVox();
  174     if ( vox  )
  175     {
  176       vox->unBindChannel();
  177     }
  178     gcDevice_->unBindChannel();
  179   }
  180   if ( m3gDevice_ )
  181   {
  182     m3gDevice_->unBindChannel();
  183   }
  184   if ( ipmDevice_ )
  185   {
  186     ipmDevice_->unBindChannel();
  187   }
  188   if ( mmDevice_ )
  189   {
  190     mmDevice_->unBindChannel();
  191     channelMgr_.freeMmDevice(mmDevice_);
  192   }
  193   if ( confDevice_ )
  194   {
  195     confDevice_->unBindChannel();
  196   }
  197   if ( confParty_ )
  198   {
  199     confParty_->unBindChannel();
  200   }
  201 
  202   delete context_;
  203 }
  204 
  205 
  206 /*
  207  * Make an outbound call on the dti or ipt device.
  208  */
  209 bool DialogicChannel::makeCall( const std::string& local_number,
  210                                 const std::string& local_name,
  211                                 const std::string& remote_number,
  212                                 bool cpa )
  213 {
  214   if ( !gcDevice_ )
  215   {
  216     return false;
  217   }
  218   direction_ = DIRECTION_OUTBOUND;
  219   return gcDevice_->makeCall(local_number, local_name, remote_number, cpa);
  220 }
  221 
  222 
  223 /*
  224  * Hangup the current call.
  225  */
  226 bool DialogicChannel::hangup( int cause )
  227 {
  228   if ( !gcDevice_ )
  229   {
  230     return false;
  231   }
  232   if ( getProtocol() == PROTOCOL_H324 )
  233   {
  234     m3gDevice_->endSession();
  235     return true;
  236   }
  237   return gcDevice_->dropCall(cause);
  238 }
  239 
  240 
  241 /*
  242  * Accept the current call.
  243  */
  244 bool DialogicChannel::accept()
  245 {
  246   if ( !gcDevice_ || (direction_ != DIRECTION_INBOUND) )
  247   {
  248     return false;
  249   }
  250   return gcDevice_->acceptCall();
  251 }
  252 
  253 
  254 /*
  255  * Answer the current call.
  256  */
  257 bool DialogicChannel::answer()
  258 {
  259   if ( !gcDevice_ || (direction_ != DIRECTION_INBOUND) )
  260   {
  261     return false;
  262   }
  263 
  264   /* stop any multi-media ringback. SIP only */
  265   if ( mmDevice_ && mmDevice_->isPlaying() )
  266   {
  267     IpmDevice* ipt_ipm = static_cast<GcIptDevice*>(gcDevice_)->getIpmDevice();
  268     ipt_ipm->removeOverlay();
  269 
  270     mmDevice_->stopPlay(PLAY_STOPPED);
  271   }
  272   return gcDevice_->answerCall();
  273 }
  274 
  275 
  276 /*
  277  * Send dtmf digits.
  278  */
  279 bool DialogicChannel::sendDtmf( const std::string& dtmf )
  280 {
  281   if ( (protocol_ == PROTOCOL_ISDN) || (protocol_ == PROTOCOL_SS7) )
  282   {
  283     /* inband using the vox device. */
  284     VoxDevice* vox = gcDevice_->getVox();
  285     if ( !vox )
  286     {
  287       return false;
  288     }
  289     gcDevice_->listen(vox);
  290     return vox->sendDtmf(dtmf);
  291   }
  292   else if ( protocol_ == PROTOCOL_H324 )
  293   {
  294     m3gDevice_->sendDtmf(dtmf);
  295     return true;
  296   }
  297   return false;
  298 }
  299 
  300 
  301 /*
  302  * Enable tone event notifications.
  303  */
  304 bool DialogicChannel::enableToneEvents()
  305 {
  306   if ( !gcDevice_ )
  307   {
  308     return false;
  309   }
  310   VoxDevice* vox = gcDevice_->getVox();
  311   if ( !vox )
  312   {
  313     return false;
  314   }
  315   vox->enableToneNotifications();
  316   return true;
  317 }
  318 
  319 
  320 /*
  321  * Disable tone event notifications.
  322  */
  323 bool DialogicChannel::disableToneEvents()
  324 {
  325   if ( !gcDevice_ )
  326   {
  327     return false;
  328   }
  329   VoxDevice* vox = gcDevice_->getVox();
  330   if ( !vox )
  331   {
  332     return false;
  333   }
  334   vox->disableToneNotifications();
  335   return true;
  336 }
  337 
  338 
  339 /*
  340  * Play media to an established call using an mm device.
  341  */
  342 bool DialogicChannel::play( const std::string& audio_uri,
  343                             const std::string& video_uri,
  344                             const std::string& overlay,
  345                             const std::string& stop_digits,
  346                             const std::string& lang,
  347                             int repeat_count )
  348 {
  349   if ( audio_uri.empty() && video_uri.empty() && overlay.empty())
  350   {
  351     return false;
  352   }
  353 
  354   player_.audioFile.clear();
  355   player_.videoFile.clear();
  356   player_.overlay.clear();
  357 
  358   if ( audio_uri.empty() && video_uri.empty() )
  359   {
  360     requestOverlay(overlay);
  361     return true;
  362   }
  363 
  364   AudioCoderInfo audioCoder;
  365   VideoCoderInfo videoCoder;
  366   if ( getProtocol() == PROTOCOL_SIP )
  367   {
  368     IpmDevice* ipt_ipm = static_cast<GcIptDevice*>(gcDevice_)->getIpmDevice();
  369     audioCoder = ipt_ipm->getLocalAudioCoder();
  370     videoCoder = ipt_ipm->getLocalVideoCoder();
  371   }
  372   else if ( getProtocol() == PROTOCOL_CONF )
  373   {
  374     audioCoder = ipmDevice_->getLocalAudioCoder();
  375     videoCoder = ipmDevice_->getLocalVideoCoder();
  376   }
  377   else if ( getProtocol() == PROTOCOL_H324 )
  378   {
  379     audioCoder = m3gDevice_->getLocalAudioCoder();
  380     videoCoder = m3gDevice_->getLocalVideoCoder();
  381   }
  382   else
  383   {
  384     return false;
  385   }
  386 
  387   if ( !audio_uri.empty() )
  388   {
  389     if ( !channelMgr_.getMediaFinder().find(audio_uri,
  390                                             audioCoder.encoding,
  391                                             lang,
  392                                             player_.audioFile,
  393                                             player_.audioEncoding) )
  394     {
  395       LOGERROR("DialogicChannel::play() " <<
  396                " audio file not found: \"" << audio_uri << "\"");
  397       return false;
  398     }
  399   }
  400 
  401   if ( !video_uri.empty() )
  402   {
  403     if ( !channelMgr_.getMediaFinder().find(video_uri,
  404                                             videoCoder.encoding,
  405                                             videoCoder.active_fmt.imageWidth,
  406                                             lang,
  407                                             player_.videoFile,
  408                                             player_.videoEncoding,
  409                                             player_.videoSize,
  410                                             player_.videoFps) )
  411     {
  412       LOGERROR("DialogicChannel::play() " <<
  413                " video file not found: \"" << video_uri << "\"");
  414       return false;
  415     }
  416   }
  417 
  418   if ( !mmDevice_ )
  419   {
  420     mmDevice_ = channelMgr_.allocMmDevice();
  421     if ( !mmDevice_ )
  422     {
  423       LOGERROR(" DialogicChannel::play() no mm device available");
  424       return false;
  425     }
  426     mmDevice_->bindChannel(this);
  427   }
  428 
  429   player_.overlay = overlay;
  430   stop_digits_ = stop_digits;
  431   player_.repeatCount = repeat_count;
  432 
  433   onMediaEvent(new Event(EVT_PLAY));
  434   return true;
  435 }
  436 
  437 
  438 /*
  439  * Record media from an established call using the mm device.
  440  * The recording will be made using the active coders.
  441  */
  442 bool DialogicChannel::record( const std::string& audio_uri,
  443                               const std::string& video_uri,
  444                               const std::string& stop_digits,
  445                               const std::string& lang,
  446                               bool beep,
  447                               unsigned int maxTime )
  448 {
  449   if ( audio_uri.empty() && video_uri.empty() )
  450   {
  451     return false;
  452   }
  453 
  454   recorder_.audioFile.clear();
  455   recorder_.videoFile.clear();
  456 
  457   AudioCoderInfo audioCoder;
  458   VideoCoderInfo videoCoder;
  459   if ( getProtocol() == PROTOCOL_SIP )
  460   {
  461     IpmDevice* ipt_ipm = static_cast<GcIptDevice*>(gcDevice_)->getIpmDevice();
  462     audioCoder = ipt_ipm->getLocalAudioCoder();
  463     videoCoder = ipt_ipm->getLocalVideoCoder();
  464   }
  465   else if ( getProtocol() == PROTOCOL_CONF )
  466   {
  467     audioCoder = ipmDevice_->getLocalAudioCoder();
  468     videoCoder = ipmDevice_->getLocalVideoCoder();
  469   }
  470   else if ( getProtocol() == PROTOCOL_H324 )
  471   {
  472     audioCoder = m3gDevice_->getLocalAudioCoder();
  473     videoCoder = m3gDevice_->getLocalVideoCoder();
  474   }
  475   else
  476   {
  477     return false;
  478   }
  479 
  480   /* build audio file path, fail if the directory does not exist.
  481    */
  482   if ( !audio_uri.empty() )
  483   {
  484     recorder_.audioFile = channelMgr_.getMediaFinder().getMediaDir();
  485     recorder_.audioFile  += '/';
  486 
  487     if ( !lang.empty() )
  488     {
  489       recorder_.audioFile  += lang;
  490     }
  491     else
  492     {
  493       recorder_.audioFile  += channelMgr_.getMediaFinder().getLanguage();
  494     }
  495     recorder_.audioFile  += '/';
  496 
  497     recorder_.audioFile  += audioCoder.encoding;
  498     recorder_.audioFile  += '/';
  499     recorder_.audioFile  += audio_uri;
  500 
  501     std::string dirPath = recorder_.audioFile .substr(0, recorder_.audioFile .rfind('/'));
  502     struct stat st;
  503     if ( lstat(dirPath.c_str(), &st) != 0 )
  504     {
  505       LOGERROR(" DialogicChannel::record() bad path: " << dirPath);
  506       return false;
  507     }
  508   }
  509 
  510   /* build video file path, fail if the directory does not exist.
  511    */
  512   if ( !video_uri.empty() )
  513   {
  514     recorder_.videoFile = channelMgr_.getMediaFinder().getMediaDir();
  515     recorder_.videoFile += '/';
  516 
  517     if ( !lang.empty() )
  518     {
  519       recorder_.videoFile += lang;
  520     }
  521     else
  522     {
  523       recorder_.videoFile += channelMgr_.getMediaFinder().getLanguage();
  524     }
  525     recorder_.videoFile += '/';
  526 
  527     recorder_.videoFile += videoCoder.encoding;
  528     recorder_.videoFile += '/';
  529 
  530     if ( videoCoder.active_fmt.imageWidth == VIDEO_IMAGE_WIDTH_352 )
  531     {
  532       recorder_.videoFile += "CIF/";
  533     }
  534     else
  535     {
  536       recorder_.videoFile += "QCIF/";
  537     }
  538 
  539     recorder_.videoFile += video_uri;
  540 
  541     std::string dirPath = recorder_.videoFile.substr(0, recorder_.videoFile.rfind('/'));
  542     struct stat st;
  543     if ( lstat(dirPath.c_str(), &st) != 0 )
  544     {
  545       LOGERROR(" DialogicChannel::record() bad path: " << dirPath);
  546       return false;
  547     }
  548   }
  549 
  550   if ( !mmDevice_ )
  551   {
  552     mmDevice_ = channelMgr_.allocMmDevice();
  553     if ( !mmDevice_ )
  554     {
  555       LOGERROR(" DialogicChannel::record() no mm device available");
  556       return false;
  557     }
  558     mmDevice_->bindChannel(this);
  559   }
  560 
  561   recorder_.audioEncoding = audioCoder.encoding,
  562   recorder_.videoEncoding = videoCoder.encoding,
  563   recorder_.videoSize = videoCoder.active_fmt.imageWidth,
  564   recorder_.videoFps = videoCoder.active_fmt.framesPerSec,
  565   recorder_.beep = beep;
  566   recorder_.maxTime = maxTime;
  567 
  568   stop_digits_ = stop_digits;
  569 
  570   onMediaEvent(new Event(EVT_RECORD));
  571 
  572   return true;
  573 }
  574 
  575 
  576 /*
  577  * Stop any active play or record, the completion event will do the rest.
  578  */
  579 bool DialogicChannel::stop()
  580 {
  581   if ( getProtocol() == PROTOCOL_SIP )
  582   {
  583     IpmDevice* ipt_ipm = static_cast<GcIptDevice*>(gcDevice_)->getIpmDevice();
  584     ipt_ipm->removeOverlay();
  585   }
  586   else /* PROTOCOL_CONF */
  587   {
  588     ipmDevice_->removeOverlay();
  589   }
  590 
  591   if ( !mmDevice_ )
  592   {
  593     return false;
  594   }
  595   /* do a blanket stop as the mm device may have a play/record queued.
  596    */
  597   mmDevice_->stopPlay(PLAY_STOPPED);
  598   mmDevice_->stopRecord(RECORD_STOPPED);
  599   return true;
  600 }
  601 
  602 
  603 /*
  604  * Request an overlay to be generated.
  605  */
  606 bool DialogicChannel::requestOverlay( const std::string& overlay )
  607 {
  608   if ( overlay.empty() )
  609   {
  610     return false;
  611   }
  612 
  613   std::string basename;
  614 
  615   /* imageMakerEvent object will be deleted by response callback */
  616   ImageMakerEvent* imageMakerEvent = new ImageMakerEvent;
  617   imageMakerEvent->duration_ms = INT_MAX;
  618 
  619   if ( getProtocol() == PROTOCOL_SIP )
  620   {
  621     IpmDevice* ipt_ipm = static_cast<GcIptDevice*>(gcDevice_)->getIpmDevice();
  622     imageMakerEvent->dev_handle = ipt_ipm->getDeviceHandle();
  623     imageMakerEvent->direction = eSM_OVERLAY_DIRECTION_NETWORK;
  624     basename = ipt_ipm->getDeviceName();
  625   }
  626   else if ( getProtocol() == PROTOCOL_CONF )
  627   {
  628     imageMakerEvent->dev_handle = ipmDevice_->getDeviceHandle();
  629     imageMakerEvent->direction = eSM_OVERLAY_DIRECTION_DEVICE;
  630     basename = ipmDevice_->getDeviceName();
  631   }
  632   else
  633   {
  634     LOGERROR("DialogicChannel::requestOverlay() Unsupported protocol");
  635     delete imageMakerEvent;
  636     return false;
  637   }
  638 
  639   LOGDEBUG("DialogicChannel::requestOverlay() overlay: \"" << overlay << "\"");
  640 
  641   std::string filename = "/tmp/" + basename + ".jpeg";
  642   channelMgr_.getImageMakerThread().create(overlay, filename, (void*)(imageMakerEvent));
  643   return true;
  644 }
  645 
  646 
  647 /*
  648  * Create an optimised media connection between this channel and another. This
  649  * will disconnect the current ipm connection and replace it with a half-duplex
  650  * connection to a device in 'other_channel'.
  651  * WARNING: If a m3g device (H324) is bridged to conference, it will not be
  652  * possible to display a caption as this feature requires an ipm device.
  653  */
  654 bool DialogicChannel::bridge( Channel* other_channel )
  655 {
  656   if ( (getProtocol() == PROTOCOL_SIP) ||
  657        (getProtocol() == PROTOCOL_CONF) ||
  658        (getProtocol() == PROTOCOL_H324) )
  659   {
  660     if ( (other_channel->getProtocol() == PROTOCOL_SIP) ||
  661          (other_channel->getProtocol() == PROTOCOL_CONF) ||
  662          (other_channel->getProtocol() == PROTOCOL_H324) )
  663     {
  664       other_channel_ = static_cast<DialogicChannel*>(other_channel);
  665       onMediaEvent(new Event(EVT_CONNECT_OTHER));
  666       return true;
  667     }
  668   }
  669   return false;
  670 }
  671 
  672 
  673 /*
  674  * Remove optimised media bridge and restore the normal media path.
  675  */
  676 bool DialogicChannel::unbridge()
  677 {
  678   if ( other_channel_ )
  679   {
  680     if ( getProtocol() == PROTOCOL_SIP )
  681     {
  682       onMediaEvent(new Event(EVT_CONNECT_SIP_GW));
  683       other_channel_ = 0;
  684       return true;
  685     }
  686     else if ( getProtocol() == PROTOCOL_CONF )
  687     {
  688       onMediaEvent(new Event(EVT_CONNECT_CONF));
  689       other_channel_ = 0;
  690       return true;
  691     }
  692     else if ( getProtocol() == PROTOCOL_H324 )
  693     {
  694       onMediaEvent(new Event(EVT_CONNECT_3G_GW));
  695       other_channel_ = 0;
  696       return true;
  697     }
  698   }
  699   return false;
  700 }
  701 
  702 
  703 /*
  704  * Test if a dtmf digit is a stop digit for the current play/record operation.
  705  */
  706 bool DialogicChannel::isStopDigit( char dtmf ) const
  707 {
  708   return (stop_digits_.find(dtmf) != std::string::npos);
  709 }
  710 
  711 
  712 /*
  713  * Start streaming media to the client.
  714  */
  715 bool DialogicChannel::startMedia()
  716 {
  717   if ( !ipmDevice_ )
  718   {
  719     return false;
  720   }
  721   return ipmDevice_->startMedia();
  722 }
  723 
  724 
  725 /*
  726  * Stop streaming media to the client.
  727  */
  728 bool DialogicChannel::stopMedia()
  729 {
  730   if ( !ipmDevice_ )
  731   {
  732     return false;
  733   }
  734   return ipmDevice_->stopMedia();
  735 }
  736 
  737 
  738 /*
  739  * Test if this is a video call.
  740  */
  741 bool DialogicChannel::isVideo() const
  742 {
  743   if ( getProtocol() == PROTOCOL_SIP )
  744   {
  745     IpmDevice* ipt_ipm = static_cast<GcIptDevice*>(gcDevice_)->getIpmDevice();
  746     IpInfo rtp_video;
  747     ipt_ipm->getRemoteMediaInfo(MEDIATYPE_VIDEO_REMOTE_RTP_INFO, rtp_video);
  748     return rtp_video.isValid();
  749   }
  750   if ( getProtocol() == PROTOCOL_CONF )
  751   {
  752     IpInfo rtp_video;
  753     ipmDevice_->getRemoteMediaInfo(MEDIATYPE_VIDEO_REMOTE_RTP_INFO, rtp_video);
  754     return rtp_video.isValid();
  755   }
  756   if ( getProtocol() == PROTOCOL_H324 )
  757   {
  758     return true;
  759   }
  760   return false;
  761 }
  762 
  763 
  764 /*
  765  * Get the local ip-address and port number for the rtp audio media.
  766  */
  767 void DialogicChannel::getLocalRtpAudioInfo( IpInfo& rtp_audio ) const
  768 {
  769   if ( ipmDevice_ )
  770   {
  771     ipmDevice_->getLocalMediaInfo(MEDIATYPE_AUDIO_LOCAL_RTP_INFO, rtp_audio);
  772   }
  773 }
  774 
  775 
  776 /*
  777  * Get the local ip-address and port number for the rtp video media.
  778  */
  779 void DialogicChannel::getLocalRtpVideoInfo( IpInfo& rtp_video ) const
  780 {
  781   if ( ipmDevice_ )
  782   {
  783     ipmDevice_->getLocalMediaInfo(MEDIATYPE_VIDEO_LOCAL_RTP_INFO, rtp_video);
  784   }
  785 }
  786 
  787 
  788 /*
  789  * Save the ip-address and port of the remote party's rtp audio.
  790  */
  791 void DialogicChannel::setRemoteRtpAudioInfo( const IpInfo& rtp_audio )
  792 {
  793   if ( ipmDevice_ )
  794   {
  795     ipmDevice_->setRemoteMediaInfo(MEDIATYPE_AUDIO_REMOTE_RTP_INFO, rtp_audio);
  796   }
  797 }
  798 
  799 
  800 /*
  801  * Get the remote ip-address and port number for the rtp audio media.
  802  */
  803 void DialogicChannel::getRemoteRtpAudioInfo( IpInfo& rtp_audio ) const
  804 {
  805   if ( ipmDevice_ )
  806   {
  807     ipmDevice_->getRemoteMediaInfo(MEDIATYPE_AUDIO_LOCAL_RTP_INFO, rtp_audio);
  808   }
  809 }
  810 
  811 
  812 /*
  813  * Save the ip-address and port of the remote party's rtp video.
  814  */
  815 void DialogicChannel::setRemoteRtpVideoInfo( const IpInfo& rtp_video )
  816 {
  817   if ( ipmDevice_ )
  818   {
  819     ipmDevice_->setRemoteMediaInfo(MEDIATYPE_VIDEO_REMOTE_RTP_INFO, rtp_video);
  820   }
  821 }
  822 
  823 
  824 /*
  825  * Get the remote ip-address and port number for the rtp video media.
  826  */
  827 void DialogicChannel::getRemoteRtpVideoInfo( IpInfo& rtp_video ) const
  828 {
  829   if ( ipmDevice_ )
  830   {
  831     ipmDevice_->getRemoteMediaInfo(MEDIATYPE_VIDEO_REMOTE_RTP_INFO, rtp_video);
  832   }
  833 }
  834 
  835 
  836 /*
  837  * Forward the event to the media state machine.
  838  */
  839 void DialogicChannel::onMediaEvent( Event* event )
  840 {
  841   if ( context_ )
  842   {
  843     LOGINFO("DialogicChannel::onMediaEvent() event: " << event->getId());
  844     context_->onEvent(event);
  845   }
  846   else
  847   {
  848     LOGERROR("DialogicChannel::onMediaEvent() no context");
  849   }
  850 }
  851 
  852 
  853 /*
  854  * Tell the client there's an incoming call.
  855  */
  856 void DialogicChannel::onIncoming( const std::string& local_number,
  857                                   const std::string& remote_number )
  858 {
  859   direction_ = DIRECTION_INBOUND;
  860   channelMgr_.getClient().onIncoming(this, local_number, remote_number);
  861 }
  862 
  863 
  864 /*
  865  * Handle a call accepted event.
  866  */
  867 void DialogicChannel::onAccepted()
  868 {
  869   if ( getProtocol() == PROTOCOL_SIP )
  870   {
  871     /* Use the state machine to connect the media, notifying the client
  872      * when complete.
  873      */
  874     onMediaEvent(new Event(EVT_CONNECT_SIP_GW));
  875     ipmDevice_->startMedia();
  876   }
  877   else if ( (getProtocol() == PROTOCOL_ISDN) || (getProtocol() == PROTOCOL_SS7) )
  878   {
  879     /* Connect the media and notify the client.
  880      */
  881     GcIsdnDevice* dti = static_cast<GcIsdnDevice*>(gcDevice_);
  882 
  883     dti->listen(ipmDevice_);
  884     ipmDevice_->listen(dti);
  885     ipmDevice_->startMedia();
  886     channelMgr_.getClient().onAccepted(this);
  887   }
  888   else /* H324 */
  889   {
  890     /* Notify the client. The media will be connected when the call has
  891      * been answered.
  892      */
  893     channelMgr_.getClient().onAccepted(this);
  894   }
  895 }
  896 
  897 
  898 /*
  899  * Handle a call answered event.
  900  */
  901 void DialogicChannel::onAnswered()
  902 {
  903   if ( getProtocol() == PROTOCOL_H324 )
  904   {
  905     /* Use the state machine to connect the media. Notify the client
  906      * when this has completed and the h245 session has been established.
  907      */
  908     onMediaEvent(new Event(EVT_CONNECT_3G_GW));
  909     ipmDevice_->startMedia();
  910   }
  911   else
  912   {
  913     channelMgr_.getClient().onAnswered(this);
  914   }
  915 }
  916 
  917 
  918 /*
  919  * Handle a call proceeding event.
  920  */
  921 void DialogicChannel::onProceeding()
  922 {
  923   if ( (getProtocol() == PROTOCOL_ISDN) || (getProtocol() == PROTOCOL_SS7) )
  924   {
  925     GcIsdnDevice* dti = static_cast<GcIsdnDevice*>(gcDevice_);
  926     dti->listen(ipmDevice_);
  927     ipmDevice_->listen(dti);
  928     ipmDevice_->startMedia();
  929   }
  930   channelMgr_.getClient().onProceeding(this);
  931 }
  932 
  933 
  934 /*
  935  * Handle a remote party ringing event.
  936  */
  937 void DialogicChannel::onRinging()
  938 {
  939   if ( (getProtocol() == PROTOCOL_ISDN) || (getProtocol() == PROTOCOL_SS7) )
  940   {
  941     GcIsdnDevice* dti = static_cast<GcIsdnDevice*>(gcDevice_);
  942     dti->listen(ipmDevice_);
  943     ipmDevice_->listen(dti);
  944   }
  945   channelMgr_.getClient().onRinging(this);
  946 }
  947 
  948 
  949 /*
  950  * Handle an 'outbound' call connected event from a dti, ipt, confparty of m3g
  951  * device, now connected the media.
  952  */
  953 void DialogicChannel::onConnect( const std::string& conn_type )
  954 {
  955   conn_type_ = conn_type;
  956 
  957   if ( getProtocol() == PROTOCOL_SIP )
  958   {
  959     /* Use the state machine to connect the media, notifying the client
  960      * when complete.
  961      */
  962     onMediaEvent(new Event(EVT_CONNECT_SIP_GW));
  963   }
  964   else if ( (getProtocol() == PROTOCOL_ISDN) || (getProtocol() == PROTOCOL_SS7) )
  965   {
  966     /* Connect the media and notify the client.
  967      */
  968     GcIsdnDevice* dti = static_cast<GcIsdnDevice*>(gcDevice_);
  969     dti->listen(ipmDevice_);
  970     ipmDevice_->listen(dti);
  971     channelMgr_.getClient().onConnect(this, conn_type_);
  972   }
  973   else if ( getProtocol() == PROTOCOL_CONF )
  974   {
  975     /* Use the state machine to connect the media, notifying the client
  976      * when complete.
  977      */
  978     onMediaEvent(new Event(EVT_CONNECT_CONF));
  979   }
  980   else  /* H324 */
  981   {
  982     /* Use the state machine to connect the media. Notify the client
  983      * when this has completed and the h245 session has been established.
  984      */
  985     onMediaEvent(new Event(EVT_CONNECT_3G_GW));
  986   }
  987   ipmDevice_->startMedia();
  988 }
  989 
  990 
  991 /*
  992  * Gateway media connections have been established. For sip/conf calls, tell the
  993  * client that the call is connected; for H324 calls, defer telling the client
  994  * until after the h245 session has been established and its media started.
  995  */
  996 void DialogicChannel::onGatewayConnected()
  997 {
  998   if ( getProtocol() == PROTOCOL_H324 )
  999   {
 1000     h324_connected_ = false;
 1001     m3gDevice_->startH245();
 1002   }
 1003   else
 1004   {
 1005     if ( direction_ == DIRECTION_OUTBOUND )
 1006     {
 1007       channelMgr_.getClient().onConnect(this, conn_type_);
 1008     }
 1009     else
 1010     {
 1011       channelMgr_.getClient().onAccepted(this);
 1012     }
 1013   }
 1014 }
 1015 
 1016 
 1017 /*
 1018  * Conference media connections have been established, tell the client that the
 1019  * call is connected.
 1020  */
 1021 void DialogicChannel::onConfConnected()
 1022 {
 1023   channelMgr_.getClient().onConnect(this, CONN_CONFERENCE);
 1024 }
 1025 
 1026 
 1027 /*
 1028  * Handle a hangup from a dti or an ipt device.
 1029  * If a play or record is active fake a completion event so that it will be
 1030  * handled before the hangup event.
 1031  */
 1032 void DialogicChannel::onHangup( GcDevice* gc,
 1033                                 int cause,
 1034                                 const std::string& cause_text,
 1035                                 const std::string& conn_type )
 1036 {
 1037   if ( mmDevice_ )
 1038   {
 1039     if ( mmDevice_->isPlaying() )
 1040     {
 1041       mmDevice_->stopPlay(PLAY_STOPPED);
 1042       channelMgr_.getClient().onPlayCompleted(this, PLAY_STOPPED, 0);
 1043       mmDevice_->disconnect();
 1044     }
 1045     if ( mmDevice_->isRecording() )
 1046     {
 1047       mmDevice_->stopRecord(RECORD_STOPPED);
 1048       channelMgr_.getClient().onRecordCompleted(this, RECORD_STOPPED, 0);
 1049       mmDevice_->disconnect();
 1050     }
 1051   }
 1052   if ( getProtocol() == PROTOCOL_H324 )
 1053   {
 1054     m3gDevice_->endSession();
 1055   }
 1056   channelMgr_.getClient().onHangup(this, cause, cause_text, conn_type);
 1057 }
 1058 
 1059 
 1060 /*
 1061  * H.324 session has ended, clear its isdn call.
 1062  */
 1063 void DialogicChannel::onHangup( M3gDevice* m3g )
 1064 {
 1065   if ( mmDevice_ )
 1066   {
 1067     if ( mmDevice_->isPlaying() )
 1068     {
 1069       mmDevice_->stopPlay(PLAY_STOPPED);
 1070       channelMgr_.getClient().onPlayCompleted(this, PLAY_STOPPED, 0);
 1071       mmDevice_->disconnect();
 1072     }
 1073     if ( mmDevice_->isRecording() )
 1074     {
 1075       mmDevice_->stopRecord(RECORD_STOPPED);
 1076       channelMgr_.getClient().onRecordCompleted(this, RECORD_STOPPED, 0);
 1077       mmDevice_->disconnect();
 1078     }
 1079   }
 1080   gcDevice_->dropCall(GC_NORMAL_CLEARING);
 1081 
 1082   int cause = GC_NORMAL_CLEARING;
 1083   std::string cause_text = "Normal Clearing";
 1084   channelMgr_.getClient().onHangup(this, cause, cause_text);
 1085 }
 1086 
 1087 
 1088 /*
 1089  * Handle a hangup from a conference party device.
 1090  * If a play or record is active fake a completion event so that it will be
 1091  * handled before the hangup event.
 1092  */
 1093 void DialogicChannel::onHangup( ConfPartyDevice* confParty )
 1094 {
 1095   if ( mmDevice_ )
 1096   {
 1097     if ( mmDevice_->isPlaying() )
 1098     {
 1099       mmDevice_->stopPlay(PLAY_STOPPED);
 1100       channelMgr_.getClient().onPlayCompleted(this, PLAY_STOPPED, 0);
 1101       mmDevice_->disconnect();
 1102     }
 1103     if ( mmDevice_->isRecording() )
 1104     {
 1105       mmDevice_->stopRecord(RECORD_STOPPED);
 1106       channelMgr_.getClient().onRecordCompleted(this, RECORD_STOPPED, 0);
 1107       mmDevice_->disconnect();
 1108     }
 1109   }
 1110   channelMgr_.getClient().onHangup(this, 16, "Normal clearing", std::string());
 1111 }
 1112 
 1113 
 1114 /*
 1115  * Handle a dtmf digit received event.
 1116  * The behaviour is modified when either a play or record operation is active.
 1117  * If playing, buffer the digit until the play completes and if the digit matches
 1118  * a 'stop' digit, terminate the play.
 1119  * If recording and the digit matches a stop digit terminate the recording. All
 1120  * digits are discarded when recording.
 1121  * If neither playing nor recording forward the digit to the client.
 1122  */
 1123 void DialogicChannel::onDtmf( char dtmf )
 1124 {
 1125   LOGDEBUG("DialogicChannel::onDtmf() digit: " << dtmf);
 1126   if ( mmDevice_ )
 1127   {
 1128     if ( mmDevice_->isPlaying() )
 1129     {
 1130       if ( isStopDigit(dtmf) )
 1131       {
 1132         mmDevice_->stopPlay(PLAY_END_DIGIT);
 1133       }
 1134       collectDigit(dtmf);
 1135       return;
 1136     }
 1137     else if ( mmDevice_->isRecording() )
 1138     {
 1139       if ( isStopDigit(dtmf) )
 1140       {
 1141         mmDevice_->stopRecord(RECORD_END_DIGIT);
 1142       }
 1143       return; /* discard */
 1144     }
 1145   }
 1146   std::string digits;
 1147   digits.push_back(dtmf);
 1148   channelMgr_.getClient().onDtmf(this, digits);
 1149 }
 1150 
 1151 
 1152 /*
 1153  * Handle a tone detection event.
 1154  */
 1155 void DialogicChannel::onTone( const std::string& name )
 1156 {
 1157   channelMgr_.getClient().onTone(this, name);
 1158 }
 1159 
 1160 
 1161 /*
 1162  * Handle a dtmf send completion event.
 1163  */
 1164 void DialogicChannel::onSendDtmfCompleted()
 1165 {
 1166   if ( (protocol_ == PROTOCOL_ISDN) || (protocol_ == PROTOCOL_SS7) )
 1167   {
 1168     gcDevice_->listen(ipmDevice_);
 1169     channelMgr_.getClient().onSendDtmfCompleted(this);
 1170   }
 1171   else if ( protocol_ == PROTOCOL_H324 )
 1172   {
 1173     channelMgr_.getClient().onSendDtmfCompleted(this);
 1174   }
 1175 }
 1176 
 1177 
 1178 /*
 1179  * Handle a media connect completion event from an ipm device.
 1180  */
 1181 void DialogicChannel::onConnectCompleted( IpmDevice* ipm )
 1182 {
 1183   LOGDEBUG("DialogicChannel::onConnectCompleted() device: " << ipm->getDeviceName());
 1184 
 1185   GcIptDevice* ipt = ipm->getIptDevice();
 1186   if ( ipt )
 1187   {
 1188     onMediaEvent(new Event(EVT_IPTIPM_CONNECTED));
 1189 
 1190     /* if this connection was made to as part of an optimised bridge to
 1191      * a conference channel, the original caption will no longer been seen
 1192      * (conf's ipm disconnected) so its regenerated here and overlayed on
 1193      * this ipm device. Note, this does not take into account the amount
 1194      * of time that the prognal caption has been shown.
 1195      */
 1196     if ( other_channel_ && (other_channel_->getProtocol() == PROTOCOL_CONF) )
 1197     {
 1198       ConfPartyDevice* confParty = other_channel_->getConfPartyDevice();
 1199       ConfDevice* confDevice = other_channel_->getConfDevice();
 1200       if ( confDevice && confParty )
 1201       {
 1202         if ( (confDevice->getCaptionDuration() > 0) && (!confParty->getCaption().empty()) )
 1203         {
 1204           confDevice->displayCaption(ipm, confParty->getCaption());
 1205         }
 1206       }
 1207     }
 1208   }
 1209   else
 1210   {
 1211     onMediaEvent(new Event(EVT_IPM_CONNECTED));
 1212   }
 1213 }
 1214 
 1215 
 1216 /*
 1217  * Handle a media disconnect completion event from an ipm device.
 1218  */
 1219 void DialogicChannel::onDisconnectCompleted( IpmDevice* ipm )
 1220 {
 1221   LOGDEBUG("DialogicChannel::onDisconnectCompleted() device: " << ipm->getDeviceName());
 1222 
 1223   GcIptDevice* ipt = ipm->getIptDevice();
 1224   if ( ipt )
 1225   {
 1226     onMediaEvent(new Event(EVT_IPTIPM_DISCONNECTED));
 1227   }
 1228   else
 1229   {
 1230     onMediaEvent(new Event(EVT_IPM_DISCONNECTED));
 1231   }
 1232 }
 1233 
 1234 
 1235 /*
 1236  * Handle a media connect completion event from a mm device.
 1237  */
 1238 void DialogicChannel::onConnectCompleted( MmDevice* mm )
 1239 {
 1240   LOGDEBUG("DialogicChannel::onConnectCompleted() device: " << mm->getDeviceName());
 1241 
 1242   onMediaEvent(new Event(EVT_MM_CONNECTED));
 1243 }
 1244 
 1245 
 1246 /*
 1247  * Handle a media disconnect completion event from a mm device.
 1248  */
 1249 void DialogicChannel::onDisconnectCompleted( MmDevice* mm )
 1250 {
 1251   LOGDEBUG("DialogicChannel::onDisconnectCompleted() device: " << mm->getDeviceName());
 1252 
 1253   mm->unBindChannel();
 1254   setMmDevice(0);
 1255   channelMgr_.freeMmDevice(mm);
 1256 
 1257   onMediaEvent(new Event(EVT_MM_DISCONNECTED));
 1258 }
 1259 
 1260 
 1261 /*
 1262  * Handle a media connect completion event from a m3g device.
 1263  */
 1264 void DialogicChannel::onConnectCompleted( M3gDevice* m3g )
 1265 {
 1266   LOGDEBUG("DialogicChannel::onConnectCompleted() device: " << m3g->getDeviceName());
 1267   onMediaEvent(new Event(EVT_M3G_CONNECTED));
 1268 }
 1269 
 1270 
 1271 /*
 1272  * Handle a media disconnect completion event from a m3g device.
 1273  */
 1274 void DialogicChannel::onDisconnectCompleted( M3gDevice* m3g )
 1275 {
 1276   LOGDEBUG("DialogicChannel::onDisconnectCompleted() device: " << m3g->getDeviceName());
 1277   onMediaEvent(new Event(EVT_M3G_DISCONNECTED));
 1278 }
 1279 
 1280 
 1281 /*
 1282  * Handle a media streaming started event from a m3g device.
 1283  */
 1284 void DialogicChannel::onMediaStarted( M3gDevice* m3g )
 1285 {
 1286   LOGDEBUG("DialogicChannel::onMediaStarted() device: " << m3g->getDeviceName());
 1287 
 1288   /* The first time that this event occurs is when the h245 session has been
 1289    * established, use it to tell the client the call is now fully connected.
 1290    */
 1291   if ( !h324_connected_ )
 1292   {
 1293     if ( direction_ == DIRECTION_OUTBOUND )
 1294     {
 1295       channelMgr_.getClient().onConnect(this, conn_type_);
 1296     }
 1297     else
 1298     {
 1299       channelMgr_.getClient().onAnswered(this);
 1300     }
 1301     h324_connected_ = true;
 1302   }
 1303 
 1304   onMediaEvent(new Event(EVT_M3G_STARTED));
 1305 }
 1306 
 1307 
 1308 /*
 1309  * Handle a media streaming stopped event from a m3g device.
 1310  */
 1311 void DialogicChannel::onMediaStopped( M3gDevice* m3g )
 1312 {
 1313   LOGDEBUG("DialogicChannel::onMediaStopped() device: " << m3g->getDeviceName());
 1314   onMediaEvent(new Event(EVT_M3G_STOPPED));
 1315 }
 1316 
 1317 
 1318 /*
 1319  * Handle a media connect completion event from a conference party device.
 1320  */
 1321 void DialogicChannel::onConnectCompleted( ConfPartyDevice* confParty )
 1322 {
 1323   LOGDEBUG("DialogicChannel::onConnectCompleted() device: " << confParty->getDeviceName());
 1324   onMediaEvent(new Event(EVT_CONF_CONNECTED));
 1325 }
 1326 
 1327 
 1328 /*
 1329  * Handle a media disconnect completion event from a conference party device.
 1330  */
 1331 void DialogicChannel::onDisconnectCompleted( ConfPartyDevice* confParty )
 1332 {
 1333   LOGDEBUG("DialogicChannel::onDisconnectCompleted() device: " << confParty->getDeviceName());
 1334   onMediaEvent(new Event(EVT_CONF_DISCONNECTED));
 1335 }
 1336 
 1337 
 1338 /*
 1339  * Handle a play started event from an mm device.
 1340  */
 1341 void DialogicChannel::onPlayStarted( MmDevice* mm )
 1342 {
 1343   if ( getProtocol() == PROTOCOL_SIP )
 1344   {
 1345     IpmDevice* ipt_ipm = static_cast<GcIptDevice*>(gcDevice_)->getIpmDevice();
 1346     ipt_ipm->generateIFrame(mm->isVideoTranscodeOn());
 1347   }
 1348 }
 1349 
 1350 
 1351 /*
 1352  * Handle a play completion event from an mm device.
 1353  */
 1354 void DialogicChannel::onPlayCompleted( MmDevice* mm,
 1355                                        const std::string& reason,
 1356                                        unsigned int duration )
 1357 {
 1358   if ( getProtocol() == PROTOCOL_SIP )
 1359   {
 1360     IpmDevice* ipt_ipm = static_cast<GcIptDevice*>(gcDevice_)->getIpmDevice();
 1361     ipt_ipm->removeOverlay();
 1362   }
 1363   else
 1364   {
 1365     ipmDevice_->removeOverlay();
 1366   }
 1367 
 1368   player_.reason = reason;
 1369   player_.duration = duration;
 1370 
 1371   onMediaEvent(new Event(EVT_MM_PLAY_COMPLETED));
 1372 }
 1373 
 1374 
 1375 /*
 1376  * Handle a play completion event from the state machine.
 1377  */
 1378 void DialogicChannel::onPlayCompleted()
 1379 {
 1380   channelMgr_.getClient().onPlayCompleted(this,
 1381                                           player_.reason,
 1382                                           player_.duration);
 1383 
 1384   channelMgr_.getClient().onDtmf(this, getDigits());
 1385   clearDigits();
 1386 }
 1387 
 1388 
 1389 /*
 1390  * Handle a record completion event from an mm device.
 1391  */
 1392 void DialogicChannel::onRecordCompleted( MmDevice* mm,
 1393                                          const std::string& reason,
 1394                                          unsigned int duration )
 1395 {
 1396   recorder_.reason = reason;
 1397   recorder_.duration = duration;
 1398 
 1399   onMediaEvent(new Event(EVT_MM_RECORD_COMPLETED));
 1400 }
 1401 
 1402 
 1403 /*
 1404  * Handle a record completion event from the state machine.
 1405  */
 1406 void DialogicChannel::onRecordCompleted()
 1407 {
 1408   channelMgr_.getClient().onRecordCompleted(this,
 1409                                             recorder_.reason,
 1410                                             recorder_.duration);
 1411 }
 1412 
 1413 /* vim:ts=4:set nu:
 1414  * EOF
 1415  */

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