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