Parent Directory
|
Revision Log
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 |