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