1/* ------------------------------------------------------------------ 2 * Copyright (C) 1998-2009 PacketVideo 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either 13 * express or implied. 14 * See the License for the specific language governing permissions 15 * and limitations under the License. 16 * ------------------------------------------------------------------- 17 */ 18 19#include "pvmf_downloadmanager_node.h" 20#include "pvmf_download_data_source.h" 21#include "pvmf_local_data_source.h" 22#include "pvmf_protocol_engine_factory.h" 23#include "pvmf_socket_factory.h" 24#include "pvmf_socket_node.h" 25#include "pvlogger.h" 26#include "oscl_error_codes.h" 27#include "oscl_str_ptr_len.h" // for OSCL_ASCII_CASE_MAGIC_BIT 28#include "pvmi_datastreamuser_interface.h" 29#include "pvpvxparser.h" 30#include "pv_mime_string_utils.h" 31#include "pvmi_kvp_util.h" 32#include "pvmf_source_context_data.h" 33 34//Log levels for node commands 35#define CMD_LOG_LEVEL PVLOGMSG_INFO 36//Log levels for subnode commands. 37#define SUB_CMD_LOG_LEVEL PVLOGMSG_INFO 38 39 40/////////////////////////////////////////////////////////////////////////////// 41// 42// Capability and config interface related constants and definitions 43// - based on pv_player_engine.h 44// 45/////////////////////////////////////////////////////////////////////////////// 46 47static const DownloadManagerKeyStringData DownloadManagerConfig_BaseKeys[] = 48{ 49 {"user-agent", PVMI_KVPTYPE_VALUE, PVMI_KVPVALTYPE_WCHARPTR}, 50 {"http-version", PVMI_KVPTYPE_VALUE, PVMI_KVPVALTYPE_UINT32}, 51 {"http-timeout", PVMI_KVPTYPE_VALUE, PVMI_KVPVALTYPE_UINT32}, 52 {"download-progress-info", PVMI_KVPTYPE_VALUE, PVMI_KVPVALTYPE_CHARPTR}, 53 {"protocol-extension-header", PVMI_KVPTYPE_VALUE, PVMI_KVPVALTYPE_CHARPTR}, 54 {"num-redirect-attempts", PVMI_KVPTYPE_VALUE, PVMI_KVPVALTYPE_UINT32}, 55 {"http-header-request-disabled", PVMI_KVPTYPE_VALUE, PVMI_KVPVALTYPE_BOOL}, 56 {"max-tcp-recv-buffer-size-download", PVMI_KVPTYPE_VALUE, PVMI_KVPVALTYPE_UINT32}, 57 {"max-tcp-recv-buffer-count-download", PVMI_KVPTYPE_VALUE, PVMI_KVPVALTYPE_UINT32} 58}; 59 60static const uint DownloadManagerConfig_NumBaseKeys = 61 (sizeof(DownloadManagerConfig_BaseKeys) / 62 sizeof(DownloadManagerKeyStringData)); 63 64enum BaseKeys_IndexMapType 65{ 66 BASEKEY_SESSION_CONTROLLER_USER_AGENT = 0, 67 BASEKEY_SESSION_CONTROLLER_HTTP_VERSION, 68 BASEKEY_SESSION_CONTROLLER_HTTP_TIMEOUT, 69 BASEKEY_SESSION_CONTROLLER_DOWNLOAD_PROGRESS_INFO, 70 BASEKEY_SESSION_CONTROLLER_PROTOCOL_EXTENSION_HEADER, 71 BASEKEY_SESSION_CONTROLLER_NUM_REDIRECT_ATTEMPTS, 72 BASEKEY_SESSION_CONTROLLER_NUM_HTTP_HEADER_REQUEST_DISABLED, 73 BASEKEY_MAX_TCP_RECV_BUFFER_SIZE, 74 BASEKEY_MAX_TCP_RECV_BUFFER_COUNT 75}; 76 77 78 79PVMFDownloadManagerNode::PVMFDownloadManagerNode(int32 aPriority) 80 : OsclActiveObject(aPriority, "PVMFDownloadManagerNode") 81{ 82 int32 err; 83 OSCL_TRY(err, ConstructL();); 84 if (err != OsclErrNone) 85 { 86 //if a leave happened, cleanup and re-throw the error 87 iInputCommands.clear(); 88 iCurrentCommand.clear(); 89 iCancelCommand.clear(); 90 iCapability.iInputFormatCapability.clear(); 91 iCapability.iOutputFormatCapability.clear(); 92 OSCL_CLEANUP_BASE_CLASS(PVMFNodeInterface); 93 OSCL_CLEANUP_BASE_CLASS(OsclActiveObject); 94 OSCL_LEAVE(err); 95 } 96 97 iDNodeUuids.clear(); 98 iDNodeUuidCount = 0; 99} 100 101void PVMFDownloadManagerNode::ConstructL() 102{ 103 iDebugMode = false; 104 iLogger = NULL; 105 iExtensionRefCount = 0; 106 iSourceFormat = PVMF_MIME_FORMAT_UNKNOWN; 107 iMimeType = PVMF_MIME_FORMAT_UNKNOWN; 108 iSourceData = NULL; 109 iPlayBackClock = NULL; 110 iClockNotificationsInf = NULL; 111 112 iNoPETrackSelect = false; 113 iMovieAtomComplete = false; 114 iParserInitAfterMovieAtom = false; 115 iParserPrepareAfterMovieAtom = false; 116 117 iParserInit = false; 118 iDataReady = false; 119 iDownloadComplete = false; 120 iRecognizerError = false; 121 122 iInitFailedLicenseRequired = false; 123 124 iProtocolEngineNodePort = NULL; 125 iSocketNodePort = NULL; 126 iPlayerNodeRegistry = NULL; 127 128 //create the sub-node command queue. Use a reserve to avoid dynamic memory failure later. 129 //Max depth is the max number of sub-node commands for any one node command. Init command may take up to 15 130 iSubNodeCmdVec.reserve(15); 131 132 //Create the input command queue. Max depth is undetermined -- just reserve 10. 133 iInputCommands.Construct(1000 //start cmd id 134 , 10);//reserve. 135 136 //Create the "current command" queue. Max depth is 1 for each of these. 137 iCurrentCommand.Construct(0, 1); 138 iCancelCommand.Construct(0, 1); 139 140 //create node containers. 141 //@TODO this will create unused node containers. think about 142 //optimizing it. 143 iFormatParserNode.Construct(PVMFDownloadManagerSubNodeContainerBase::EFormatParser, this); 144 iProtocolEngineNode.Construct(PVMFDownloadManagerSubNodeContainerBase::EProtocolEngine, this); 145 iSocketNode.Construct(PVMFDownloadManagerSubNodeContainerBase::ESocket, this); 146 iRecognizerNode.Construct(PVMFDownloadManagerSubNodeContainerBase::ERecognizer, this); 147 148 //Set the node capability data. 149 iCapability.iCanSupportMultipleInputPorts = false; 150 iCapability.iCanSupportMultipleOutputPorts = true; 151 iCapability.iHasMaxNumberOfPorts = true; 152 iCapability.iMaxNumberOfPorts = 6; 153 iCapability.iInputFormatCapability.push_back(PVMF_MIME_MPEG4FF); 154 iCapability.iInputFormatCapability.push_back(PVMF_MIME_ASFFF); 155 iCapability.iInputFormatCapability.push_back(PVMF_MIME_RMFF); 156 iCapability.iOutputFormatCapability.push_back(PVMF_MIME_AMR_IETF); 157 iCapability.iOutputFormatCapability.push_back(PVMF_MIME_MPEG4_AUDIO); 158 iCapability.iOutputFormatCapability.push_back(PVMF_MIME_M4V); 159 iCapability.iOutputFormatCapability.push_back(PVMF_MIME_H2631998); 160 iCapability.iOutputFormatCapability.push_back(PVMF_MIME_H2632000); 161 iCapability.iOutputFormatCapability.push_back(PVMF_MIME_REAL_VIDEO); 162 iCapability.iOutputFormatCapability.push_back(PVMF_MIME_WMV); 163 iCapability.iOutputFormatCapability.push_back(PVMF_MIME_DIVXFF); 164 165 iFileBufferDatastreamFactory = NULL; 166#if(PVMF_DOWNLOADMANAGER_SUPPORT_PPB) 167 iMemoryBufferDatastreamFactory = NULL; 168#endif//PVMF_DOWNLOADMANAGER_SUPPORT_PPB 169 170 iDownloadFileName = NULL; 171 iContentTypeMIMEString = NULL; 172 173 iProtocolEngineNode.iNode = PVMFProtocolEngineNodeFactory::CreatePVMFProtocolEngineNode(OsclActiveObject::EPriorityNominal); 174 OsclError::LeaveIfNull(iProtocolEngineNode.iNode); 175 iProtocolEngineNode.Connect(); 176 177 iSocketNode.iNode = PVMFSocketNodeFactory::CreatePVMFSocketNode(OsclActiveObject::EPriorityNominal); 178 OsclError::LeaveIfNull(iSocketNode.iNode); 179 iSocketNode.Connect(); 180} 181 182PVMFDownloadManagerNode::~PVMFDownloadManagerNode() 183{ 184 if (iPlayBackClock != NULL) 185 { 186 if (iClockNotificationsInf != NULL) 187 { 188 iClockNotificationsInf->RemoveClockStateObserver(*this); 189 iPlayBackClock->DestroyMediaClockNotificationsInterface(iClockNotificationsInf); 190 } 191 } 192 193 Cancel(); 194 if (IsAdded()) 195 RemoveFromScheduler(); 196 197 //if any sub-node commands are outstanding, there will be 198 //a crash when they callback-- so panic here instead. 199 200 if (iFormatParserNode.CmdPending() 201 || iProtocolEngineNode.CmdPending() 202 || iSocketNode.CmdPending() 203 || iRecognizerNode.CmdPending() 204 ) 205 { 206 OSCL_ASSERT(0); 207 } 208 209 //this is to ensure that there are no more callbacks from PE node to parser node, 210 //in case parser node had some outstanding request resume notifications 211 if (iProtocolEngineNode.DownloadProgress() != NULL) 212 { 213 (iProtocolEngineNode.DownloadProgress())->setFormatDownloadSupportInterface(NULL); 214 } 215 216 //make sure the subnodes got cleaned up 217 iFormatParserNode.Cleanup(); 218 iProtocolEngineNode.Cleanup(); 219 iSocketNode.Cleanup(); 220 iRecognizerNode.Cleanup(); 221 222 //delete the subnodes 223 if (iFormatParserNode.iNode) 224 { 225 iDNodeUuidCount--; 226 227 bool release_status = false; 228 int32 leavecode = 0; 229 OSCL_TRY(leavecode, release_status = iPlayerNodeRegistry->ReleaseNode(iDNodeUuids[iDNodeUuidCount], iFormatParserNode.iNode)); 230 //ignore errors. 231 iDNodeUuids.clear(); 232 } 233 234 if (iProtocolEngineNode.iNode) 235 PVMFProtocolEngineNodeFactory::DeletePVMFProtocolEngineNode(iProtocolEngineNode.iNode); 236 237 if (iSocketNode.iNode) 238 PVMFSocketNodeFactory::DeletePVMFSocketNode(iSocketNode.iNode); 239 240 // delete the data stream factory (This has to come after deleting anybody who uses it, like the protocol engine node or the parser node.) 241 if (iFileBufferDatastreamFactory) 242 { 243 OSCL_DELETE(iFileBufferDatastreamFactory); 244 iFileBufferDatastreamFactory = NULL; 245 } 246#if(PVMF_DOWNLOADMANAGER_SUPPORT_PPB) 247 if (iMemoryBufferDatastreamFactory) 248 { 249 OSCL_DELETE(iMemoryBufferDatastreamFactory); 250 iMemoryBufferDatastreamFactory = NULL; 251 } 252#endif//PVMF_DOWNLOADMANAGER_SUPPORT_PPB 253 254 //The command queues are self-deleting, but we want to notify the observer of unprocessed commands. 255 while (!iCurrentCommand.empty()) 256 CommandComplete(iCurrentCommand, iCurrentCommand.front(), PVMFFailure, NULL, NULL); 257 while (!iCancelCommand.empty()) 258 CommandComplete(iCancelCommand, iCancelCommand.front(), PVMFFailure, NULL, NULL); 259 while (!iInputCommands.empty()) 260 CommandComplete(iInputCommands, iInputCommands.front(), PVMFFailure, NULL, NULL); 261} 262 263//Public API From node interface. 264PVMFStatus PVMFDownloadManagerNode::ThreadLogon() 265{ 266 if (iInterfaceState != EPVMFNodeCreated) 267 return PVMFErrInvalidState; 268 269 //logon this node. 270 if (!IsAdded()) 271 AddToScheduler(); 272 273 iLogger = PVLogger::GetLoggerObject("pvdownloadmanagernode"); 274 275 PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, CMD_LOG_LEVEL, (0, "PVMFDownloadManagerNode::ThreadLogon() called")); 276 277 //logon the sub-nodes. 278 if (iProtocolEngineNode.iNode) 279 iProtocolEngineNode.iNode->ThreadLogon(); 280 281 if (iSocketNode.iNode) 282 iSocketNode.iNode->ThreadLogon(); 283 284 ChangeNodeState(EPVMFNodeIdle); 285 return PVMFSuccess; 286} 287 288 289//Public API From node interface. 290PVMFStatus PVMFDownloadManagerNode::ThreadLogoff() 291{ 292 PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, CMD_LOG_LEVEL, (0, "PVMFDownloadManagerNode::ThreadLogoff() called")); 293 294 if (iInterfaceState != EPVMFNodeIdle) 295 return PVMFErrInvalidState; 296 297 //logoff this node. 298 if (IsAdded()) 299 RemoveFromScheduler(); 300 301 iLogger = NULL; 302 303 //logoff the sub-nodes. 304 if (iFormatParserNode.iNode) 305 iFormatParserNode.iNode->ThreadLogoff(); 306 if (iProtocolEngineNode.iNode) 307 iProtocolEngineNode.iNode->ThreadLogoff(); 308 if (iSocketNode.iNode) 309 iSocketNode.iNode->ThreadLogoff(); 310 311 ChangeNodeState(EPVMFNodeCreated); 312 return PVMFSuccess; 313} 314 315 316//Public API From node interface. 317PVMFStatus PVMFDownloadManagerNode::GetCapability(PVMFNodeCapability& aNodeCapability) 318{ 319 PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, CMD_LOG_LEVEL, (0, "PVMFDownloadManagerNode::GetCapability() called")); 320 321 aNodeCapability = iCapability; 322 323 return PVMFSuccess; 324} 325 326 327//Public API From node interface. 328PVMFPortIter* PVMFDownloadManagerNode::GetPorts(const PVMFPortFilter* aFilter) 329{ 330 PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, CMD_LOG_LEVEL, (0, "PVMFDownloadManagerNode::GetPorts() called")); 331 332 if (iFormatParserNode.iNode) 333 return iFormatParserNode.iNode->GetPorts(aFilter); 334 return NULL; 335} 336 337 338//Public API From node interface. 339PVMFCommandId PVMFDownloadManagerNode::QueryUUID(PVMFSessionId aSessionId, const PvmfMimeString& aMimeType, 340 Oscl_Vector<PVUuid, OsclMemAllocator>& aUuids, bool aExactUuidsOnly, const OsclAny* aContext) 341{ 342 343 PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, CMD_LOG_LEVEL, (0, "PVMFDownloadManagerNode::QueryUUID() called")); 344 345 PVMFDownloadManagerNodeCommand cmd; 346 cmd.PVMFDownloadManagerNodeCommandBase::Construct(aSessionId, PVMF_GENERIC_NODE_QUERYUUID, aMimeType, aUuids, aExactUuidsOnly, aContext); 347 return QueueCommandL(cmd); 348} 349 350 351//Public API From node interface. 352PVMFCommandId PVMFDownloadManagerNode::QueryInterface(PVMFSessionId aSessionId, const PVUuid& aUuid, 353 PVInterface*& aInterfacePtr, const OsclAny* aContext) 354{ 355 PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, CMD_LOG_LEVEL, (0, "PVMFDownloadManagerNode::QueryInterface() called")); 356 357 PVMFDownloadManagerNodeCommand cmd; 358 cmd.PVMFDownloadManagerNodeCommandBase::Construct(aSessionId, PVMF_GENERIC_NODE_QUERYINTERFACE, aUuid, aInterfacePtr, aContext); 359 return QueueCommandL(cmd); 360} 361 362 363//Public API From node interface. 364PVMFCommandId PVMFDownloadManagerNode::RequestPort(PVMFSessionId aSessionId, int32 aPortTag, 365 const PvmfMimeString* aPortConfig, const OsclAny* aContext) 366{ 367 PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, CMD_LOG_LEVEL, (0, "PVMFDownloadManagerNode::RequestPort() called")); 368 369 PVMFDownloadManagerNodeCommand cmd; 370 cmd.PVMFDownloadManagerNodeCommandBase::Construct(aSessionId, PVMF_GENERIC_NODE_REQUESTPORT, aPortTag, aPortConfig, aContext); 371 return QueueCommandL(cmd); 372} 373 374 375//Public API From node interface. 376PVMFStatus PVMFDownloadManagerNode::ReleasePort(PVMFSessionId aSessionId, PVMFPortInterface& aPort, const OsclAny* aContext) 377{ 378 PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, CMD_LOG_LEVEL, (0, "PVMFDownloadManagerNode::ReleasePort() called")); 379 380 PVMFDownloadManagerNodeCommand cmd; 381 cmd.PVMFDownloadManagerNodeCommandBase::Construct(aSessionId, PVMF_GENERIC_NODE_RELEASEPORT, aPort, aContext); 382 return QueueCommandL(cmd); 383} 384 385 386//Public API From node interface. 387PVMFCommandId PVMFDownloadManagerNode::Init(PVMFSessionId aSessionId, const OsclAny* aContext) 388{ 389 PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, CMD_LOG_LEVEL, (0, "PVMFDownloadManagerNode::Init() called")); 390 391 PVMFDownloadManagerNodeCommand cmd; 392 cmd.PVMFDownloadManagerNodeCommandBase::Construct(aSessionId, PVMF_GENERIC_NODE_INIT, aContext); 393 return QueueCommandL(cmd); 394} 395 396 397//Public API From node interface. 398PVMFCommandId PVMFDownloadManagerNode::Prepare(PVMFSessionId aSessionId, const OsclAny* aContext) 399{ 400 PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, CMD_LOG_LEVEL, (0, "PVMFDownloadManagerNode::Prepare() called")); 401 402 PVMFDownloadManagerNodeCommand cmd; 403 cmd.PVMFDownloadManagerNodeCommandBase::Construct(aSessionId, PVMF_GENERIC_NODE_PREPARE, aContext); 404 return QueueCommandL(cmd); 405} 406 407 408//Public API From node interface. 409PVMFCommandId PVMFDownloadManagerNode::Start(PVMFSessionId aSessionId, const OsclAny* aContext) 410{ 411 PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, CMD_LOG_LEVEL, (0, "PVMFDownloadManagerNode::Start() called")); 412 413 PVMFDownloadManagerNodeCommand cmd; 414 cmd.PVMFDownloadManagerNodeCommandBase::Construct(aSessionId, PVMF_GENERIC_NODE_START, aContext); 415 return QueueCommandL(cmd); 416} 417 418 419//Public API From node interface. 420PVMFCommandId PVMFDownloadManagerNode::Stop(PVMFSessionId aSessionId, const OsclAny* aContext) 421{ 422 PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, CMD_LOG_LEVEL, (0, "PVMFDownloadManagerNode::Stop() called")); 423 424 PVMFDownloadManagerNodeCommand cmd; 425 cmd.PVMFDownloadManagerNodeCommandBase::Construct(aSessionId, PVMF_GENERIC_NODE_STOP, aContext); 426 return QueueCommandL(cmd); 427} 428 429 430//Public API From node interface. 431PVMFCommandId PVMFDownloadManagerNode::Flush(PVMFSessionId aSessionId, const OsclAny* aContext) 432{ 433 PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, CMD_LOG_LEVEL, (0, "PVMFDownloadManagerNode::Flush() called")); 434 435 PVMFDownloadManagerNodeCommand cmd; 436 cmd.PVMFDownloadManagerNodeCommandBase::Construct(aSessionId, PVMF_GENERIC_NODE_FLUSH, aContext); 437 return QueueCommandL(cmd); 438} 439 440 441//Public API From node interface. 442PVMFCommandId PVMFDownloadManagerNode::Pause(PVMFSessionId aSessionId, const OsclAny* aContext) 443{ 444 PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, CMD_LOG_LEVEL, (0, "PVMFDownloadManagerNode::Pause() called")); 445 446 PVMFDownloadManagerNodeCommand cmd; 447 cmd.PVMFDownloadManagerNodeCommandBase::Construct(aSessionId, PVMF_GENERIC_NODE_PAUSE, aContext); 448 return QueueCommandL(cmd); 449} 450 451 452//Public API From node interface. 453PVMFCommandId PVMFDownloadManagerNode::Reset(PVMFSessionId aSessionId, const OsclAny* aContext) 454{ 455 PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, CMD_LOG_LEVEL, (0, "PVMFDownloadManagerNode::Reset() called")); 456 457 PVMFDownloadManagerNodeCommand cmd; 458 cmd.PVMFDownloadManagerNodeCommandBase::Construct(aSessionId, PVMF_GENERIC_NODE_RESET, aContext); 459 return QueueCommandL(cmd); 460} 461 462 463//Public API From node interface. 464PVMFCommandId PVMFDownloadManagerNode::CancelAllCommands(PVMFSessionId aSessionId, const OsclAny* aContext) 465{ 466 PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, CMD_LOG_LEVEL, (0, "PVMFDownloadManagerNode::CancelAllCommands() called")); 467 468 PVMFDownloadManagerNodeCommand cmd; 469 cmd.PVMFDownloadManagerNodeCommandBase::Construct(aSessionId, PVMF_GENERIC_NODE_CANCELALLCOMMANDS, aContext); 470 return QueueCommandL(cmd); 471} 472 473 474//Public API From node interface. 475PVMFCommandId PVMFDownloadManagerNode::CancelCommand(PVMFSessionId aSessionId, PVMFCommandId aCmdId, const OsclAny* aContext) 476{ 477 PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, CMD_LOG_LEVEL, (0, "PVMFDownloadManagerNode::CancelCommand() called")); 478 479 PVMFDownloadManagerNodeCommand cmd; 480 cmd.PVMFDownloadManagerNodeCommandBase::Construct(aSessionId, PVMF_GENERIC_NODE_CANCELCOMMAND, aCmdId, aContext); 481 return QueueCommandL(cmd); 482} 483 484//public API from PVInterface 485void PVMFDownloadManagerNode::addRef() 486{ 487 ++iExtensionRefCount; 488} 489 490//public API from PVInterface 491void PVMFDownloadManagerNode::removeRef() 492{ 493 --iExtensionRefCount; 494} 495 496//public API from PVInterface 497bool PVMFDownloadManagerNode::queryInterface(const PVUuid& uuid, PVInterface*& iface) 498{ 499 PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE, (0, "PVMFDownloadManagerNode::queryInterface() In")); 500 501 if (uuid == PVMF_TRACK_SELECTION_INTERFACE_UUID) 502 { 503 PVMFTrackSelectionExtensionInterface* myInterface = OSCL_STATIC_CAST(PVMFTrackSelectionExtensionInterface*, this); 504 iface = OSCL_STATIC_CAST(PVInterface*, myInterface); 505 } 506 else if (uuid == PVMF_DATA_SOURCE_INIT_INTERFACE_UUID) 507 { 508 PVMFDataSourceInitializationExtensionInterface* myInterface = OSCL_STATIC_CAST(PVMFDataSourceInitializationExtensionInterface*, this); 509 iface = OSCL_STATIC_CAST(PVInterface*, myInterface); 510 } 511 else if (uuid == KPVMFMetadataExtensionUuid) 512 { 513 PVMFMetadataExtensionInterface* myInterface = OSCL_STATIC_CAST(PVMFMetadataExtensionInterface*, this); 514 iface = OSCL_STATIC_CAST(PVInterface*, myInterface); 515 } 516 else if (uuid == PVMF_DATA_SOURCE_NODE_REGISRTY_INIT_INTERFACE_UUID) 517 { 518 PVMFDataSourceNodeRegistryInitInterface* myInterface = 519 OSCL_STATIC_CAST(PVMFDataSourceNodeRegistryInitInterface*, this); 520 iface = OSCL_STATIC_CAST(PVInterface*, myInterface); 521 } 522 else if (uuid == PvmfDataSourcePlaybackControlUuid) 523 { 524 PvmfDataSourcePlaybackControlInterface* myInterface = OSCL_STATIC_CAST(PvmfDataSourcePlaybackControlInterface*, this); 525 iface = OSCL_STATIC_CAST(PVInterface*, myInterface); 526 } 527 else if (uuid == PVMI_CAPABILITY_AND_CONFIG_PVUUID) 528 { 529 PvmiCapabilityAndConfig* myInterface = OSCL_STATIC_CAST(PvmiCapabilityAndConfig*, this); 530 iface = OSCL_STATIC_CAST(PVInterface*, myInterface); 531 } 532 else if (uuid == PVMFCPMPluginLicenseInterfaceUuid) 533 { 534 PVMFCPMPluginLicenseInterface* myInterface = OSCL_STATIC_CAST(PVMFCPMPluginLicenseInterface*, this); 535 iface = OSCL_STATIC_CAST(PVInterface*, myInterface); 536 } 537 else 538 { 539 return false; 540 } 541 542 ++iExtensionRefCount; 543 return true; 544} 545 546 547//public API from data source initialization interface 548PVMFStatus PVMFDownloadManagerNode::SetSourceInitializationData(OSCL_wString& aSourceURL, PVMFFormatType& aSourceFormat, OsclAny* aSourceData) 549{ 550 PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE, (0, "PVMFDownloadManagerNode::SetSourceInitializationData() called")); 551 552 //this method must be called before the Init command. 553 if (iInterfaceState != EPVMFNodeIdle && iInterfaceState != EPVMFNodeCreated) 554 return PVMFErrInvalidState; 555 556 557 // Pass the source info directly to the protocol engine node. 558 559 if (!iProtocolEngineNode.DataSourceInit()) 560 { 561 PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_ERR, (0, 562 "PVMFDownloadManagerNode:SetSourceInitializationData() Can't find datasourceinit interface in protocol engine subnode container.")); 563 return PVMFFailure; //no source init interface. 564 } 565 566 PVMFStatus status = (iProtocolEngineNode.DataSourceInit())->SetSourceInitializationData(aSourceURL, aSourceFormat, aSourceData); 567 if (status != PVMFSuccess) 568 return status; 569 570 if (!iProtocolEngineNode.ProtocolEngineExtension()) 571 { 572 PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_ERR, (0, 573 "PVMFDownloadManagerNode:SetSourceInitializationData() Can't get ProtocolEngineExtension interface from protocol subnode container.")); 574 return PVMFFailure; //no ProtocolNodeExtension interface. 575 } 576 577 bool socketConfigOK = (iProtocolEngineNode.ProtocolEngineExtension())->GetSocketConfig(iServerAddr); 578 if (!socketConfigOK) 579 { 580 PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_ERR, (0, 581 "PVMFDownloadManagerNode: SetSourceInitializationData() Call to GetSocketConfig() on protocol engine node returned failure.")); 582 return PVMFErrProcessing; 583 } 584 585 if (aSourceFormat == PVMF_MIME_DATA_SOURCE_HTTP_URL) 586 { 587 if (!aSourceData) 588 { 589 PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_ERR, (0, 590 "PVMFDownloadManagerNode:SetSourceInitializationData() Missing source data")); 591 return PVMFErrArgument; 592 } 593 PVInterface* pvinterface = (PVInterface*)aSourceData; 594 PVUuid uuid(PVMF_DOWNLOAD_DATASOURCE_HTTP_UUID); 595 PVInterface* temp = NULL; 596 if (pvinterface->queryInterface(uuid, temp)) 597 { 598 PVMFDownloadDataSourceHTTP* data = OSCL_STATIC_CAST(PVMFDownloadDataSourceHTTP*, temp); 599 //extract the download file name from the opaque data. 600 iDownloadFileName = data->iDownloadFileName; 601 602 //extract the playback mode 603 switch (data->iPlaybackControl) 604 { 605 case PVMFDownloadDataSourceHTTP::ENoPlayback: 606 iPlaybackMode = EDownloadOnly; 607 break; 608 case PVMFDownloadDataSourceHTTP::EAfterDownload: 609 iPlaybackMode = EDownloadThenPlay; 610 break; 611 case PVMFDownloadDataSourceHTTP::EAsap: 612 iPlaybackMode = EPlayAsap; 613 break; 614 615 case PVMFDownloadDataSourceHTTP::ENoSaveToFile: 616#if(PVMF_DOWNLOADMANAGER_SUPPORT_PPB) 617 iPlaybackMode = EPlaybackOnly; 618 break; 619#else 620 PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_ERR, (0, 621 "PVMFDownloadManagerNode:SetSourceInitializationData() NoSaveToFile is not supported!")); 622 return PVMFErrArgument;//unsupported mode. 623#endif//PVMF_DOWNLOADMANAGER_SUPPORT_PPB 624 625 default: 626 iPlaybackMode = EPlayAsap; 627 break; 628 } 629 } 630 else 631 { 632 PVUuid uuid(PVMF_SOURCE_CONTEXT_DATA_DOWNLOAD_HTTP_UUID); 633 temp = NULL; 634 if (pvinterface->queryInterface(uuid, temp)) 635 { 636 PVMFSourceContextDataDownloadHTTP* data = OSCL_STATIC_CAST(PVMFSourceContextDataDownloadHTTP*, temp); 637 //extract the download file name from the opaque data. 638 iDownloadFileName = data->iDownloadFileName; 639 640 //extract the playback mode 641 switch (data->iPlaybackControl) 642 { 643 case PVMFSourceContextDataDownloadHTTP::ENoPlayback: 644 iPlaybackMode = EDownloadOnly; 645 break; 646 case PVMFSourceContextDataDownloadHTTP::EAfterDownload: 647 iPlaybackMode = EDownloadThenPlay; 648 break; 649 case PVMFSourceContextDataDownloadHTTP::EAsap: 650 iPlaybackMode = EPlayAsap; 651 break; 652 653 case PVMFSourceContextDataDownloadHTTP::ENoSaveToFile: 654#if(PVMF_DOWNLOADMANAGER_SUPPORT_PPB) 655 iPlaybackMode = EPlaybackOnly; 656 break; 657#else 658 PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_ERR, (0, 659 "PVMFDownloadManagerNode:SetSourceInitializationData() NoSaveToFile is not supported!")); 660 return PVMFErrArgument;//unsupported mode. 661#endif//PVMF_DOWNLOADMANAGER_SUPPORT_PPB 662 663 default: 664 iPlaybackMode = EPlayAsap; 665 break; 666 } 667 } 668 else 669 {//invalid source data 670 return PVMFErrArgument; 671 } 672 } 673 } 674 else if (aSourceFormat == PVMF_MIME_DATA_SOURCE_PVX_FILE) 675 { 676 if (!aSourceData) 677 { 678 PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_ERR, (0, 679 "PVMFDownloadManagerNode:SetSourceInitializationData() Missing source data")); 680 return PVMFErrArgument; 681 } 682 PVInterface* pvinterface = (PVInterface*)aSourceData; 683 PVUuid uuid(PVMF_DOWNLOAD_DATASOURCE_PVX_UUID); 684 PVInterface* temp = NULL; 685 if (pvinterface->queryInterface(uuid, temp)) 686 { 687 PVMFDownloadDataSourcePVX* data = OSCL_STATIC_CAST(PVMFDownloadDataSourcePVX*, temp); 688 iDownloadFileName = data->iDownloadFileName; 689 //get the playback mode from the PVX info 690 switch (data->iPvxInfo.iPlaybackControl) 691 { 692 case CPVXInfo::ENoPlayback: 693 iPlaybackMode = EDownloadOnly; 694 break; 695 case CPVXInfo::EAfterDownload: 696 iPlaybackMode = EDownloadThenPlay; 697 break; 698 case CPVXInfo::EAsap: 699 iPlaybackMode = EPlayAsap; 700 break; 701 default: 702 iPlaybackMode = EPlayAsap; 703 break; 704 } 705 } 706 else 707 { 708 PVUuid uuid(PVMF_SOURCE_CONTEXT_DATA_DOWNLOAD_PVX_UUID); 709 temp = NULL; 710 if (pvinterface->queryInterface(uuid, temp)) 711 { 712 PVMFSourceContextDataDownloadPVX* data = OSCL_STATIC_CAST(PVMFSourceContextDataDownloadPVX*, temp); 713 iDownloadFileName = data->iDownloadFileName; 714 if (!data->iPvxInfo) 715 {//invalid source data 716 return PVMFErrArgument; 717 } 718 //get the playback mode from the PVX info 719 switch (data->iPvxInfo->iPlaybackControl) 720 { 721 case CPVXInfo::ENoPlayback: 722 iPlaybackMode = EDownloadOnly; 723 break; 724 case CPVXInfo::EAfterDownload: 725 iPlaybackMode = EDownloadThenPlay; 726 break; 727 case CPVXInfo::EAsap: 728 iPlaybackMode = EPlayAsap; 729 break; 730 default: 731 iPlaybackMode = EPlayAsap; 732 break; 733 } 734 } 735 else 736 {//invalid source data 737 return PVMFErrArgument; 738 } 739 } 740 } 741 else if (aSourceFormat == PVMF_MIME_DATA_SOURCE_SHOUTCAST_URL) 742 { 743 if (!aSourceData) 744 { 745 PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_ERR, (0, 746 "PVMFDownloadManagerNode:SetSourceInitializationData() Missing source data")); 747 return PVMFErrArgument; 748 } 749 PVInterface* pvinterface = (PVInterface*)aSourceData; 750 PVUuid uuid(PVMF_DOWNLOAD_DATASOURCE_HTTP_UUID); 751 PVInterface* temp = NULL; 752 if (pvinterface->queryInterface(uuid, temp)) 753 { 754 PVMFDownloadDataSourceHTTP* data = OSCL_STATIC_CAST(PVMFDownloadDataSourceHTTP*, temp); 755 756 //extract the download file name from the opaque data. 757 iDownloadFileName = data->iDownloadFileName; 758 759 //extract the playback mode 760 switch (data->iPlaybackControl) 761 { 762 case PVMFDownloadDataSourceHTTP::ENoSaveToFile: 763 764#if(PVMF_DOWNLOADMANAGER_SUPPORT_PPB) 765 iPlaybackMode = EPlaybackOnly; 766 break; 767#else 768 PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_ERR, (0, 769 "PVMFDownloadManagerNode:SetSourceInitializationData() NoSaveToFile is not supported!")); 770 return PVMFErrArgument;//unsupported mode. 771#endif//PVMF_DOWNLOADMANAGER_SUPPORT_PPB 772 773 default: 774 775 PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_ERR, (0, 776 "PVMFDownloadManagerNode:SetSourceInitializationData() Only NoSaveToFile mode is supported for PVMF_MIME_DATA_SOURCE_SHOUTCAST_URL!")); 777 return PVMFErrArgument;//unsupported mode. 778 break; 779 } 780 } 781 else 782 { 783 PVUuid uuid(PVMF_SOURCE_CONTEXT_DATA_DOWNLOAD_HTTP_UUID); 784 if (pvinterface->queryInterface(uuid, temp)) 785 { 786 PVMFSourceContextDataDownloadHTTP* data = OSCL_STATIC_CAST(PVMFSourceContextDataDownloadHTTP*, temp); 787 //extract the download file name from the opaque data. 788 iDownloadFileName = data->iDownloadFileName; 789 790 //extract the playback mode 791 switch (data->iPlaybackControl) 792 { 793 case PVMFSourceContextDataDownloadHTTP::ENoSaveToFile: 794 795#if(PVMF_DOWNLOADMANAGER_SUPPORT_PPB) 796 iPlaybackMode = EPlaybackOnly; 797 break; 798#else 799 PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_ERR, (0, 800 "PVMFDownloadManagerNode:SetSourceInitializationData() NoSaveToFile is not supported!")); 801 return PVMFErrArgument;//unsupported mode. 802#endif//PVMF_DOWNLOADMANAGER_SUPPORT_PPB 803 804 default: 805 PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_ERR, (0, 806 "PVMFDownloadManagerNode:SetSourceInitializationData() Only NoSaveToFile mode is supported for PVMF_MIME_DATA_SOURCE_SHOUTCAST_URL!")); 807 return PVMFErrArgument;//unsupported mode. 808 break; 809 } 810 } 811 else 812 {//invalid source data 813 return PVMFErrArgument; 814 } 815 } 816 } 817 else 818 { 819 PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_ERR, (0, 820 "PVMFDownloadManagerNode:SetSourceInitializationData() Unsupported source type")); 821 return PVMFErrArgument; 822 } 823 824#if(PVMF_DOWNLOADMANAGER_SUPPORT_PPB) 825 //Configure the MBDS 826 if (iPlaybackMode == EPlaybackOnly) 827 { 828 // make sure we have enough TCP buffers for PPB and shoutcast 829 if (aSourceFormat == PVMF_MIME_DATA_SOURCE_SHOUTCAST_URL) 830 { 831 // calculate MBDS cache size in bytes 832 // max bitrate in bytes per second * cache size in secs 833 uint32 bitRate = PVMF_DOWNLOADMANAGER_MAX_BITRATE_FOR_SC * 1000 / 8; 834 uint32 cacheSize = bitRate * PVMF_DOWNLOADMANAGER_CACHE_SIZE_FOR_SC_IN_SECONDS; 835 836 if (iSocketNode.iNode) 837 { 838 // TCP buffer size for shoutcast is 1564 (1500 data + 64 overhead) 839 // add 1 second margin 840 ((PVMFSocketNode*)iSocketNode.iNode)->SetMaxTCPRecvBufferCount((cacheSize + bitRate) / PVMF_DOWNLOADMANAGER_TCP_BUFFER_SIZE_FOR_SC); 841 842 ((PVMFSocketNode*)iSocketNode.iNode)->SetMaxTCPRecvBufferSize(PVMF_DOWNLOADMANAGER_TCP_BUFFER_SIZE_FOR_SC + PVMF_DOWNLOADMANAGER_TCP_BUFFER_OVERHEAD); 843 } 844 845 // Use Memory Buffer Data Stream for progressive playback and Shoutcast 846 iMemoryBufferDatastreamFactory = OSCL_NEW(PVMFMemoryBufferDataStream, (aSourceFormat, cacheSize)); 847 } 848 else 849 { 850 uint32 bufSize = PVMF_DOWNLOADMANAGER_TCP_BUFFER_SIZE_FOR_PPB; 851 if (iSocketNode.iNode) 852 { 853 ((PVMFSocketNode*)iSocketNode.iNode)->SetMaxTCPRecvBufferCount(PVMF_DOWNLOADMANAGER_MIN_TCP_BUFFERS_FOR_PPB); 854 // get buffer size 855 ((PVMFSocketNode*)iSocketNode.iNode)->GetMaxTCPRecvBufferSize(bufSize); 856 } 857 858 // MBDS cache size calculation 859 // TCP buffer size is 64000 (the default), assume worst case that the average packet size is 250 bytes 860 // Packet overhead is 64 bytes per packet 861 // 8 buffers will yield a cache of 305500, 13 buffers will yield a cache of 560500 862 uint32 totalPoolSizeMinusTwoBuffers = (PVMF_DOWNLOADMANAGER_MIN_TCP_BUFFERS_FOR_PPB - PVMF_DOWNLOADMANAGER_TCP_BUFFER_NOT_AVAILABLE) * bufSize; 863 uint32 numPacketsToFitInPool = totalPoolSizeMinusTwoBuffers / (PVMF_DOWNLOADMANAGER_TCP_AVG_SMALL_PACKET_SIZE + PVMF_DOWNLOADMANAGER_TCP_BUFFER_OVERHEAD); 864 uint32 maxDataMinusOverheadInPool = numPacketsToFitInPool * PVMF_DOWNLOADMANAGER_TCP_AVG_SMALL_PACKET_SIZE; 865 866 // Use Memory Buffer Data Stream for progressive playback and Shoutcast 867 iMemoryBufferDatastreamFactory = OSCL_NEW(PVMFMemoryBufferDataStream, (aSourceFormat, maxDataMinusOverheadInPool)); 868 } 869 870 OSCL_ASSERT(iMemoryBufferDatastreamFactory != NULL); 871 872 iReadFactory = iMemoryBufferDatastreamFactory->GetReadDataStreamFactoryPtr(); 873 iWriteFactory = iMemoryBufferDatastreamFactory->GetWriteDataStreamFactoryPtr(); 874 } 875 else 876#endif//PVMF_DOWNLOADMANAGER_SUPPORT_PPB 877 { 878 // Now that we have the download file name, we can instantiate the file buffer data stream object 879 // Create the filebuffer data stream factory 880 iFileBufferDatastreamFactory = OSCL_NEW(PVMFFileBufferDataStream, (iDownloadFileName)); 881 OSCL_ASSERT(iFileBufferDatastreamFactory != NULL); 882 iReadFactory = iFileBufferDatastreamFactory->GetReadDataStreamFactoryPtr(); 883 iWriteFactory = iFileBufferDatastreamFactory->GetWriteDataStreamFactoryPtr(); 884 } 885 886//save the source info 887 iSourceFormat = aSourceFormat; 888 iSourceURL = aSourceURL; 889 iSourceData = aSourceData; 890 891 return PVMFSuccess; 892} 893 894//public API from data source initialization interface 895PVMFStatus PVMFDownloadManagerNode::SetClientPlayBackClock(PVMFMediaClock* aClientClock) 896{ 897 PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE, (0, "PVMFDownloadManagerNode::SetClientPlayBackClock() called")); 898 899 iPlayBackClock = aClientClock; 900 if (iPlayBackClock) 901 { 902 iPlayBackClock->ConstructMediaClockNotificationsInterface(iClockNotificationsInf, *this); 903 } 904 905 if (iClockNotificationsInf != NULL) 906 { 907 iClockNotificationsInf->SetClockStateObserver(*this); 908 } 909 910 //pass the source info directly to the download node. 911 if (NULL == iProtocolEngineNode.DataSourceInit()) 912 return PVMFFailure;//no source init interface. 913 914 PVMFStatus status = (iProtocolEngineNode.DataSourceInit())->SetClientPlayBackClock(aClientClock); 915 916 return status; 917} 918 919//public API from data source initialization interface 920PVMFStatus PVMFDownloadManagerNode::SetEstimatedServerClock(PVMFMediaClock*) 921{ 922 //not needed for download. 923 return PVMFErrNotSupported; 924} 925 926PVMFDownloadManagerSubNodeContainer& PVMFDownloadManagerNode::TrackSelectNode() 927{ 928 //Decide which sub-node is supporting track selection. 929 if (iSourceFormat == PVMF_MIME_DATA_SOURCE_PVX_FILE) 930 { 931 //for pvx file, the PE node may or may not do track selection. 932 //the final decision isn't available until PE node prepare is done 933 //and we've queried for the TS interface, at which point the 934 //iNoPETrackSelect may be set. 935 if (iNoPETrackSelect) 936 return iFormatParserNode; 937 938 //if download is already complete, such as after a stop, then 939 //the parser node will do track selection. 940 if (iDownloadComplete && iPlaybackMode != EDownloadOnly) 941 return iFormatParserNode; 942 943 return iProtocolEngineNode; 944 } 945 else 946 { 947 //for 3gpp & shoutcast, parser does track selection. 948 return iFormatParserNode; 949 } 950} 951 952//Public API From track selection interface. 953PVMFStatus PVMFDownloadManagerNode::GetMediaPresentationInfo(PVMFMediaPresentationInfo& aInfo) 954{ 955 //this is assumed to happen only after node initialization. 956 if (iInterfaceState != EPVMFNodeInitialized && iInterfaceState != EPVMFNodePrepared) 957 return PVMFErrInvalidState; 958 959 if (TrackSelectNode().TrackSelection()) 960 return (TrackSelectNode().TrackSelection())->GetMediaPresentationInfo(aInfo); 961 else 962 return PVMFFailure; //no track selection interface! 963} 964 965//Public API From track selection interface. 966PVMFStatus PVMFDownloadManagerNode::SelectTracks(PVMFMediaPresentationInfo& aInfo) 967{ 968 //this needs to happen after initialization. 969 if (iInterfaceState != EPVMFNodeInitialized && iInterfaceState != EPVMFNodePrepared) 970 return PVMFErrInvalidState; 971 972 if (TrackSelectNode().TrackSelection()) 973 return (TrackSelectNode().TrackSelection())->SelectTracks(aInfo); 974 else 975 return PVMFFailure;//no track selection interface! 976} 977 978 979uint32 PVMFDownloadManagerNode::GetNumMetadataKeys(char* query_key) 980{ 981 PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE, (0, "PVMFDownloadManagerNode::GetNumMetadataKeys() called")); 982 if (iFormatParserNode.Metadata()) 983 { 984 return (iFormatParserNode.Metadata())->GetNumMetadataKeys(query_key); 985 } 986 return 0; 987} 988 989uint32 PVMFDownloadManagerNode::GetNumMetadataValues(PVMFMetadataList& aKeyList) 990{ 991 PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE, (0, "PVMFDownloadManagerNode::GetNumMetadataValues() called")); 992 if (iFormatParserNode.Metadata()) 993 { 994 return (iFormatParserNode.Metadata())->GetNumMetadataValues(aKeyList); 995 } 996 return 0; 997} 998 999 1000PVMFCommandId PVMFDownloadManagerNode::GetNodeMetadataKeys(PVMFSessionId aSessionId, PVMFMetadataList& aKeyList, uint32 starting_index, int32 max_entries, char* query_key, const OsclAny* aContext) 1001{ 1002 PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE, (0, "PVMFDownloadManagerNode::GetNodeMetadataKeys() called")); 1003 1004 PVMFDownloadManagerNodeCommand cmd; 1005 cmd.PVMFDownloadManagerNodeCommand::Construct(aSessionId, PVDLM_NODE_CMD_GETNODEMETADATAKEY, aKeyList, starting_index, max_entries, query_key, aContext); 1006 return QueueCommandL(cmd); 1007} 1008 1009 1010PVMFCommandId PVMFDownloadManagerNode::GetNodeMetadataValues(PVMFSessionId aSessionId, PVMFMetadataList& aKeyList, Oscl_Vector<PvmiKvp, OsclMemAllocator>& aValueList, uint32 starting_index, int32 max_entries, const OsclAny* aContext) 1011{ 1012 PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE, (0, "PVMFDownloadManagerNode::GetNodeMetadataValue() called")); 1013 1014 PVMFDownloadManagerNodeCommand cmd; 1015 cmd.PVMFDownloadManagerNodeCommand::Construct(aSessionId, PVDLM_NODE_CMD_GETNODEMETADATAVALUE, aKeyList, aValueList, starting_index, max_entries, aContext); 1016 return QueueCommandL(cmd); 1017} 1018 1019// From PVMFMetadataExtensionInterface 1020PVMFStatus PVMFDownloadManagerNode::ReleaseNodeMetadataKeys(PVMFMetadataList& keys, 1021 uint32 start , 1022 uint32 end) 1023{ 1024 PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE, (0, "PVMFDownloadManagerNode::ReleaseNodeMetadataKeys() called")); 1025 if (iFormatParserNode.Metadata()) 1026 { 1027 return iFormatParserNode.Metadata()->ReleaseNodeMetadataKeys(keys, start, end); 1028 } 1029 return PVMFFailure; 1030} 1031 1032// From PVMFMetadataExtensionInterface 1033PVMFStatus PVMFDownloadManagerNode::ReleaseNodeMetadataValues(Oscl_Vector<PvmiKvp, OsclMemAllocator>& aValueList, 1034 uint32 start, 1035 uint32 end) 1036{ 1037 PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE, (0, "PVMFDownloadManagerNode::ReleaseNodeMetadataValues() called")); 1038 1039 if (iFormatParserNode.Metadata()) 1040 { 1041 return iFormatParserNode.Metadata()->ReleaseNodeMetadataValues(aValueList, start, end); 1042 } 1043 return PVMFFailure; 1044} 1045 1046//public API from data source playback interface 1047PVMFCommandId PVMFDownloadManagerNode::SetDataSourcePosition(PVMFSessionId aSessionId, PVMFTimestamp aTargetNPT, 1048 PVMFTimestamp& aActualNPT, 1049 PVMFTimestamp& aActualMediaDataTS, 1050 bool aSeekToSyncPoint, 1051 uint32 aStreamID, 1052 OsclAny* aContext) 1053{ 1054 PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE, 1055 (0, "PVMFDownloadManagerNode::SetDataSourcePosition: aTargetNPT=%d, aSeekToSyncPoint=%d, aContext=0x%x", 1056 aTargetNPT, aSeekToSyncPoint, aContext)); 1057 1058 PVMFDownloadManagerNodeCommand cmd; 1059 cmd.PVMFDownloadManagerNodeCommand::Construct(aSessionId, PVDLM_NODE_CMD_SETDATASOURCEPOSITION, aTargetNPT, aActualNPT, 1060 aActualMediaDataTS, aSeekToSyncPoint, aStreamID, aContext); 1061 return QueueCommandL(cmd); 1062} 1063 1064PVMFCommandId PVMFDownloadManagerNode::QueryDataSourcePosition(PVMFSessionId aSessionId, 1065 PVMFTimestamp aTargetNPT, 1066 PVMFTimestamp& aSeekPointBeforeTargetNPT, 1067 PVMFTimestamp& aSeekPointAfterTargetNPT, 1068 OsclAny* aContextData, 1069 bool aSeekToSyncPoint) 1070{ 1071 OSCL_UNUSED_ARG(aSeekPointAfterTargetNPT); 1072 // Implemented to complete interface file definition 1073 // Not tested on logical plane 1074 PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE, 1075 (0, "PVMFDownloadManagerNode::QueryDataSourcePosition: aTargetNPT=%d, aSeekToSyncPoint=%d, aContext=0x%x", aTargetNPT, 1076 aContextData, aSeekToSyncPoint)); 1077 1078 PVMFDownloadManagerNodeCommand cmd; 1079 cmd.PVMFDownloadManagerNodeCommand::Construct(aSessionId, PVDLM_NODE_CMD_QUERYDATASOURCEPOSITION, aTargetNPT, aSeekPointBeforeTargetNPT, 1080 aSeekToSyncPoint, aContextData); 1081 return QueueCommandL(cmd); 1082} 1083 1084PVMFCommandId PVMFDownloadManagerNode::QueryDataSourcePosition(PVMFSessionId aSessionId, PVMFTimestamp aTargetNPT, 1085 PVMFTimestamp& aActualNPT, 1086 bool aSeekToSyncPoint, 1087 OsclAny* aContext) 1088{ 1089 PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE, 1090 (0, "PVMFDownloadManagerNode::QueryDataSourcePosition: aTargetNPT=%d, aSeekToSyncPoint=%d, aContext=0x%x", 1091 aTargetNPT, aSeekToSyncPoint, aContext)); 1092 1093 PVMFDownloadManagerNodeCommand cmd; 1094 cmd.PVMFDownloadManagerNodeCommand::Construct(aSessionId, PVDLM_NODE_CMD_QUERYDATASOURCEPOSITION, aTargetNPT, aActualNPT, 1095 aSeekToSyncPoint, aContext); 1096 return QueueCommandL(cmd); 1097} 1098 1099 1100PVMFCommandId PVMFDownloadManagerNode::SetDataSourceRate(PVMFSessionId aSessionId, int32 aRate, PVMFTimebase* aTimebase, OsclAny* aContext) 1101{ 1102 PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE, 1103 (0, "PVMFDownloadManagerNode::SetDataSourceRate: aRate=%d", aRate)); 1104 1105 PVMFDownloadManagerNodeCommand cmd; 1106 cmd.PVMFDownloadManagerNodeCommand::Construct(aSessionId, PVDLM_NODE_CMD_SETDATASOURCERATE, aRate, aTimebase, aContext); 1107 return QueueCommandL(cmd); 1108} 1109 1110PVMFStatus PVMFDownloadManagerNode::SetPlayerNodeRegistry(PVPlayerNodeRegistryInterface* aRegistry) 1111{ 1112 iPlayerNodeRegistry = aRegistry; 1113 return PVMFSuccess; 1114} 1115 1116void PVMFDownloadManagerNode::Run() 1117{ 1118 //Process async node commands. 1119 if (!iInputCommands.empty()) 1120 ProcessCommand(); 1121 1122 //Issue commands to the sub-nodes. 1123 if (!iProtocolEngineNode.CmdPending() 1124 && !iFormatParserNode.CmdPending() 1125 && !iSocketNode.CmdPending() 1126 && !iRecognizerNode.CmdPending() 1127 && !iSubNodeCmdVec.empty()) 1128 { 1129 PVMFStatus status = iSubNodeCmdVec.front().iNC->IssueCommand(iSubNodeCmdVec.front().iCmd); 1130 if (status != PVMFPending) 1131 iSubNodeCmdVec.front().iNC->CommandDone(status, NULL, NULL); 1132 } 1133} 1134 1135PVMFCommandId PVMFDownloadManagerNode::QueueCommandL(PVMFDownloadManagerNodeCommand& aCmd) 1136{ 1137 //add a command to the async node command queue and return command ID 1138 1139 PVMFCommandId id = iInputCommands.AddL(aCmd); 1140 1141 // Wakeup the AO 1142 RunIfNotReady(); 1143 1144 PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, CMD_LOG_LEVEL, (0, "PVMFDownloadManagerNode::QueueCommandL() returning %d", id)); 1145 1146 return id; 1147} 1148 1149void PVMFDownloadManagerNode::ProcessCommand() 1150{ 1151 //This call will process the first node command in the input queue. 1152 1153 1154 //Can't do anything when an asynchronous cancel is in progress -- just need to wait on completion. 1155 if (!iCancelCommand.empty()) 1156 return; //keep waiting. 1157 1158 //If a command is in progress, only a hi-pri command can interrupt it. 1159 if (!iCurrentCommand.empty() 1160 && !iInputCommands.front().hipri() 1161 ) 1162 { 1163 return; //keep waiting 1164 } 1165 1166 //The newest or highest pri command is in the front of the queue. 1167 OSCL_ASSERT(!iInputCommands.empty()); 1168 PVMFDownloadManagerNodeCommand& aCmd = iInputCommands.front(); 1169 1170 PVMFStatus cmdstatus; 1171 if (aCmd.hipri()) 1172 { 1173 //Process the Hi-Pri commands. 1174 switch (aCmd.iCmd) 1175 { 1176 case PVMF_GENERIC_NODE_CANCELALLCOMMANDS: 1177 cmdstatus = DoCancelAllCommands(aCmd); 1178 break; 1179 1180 case PVMF_GENERIC_NODE_CANCELCOMMAND: 1181 cmdstatus = DoCancelCommand(aCmd); 1182 break; 1183 1184 case PVDLM_NODE_CMD_CANCEL_GET_LICENSE: 1185 cmdstatus = DoCancelGetLicense(aCmd); 1186 break; 1187 1188 default: 1189 cmdstatus = PVMFErrNotSupported; 1190 break; 1191 } 1192 1193 //If completion is pending, move the command from 1194 //the input queue to the cancel queue. 1195 //This is necessary since the input queue could get 1196 //rearranged by new commands coming in. 1197 if (cmdstatus == PVMFPending) 1198 { 1199 iCancelCommand.StoreL(aCmd); 1200 iInputCommands.Erase(&aCmd); 1201 } 1202 } 1203 else 1204 { 1205 //Process the normal pri commands. 1206 switch (aCmd.iCmd) 1207 { 1208 case PVMF_GENERIC_NODE_QUERYUUID: 1209 cmdstatus = DoQueryUuid(aCmd); 1210 break; 1211 1212 case PVMF_GENERIC_NODE_QUERYINTERFACE: 1213 cmdstatus = DoQueryInterface(aCmd); 1214 break; 1215 1216 case PVMF_GENERIC_NODE_REQUESTPORT: 1217 cmdstatus = DoRequestPort(aCmd); 1218 break; 1219 1220 case PVMF_GENERIC_NODE_RELEASEPORT: 1221 cmdstatus = DoReleasePort(aCmd); 1222 break; 1223 1224 case PVMF_GENERIC_NODE_INIT: 1225 cmdstatus = DoInitNode(aCmd); 1226 break; 1227 1228 case PVMF_GENERIC_NODE_PREPARE: 1229 cmdstatus = DoPrepareNode(aCmd); 1230 break; 1231 1232 case PVMF_GENERIC_NODE_START: 1233 cmdstatus = DoStartNode(aCmd); 1234 break; 1235 1236 case PVMF_GENERIC_NODE_STOP: 1237 cmdstatus = DoStopNode(aCmd); 1238 break; 1239 1240 case PVMF_GENERIC_NODE_FLUSH: 1241 cmdstatus = DoFlushNode(aCmd); 1242 break; 1243 1244 case PVMF_GENERIC_NODE_PAUSE: 1245 cmdstatus = DoPauseNode(aCmd); 1246 break; 1247 1248 case PVMF_GENERIC_NODE_RESET: 1249 cmdstatus = DoResetNode(aCmd); 1250 break; 1251 1252 case PVDLM_NODE_CMD_GETNODEMETADATAKEY: 1253 cmdstatus = DoGetNodeMetadataKey(aCmd); 1254 break; 1255 1256 case PVDLM_NODE_CMD_GETNODEMETADATAVALUE: 1257 cmdstatus = DoGetNodeMetadataValue(aCmd); 1258 break; 1259 1260 case PVDLM_NODE_CMD_SETDATASOURCEPOSITION: 1261 cmdstatus = DoSetDataSourcePosition(aCmd); 1262 break; 1263 1264 case PVDLM_NODE_CMD_QUERYDATASOURCEPOSITION: 1265 cmdstatus = DoQueryDataSourcePosition(aCmd); 1266 break; 1267 1268 case PVDLM_NODE_CMD_SETDATASOURCERATE: 1269 // Rate change not supported for download 1270 cmdstatus = PVMFErrNotSupported; 1271 break; 1272 1273 case PVDLM_NODE_CMD_GET_LICENSE_W: 1274 cmdstatus = DoGetLicense(aCmd, true); 1275 break; 1276 1277 case PVDLM_NODE_CMD_GET_LICENSE: 1278 cmdstatus = DoGetLicense(aCmd); 1279 break; 1280 1281 default: 1282 OSCL_ASSERT(false); 1283 cmdstatus = PVMFFailure; 1284 break; 1285 } 1286 1287 //If completion is pending, move the command from the input queue to the current command. 1288 //This is necessary since the input queue could get rearranged by new commands coming in. 1289 if (cmdstatus == PVMFPending) 1290 { 1291 iCurrentCommand.StoreL(aCmd); 1292 iInputCommands.Erase(&aCmd); 1293 } 1294 } 1295 1296 if (cmdstatus != PVMFPending) 1297 CommandComplete(iInputCommands, aCmd, cmdstatus, NULL, NULL); 1298} 1299 1300void PVMFDownloadManagerNode::CommandComplete(PVMFDownloadManagerNodeCmdQueue& aCmdQ, PVMFDownloadManagerNodeCommand& aCmd, PVMFStatus aStatus, 1301 PVInterface*aExtMsg, OsclAny* aEventData) 1302{ 1303 //Complete a node command 1304 1305 PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, CMD_LOG_LEVEL, (0, "PVMFDownloadManagerNode::CommandComplete() In Id %d Cmd %d Status %d Context %d Data %d", 1306 aCmd.iId, aCmd.iCmd, aStatus, aCmd.iContext, aEventData)); 1307 1308 if (aStatus != PVMFSuccess) 1309 { 1310 PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, CMD_LOG_LEVEL, 1311 (0, "PVMFDownloadManagerNode::CommandComplete() Failure!")); 1312 } 1313 1314 //if the command failed or was cancelled there may be un-processed sub-node commands, so clear the vector now. 1315 if (!iSubNodeCmdVec.empty()) 1316 iSubNodeCmdVec.clear(); 1317 1318 //We may need to wait on the movie atom before the node cmd can complete. 1319 //This is a good place to catch that condition and suppress the node 1320 //cmd completion. 1321 if (iParserInitAfterMovieAtom 1322 || iParserPrepareAfterMovieAtom) 1323 { 1324 if (aStatus == PVMFSuccess) 1325 { 1326 PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE, 1327 (0, "PVMFDownloadManagerNode::CommandComplete() Blocking Command Completion until Movie Atom Downloaded.")); 1328 return;//keep waiting on movie atom complete. 1329 } 1330 else 1331 { 1332 //if command failed or was cancelled then clear any movie atom wait 1333 //flags. 1334 iParserInitAfterMovieAtom = false; 1335 iParserPrepareAfterMovieAtom = false; 1336 } 1337 } 1338 1339 //Do the post-command state changes and anything else. 1340 if (aStatus == PVMFSuccess) 1341 { 1342 switch (aCmd.iCmd) 1343 { 1344 case PVMF_GENERIC_NODE_INIT: 1345 ChangeNodeState(EPVMFNodeInitialized); 1346 break; 1347 case PVMF_GENERIC_NODE_PREPARE: 1348 ChangeNodeState(EPVMFNodePrepared); 1349 break; 1350 case PVMF_GENERIC_NODE_START: 1351 ChangeNodeState(EPVMFNodeStarted); 1352 break; 1353 case PVMF_GENERIC_NODE_PAUSE: 1354 ChangeNodeState(EPVMFNodePaused); 1355 break; 1356 case PVMF_GENERIC_NODE_STOP: 1357 ChangeNodeState(EPVMFNodePrepared); 1358 break; 1359 case PVMF_GENERIC_NODE_FLUSH: 1360 ChangeNodeState(EPVMFNodePrepared); 1361 break; 1362 case PVMF_GENERIC_NODE_RESET: 1363 //drive this node back to Created state. 1364 ChangeNodeState(EPVMFNodeIdle); 1365 break; 1366 } 1367 } 1368 1369 //create response 1370 PVMFCmdResp resp(aCmd.iId, aCmd.iContext, aStatus, aExtMsg, aEventData); 1371 PVMFSessionId session = aCmd.iSession; 1372 1373 //Erase the command from the queue. 1374 aCmdQ.Erase(&aCmd); 1375 1376 //Report completion to the session observer. 1377 ReportCmdCompleteEvent(session, resp); 1378 1379 //re-schedule if there are more commands and node isn't logged off 1380 if (!iInputCommands.empty() 1381 && IsAdded()) 1382 RunIfNotReady(); 1383} 1384 1385 1386void PVMFDownloadManagerNode::ReportErrorEvent(PVMFEventType aEventType, PVInterface*aExtMsg, OsclAny* aEventData) 1387{ 1388 //Report a node error event 1389 1390 PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE, (0, "PVMFDownloadManagerNode::ReportErrorEvent() In Type %d Data %d ExtMsg %d", 1391 aEventType, aEventData, aExtMsg)); 1392 1393 PVMFNodeInterface::ReportErrorEvent(aEventType, aEventData, aExtMsg); 1394} 1395 1396 1397void PVMFDownloadManagerNode::ReportInfoEvent(PVMFAsyncEvent &aEvent) 1398{ 1399 //Report a node info event 1400 1401 PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE, (0, "PVMFDownloadManagerNode::ReportInfoEvent() In Type %d Data %d ExtMsg %d", 1402 aEvent.GetEventType(), aEvent.GetEventData(), aEvent.GetEventExtensionInterface())); 1403 1404 PVMFNodeInterface::ReportInfoEvent(aEvent); 1405 1406 //For download-then-play mode, generate data ready event when buffering 1407 //is complete. We will have suppressed the real initial data ready 1408 //event from PE node in this case. 1409 if (aEvent.GetEventType() == PVMFInfoBufferingComplete 1410 && iPlaybackMode == PVMFDownloadManagerNode::EDownloadThenPlay 1411 && !iDataReady) 1412 { 1413 GenerateDataReadyEvent(); 1414 } 1415 else if (aEvent.GetEventType() == PVMFInfoContentType) 1416 { 1417 // copy and save MIME string for recognizer to use as hint 1418 iContentTypeMIMEString = (char *)aEvent.GetEventData(); 1419 } 1420} 1421 1422void PVMFDownloadManagerNode::GenerateDataReadyEvent() 1423{ 1424 PVMFAsyncEvent info(PVMFInfoEvent, PVMFInfoDataReady, NULL, NULL); 1425 ReportInfoEvent(info); 1426 iDataReady = true; 1427} 1428 1429bool PVMFDownloadManagerNode::FilterPlaybackEventsFromSubNodes(const PVMFAsyncEvent& aEvent) 1430{ 1431 switch (aEvent.GetEventType()) 1432 { 1433 case PVMFInfoUnderflow: 1434 //filter any underflow that happens before data ready 1435 if (!iDataReady) 1436 return true; 1437 else 1438 iDataReady = false; 1439 break; 1440 case PVMFInfoDataReady: 1441 //filter any data ready that happens before download complete 1442 //in dl-then-play mode 1443 if (iPlaybackMode == EDownloadThenPlay 1444 && !iDownloadComplete) 1445 { 1446 return true; 1447 } 1448 //filter any data ready in dl-only mode, though I don't 1449 //think it's possible. 1450 if (iPlaybackMode == EDownloadOnly) 1451 return true; 1452 1453 iDataReady = true; 1454 1455 break; 1456 case PVMFInfoRemoteSourceNotification: 1457 //we get this event for "not pseudostreamable" for both PVX 1458 //and 3gpp. Only pass it up for 3gpp. 1459 if (iSourceFormat != PVMF_MIME_DATA_SOURCE_HTTP_URL) 1460 return true; 1461 break; 1462 default: 1463 break; 1464 } 1465 return false; 1466} 1467 1468void PVMFDownloadManagerNode::ChangeNodeState(TPVMFNodeInterfaceState aNewState) 1469{ 1470 //Update the node state 1471 1472 PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE, (0, "PVMFDownloadManagerNode::ChangeNodeState() Old %d New %d", iInterfaceState, aNewState)); 1473 1474 PVMFNodeInterface::SetState(aNewState); 1475} 1476 1477 1478PVMFStatus PVMFDownloadManagerNode::DoQueryUuid(PVMFDownloadManagerNodeCommand& aCmd) 1479{ 1480 //Start executing a node command 1481 1482 PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE, (0, "PVMFDownloadManagerNode::DoQueryUuid() In")); 1483 1484 OSCL_String* mimetype; 1485 Oscl_Vector<PVUuid, OsclMemAllocator> *uuidvec; 1486 bool exactmatch; 1487 aCmd.PVMFDownloadManagerNodeCommandBase::Parse(mimetype, uuidvec, exactmatch); 1488 1489 // @TODO Add MIME string matching 1490 // For now just return all available extension interface UUID 1491 uuidvec->push_back(PVMF_TRACK_SELECTION_INTERFACE_UUID); 1492 uuidvec->push_back(PVMF_DATA_SOURCE_INIT_INTERFACE_UUID); 1493 uuidvec->push_back(KPVMFMetadataExtensionUuid); 1494 uuidvec->push_back(PvmfDataSourcePlaybackControlUuid); 1495 uuidvec->push_back(PVMI_CAPABILITY_AND_CONFIG_PVUUID); 1496 1497 return PVMFSuccess; 1498} 1499 1500 1501PVMFStatus PVMFDownloadManagerNode::DoQueryInterface(PVMFDownloadManagerNodeCommand& aCmd) 1502{ 1503 //Start executing a node command 1504 1505 PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE, (0, "PVMFDownloadManagerNode::DoQueryInterface() In")); 1506 1507 PVUuid* uuid; 1508 PVInterface** ptr; 1509 aCmd.PVMFDownloadManagerNodeCommandBase::Parse(uuid, ptr); 1510 1511 if (queryInterface(*uuid, *ptr)) 1512 { 1513 //Schedule further queries on sub-nodes... 1514 return ScheduleSubNodeCommands(aCmd); 1515 } 1516 else 1517 { 1518 //interface not supported 1519 *ptr = NULL; 1520 return PVMFFailure; 1521 } 1522} 1523 1524PVMFStatus PVMFDownloadManagerNode::DoRequestPort(PVMFDownloadManagerNodeCommand& aCmd) 1525{ 1526 //Start executing a node command 1527 1528 PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE, (0, "PVMFDownloadManagerNode::DoRequestPort() In")); 1529 1530 if (iInterfaceState != EPVMFNodePrepared) 1531 return PVMFErrInvalidState; 1532 1533 return ScheduleSubNodeCommands(aCmd); 1534} 1535 1536PVMFStatus PVMFDownloadManagerNode::DoReleasePort(PVMFDownloadManagerNodeCommand& aCmd) 1537{ 1538 //Start executing a node command 1539 1540 PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE, (0, "PVMFDownloadManagerNode::DoReleasePort() In")); 1541 1542 return ScheduleSubNodeCommands(aCmd); 1543} 1544 1545PVMFStatus PVMFDownloadManagerNode::DoInitNode(PVMFDownloadManagerNodeCommand& aCmd) 1546{ 1547 //Start executing a node command 1548 1549 PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE, (0, "PVMFDownloadManagerNode::DoInitNode() In")); 1550 1551 if (iInterfaceState != EPVMFNodeIdle) 1552 return PVMFErrInvalidState; 1553 1554 return ScheduleSubNodeCommands(aCmd); 1555} 1556 1557PVMFStatus PVMFDownloadManagerNode::DoPrepareNode(PVMFDownloadManagerNodeCommand& aCmd) 1558{ 1559 //Start executing a node command 1560 1561 PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE, (0, "PVMFDownloadManagerNode::DoPrepareNode() In")); 1562 1563 if (iInterfaceState != EPVMFNodeInitialized) 1564 return PVMFErrInvalidState; 1565 1566 return ScheduleSubNodeCommands(aCmd); 1567} 1568 1569PVMFStatus PVMFDownloadManagerNode::DoStartNode(PVMFDownloadManagerNodeCommand& aCmd) 1570{ 1571 //Start executing a node command 1572 1573 PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE, (0, "PVMFDownloadManagerNode::DoStartNode() In")); 1574 1575 if (iInterfaceState != EPVMFNodePrepared 1576 && iInterfaceState != EPVMFNodePaused) 1577 return PVMFErrInvalidState; 1578 1579 return ScheduleSubNodeCommands(aCmd); 1580} 1581 1582PVMFStatus PVMFDownloadManagerNode::DoStopNode(PVMFDownloadManagerNodeCommand& aCmd) 1583{ 1584 //Start executing a node command 1585 1586 PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE, (0, "PVMFDownloadManagerNode::DoStopNode() In")); 1587 1588 if (iInterfaceState != EPVMFNodeStarted 1589 && iInterfaceState != EPVMFNodePaused 1590 && iInterfaceState != EPVMFNodeError)//allow a stop in error state. 1591 return PVMFErrInvalidState; 1592 1593 return ScheduleSubNodeCommands(aCmd); 1594} 1595 1596PVMFStatus PVMFDownloadManagerNode::DoFlushNode(PVMFDownloadManagerNodeCommand& aCmd) 1597{ 1598 //Start executing a node command 1599 1600 PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE, (0, "PVMFDownloadManagerNode::DoFlushNode() In")); 1601 1602 if (iInterfaceState != EPVMFNodeStarted 1603 && iInterfaceState != EPVMFNodePaused) 1604 return PVMFErrInvalidState; 1605 1606 return ScheduleSubNodeCommands(aCmd); 1607} 1608 1609PVMFStatus PVMFDownloadManagerNode::DoPauseNode(PVMFDownloadManagerNodeCommand& aCmd) 1610{ 1611 //Start executing a node command 1612 1613 PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE, (0, "PVMFDownloadManagerNode::DoPauseNode() In")); 1614 1615 if (iInterfaceState != EPVMFNodeStarted) 1616 return PVMFErrInvalidState; 1617 1618 return ScheduleSubNodeCommands(aCmd); 1619} 1620 1621PVMFStatus PVMFDownloadManagerNode::DoResetNode(PVMFDownloadManagerNodeCommand& aCmd) 1622{ 1623 //remove the clock observer 1624 if (iPlayBackClock != NULL) 1625 { 1626 if (iClockNotificationsInf != NULL) 1627 { 1628 iClockNotificationsInf->RemoveClockStateObserver(*this); 1629 iPlayBackClock->DestroyMediaClockNotificationsInterface(iClockNotificationsInf); 1630 iClockNotificationsInf = NULL; 1631 } 1632 } 1633 1634 //Start executing a node command 1635 PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE, (0, "PVMFDownloadManagerNode::DoResetNode() In")); 1636 1637 //Reset the sub-nodes first. 1638 return ScheduleSubNodeCommands(aCmd); 1639} 1640 1641PVMFStatus PVMFDownloadManagerNode::DoCancelAllCommands(PVMFDownloadManagerNodeCommand& aCmd) 1642{ 1643 OSCL_UNUSED_ARG(aCmd); 1644 //Start executing a node command 1645 1646 PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE, (0, "PVMFDownloadManagerNode::DoCancelAllCommands() In")); 1647 1648 //first cancel the current command if any 1649 while (!iCurrentCommand.empty()) 1650 { 1651 if (iFormatParserNode.CancelPendingCommand() 1652 || iProtocolEngineNode.CancelPendingCommand() 1653 || iSocketNode.CancelPendingCommand() 1654 || iRecognizerNode.CancelPendingCommand() 1655 ) 1656 { 1657 return PVMFPending;//wait on sub-node cancel to complete. 1658 } 1659 CommandComplete(iCurrentCommand, iCurrentCommand.front(), PVMFErrCancelled, NULL, NULL); 1660 } 1661 1662 //next cancel all queued commands 1663 //start at element 1 since this cancel command is element 0. 1664 while (iInputCommands.size() > 1) 1665 { 1666 CommandComplete(iInputCommands, iInputCommands[1], PVMFErrCancelled, NULL, NULL); 1667 } 1668 1669 return PVMFSuccess; 1670} 1671 1672PVMFStatus PVMFDownloadManagerNode::DoCancelCommand(PVMFDownloadManagerNodeCommand& aCmd) 1673{ 1674 //Start executing a node command 1675 1676 PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE, (0, "PVMFDownloadManagerNode::DoCancelCommand() In")); 1677 1678 //extract the command ID from the parameters. 1679 PVMFCommandId id; 1680 aCmd.PVMFDownloadManagerNodeCommandBase::Parse(id); 1681 1682 //first check "current" command if any 1683 PVMFDownloadManagerNodeCommand* cmd = iCurrentCommand.FindById(id); 1684 if (cmd) 1685 { 1686 if (iFormatParserNode.CancelPendingCommand() 1687 || iProtocolEngineNode.CancelPendingCommand() 1688 || iRecognizerNode.CancelPendingCommand() 1689 ) 1690 { 1691 return PVMFPending;//wait on sub-node cancel to complete. 1692 } 1693 CommandComplete(iCurrentCommand, *cmd, PVMFErrCancelled, NULL, NULL); 1694 return PVMFSuccess; 1695 } 1696 1697 //next check input queue. 1698 //start at element 1 since this cancel command is element 0. 1699 cmd = iInputCommands.FindById(id, 1); 1700 if (cmd) 1701 { 1702 //cancel the queued command 1703 CommandComplete(iInputCommands, *cmd, PVMFErrCancelled, NULL, NULL); 1704 //report cancel success 1705 return PVMFSuccess; 1706 } 1707 1708 //if we get here the command isn't queued so the cancel fails. 1709 return PVMFFailure; 1710} 1711 1712 1713PVMFStatus PVMFDownloadManagerNode::DoGetNodeMetadataKey(PVMFDownloadManagerNodeCommand& aCmd) 1714{ 1715 //Start executing a node command 1716 1717 PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE, (0, "PVMFDownloadManagerNode::DoGetNodeMetadataKey() In")); 1718 1719 return ScheduleSubNodeCommands(aCmd); 1720} 1721 1722 1723 1724PVMFStatus PVMFDownloadManagerNode::DoGetNodeMetadataValue(PVMFDownloadManagerNodeCommand& aCmd) 1725{ 1726 //Start executing a node command 1727 1728 PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE, (0, "PVMFDownloadManagerNode::DoGetNodeMetadataValue() In")); 1729 1730 return ScheduleSubNodeCommands(aCmd); 1731} 1732 1733 1734 1735PVMFStatus PVMFDownloadManagerNode::DoSetDataSourcePosition(PVMFDownloadManagerNodeCommand& aCmd) 1736{ 1737 //Start executing a node command 1738 1739 PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE, (0, "PVMFDownloadManagerNode::DoSetDataSourcePosition() In")); 1740 1741 return ScheduleSubNodeCommands(aCmd); 1742} 1743 1744 1745PVMFStatus PVMFDownloadManagerNode::DoQueryDataSourcePosition(PVMFDownloadManagerNodeCommand& aCmd) 1746{ 1747 //Start executing a node command 1748 1749 PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE, (0, "PVMFDownloadManagerNode::DoQueryDataSourcePosition() In")); 1750 1751 return ScheduleSubNodeCommands(aCmd); 1752} 1753 1754void PVMFDownloadManagerNode::ContinueInitAfterTrackSelectDecision() 1755{ 1756 //this is called during the Init sequence, once we have enough information 1757 //to make a definite track select decision. 1758 1759 //See whether we need to stop to allow track selection on the download server. 1760 //If it's download-only, we don't offer this option, since the download must 1761 //be started in the Init. 1762 if (iPlaybackMode != EDownloadOnly 1763 && TrackSelectNode().iType == PVMFDownloadManagerSubNodeContainerBase::EProtocolEngine) 1764 { 1765 //stop the Init sequence here so we can do track selection on the download 1766 //server. 1767 ; 1768 } 1769 else 1770 { 1771 //else download-only, or there's no track selection available from the 1772 //PE node. Continue the Init or Prepare sequence. 1773 ContinueFromDownloadTrackSelectionPoint(); 1774 } 1775} 1776 1777void PVMFDownloadManagerNode::ContinueFromDownloadTrackSelectionPoint() 1778{ 1779 //Continue the Init or Prepare sequence, stopping at parser init. 1780 1781 //start the download. 1782 Push(iProtocolEngineNode, PVMFDownloadManagerSubNodeContainerBase::EStart); 1783 1784 //initiate file recognize & parse, unless this is download-only mode. 1785 if (iPlaybackMode != EDownloadOnly) 1786 { 1787 //do recognizer sequence if needed. 1788 if (iSourceFormat == PVMF_MIME_DATA_SOURCE_PVX_FILE) 1789 { 1790 //PXV is always assumed to be MP4 1791 PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE, (0, 1792 "PVMFDownloadManagerNode::ContinueFromDownloadTrackSelectionPoint Setting format to MP4")); 1793 iMimeType = PVMF_MIME_MPEG4FF; 1794 } 1795 else 1796 { 1797 //for other source formats, use the recognizer to determine the format. 1798 Push(iRecognizerNode, PVMFDownloadManagerSubNodeContainerBase::ERecognizerStart); 1799 Push(iRecognizerNode, PVMFDownloadManagerSubNodeContainerBase::ERecognizerClose); 1800 } 1801 1802 //create parser 1803 Push(iFormatParserNode, PVMFDownloadManagerSubNodeContainerBase::EParserCreate); 1804 1805 // Send commands to the parser node to query these extension interfaces. 1806 Push(iFormatParserNode, PVMFDownloadManagerSubNodeContainerBase::EQueryDataSourceInit); 1807 Push(iFormatParserNode, PVMFDownloadManagerSubNodeContainerBase::EQueryTrackSelection); 1808 Push(iFormatParserNode, PVMFDownloadManagerSubNodeContainerBase::EQueryMetadata); 1809 Push(iFormatParserNode, PVMFDownloadManagerSubNodeContainerBase::EQueryDatastreamUser); 1810 Push(iFormatParserNode, PVMFDownloadManagerSubNodeContainerBase::EQueryDataSourcePlayback); 1811 Push(iFormatParserNode, PVMFDownloadManagerSubNodeContainerBase::EQueryFFProgDownload); 1812 Push(iProtocolEngineNode, PVMFDownloadManagerSubNodeContainerBase::ESetFFProgDownloadSupport); 1813 Push(iFormatParserNode, PVMFDownloadManagerSubNodeContainerBase::ECPMQueryLicenseInterface); 1814 1815 //if this is PVX, we need to wait on movie atom before we can 1816 //init parser. 1817 if (iSourceFormat == PVMF_MIME_DATA_SOURCE_PVX_FILE) 1818 { 1819 if (iMovieAtomComplete || iDownloadComplete) 1820 { 1821 iParserInit = true; 1822 Push(iFormatParserNode, PVMFDownloadManagerSubNodeContainerBase::EInit); 1823 } 1824 else 1825 { 1826 PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE, (0, 1827 "PVMFDownloadManagerNode::ContinueFromDownloadTrackSelectionPoint Setting flag to Init Parser after Movie Atom Downloaded")); 1828 //set this flag to trigger parser init when movie atom is done. 1829 iParserInitAfterMovieAtom = true; 1830 } 1831 } 1832 else 1833 { 1834 //for other formats, go ahead and init parser. Init will block until 1835 //receiving movie atom. 1836 iParserInit = true; 1837 Push(iFormatParserNode, PVMFDownloadManagerSubNodeContainerBase::EInit); 1838 } 1839 } 1840} 1841 1842//Called when movie atom is received, or when download is complete 1843//but movie atom was never received. 1844void PVMFDownloadManagerNode::ContinueAfterMovieAtom() 1845{ 1846 PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE, 1847 (0, "PVMFDownloadManagerNode::ContinueAfterMovieAtom() ")); 1848 1849 if (!iMovieAtomComplete) 1850 { 1851 iMovieAtomComplete = true; 1852 //see whether we need to continue with parser init 1853 if (iParserInitAfterMovieAtom) 1854 { 1855 PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE, 1856 (0, "PVMFDownloadManagerNode::ContinueAfterMovieAtom() Continuing to Parser Init")); 1857 iParserInitAfterMovieAtom = false; 1858 iParserInit = true; 1859 Push(iFormatParserNode, PVMFDownloadManagerSubNodeContainerBase::EInit); 1860 RunIfNotReady(); 1861 } 1862 //see whether we need to continue with parser prepare 1863 if (iParserPrepareAfterMovieAtom) 1864 { 1865 PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE, 1866 (0, "PVMFDownloadManagerNode::ContinueAfterMovieAtom() Continuing to Parser Prepare")); 1867 iParserPrepareAfterMovieAtom = false; 1868 Push(iFormatParserNode, PVMFDownloadManagerSubNodeContainerBase::EPrepare); 1869 RunIfNotReady(); 1870 } 1871 } 1872} 1873 1874PVMFNodeInterface* PVMFDownloadManagerNode::CreateParser() 1875{ 1876 if (!(iMimeType == PVMF_MIME_FORMAT_UNKNOWN)) 1877 { 1878 PVMFNodeInterface *iSourceNode = NULL; 1879 PVMFFormatType outputFormatType = PVMF_MIME_FORMAT_UNKNOWN; 1880 iFmt = iMimeType.get_str(); 1881 PVMFStatus status = 1882 iPlayerNodeRegistry->QueryRegistry(iFmt, outputFormatType, iDNodeUuids); 1883 if ((status == PVMFSuccess) && (iDNodeUuids.size() > 0)) 1884 { 1885 int32 leavecode = 0; 1886 OSCL_TRY(leavecode, iSourceNode = iPlayerNodeRegistry->CreateNode(iDNodeUuids[iDNodeUuidCount])); 1887 OSCL_FIRST_CATCH_ANY(leavecode, return NULL); 1888 iDNodeUuidCount++; 1889 return iSourceNode; 1890 } 1891 } 1892 return NULL; 1893} 1894 1895PVMFStatus PVMFDownloadManagerNode::ScheduleSubNodeCommands(PVMFDownloadManagerNodeCommand& aCmd) 1896{ 1897 //given the node command ID, create the sub-node command vector, initiate the processing and return the node command status. 1898 1899 OSCL_ASSERT(iSubNodeCmdVec.empty()); 1900 1901 //Create the vector of all the commands in the sequence. 1902 switch (aCmd.iCmd) 1903 { 1904 1905 case PVMF_GENERIC_NODE_QUERYINTERFACE: 1906 { 1907 //When we get here we've already called queryInterface on this node 1908 //for the interface. This code schedules any additional sub-node commands 1909 //that are needed to support the interface. 1910 1911 //extract uuid from Node command... 1912 PVUuid*aUuid; 1913 PVInterface**aInterface; 1914 aCmd.PVMFDownloadManagerNodeCommandBase::Parse(aUuid, aInterface); 1915 OSCL_ASSERT(aUuid != NULL); 1916 1917 if (*aUuid == PVMF_DATA_SOURCE_INIT_INTERFACE_UUID) 1918 { 1919 //To support data source init interface we need a bunch of sub-node interfaces. 1920 Push(iProtocolEngineNode, PVMFDownloadManagerSubNodeContainerBase::EQueryProtocolEngine); 1921 Push(iProtocolEngineNode, PVMFDownloadManagerSubNodeContainerBase::EQueryDatastreamUser); 1922 Push(iProtocolEngineNode, PVMFDownloadManagerSubNodeContainerBase::EQueryDataSourceInit); 1923 Push(iProtocolEngineNode, PVMFDownloadManagerSubNodeContainerBase::EQueryDownloadProgress); 1924 } 1925 //else nothing else needed for other interfaces. 1926 } 1927 break; 1928 1929 case PVMF_GENERIC_NODE_INIT: 1930 //check for second "Init" command after a license acquire. 1931 if (iInitFailedLicenseRequired) 1932 { 1933 iParserInit = true; 1934 Push(iFormatParserNode, PVMFDownloadManagerSubNodeContainerBase::EInit); 1935 } 1936 else 1937 1938 { 1939 //reset any prior download/playback event 1940 iDownloadComplete = false; 1941 iParserInit = false; 1942 iDataReady = false; 1943 iMovieAtomComplete = false; 1944 iParserInitAfterMovieAtom = false; 1945 iParserPrepareAfterMovieAtom = false; 1946 iRecognizerError = false; 1947 iInitFailedLicenseRequired = false; 1948 1949 //reset any prior track select decisions. 1950 iFormatParserNode.iTrackSelection = NULL; 1951 iProtocolEngineNode.iTrackSelection = NULL; 1952 iNoPETrackSelect = false; 1953 1954 //reset any prior recognizer decisions. 1955 iMimeType = PVMF_MIME_FORMAT_UNKNOWN; 1956 1957 // Send the INIT command to the protocol engine node, followed by the Socket Node. 1958 Push(iProtocolEngineNode, PVMFDownloadManagerSubNodeContainerBase::EInit); 1959 Push(iSocketNode, PVMFDownloadManagerSubNodeContainerBase::EInit); 1960 // Issue the port request to the Protocol Engine Node and the socket node 1961 // NOTE: The request for the socket node's port must come first, followed by the protocol node, 1962 // because the code to connect the two ports in CommandDone() will do so when the protocol node's port is returned. 1963 Push(iSocketNode, PVMFDownloadManagerSubNodeContainerBase::ERequestPort); 1964 Push(iProtocolEngineNode, PVMFDownloadManagerSubNodeContainerBase::ERequestPort); 1965 // The two ports will be connected in CommandDone, when the 2nd port request completes. 1966 // After the ports are connected, the datastream factory is passed to the protocol engine node. 1967 Push(iSocketNode, PVMFDownloadManagerSubNodeContainerBase::EPrepare); 1968 Push(iSocketNode, PVMFDownloadManagerSubNodeContainerBase::EStart); 1969 Push(iProtocolEngineNode, PVMFDownloadManagerSubNodeContainerBase::EPrepare); 1970 1971 if (TrackSelectNode().iType == PVMFDownloadManagerSubNodeContainerBase::EFormatParser) 1972 { 1973 //parser is doing track selection, there's no question 1974 ContinueInitAfterTrackSelectDecision(); 1975 } 1976 else 1977 { 1978 //PE node may be doing track selection, but to be sure, we need 1979 //to wait until it is prepared, then request the track selection interface. 1980 iProtocolEngineNode.iTrackSelection = NULL; 1981 Push(iProtocolEngineNode, PVMFDownloadManagerSubNodeContainerBase::EQueryTrackSelection); 1982 //once this command is complete, we will call ContinueInitAfterTrackSelectDecision() 1983 } 1984 } 1985 break; 1986 1987 case PVMF_GENERIC_NODE_PREPARE: 1988 //if protocol engine node did track selection, then we need to continue 1989 //to the file parse stage here. Otherwise it was already done in the Init. 1990 if (TrackSelectNode().iType == PVMFDownloadManagerSubNodeContainerBase::EProtocolEngine) 1991 { 1992 ContinueFromDownloadTrackSelectionPoint(); 1993 } 1994 //if we initiated file parse sequence already, then go ahead and prepare 1995 //the parser node. 1996 if (iParserInit) 1997 { 1998 Push(iFormatParserNode, PVMFDownloadManagerSubNodeContainerBase::EPrepare); 1999 } 2000 //if we're waiting on movie atom to init parser, then set a flag so we'll 2001 //also do the parser prepare when it arrives. 2002 else if (iParserInitAfterMovieAtom) 2003 { 2004 PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE, (0, 2005 "PVMFDownloadManagerNode::ScheduleSubNodeCommands Setting flag to Prepare Parser after Movie Atom Downloaded")); 2006 iParserPrepareAfterMovieAtom = true; 2007 } 2008 break; 2009 2010 case PVMF_GENERIC_NODE_REQUESTPORT: 2011 //if file isn't parsed (as in download-only), then fail command 2012 if (!iFormatParserNode.iNode) 2013 return PVMFErrNotSupported; 2014 Push(iFormatParserNode, PVMFDownloadManagerSubNodeContainerBase::ERequestPort); 2015 break; 2016 2017 case PVMF_GENERIC_NODE_RELEASEPORT: 2018 //if file isn't parsed (as in download-only), then fail command 2019 if (!iFormatParserNode.iNode) 2020 return PVMFErrNotSupported; 2021 Push(iFormatParserNode, PVMFDownloadManagerSubNodeContainerBase::EReleasePort); 2022 break; 2023 2024 case PVMF_GENERIC_NODE_START: 2025 //Re-start socket node & PE node in case they were stopped by a prior 2026 //stop command. 2027 if (iSocketNode.iNode->GetState() == EPVMFNodePrepared) 2028 Push(iSocketNode, PVMFDownloadManagerSubNodeContainerBase::EStart); 2029 if (iProtocolEngineNode.iNode->GetState() == EPVMFNodePrepared) 2030 Push(iProtocolEngineNode, PVMFDownloadManagerSubNodeContainerBase::EStart); 2031 //Start or re-start parser node (unless download-only) 2032 if (iFormatParserNode.iNode) 2033 Push(iFormatParserNode, PVMFDownloadManagerSubNodeContainerBase::EStart); 2034 break; 2035 2036 case PVMF_GENERIC_NODE_STOP: 2037 iDataReady = false; 2038 //Stop parser (unless download-only) 2039 if (iFormatParserNode.iNode) 2040 Push(iFormatParserNode, PVMFDownloadManagerSubNodeContainerBase::EStop); 2041 //Stop PE node & socket node. 2042 Push(iProtocolEngineNode, PVMFDownloadManagerSubNodeContainerBase::EStop); 2043 Push(iSocketNode, PVMFDownloadManagerSubNodeContainerBase::EStop); 2044 break; 2045 2046 case PVMF_GENERIC_NODE_FLUSH: 2047 if (iFormatParserNode.iNode) 2048 Push(iFormatParserNode, PVMFDownloadManagerSubNodeContainerBase::EFlush); 2049 break; 2050 2051 case PVMF_GENERIC_NODE_PAUSE: 2052 //note: pause/resume download is not supported. 2053 if (iFormatParserNode.iNode) 2054 Push(iFormatParserNode, PVMFDownloadManagerSubNodeContainerBase::EPause); 2055 break; 2056 2057 case PVMF_GENERIC_NODE_RESET: 2058 //Stop socket node if needed. 2059 if (iSocketNode.iNode->GetState() == EPVMFNodeStarted 2060 || iSocketNode.iNode->GetState() == EPVMFNodePaused) 2061 { 2062 Push(iSocketNode, PVMFDownloadManagerSubNodeContainerBase::EStop); 2063 } 2064 //Stop PE node if needed. 2065 if (iProtocolEngineNode.iNode->GetState() == EPVMFNodeStarted 2066 || iProtocolEngineNode.iNode->GetState() == EPVMFNodePaused) 2067 { 2068 Push(iProtocolEngineNode, PVMFDownloadManagerSubNodeContainerBase::EStop); 2069 } 2070 //Reset & cleanup all nodes. 2071 if (iFormatParserNode.iNode) 2072 Push(iFormatParserNode, PVMFDownloadManagerSubNodeContainerBase::EReset); 2073 Push(iSocketNode, PVMFDownloadManagerSubNodeContainerBase::EReset); 2074 Push(iProtocolEngineNode, PVMFDownloadManagerSubNodeContainerBase::EReset); 2075 Push(iFormatParserNode, PVMFDownloadManagerSubNodeContainerBase::ECleanup); 2076 Push(iProtocolEngineNode, PVMFDownloadManagerSubNodeContainerBase::ECleanup); 2077 Push(iSocketNode, PVMFDownloadManagerSubNodeContainerBase::ECleanup); 2078 break; 2079 2080 case PVDLM_NODE_CMD_SETDATASOURCEPOSITION: 2081 //if file isn't parsed (as in download-only), then fail command 2082 if (!iFormatParserNode.iNode) 2083 return PVMFErrNotSupported; 2084 Push(iFormatParserNode, PVMFDownloadManagerSubNodeContainerBase::ESetDataSourcePosition); 2085 break; 2086 2087 case PVDLM_NODE_CMD_QUERYDATASOURCEPOSITION: 2088 //if file isn't parsed (as in download-only), then fail command 2089 if (!iFormatParserNode.iNode) 2090 return PVMFErrNotSupported; 2091 Push(iFormatParserNode, PVMFDownloadManagerSubNodeContainerBase::EQueryDataSourcePosition); 2092 break; 2093 2094 case PVDLM_NODE_CMD_GETNODEMETADATAKEY: 2095 //if file isn't parsed (as in download-only), then fail command 2096 if (!iFormatParserNode.iNode) 2097 return PVMFErrNotSupported; 2098 Push(iFormatParserNode, PVMFDownloadManagerSubNodeContainerBase::EGetMetadataKey); 2099 break; 2100 2101 case PVDLM_NODE_CMD_GETNODEMETADATAVALUE: 2102 //if file isn't parsed (as in download-only), then fail command 2103 if (!iFormatParserNode.iNode) 2104 return PVMFErrNotSupported; 2105 Push(iFormatParserNode, PVMFDownloadManagerSubNodeContainerBase::EGetMetadataValue); 2106 break; 2107 2108 default: 2109 OSCL_ASSERT(false); 2110 break; 2111 } 2112 2113 if (iSubNodeCmdVec.empty()) 2114 { 2115 //in a few cases there's nothing needed and no new commands 2116 //were issued-- so succeed here. 2117 return PVMFSuccess; 2118 } 2119 else 2120 { 2121 //Wakeup the node to start issuing the sub-node commands. 2122 RunIfNotReady(); 2123 2124 //the node command is pending. 2125 return PVMFPending; 2126 } 2127} 2128 2129void PVMFDownloadManagerNode::Push(PVMFDownloadManagerSubNodeContainerBase& n, PVMFDownloadManagerSubNodeContainerBase::CmdType c) 2130{ 2131 //push a sub-node command onto the cmd vector 2132 CmdElem elem; 2133 elem.iCmd = c; 2134 elem.iNC = &n; 2135 iSubNodeCmdVec.push_back(elem); 2136} 2137 2138PVMFCommandId 2139PVMFDownloadManagerNode::GetLicense(PVMFSessionId aSessionId, 2140 OSCL_wString& aContentName, 2141 OsclAny* aData, 2142 uint32 aDataSize, 2143 int32 aTimeoutMsec, 2144 OsclAny* aContextData) 2145{ 2146 PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE, (0, "PVMFDownloadManagerNode::GetLicense - Wide called")); 2147 PVMFDownloadManagerNodeCommand cmd; 2148 cmd.PVMFDownloadManagerNodeCommand::Construct(aSessionId, 2149 PVDLM_NODE_CMD_GET_LICENSE_W, 2150 aContentName, 2151 aData, 2152 aDataSize, 2153 aTimeoutMsec, 2154 aContextData); 2155 return QueueCommandL(cmd); 2156} 2157 2158PVMFCommandId 2159PVMFDownloadManagerNode::GetLicense(PVMFSessionId aSessionId, 2160 OSCL_String& aContentName, 2161 OsclAny* aData, 2162 uint32 aDataSize, 2163 int32 aTimeoutMsec, 2164 OsclAny* aContextData) 2165{ 2166 PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE, (0, "PVMFDownloadManagerNode::GetLicense - Non-Wide called")); 2167 PVMFDownloadManagerNodeCommand cmd; 2168 cmd.PVMFDownloadManagerNodeCommand::Construct(aSessionId, 2169 PVDLM_NODE_CMD_GET_LICENSE, 2170 aContentName, 2171 aData, 2172 aDataSize, 2173 aTimeoutMsec, 2174 aContextData); 2175 return QueueCommandL(cmd); 2176} 2177 2178 2179PVMFCommandId 2180PVMFDownloadManagerNode::CancelGetLicense(PVMFSessionId aSessionId 2181 , PVMFCommandId aCmdId 2182 , OsclAny* aContextData) 2183{ 2184 PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE, (0, "PVMFDownloadManagerNode::GetLicense - Non-Wide called")); 2185 PVMFDownloadManagerNodeCommand cmd; 2186 cmd.PVMFDownloadManagerNodeCommandBase::Construct(aSessionId, 2187 PVDLM_NODE_CMD_CANCEL_GET_LICENSE, 2188 aCmdId, 2189 aContextData); 2190 return QueueCommandL(cmd); 2191} 2192 2193PVMFStatus PVMFDownloadManagerNode::DoGetLicense(PVMFDownloadManagerNodeCommand& aCmd, 2194 bool aWideCharVersion) 2195{ 2196 OSCL_UNUSED_ARG(aCmd); 2197 if (iFormatParserNode.LicenseInterface() == NULL) 2198 { 2199 return PVMFErrNotSupported; 2200 } 2201 2202 if (aWideCharVersion == true) 2203 { 2204 Push(iFormatParserNode, PVMFDownloadManagerSubNodeContainerBase::ECPMGetLicenseW); 2205 } 2206 else 2207 { 2208 Push(iFormatParserNode, PVMFDownloadManagerSubNodeContainerBase::ECPMGetLicense); 2209 } 2210 RunIfNotReady(); 2211 return PVMFPending; 2212} 2213 2214void PVMFDownloadManagerNode::CompleteGetLicense() 2215{ 2216 CommandComplete(iCurrentCommand, 2217 iCurrentCommand.front(), 2218 PVMFSuccess, NULL, NULL); 2219} 2220 2221PVMFStatus PVMFDownloadManagerNode::DoCancelGetLicense(PVMFDownloadManagerNodeCommand& aCmd) 2222{ 2223 OSCL_UNUSED_ARG(aCmd); 2224 PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE, (0, "PVMFDownloadManagerNode::DoCancelGetLicense called")); 2225 if (iFormatParserNode.LicenseInterface() == NULL) 2226 { 2227 return PVMFErrNotSupported; 2228 } 2229 else 2230 { 2231 iFormatParserNode.iCancelCmdState = PVMFDownloadManagerSubNodeContainerBase::EBusy; 2232 iFormatParserNode.iCPMCancelGetLicenseCmdId = 2233 iFormatParserNode.LicenseInterface()->CancelGetLicense(iFormatParserNode.iSessionId, iFormatParserNode.iCPMGetLicenseCmdId); 2234 RunIfNotReady(); 2235 } 2236 return PVMFPending; 2237} 2238 2239// 2240// PVMFDownloadManagerSubNodeContainer Implementation. 2241// 2242 2243PVMFDownloadManagerSubNodeContainerBase::PVMFDownloadManagerSubNodeContainerBase() 2244{ 2245 iCmdState = EIdle; 2246 iCancelCmdState = EIdle; 2247} 2248 2249void PVMFDownloadManagerSubNodeContainerBase::Construct(NodeType t, PVMFDownloadManagerNode* c) 2250{ 2251 iContainer = c; 2252 iType = t; 2253} 2254 2255void PVMFDownloadManagerSubNodeContainer::Cleanup() 2256{ 2257 //release all the queried interfaces. 2258 if (iDataSourceInit) 2259 { 2260 iDataSourceInit->removeRef(); 2261 iDataSourceInit = NULL; 2262 } 2263 if (iProtocolEngineExtensionInt) 2264 { 2265 iProtocolEngineExtensionInt->removeRef(); 2266 iProtocolEngineExtensionInt = NULL; 2267 } 2268 if (iDatastreamUser) 2269 { 2270 iDatastreamUser->removeRef(); 2271 iDatastreamUser = NULL; 2272 } 2273 if (iTrackSelection) 2274 { 2275 iTrackSelection->removeRef(); 2276 iTrackSelection = NULL; 2277 } 2278 if (iMetadata) 2279 { 2280 iMetadata->removeRef(); 2281 iMetadata = NULL; 2282 } 2283 if (iDataSourcePlayback) 2284 { 2285 iDataSourcePlayback->removeRef(); 2286 iDataSourcePlayback = NULL; 2287 } 2288 if (iFormatProgDownloadSupport) 2289 { 2290 iFormatProgDownloadSupport->removeRef(); 2291 iFormatProgDownloadSupport = NULL; 2292 } 2293 if (iDownloadProgress) 2294 { 2295 iDownloadProgress->removeRef(); 2296 iDownloadProgress = NULL; 2297 } 2298 if (iLicenseInterface) 2299 { 2300 iLicenseInterface->removeRef(); 2301 iLicenseInterface = NULL; 2302 } 2303 //the node instance is cleaned up elsewhere. 2304} 2305 2306void PVMFDownloadManagerRecognizerContainer::Cleanup() 2307{ 2308 // Nothing to do here 'til recognizer is integrated 2309} 2310 2311void PVMFDownloadManagerSubNodeContainer::Connect() 2312{ 2313 //Issue connect command to the sub-node. 2314 2315 //This container class is the observer. 2316 PVMFNodeSessionInfo info(this //cmd 2317 , this, NULL //info 2318 , this, NULL); //err 2319 2320 if (iNode) 2321 iSessionId = iNode->Connect(info); 2322} 2323 2324#define LOGSUBCMD(x) PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iContainer->iLogger, SUB_CMD_LOG_LEVEL, x) 2325#define GETNODESTR (iType==EFormatParser)?"Parser":((iType==EProtocolEngine)?"ProtEngine":"SockNode") 2326 2327PVMFStatus PVMFDownloadManagerSubNodeContainer::IssueCommand(int32 aCmd) 2328{ 2329 //Issue a command to the sub-node. 2330 //Return the sub-node completion status-- either pending, success, or failure. 2331 2332 LOGSUBCMD((0, "PVMFDownloadManagerSubNodeContainer::IssueCommand %s () In", GETNODESTR)); 2333 2334 OSCL_ASSERT(!CmdPending()); 2335 2336 //find the current node command since we may need its parameters. 2337 2338 OSCL_ASSERT(!iContainer->iCurrentCommand.empty()); 2339 PVMFDownloadManagerNodeCommand* nodeCmd = &iContainer->iCurrentCommand.front(); 2340 2341 //save the sub-node command code 2342 iCmd = aCmd; 2343 2344 switch (aCmd) 2345 { 2346 case ECleanup: 2347 LOGSUBCMD((0, "PVMFDownloadManagerSubNodeContainer::IssueCommand %s Calling Cleanup", GETNODESTR)); 2348 Cleanup(); 2349 return PVMFSuccess; 2350 2351 case EParserCreate: 2352 iNode = iContainer->CreateParser(); 2353 if (iNode) 2354 { 2355 Connect(); 2356 iNode->ThreadLogon(); 2357 return PVMFSuccess; 2358 } 2359 return PVMFErrCorrupt; 2360 2361 case EQueryDataSourceInit: 2362 OSCL_ASSERT(iNode != NULL); 2363 LOGSUBCMD((0, "PVMFDownloadManagerSubNodeContainer::IssueCommand %s Calling QueryInterface(data source init)", GETNODESTR)); 2364 iCmdState = EBusy; 2365 iCmdId = iNode->QueryInterface(iSessionId, PVMF_DATA_SOURCE_INIT_INTERFACE_UUID, iDataSourceInit); 2366 LOGSUBCMD((0, "PVMFDownloadManagerSubNodeContainer::IssueCommand %s CmdId %d ", GETNODESTR, iCmdId)); 2367 return PVMFPending; 2368 2369 case EQueryProtocolEngine: 2370 OSCL_ASSERT(iNode != NULL); 2371 LOGSUBCMD((0, "PVMFDownloadManagerSubNodeContainer::IssueCommand %s Calling QueryInterface(ProtocolEngine)", GETNODESTR)); 2372 iCmdState = EBusy; 2373 iCmdId = iNode->QueryInterface(iSessionId, KPVMFProtocolEngineNodeExtensionUuid, iProtocolEngineExtensionInt); 2374 LOGSUBCMD((0, "PVMFDownloadManagerSubNodeContainer::IssueCommand %s CmdId %d ", GETNODESTR, iCmdId)); 2375 return PVMFPending; 2376 2377 case EQueryDatastreamUser: 2378 OSCL_ASSERT(iNode != NULL); 2379 LOGSUBCMD((0, "PVMFDownloadManagerSubNodeContainer::IssueCommand %s Calling QueryInterface(DatastreamUser)", GETNODESTR)); 2380 iCmdState = EBusy; 2381 iCmdId = iNode->QueryInterface(iSessionId, PVMIDatastreamuserInterfaceUuid, iDatastreamUser); 2382 LOGSUBCMD((0, "PVMFDownloadManagerSubNodeContainer::IssueCommand %s CmdId %d ", GETNODESTR, iCmdId)); 2383 return PVMFPending; 2384 2385 case EQueryTrackSelection: 2386 OSCL_ASSERT(iNode != NULL); 2387 LOGSUBCMD((0, "PVMFDownloadManagerSubNodeContainer::IssueCommand %s Calling QueryInterface(track selection)", GETNODESTR)); 2388 iCmdState = EBusy; 2389 iCmdId = iNode->QueryInterface(iSessionId, PVMF_TRACK_SELECTION_INTERFACE_UUID, iTrackSelection); 2390 LOGSUBCMD((0, "PVMFDownloadManagerSubNodeContainer::IssueCommand %s CmdId %d ", GETNODESTR, iCmdId)); 2391 return PVMFPending; 2392 2393 case EQueryMetadata: 2394 OSCL_ASSERT(iNode != NULL); 2395 LOGSUBCMD((0, "PVMFDownloadManagerSubNodeContainer::IssueCommand %s Calling QueryInterface(metadata)", GETNODESTR)); 2396 iCmdState = EBusy; 2397 iCmdId = iNode->QueryInterface(iSessionId, KPVMFMetadataExtensionUuid, iMetadata); 2398 LOGSUBCMD((0, "PVMFDownloadManagerSubNodeContainer::IssueCommand %s CmdId %d ", GETNODESTR, iCmdId)); 2399 return PVMFPending; 2400 2401 case ECPMQueryLicenseInterface: 2402 OSCL_ASSERT(iNode != NULL); 2403 LOGSUBCMD((0, "PVMFDownloadManagerSubNodeContainer::IssueCommand %s Calling QueryInterface(License)", GETNODESTR)); 2404 iCmdState = EBusy; 2405 iCmdId = iNode->QueryInterface(iSessionId, PVMFCPMPluginLicenseInterfaceUuid, iLicenseInterface); 2406 LOGSUBCMD((0, "PVMFDownloadManagerSubNodeContainer::IssueCommand %s CmdId %d ", GETNODESTR, iCmdId)); 2407 return PVMFPending; 2408 2409 case EQueryDataSourcePlayback: 2410 OSCL_ASSERT(iNode != NULL); 2411 LOGSUBCMD((0, "PVMFDownloadManagerSubNodeContainer::IssueCommand %s Calling QueryInterface(datasourcePB)", GETNODESTR)); 2412 iCmdState = EBusy; 2413 iCmdId = iNode->QueryInterface(iSessionId, PvmfDataSourcePlaybackControlUuid, iDataSourcePlayback); 2414 LOGSUBCMD((0, "PVMFDownloadManagerSubNodeContainer::IssueCommand %s CmdId %d ", GETNODESTR, iCmdId)); 2415 return PVMFPending; 2416 2417 case EInit: 2418 OSCL_ASSERT(iNode != NULL); 2419 if (iType == EFormatParser) 2420 { 2421 // For this command, which gets pushed to the format parser node, we set the source init and also 2422 // set the datstream factory 2423 LOGSUBCMD((0, "PVMFDownloadManagerSubNodeContainer::IssueCommand %s Calling SetSourceInitializationData", GETNODESTR)); 2424 2425 if (!DataSourceInit()) 2426 return PVMFFailure; //no source init interface? 2427 if (!DatastreamUser()) 2428 return PVMFFailure; //no datastreamuser interface? 2429 2430 //Pass data to the parser node. 2431 if (iContainer->iInitFailedLicenseRequired) 2432 { 2433 ;//do nothing-- data was already set on the first init call. 2434 } 2435 else 2436 { 2437 //Pass source data 2438 if (iContainer->iSourceFormat == PVMF_MIME_DATA_SOURCE_PVX_FILE) 2439 { 2440 // let the parser know this is PVX format. 2441 PVMFFormatType fmt = PVMF_MIME_DATA_SOURCE_PVX_FILE; 2442 (DataSourceInit())->SetSourceInitializationData(iContainer->iDownloadFileName 2443 , fmt 2444 , (OsclAny*)&iContainer->iLocalDataSource); 2445 } 2446 else if (iContainer->iSourceFormat == PVMF_MIME_DATA_SOURCE_SHOUTCAST_URL) 2447 { 2448 // let the parser node know that it is playing from a shoutcast stream 2449 (DataSourceInit())->SetSourceInitializationData(iContainer->iDownloadFileName 2450 , iContainer->iSourceFormat 2451 , (OsclAny*)iContainer->iSourceData); 2452 } 2453 else 2454 { 2455 // pass the recognized format to the parser. 2456 (DataSourceInit())->SetSourceInitializationData(iContainer->iDownloadFileName 2457 , iContainer->iFmt 2458 , (OsclAny*)iContainer->iSourceData); 2459 } 2460 2461 //Pass datastream data. 2462 (DatastreamUser())->PassDatastreamFactory(*(iContainer->iReadFactory), (int32)0); 2463 PVMFFileBufferDataStreamWriteDataStreamFactoryImpl* wdsfactory = 2464 OSCL_STATIC_CAST(PVMFFileBufferDataStreamWriteDataStreamFactoryImpl*, iContainer->iWriteFactory); 2465 int32 leavecode = 0; 2466 OSCL_TRY(leavecode, 2467 PVMFDataStreamReadCapacityObserver* obs = 2468 OSCL_STATIC_CAST(PVMFDataStreamReadCapacityObserver*, wdsfactory); 2469 (DatastreamUser())->PassDatastreamReadCapacityObserver(obs)); 2470 OSCL_FIRST_CATCH_ANY(leavecode, 2471 LOGSUBCMD((0, "PVMFDownloadManagerSubNodeContainer::IssueCommand %s PassDatastreamReadCapacityObserver not supported", GETNODESTR)); 2472 ); 2473 } 2474 2475 LOGSUBCMD((0, "PVMFDownloadManagerSubNodeContainer::IssueCommand %s Calling Init ", GETNODESTR)); 2476 iCmdState = EBusy; 2477 iCmdId = iNode->Init(iSessionId); 2478 LOGSUBCMD((0, "PVMFDownloadManagerSubNodeContainer::IssueCommand %s CmdId %d ", GETNODESTR, iCmdId)); 2479 return PVMFPending; 2480 } 2481 else 2482 { 2483 LOGSUBCMD((0, "PVMFDownloadManagerSubNodeContainer::IssueCommand %s Calling Init ", GETNODESTR)); 2484 iCmdState = EBusy; 2485 iCmdId = iNode->Init(iSessionId); 2486 LOGSUBCMD((0, "PVMFDownloadManagerSubNodeContainer::IssueCommand %s CmdId %d ", GETNODESTR, iCmdId)); 2487 return PVMFPending; 2488 } 2489 2490 case ECPMGetLicenseW: 2491 { 2492 OSCL_ASSERT(iNode != NULL); 2493 LOGSUBCMD((0, "PVMFDownloadManagerSubNodeContainer::IssueCommand %s Calling ECPMGetLicenseW", GETNODESTR)); 2494 iCmdState = EBusy; 2495 OSCL_wString* contentName = NULL; 2496 OsclAny* data = NULL; 2497 uint32 dataSize = 0; 2498 int32 timeoutMsec = 0; 2499 nodeCmd->Parse(contentName, 2500 data, 2501 dataSize, 2502 timeoutMsec); 2503 iCmdId = 2504 LicenseInterface()->GetLicense(iSessionId, 2505 *contentName, 2506 data, 2507 dataSize, 2508 timeoutMsec); 2509 iCPMGetLicenseCmdId = iCmdId; 2510 2511 LOGSUBCMD((0, "PVMFDownloadManagerSubNodeContainer::IssueCommand %s CmdId %d ", GETNODESTR, iCmdId)); 2512 return PVMFPending; 2513 } 2514 case ECPMGetLicense: 2515 { 2516 OSCL_ASSERT(iNode != NULL); 2517 LOGSUBCMD((0, "PVMFDownloadManagerSubNodeContainer::IssueCommand %s Calling ECPMGetLicense", GETNODESTR)); 2518 iCmdState = EBusy; 2519 OSCL_String* contentName = NULL; 2520 OsclAny* data = NULL; 2521 uint32 dataSize = 0; 2522 int32 timeoutMsec = 0; 2523 nodeCmd->Parse(contentName, 2524 data, 2525 dataSize, 2526 timeoutMsec); 2527 iCmdId = 2528 LicenseInterface()->GetLicense(iSessionId, 2529 *contentName, 2530 data, 2531 dataSize, 2532 timeoutMsec); 2533 iCPMGetLicenseCmdId = iCmdId; 2534 2535 LOGSUBCMD((0, "PVMFDownloadManagerSubNodeContainer::IssueCommand %s CmdId %d ", GETNODESTR, iCmdId)); 2536 return PVMFPending; 2537 } 2538 2539 case ERequestPort: 2540 OSCL_ASSERT(iNode != NULL); 2541 // The parameters to RequestPort vary depending on which node we're getting a port from, so we switch on it. 2542 switch (iType) 2543 { 2544 case EProtocolEngine: 2545 LOGSUBCMD((0, "PVMFDownloadManagerSubNodeContainer::IssueCommand %s Calling RequestPort ", GETNODESTR)); 2546 iCmdState = EBusy; 2547 // For protocol engine port request, we don't need port tag or config info because it's the only port we ask it for. 2548 iCmdId = iNode->RequestPort(iSessionId, (int32)0); 2549 LOGSUBCMD((0, "PVMFDownloadManagerSubNodeContainer::IssueCommand %s CmdId %d ", GETNODESTR, iCmdId)); 2550 return PVMFPending; 2551 2552 case ESocket: 2553 LOGSUBCMD((0, "PVMFDownloadManagerSubNodeContainer::IssueCommand %s Calling RequestPort with port config %s", GETNODESTR, iContainer->iServerAddr.get_cstr())); 2554 iCmdState = EBusy; 2555 //append a mimestring to the port for socket node logging 2556 iContainer->iServerAddr += ";mime=download"; 2557 iCmdId = iNode->RequestPort(iSessionId, PVMF_SOCKET_NODE_PORT_TYPE_PASSTHRU, &iContainer->iServerAddr); 2558 LOGSUBCMD((0, "PVMFDownloadManagerSubNodeContainer::IssueCommand %s CmdId %d ", GETNODESTR, iCmdId)); 2559 return PVMFPending; 2560 2561 case EFormatParser: 2562 //extract params from current Node command. 2563 OSCL_ASSERT(nodeCmd->iCmd == PVMF_GENERIC_NODE_REQUESTPORT); 2564 { 2565 int32 aPortTag; 2566 OSCL_String*aMimetype; 2567 nodeCmd->PVMFDownloadManagerNodeCommandBase::Parse(aPortTag, aMimetype); 2568 2569 LOGSUBCMD((0, "PVMFDownloadManagerSubNodeContainer::IssueCommand %s Calling RequestPort ", GETNODESTR)); 2570 iCmdState = EBusy; 2571 iCmdId = iNode->RequestPort(iSessionId, aPortTag, aMimetype); 2572 } 2573 LOGSUBCMD((0, "PVMFDownloadManagerSubNodeContainer::IssueCommand %s CmdId %d ", GETNODESTR, iCmdId)); 2574 return PVMFPending; 2575 2576 default: 2577 OSCL_ASSERT(false); 2578 return PVMFFailure; 2579 } 2580 2581 case EReleasePort: 2582 OSCL_ASSERT(iNode != NULL); 2583 { 2584 //extract params from current Node command. 2585 OSCL_ASSERT(nodeCmd->iCmd == PVMF_GENERIC_NODE_RELEASEPORT); 2586 PVMFPortInterface *port; 2587 nodeCmd->PVMFDownloadManagerNodeCommandBase::Parse(port); 2588 OSCL_ASSERT(port != NULL); 2589 2590 LOGSUBCMD((0, "PVMFDownloadManagerSubNodeContainer::IssueCommand %s Calling ReleasePort", GETNODESTR)); 2591 iCmdState = EBusy; 2592 iCmdId = iNode->ReleasePort(iSessionId, *port); 2593 LOGSUBCMD((0, "PVMFDownloadManagerSubNodeContainer::IssueCommand %s CmdId %d ", GETNODESTR, iCmdId)); 2594 return PVMFPending; 2595 } 2596 2597 case EPrepare: 2598 OSCL_ASSERT(iNode != NULL); 2599 LOGSUBCMD((0, "PVMFDownloadManagerSubNodeContainer::IssueCommand %s Calling Prepare", GETNODESTR)); 2600 iCmdState = EBusy; 2601 iCmdId = iNode->Prepare(iSessionId); 2602 LOGSUBCMD((0, "PVMFDownloadManagerSubNodeContainer::IssueCommand %s CmdId %d ", GETNODESTR, iCmdId)); 2603 return PVMFPending; 2604 2605 case EStop: 2606 OSCL_ASSERT(iNode != NULL); 2607 LOGSUBCMD((0, "PVMFDownloadManagerSubNodeContainer::IssueCommand %s Calling Stop", GETNODESTR)); 2608 iCmdState = EBusy; 2609 iCmdId = iNode->Stop(iSessionId); 2610 LOGSUBCMD((0, "PVMFDownloadManagerSubNodeContainer::IssueCommand %s CmdId %d ", GETNODESTR, iCmdId)); 2611 return PVMFPending; 2612 2613 case EStart: 2614 OSCL_ASSERT(iNode != NULL); 2615 LOGSUBCMD((0, "PVMFDownloadManagerSubNodeContainer::IssueCommand %s Calling Start", GETNODESTR)); 2616 iCmdState = EBusy; 2617 iCmdId = iNode->Start(iSessionId); 2618 LOGSUBCMD((0, "PVMFDownloadManagerSubNodeContainer::IssueCommand %s CmdId %d ", GETNODESTR, iCmdId)); 2619 return PVMFPending; 2620 2621 case EPause: 2622 OSCL_ASSERT(iNode != NULL); 2623 LOGSUBCMD((0, "PVMFDownloadManagerSubNodeContainer::IssueCommand %s Calling Pause", GETNODESTR)); 2624 iCmdState = EBusy; 2625 iCmdId = iNode->Pause(iSessionId); 2626 LOGSUBCMD((0, "PVMFDownloadManagerSubNodeContainer::IssueCommand %s CmdId %d ", GETNODESTR, iCmdId)); 2627 return PVMFPending; 2628 2629 case EFlush: 2630 OSCL_ASSERT(iNode != NULL); 2631 LOGSUBCMD((0, "PVMFDownloadManagerSubNodeContainer::IssueCommand %s Calling Flush", GETNODESTR)); 2632 iCmdState = EBusy; 2633 iCmdId = iNode->Flush(iSessionId); 2634 LOGSUBCMD((0, "PVMFDownloadManagerSubNodeContainer::IssueCommand %s CmdId %d ", GETNODESTR, iCmdId)); 2635 return PVMFPending; 2636 2637 case EReset: 2638 OSCL_ASSERT(iNode != NULL); 2639 LOGSUBCMD((0, "PVMFDownloadManagerSubNodeContainer::IssueCommand %s Calling Reset", GETNODESTR)); 2640 iCmdState = EBusy; 2641 iCmdId = iNode->Reset(iSessionId); 2642 LOGSUBCMD((0, "PVMFDownloadManagerSubNodeContainer::IssueCommand %s CmdId %d ", GETNODESTR, iCmdId)); 2643 return PVMFPending; 2644 2645 case EGetMetadataKey: 2646 OSCL_ASSERT(iNode != NULL); 2647 { 2648 if (!Metadata()) 2649 return PVMFErrNotSupported;//no interface! 2650 2651 //extract params from current Node command. 2652 OSCL_ASSERT(nodeCmd->iCmd == PVDLM_NODE_CMD_GETNODEMETADATAKEY); 2653 2654 PVMFMetadataList* aKeyList; 2655 uint32 starting_index; 2656 int32 max_entries; 2657 char* query_key; 2658 2659 nodeCmd->Parse(aKeyList, starting_index, max_entries, query_key); 2660 OSCL_ASSERT(aKeyList != NULL); 2661 LOGSUBCMD((0, "PVMFDownloadManagerSubNodeContainer::IssueCommand %s Calling GetNodeMetadataKeys", GETNODESTR)); 2662 iCmdState = EBusy; 2663 iCmdId = (Metadata())->GetNodeMetadataKeys(iSessionId, *aKeyList, starting_index, max_entries, query_key, NULL); 2664 2665 LOGSUBCMD((0, "PVMFDownloadManagerSubNodeContainer::IssueCommand %s CmdId %d ", GETNODESTR, iCmdId)); 2666 return PVMFPending; 2667 } 2668 2669 2670 case EGetMetadataValue: 2671 OSCL_ASSERT(iNode != NULL); 2672 { 2673 if (!Metadata()) 2674 return PVMFErrNotSupported;//no interface! 2675 2676 //extract params from current Node command. 2677 OSCL_ASSERT(nodeCmd->iCmd == PVDLM_NODE_CMD_GETNODEMETADATAVALUE); 2678 PVMFMetadataList* aKeyList; 2679 Oscl_Vector<PvmiKvp, OsclMemAllocator>* aValueList; 2680 uint32 starting_index; 2681 int32 max_entries; 2682 nodeCmd->Parse(aKeyList, aValueList, starting_index, max_entries); 2683 OSCL_ASSERT(aKeyList != NULL); 2684 OSCL_ASSERT(aValueList != NULL); 2685 2686 LOGSUBCMD((0, "PVMFDownloadManagerSubNodeContainer::IssueCommand %s Calling GetNodeMetadataValues", GETNODESTR)); 2687 iCmdState = EBusy; 2688 iCmdId = (Metadata())->GetNodeMetadataValues(iSessionId, *aKeyList, *aValueList, starting_index, max_entries, NULL); 2689 LOGSUBCMD((0, "PVMFDownloadManagerSubNodeContainer::IssueCommand %s CmdId %d ", GETNODESTR, iCmdId)); 2690 return PVMFPending; 2691 } 2692 2693 case EQueryFFProgDownload: 2694 OSCL_ASSERT(iNode != NULL); 2695 LOGSUBCMD((0, "PVMFDownloadManagerSubNodeContainer::IssueCommand %s Calling QueryInterface (format prog dl)", GETNODESTR)); 2696 iCmdState = EBusy; 2697 iCmdId = iNode->QueryInterface(iSessionId, PVMF_FF_PROGDOWNLOAD_SUPPORT_INTERFACE_UUID, iFormatProgDownloadSupport); 2698 LOGSUBCMD((0, "PVMFDownloadManagerSubNodeContainer::IssueCommand %s CmdId %d ", GETNODESTR, iCmdId)); 2699 return PVMFPending; 2700 2701 case EQueryDownloadProgress: 2702 OSCL_ASSERT(iNode != NULL); 2703 LOGSUBCMD((0, "PVMFDownloadManagerSubNodeContainer::IssueCommand %s Calling QueryInterface (dl prog)", GETNODESTR)); 2704 iCmdState = EBusy; 2705 iCmdId = iNode->QueryInterface(iSessionId, PVMF_DOWNLOAD_PROGRESS_INTERFACE_UUID, iDownloadProgress); 2706 LOGSUBCMD((0, "PVMFDownloadManagerSubNodeContainer::IssueCommand %s CmdId %d ", GETNODESTR, iCmdId)); 2707 return PVMFPending; 2708 2709 case ESetFFProgDownloadSupport: 2710 OSCL_ASSERT(iNode != NULL); 2711 2712 if (!DownloadProgress() || !iContainer->iFormatParserNode.FormatProgDownloadSupport()) 2713 return PVMFErrNotSupported;//no interface! 2714 2715 //pass parser node format prog download interface to the protocol node. 2716 LOGSUBCMD((0, "PVMFDownloadManagerSubNodeContainer::IssueCommand %s Calling setFormatDownloadSupportInterface", GETNODESTR)); 2717 (DownloadProgress())->setFormatDownloadSupportInterface(iContainer->iFormatParserNode.FormatProgDownloadSupport()); 2718 return PVMFSuccess; 2719 2720 case ESetDataSourcePosition: 2721 OSCL_ASSERT(iNode != NULL); 2722 { 2723 if (!DataSourcePlayback()) 2724 return PVMFErrNotSupported;//no interface! 2725 2726 //extract params from current Node command. 2727 OSCL_ASSERT(nodeCmd->iCmd == PVDLM_NODE_CMD_SETDATASOURCEPOSITION); 2728 PVMFTimestamp aTargetNPT; 2729 PVMFTimestamp* aActualNPT; 2730 PVMFTimestamp* aActualMediaDataTS; 2731 uint32 streamID = 0; 2732 bool aJump; 2733 nodeCmd->Parse(aTargetNPT, aActualNPT, aActualMediaDataTS, aJump, streamID); 2734 OSCL_ASSERT(aActualNPT != NULL); 2735 OSCL_ASSERT(aActualMediaDataTS != NULL); 2736 2737 LOGSUBCMD((0, "PVMFDownloadManagerSubNodeContainer::IssueCommand %s Calling SetDataSourcePosition", GETNODESTR)); 2738 iCmdState = EBusy; 2739 iCmdId = (DataSourcePlayback())->SetDataSourcePosition(iSessionId, aTargetNPT, *aActualNPT, *aActualMediaDataTS, aJump, streamID); 2740 LOGSUBCMD((0, "PVMFDownloadManagerSubNodeContainer::IssueCommand %s CmdId %d ", GETNODESTR, iCmdId)); 2741 return PVMFPending; 2742 } 2743 2744 case EQueryDataSourcePosition: 2745 OSCL_ASSERT(iNode != NULL); 2746 { 2747 if (!DataSourcePlayback()) 2748 return PVMFErrNotSupported;//no interface! 2749 2750 //extract params from current Node command. 2751 OSCL_ASSERT(nodeCmd->iCmd == PVDLM_NODE_CMD_QUERYDATASOURCEPOSITION); 2752 PVMFTimestamp aTargetNPT; 2753 PVMFTimestamp* aActualNPT; 2754 bool aJump; 2755 nodeCmd->Parse(aTargetNPT, aActualNPT, aJump); 2756 OSCL_ASSERT(aActualNPT != NULL); 2757 2758 LOGSUBCMD((0, "PVMFDownloadManagerSubNodeContainer::IssueCommand %s Calling QueryDataSourcePosition", GETNODESTR)); 2759 iCmdState = EBusy; 2760 iCmdId = (DataSourcePlayback())->QueryDataSourcePosition(iSessionId, aTargetNPT, *aActualNPT, aJump); 2761 LOGSUBCMD((0, "PVMFDownloadManagerSubNodeContainer::IssueCommand %s CmdId %d ", GETNODESTR, iCmdId)); 2762 return PVMFPending; 2763 } 2764 2765 default: 2766 OSCL_ASSERT(false); 2767 return PVMFFailure; 2768 } 2769} 2770 2771 2772PVMFStatus PVMFDownloadManagerRecognizerContainer::IssueCommand(int32 aCmd) 2773{ 2774 //Issue a command to the Recognizer. 2775 //Return the completion status-- either pending, success, or failure. 2776 2777 LOGSUBCMD((0, "PVMFDownloadManagerRecognizerContainer::IssueCommand In")); 2778 2779 OSCL_ASSERT(!CmdPending()); 2780 2781 //save the sub-node command code 2782 iCmd = aCmd; 2783 2784 switch (aCmd) 2785 { 2786 case ERecognizerStart: 2787 { 2788 PVMFStatus status = PVMFRecognizerRegistry::OpenSession(iRecognizerSessionId, (*this)); 2789 if (status == PVMFSuccess) 2790 { 2791 //Issue the asynchronous command to the recognizer. 2792 iCmdState = EBusy; 2793 iCmdId = PVMFRecognizerRegistry::Recognize(iRecognizerSessionId, 2794 *(iContainer->iReadFactory), 2795 NULL, 2796 iRecognizerResultVec); 2797 LOGSUBCMD((0, "PVMFDownloadManagerRecognizerContainer::IssueCommand Recognize Pending Cmd ID %d", iCmdId)); 2798 return PVMFPending; 2799 //wait on the RecognizerCommandCompleted callback. 2800 } 2801 else 2802 { 2803 PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iContainer->iLogger, PVLOGMSG_ERR, (0, 2804 "PVMFDownloadManagerRecognizerContainer::IssueCommand Open Session Failed, status %d", status)); 2805 } 2806 return status; 2807 } 2808 // break; This statement was removed to avoid compiler warning for Unreachable Code 2809 2810 case ERecognizerClose: 2811 //close the recognizer session. 2812 { 2813 PVMFStatus status = PVMFRecognizerRegistry::CloseSession(iRecognizerSessionId); 2814 if (status != PVMFSuccess) 2815 { 2816 PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iContainer->iLogger, PVLOGMSG_ERR, (0, 2817 "PVMFDownloadManagerRecognizerContainer::IssueCommand CloseSession status %d", status)); 2818 } 2819 return status; 2820 } 2821 2822 default: 2823 LOGSUBCMD((0, "PVMFDownloadManagerRecognizerContainer::IssueCommand Error, Unknown Recognizer Command!")); 2824 OSCL_ASSERT(false);//unknown command type for recognizer. 2825 return PVMFFailure; 2826 } 2827} 2828 2829//this is the callback from the Recognizer::Recognize command. 2830void PVMFDownloadManagerRecognizerContainer::RecognizerCommandCompleted(const PVMFCmdResp& aResponse) 2831{ 2832 if (aResponse.GetCmdId() == iCmdId 2833 && iCmdState == EBusy) 2834 { 2835 //save the result. 2836 if (aResponse.GetCmdStatus() == PVMFSuccess 2837 && iRecognizerResultVec.size() > 0) 2838 { 2839 // if there is only 1, use it 2840 // if more than 1, check the confidence level 2841 if (1 == iRecognizerResultVec.size()) 2842 { 2843 iContainer->iMimeType = iRecognizerResultVec[0].iRecognizedFormat; 2844 } 2845 else 2846 { 2847 // if certain, use it 2848 // if possible, keep looking 2849 bool found = false; 2850 for (uint32 i = 0; i < iRecognizerResultVec.size(); i++) 2851 { 2852 if (PVMFRecognizerConfidenceCertain == iRecognizerResultVec[i].iRecognitionConfidence) 2853 { 2854 found = true; 2855 iContainer->iMimeType = iRecognizerResultVec[i].iRecognizedFormat; 2856 break; 2857 } 2858 } 2859 2860 // if Content-Type may not be known, just use the first result 2861 if (!found && (0 != iContainer->iContentTypeMIMEString.get_size())) 2862 { 2863 // no certain, all possibles 2864 // compare with the Content-Type hint, which is in IANA MIME string format 2865 // these are file formats, does not include streaming formats 2866 // @TODO: need to add the following to "pvmi/pvmf/include/pvmf_format_type.h" 2867 // 2868 // MP4 + 3GPP = "video/3gpp", "video/mp4", "audio/3gpp", "audio/mp4", "video/3gpp-tt" 2869 // AMR = "audio/amr", "audio/amr-wb" 2870 // AAC = "audio/aac", "audio/x-aac", "audio/aacp" 2871 // MP3 = "audio/mpeg" 2872 // WM + ASF = "video/x-ms-wmv", "video/x-ms-wm", "video/x-ms-asf","audio/x-ms-wma", 2873 // RM = "video/vnd.rn-realvideo", "audio/vnd.rn-realaudio" 2874 // WAV = "audio/wav", "audio/x-wav", "audio/wave" 2875 // 2876 // the recognizer plugins may return PV proprietary format, X-... 2877 // in "pvmi/pvmf/include/pvmf_format_type.h" 2878 // #define PVMF_MIME_MPEG4FF "video/MP4" 2879 // #define PVMF_MIME_AMRFF "X-AMR-FF" 2880 // #define PVMF_MIME_AACFF "X-AAC-FF" 2881 // #define PVMF_MIME_MP3FF "X-MP3-FF" 2882 // #define PVMF_MIME_WAVFF "X-WAV-FF" 2883 // #define PVMF_MIME_ASFFF "x-pvmf/mux/asf" 2884 // #define PVMF_MIME_RMFF "x-pvmf/mux/rm" 2885 2886 // need case insensitive compares 2887 const char* mimeStr = iContainer->iContentTypeMIMEString.get_cstr(); 2888 2889 for (uint32 i = 0; !found && i < iRecognizerResultVec.size(); i++) 2890 { 2891 const char* recognizedStr = iRecognizerResultVec[i].iRecognizedFormat.get_cstr(); 2892 if (0 == oscl_CIstrcmp(recognizedStr, PVMF_MIME_MPEG4FF)) 2893 { 2894 if ((0 == oscl_CIstrcmp(mimeStr, "video/3gpp")) || 2895 (0 == oscl_CIstrcmp(mimeStr, "video/mp4")) || 2896 (0 == oscl_CIstrcmp(mimeStr, "audio/3gpp")) || 2897 (0 == oscl_CIstrcmp(mimeStr, "audio/mp4")) || 2898 (0 == oscl_CIstrcmp(mimeStr, "video/3gpp-tt"))) 2899 { 2900 found = true; 2901 iContainer->iMimeType = iRecognizerResultVec[i].iRecognizedFormat; 2902 } 2903 } 2904 else if (0 == oscl_CIstrcmp(recognizedStr, PVMF_MIME_MP3FF)) 2905 { 2906 if ((0 == oscl_CIstrcmp(mimeStr, "audio/mpeg"))) 2907 { 2908 found = true; 2909 iContainer->iMimeType = iRecognizerResultVec[i].iRecognizedFormat; 2910 } 2911 } 2912 else if (0 == oscl_CIstrcmp(recognizedStr, PVMF_MIME_AACFF)) 2913 { 2914 if ((0 == oscl_CIstrcmp(mimeStr, "audio/aac")) || 2915 (0 == oscl_CIstrcmp(mimeStr, "audio/x-aac")) || 2916 (0 == oscl_CIstrcmp(mimeStr, "audio/aacp"))) 2917 { 2918 found = true; 2919 iContainer->iMimeType = iRecognizerResultVec[i].iRecognizedFormat; 2920 } 2921 } 2922 else if (0 == oscl_CIstrcmp(recognizedStr, PVMF_MIME_AMRFF)) 2923 { 2924 if ((0 == oscl_CIstrcmp(mimeStr, "audio/amr")) || 2925 (0 == oscl_CIstrcmp(mimeStr, "audio/amr-wb"))) 2926 { 2927 found = true; 2928 iContainer->iMimeType = iRecognizerResultVec[i].iRecognizedFormat; 2929 } 2930 } 2931 else if (0 == oscl_CIstrcmp(recognizedStr, PVMF_MIME_ASFFF)) 2932 { 2933 if ((0 == oscl_CIstrcmp(mimeStr, "video/x-ms-wmv")) || 2934 (0 == oscl_CIstrcmp(mimeStr, "video/x-ms-wm")) || 2935 (0 == oscl_CIstrcmp(mimeStr, "video/x-ms-asf")) || 2936 (0 == oscl_CIstrcmp(mimeStr, "audio/x-ms-wma"))) 2937 { 2938 found = true; 2939 iContainer->iMimeType = iRecognizerResultVec[i].iRecognizedFormat; 2940 } 2941 } 2942 else if (0 == oscl_CIstrcmp(recognizedStr, PVMF_MIME_RMFF)) 2943 { 2944 if ((0 == oscl_CIstrcmp(mimeStr, "video/vnd.rn-realvideo")) || 2945 (0 == oscl_CIstrcmp(mimeStr, "audio/vnd.rn-realaudio"))) 2946 { 2947 found = true; 2948 iContainer->iMimeType = iRecognizerResultVec[i].iRecognizedFormat; 2949 } 2950 } 2951 else if ((0 == oscl_CIstrcmp(recognizedStr, PVMF_MIME_WAVFF))) 2952 { 2953 if ((0 == oscl_CIstrcmp(mimeStr, "audio/wav")) || 2954 (0 == oscl_CIstrcmp(mimeStr, "audio/wave")) || 2955 (0 == oscl_CIstrcmp(mimeStr, "audio/x-wav"))) 2956 { 2957 found = true; 2958 iContainer->iMimeType = iRecognizerResultVec[i].iRecognizedFormat; 2959 } 2960 } 2961 else 2962 { 2963 // some new format that this component does not know about 2964 // we'll use it 2965 found = true; 2966 iContainer->iMimeType = iRecognizerResultVec[i].iRecognizedFormat; 2967 } 2968 } 2969 } 2970 2971 // if still no match found 2972 // need to wait for more data and run the recognizer again, will implement this later 2973 // just use the first one for now 2974 if (!found) 2975 { 2976 // @TODO - implement the recognizer loop later 2977 iContainer->iMimeType = iRecognizerResultVec[0].iRecognizedFormat; 2978 } 2979 } 2980 } 2981 2982 CommandDone(aResponse.GetCmdStatus(), aResponse.GetEventExtensionInterface(), aResponse.GetEventData()); 2983 2984 //catch completion of cancel for recognizer commands 2985 //since there's no cancel to the recognizer module, the cancel 2986 //is done whenever the current recognizer command is done. 2987 if (iCancelCmdState != EIdle) 2988 { 2989 CancelCommandDone(PVMFSuccess, NULL, NULL); 2990 } 2991 } 2992 else 2993 { 2994 OSCL_ASSERT(false);//unexpected response. 2995 } 2996} 2997 2998//from PVMFNodeErrorEventObserver 2999void PVMFDownloadManagerSubNodeContainer::HandleNodeErrorEvent(const PVMFAsyncEvent& aEvent) 3000{ 3001 //A sub-node is reporting an event. 3002 3003 //print events 3004 switch (iType) 3005 { 3006 case EFormatParser: 3007 PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iContainer->iLogger, PVLOGMSG_ERR, (0, 3008 "PVMFDownloadManagerSubNodeContainer::HandleNodeErrorEvent Parser Node Error Event %d", aEvent.GetEventType())); 3009 break; 3010 case EProtocolEngine: 3011 PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iContainer->iLogger, PVLOGMSG_ERR, (0, 3012 "PVMFDownloadManagerSubNodeContainer::HandleNodeErrorEvent ProtocolEngine Node Error Event %d", aEvent.GetEventType())); 3013 break; 3014 case ESocket: 3015 PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iContainer->iLogger, PVLOGMSG_ERR, (0, 3016 "PVMFDownloadManagerSubNodeContainer::HandleNodeErrorEvent Socket Node Error Event %d", aEvent.GetEventType())); 3017 if (iContainer->iDownloadComplete) 3018 return; // Suppress socket node error, if the download is already complete. 3019 break; 3020 default: 3021 OSCL_ASSERT(false); 3022 break; 3023 } 3024 3025 //duplicate any PVMF Error events from either node. 3026 if (IsPVMFErrCode(aEvent.GetEventType())) 3027 iContainer->ReportErrorEvent(aEvent.GetEventType(), aEvent.GetEventExtensionInterface(), aEvent.GetEventData()); 3028} 3029 3030#include "pvmf_protocol_engine_node_events.h" 3031 3032//from PVMFNodeInfoEventObserver 3033void PVMFDownloadManagerSubNodeContainer::HandleNodeInformationalEvent(const PVMFAsyncEvent& aEvent) 3034{ 3035 //A sub-node is reporting an event. 3036 3037 //detect sub-node error states. 3038 if (aEvent.GetEventType() == PVMFInfoStateChanged 3039 && iNode->GetState() == EPVMFNodeError) 3040 { 3041 iContainer->SetState(EPVMFNodeError); 3042 } 3043 3044 //detect important status events. 3045 if (iType == EProtocolEngine) 3046 { 3047 switch (aEvent.GetEventType()) 3048 { 3049 case PVMFInfoBufferingComplete: 3050 iContainer->iDownloadComplete = true; 3051 iContainer->NotifyDownloadComplete(); 3052 //not sure whether this is possible, but just in case download 3053 //completes before movie atom notice, go ahead and do anything 3054 //that was waiting on movie atom. 3055 if (!iContainer->iMovieAtomComplete) 3056 iContainer->ContinueAfterMovieAtom(); 3057 break; 3058 case PVMFPROTOCOLENGINE_INFO_MovieAtomCompleted: 3059 //we may be waiting on this event to continue Parser init. 3060 if (!iContainer->iMovieAtomComplete) 3061 iContainer->ContinueAfterMovieAtom(); 3062 if (iContainer->iDebugMode) 3063 { 3064 iContainer->ReportInfoEvent((PVMFAsyncEvent&)aEvent); 3065 } 3066 break; 3067 default: 3068 break; 3069 } 3070 } 3071 3072 //filter out events that we don't want to pass up to observer 3073 bool filter = false; 3074 if (iType == ESocket) 3075 { 3076 switch (aEvent.GetEventType()) 3077 { 3078 case PVMFInfoRemoteSourceNotification: //To let the socket node events propagate to pvengine 3079 filter = false; 3080 break; 3081 default: 3082 filter = true; 3083 } 3084 } 3085 else 3086 { 3087 switch (aEvent.GetEventType()) 3088 { 3089 case PVMFInfoStateChanged: 3090 filter = true;//always ignore 3091 break; 3092 case PVMFInfoPortDeleted: 3093 case PVMFInfoPortCreated: 3094 case PVMFInfoPortConnected: 3095 case PVMFInfoPortDisconnected: 3096 if (iType != EFormatParser) 3097 filter = true;//ignore port events unless from format parser 3098 break; 3099 case PVMFInfoUnderflow: 3100 case PVMFInfoDataReady: 3101 case PVMFInfoRemoteSourceNotification: 3102 //apply some filtering to these 3103 if (iContainer->FilterPlaybackEventsFromSubNodes(aEvent)) 3104 filter = true; 3105 break; 3106 default: 3107 break; 3108 } 3109 } 3110 3111 //duplicate all remaining PVMFInfo events. 3112 if (!filter 3113 && IsPVMFInfoCode(aEvent.GetEventType())) 3114 { 3115 iContainer->ReportInfoEvent((PVMFAsyncEvent&)aEvent); 3116 } 3117 3118 //just print and ignore other events 3119 switch (iType) 3120 { 3121 case EFormatParser: 3122 PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iContainer->iLogger, PVLOGMSG_DEBUG, (0, 3123 "PVMFDownloadManagerSubNodeContainer::HandleNodeInfoEvent Parser Node Info Event %d", aEvent.GetEventType())); 3124 break; 3125 case EProtocolEngine: 3126 PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iContainer->iLogger, PVLOGMSG_DEBUG, (0, 3127 "PVMFDownloadManagerSubNodeContainer::HandleNodeInfoEvent ProtocolEngine Node Info Event %d", aEvent.GetEventType())); 3128 break; 3129 case ESocket: 3130 PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iContainer->iLogger, PVLOGMSG_DEBUG, (0, 3131 "PVMFDownloadManagerSubNodeContainer::HandleNodeInfoEvent Socket Node Info Event %d", aEvent.GetEventType())); 3132 break; 3133 3134 default: 3135 OSCL_ASSERT(false); 3136 break; 3137 } 3138} 3139 3140bool PVMFDownloadManagerSubNodeContainer::CancelPendingCommand() 3141{ 3142 //initiate sub-node command cancel, return True if cancel initiated. 3143 3144 if (iCmdState != EBusy) 3145 return false;//nothing to cancel 3146 3147 iCancelCmdState = EBusy; 3148 3149 if (iNode) 3150 { 3151 LOGSUBCMD((0, "PVMFDownloadManagerSubNodeContainer::CancelPendingCommand Calling Cancel")); 3152 iCancelCmdId = iNode->CancelCommand(iSessionId, iCmdId, NULL); 3153 LOGSUBCMD((0, "PVMFDownloadManagerSubNodeContainer::CancelPendingCommand CmdId %d", iCancelCmdId)); 3154 } 3155 3156 return true;//cancel initiated 3157} 3158 3159bool PVMFDownloadManagerRecognizerContainer::CancelPendingCommand() 3160{ 3161 //initiate sub-node command cancel, return True if cancel initiated. 3162 3163 if (iCmdState != EBusy) 3164 return false;//nothing to cancel 3165 3166 iCancelCmdState = EBusy; 3167 3168 LOGSUBCMD((0, "PVMFDownloadManagerRecognizerContainer::CancelPendingCommand Calling Cancel")); 3169 iCancelCmdId = PVMFRecognizerRegistry::CancelCommand(iRecognizerSessionId, iCmdId, NULL); 3170 LOGSUBCMD((0, "PVMFDownloadManagerRecognizerContainer::CancelPendingCommand CmdId %d", iCancelCmdId)); 3171 3172 return true;//cancel initiated 3173} 3174 3175 3176void PVMFDownloadManagerSubNodeContainerBase::CommandDone(PVMFStatus aStatus, PVInterface*aExtMsg, OsclAny*aEventData) 3177{ 3178 //a sub-node command is done-- process the result. 3179 3180 OSCL_ASSERT(aStatus != PVMFPending); 3181 3182 //pop the sub-node command vector. 3183 OSCL_ASSERT(!iContainer->iSubNodeCmdVec.empty()); 3184 iContainer->iSubNodeCmdVec.erase(&iContainer->iSubNodeCmdVec.front()); 3185 3186 iCmdState = EIdle; 3187 3188 PVMFStatus status = aStatus; 3189 3190 // Set "Init Failed License Required" flag with the results of parser Init. 3191 if (iType == EFormatParser && iCmd == EInit) 3192 { 3193 iContainer->iInitFailedLicenseRequired = (status == PVMFErrLicenseRequired); 3194 } 3195 3196 // Watch for the request port command completion from the protocol node, because we need to save the port pointer 3197 if (iType == EProtocolEngine && iCmd == ERequestPort && status == PVMFSuccess) 3198 { 3199 iContainer->iProtocolEngineNodePort = (PVMFPortInterface*)aEventData; 3200 // If both ports are non-null, connect them. 3201 if (iContainer->iSocketNodePort && iContainer->iProtocolEngineNodePort) 3202 { 3203 iContainer->iSocketNodePort->Connect(iContainer->iProtocolEngineNodePort); 3204 3205 // The ports are connected, so now we pass the datastream factory to the protocol node via the extension interface, if it's available. 3206 if (iContainer->iProtocolEngineNode.iDatastreamUser) 3207 { 3208 ((PVMIDatastreamuserInterface*)iContainer->iProtocolEngineNode.iDatastreamUser)->PassDatastreamFactory(*(iContainer->iWriteFactory), (int32)0); 3209 } 3210 } 3211 } 3212 3213 // Watch for the request port command completion from the socket node, because we need to save the port pointer 3214 if (iType == ESocket && iCmd == ERequestPort && status == PVMFSuccess) 3215 { 3216 iContainer->iSocketNodePort = (PVMFPortInterface*)aEventData; 3217 } 3218 3219 3220 // Watch for the query track selection interface completion from the protocol engine node. 3221 if (iType == EProtocolEngine && iCmd == EQueryTrackSelection) 3222 { 3223 //see whether we got the TS interface from PE node. 3224 iContainer->iNoPETrackSelect = (status != PVMFSuccess || iContainer->iProtocolEngineNode.iTrackSelection == NULL); 3225 //ignore cmd failure so it won't terminate the Init sequence 3226 if (status != PVMFSuccess) 3227 status = PVMFSuccess; 3228 //Continue the Init sequence now that we have the track select decision. 3229 iContainer->ContinueInitAfterTrackSelectDecision(); 3230 } 3231 3232 // Watch for recognizer start failure 3233 if (iType == ERecognizer && iCmd == ERecognizerStart && aStatus != PVMFSuccess) 3234 { 3235 iContainer->iRecognizerError = true; 3236 //save the error code to report after recognizer close. 3237 iContainer->iRecognizerStartStatus = status; 3238 //purge everything from the subnode command vector except the recognizer 3239 //close command 3240 iContainer->iSubNodeCmdVec.clear(); 3241 iContainer->Push(iContainer->iRecognizerNode, PVMFDownloadManagerSubNodeContainerBase::ERecognizerClose); 3242 //set status to "success" so that we'll continue with processing 3243 status = PVMFSuccess; 3244 } 3245 // Watch for recognizer close completion after a start failure 3246 else if (iContainer->iRecognizerError) 3247 { 3248 OSCL_ASSERT(iCmd == ERecognizerClose); 3249 iContainer->iRecognizerError = false; 3250 //restore the original error code from the recognizer start. 3251 status = iContainer->iRecognizerStartStatus; 3252 } 3253 3254 //Check whether the node command is being cancelled. 3255 if (iCancelCmdState != EIdle) 3256 { 3257 if (!iContainer->iSubNodeCmdVec.empty()) 3258 { 3259 //even if this command succeeded, we want to report 3260 //the node command status as cancelled since some sub-node 3261 //commands were not yet issued. 3262 status = PVMFErrCancelled; 3263 //go into an error state since it's not clear 3264 //how to recover from a partially completed command. 3265 iContainer->SetState(EPVMFNodeError); 3266 } 3267 } 3268 3269 //figure out the next step in the sequence... 3270 //A node command is done when either all sub-node commands are 3271 //done or when one fails. 3272 if (status == PVMFSuccess 3273 && !iContainer->iSubNodeCmdVec.empty()) 3274 { 3275 //The node needs to issue the next sub-node command. 3276 iContainer->RunIfNotReady(); 3277 } 3278 else 3279 { 3280 //node command is done. 3281 OSCL_ASSERT(!iContainer->iCurrentCommand.empty()); 3282 iContainer->CommandComplete(iContainer->iCurrentCommand, iContainer->iCurrentCommand.front(), status, aExtMsg, aEventData); 3283 } 3284} 3285 3286void PVMFDownloadManagerSubNodeContainerBase::CancelCommandDone(PVMFStatus aStatus, PVInterface*aExtMsg, OsclAny*aEventData) 3287{ 3288 OSCL_UNUSED_ARG(aExtMsg); 3289 OSCL_UNUSED_ARG(aEventData); 3290 //a sub-node cancel command is done-- process the result. 3291 3292 OSCL_ASSERT(aStatus != PVMFPending); 3293 3294 iCancelCmdState = EIdle; 3295 //print and ignore any failed sub-node cancel commands. 3296 if (aStatus != PVMFSuccess) 3297 { 3298 switch (iType) 3299 { 3300 case EFormatParser: 3301 PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iContainer->iLogger, PVLOGMSG_DEBUG, (0, 3302 "PVMFDownloadManagerSubNodeContainer::CancelCommandDone Parser Node Cancel failed")); 3303 break; 3304 case EProtocolEngine: 3305 PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iContainer->iLogger, PVLOGMSG_DEBUG, (0, 3306 "PVMFDownloadManagerSubNodeContainer::CancelCommandDone ProtocolEngine Node Cancel failed")); 3307 break; 3308 case ESocket: 3309 PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iContainer->iLogger, PVLOGMSG_DEBUG, (0, 3310 "PVMFDownloadManagerSubNodeContainer::CancelCommandDone Socket Node Cancel failed")); 3311 break; 3312 default: 3313 OSCL_ASSERT(false); 3314 break; 3315 } 3316 } 3317 3318 //Node cancel command is now done. 3319 OSCL_ASSERT(!iContainer->iCancelCommand.empty()); 3320 iContainer->CommandComplete(iContainer->iCancelCommand, iContainer->iCancelCommand.front(), aStatus, NULL, NULL); 3321} 3322 3323//from PVMFNodeCmdStatusObserver 3324void PVMFDownloadManagerSubNodeContainer::NodeCommandCompleted(const PVMFCmdResp& aResponse) 3325{ 3326 //A command to a sub-node is complete 3327 LOGSUBCMD((0, "PVMFDownloadManagerSubNodeContainer::NodeCommandCompleted %s () In CmdId %d Status %d", GETNODESTR, aResponse.GetCmdId(), aResponse.GetCmdStatus())); 3328 3329 if (aResponse.GetCmdStatus() != PVMFSuccess) 3330 { 3331 PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iContainer->iLogger, PVLOGMSG_DEBUG, (0, "PVMFDownloadManagerSubNodeContainer::NodeCommandCompleted Failure! %d", aResponse.GetCmdStatus())); 3332 } 3333 3334 if (aResponse.GetCmdId() == iCmdId 3335 && iCmdState == EBusy) 3336 { 3337 //Process normal command response. 3338 CommandDone(aResponse.GetCmdStatus(), aResponse.GetEventExtensionInterface(), aResponse.GetEventData()); 3339 } 3340 else if (aResponse.GetCmdId() == iCancelCmdId 3341 && iCancelCmdState == EBusy) 3342 { 3343 //Process node cancel command response 3344 CancelCommandDone(aResponse.GetCmdStatus(), aResponse.GetEventExtensionInterface(), aResponse.GetEventData()); 3345 } 3346 //Process Get License cancel command response. 3347 else if (aResponse.GetCmdId() == iCPMCancelGetLicenseCmdId 3348 && iCancelCmdState == EBusy) 3349 { 3350 CancelCommandDone(aResponse.GetCmdStatus(), aResponse.GetEventExtensionInterface(), aResponse.GetEventData()); 3351 } 3352 else 3353 { 3354 OSCL_ASSERT(false);//unexpected response. 3355 } 3356} 3357 3358 3359//From capability and config interface 3360PVMFStatus PVMFDownloadManagerNode::getParametersSync(PvmiMIOSession aSession, 3361 PvmiKeyType aIdentifier, 3362 PvmiKvp*& aParameters, 3363 int& aNumParamElements, 3364 PvmiCapabilityContext aContext) 3365{ 3366 OSCL_UNUSED_ARG(aSession); 3367 OSCL_UNUSED_ARG(aContext); 3368 // Initialize the output parameters 3369 aNumParamElements = 0; 3370 aParameters = NULL; 3371 3372 // Count the number of components and parameters in the key 3373 int compcount = pv_mime_string_compcnt(aIdentifier); 3374 // Retrieve the first component from the key string 3375 char* compstr = NULL; 3376 pv_mime_string_extract_type(0, aIdentifier, compstr); 3377 3378 if ((pv_mime_strcmp(compstr, _STRLIT_CHAR("x-pvmf")) < 0) || compcount < 2) 3379 { 3380 // First component should be "x-pvmf" and there must 3381 // be at least two components to go past x-pvmf 3382 PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_ERR, (0, "PVMFDownloadManagerNode::getParametersSync() Invalid key string")); 3383 return PVMFErrArgument; 3384 } 3385 3386 // Retrieve the second component from the key string 3387 pv_mime_string_extract_type(1, aIdentifier, compstr); 3388 3389 // Check if it is key string for Download manager 3390 if (pv_mime_strcmp(compstr, _STRLIT_CHAR("net")) < 0) 3391 { 3392 PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_ERR, (0, "PVMFDownloadManagerNode::getParametersSync() Unsupported key")); 3393 return PVMFFailure; 3394 } 3395 3396 3397 if (compcount == 2) 3398 { 3399 // Since key is "x-pvmf/net" return all 3400 // nodes available at this level. Ignore attribute 3401 // since capability is only allowed 3402 3403 // Allocate memory for the KVP list 3404 aParameters = (PvmiKvp*)oscl_malloc(DownloadManagerConfig_NumBaseKeys * sizeof(PvmiKvp)); 3405 if (aParameters == NULL) 3406 { 3407 PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_ERR, (0, "PVMFDownloadManagerNode::getParametersSync() Memory allocation for KVP failed")); 3408 return PVMFErrNoMemory; 3409 } 3410 oscl_memset(aParameters, 0, DownloadManagerConfig_NumBaseKeys*sizeof(PvmiKvp)); 3411 // Allocate memory for the key strings in each KVP 3412 PvmiKeyType memblock = (PvmiKeyType)oscl_malloc(DownloadManagerConfig_NumBaseKeys * DLMCONFIG_KEYSTRING_SIZE * sizeof(char)); 3413 if (memblock == NULL) 3414 { 3415 oscl_free(aParameters); 3416 PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_ERR, (0, "PVMFDownloadManagerNode::getParametersSync() Memory allocation for key string failed")); 3417 return PVMFErrNoMemory; 3418 } 3419 oscl_strset(memblock, 0, DownloadManagerConfig_NumBaseKeys*DLMCONFIG_KEYSTRING_SIZE*sizeof(char)); 3420 // Assign the key string buffer to each KVP 3421 uint32 j; 3422 for (j = 0; j < DownloadManagerConfig_NumBaseKeys; ++j) 3423 { 3424 aParameters[j].key = memblock + (j * DLMCONFIG_KEYSTRING_SIZE); 3425 } 3426 // Copy the requested info 3427 for (j = 0; j < DownloadManagerConfig_NumBaseKeys; ++j) 3428 { 3429 oscl_strncat(aParameters[j].key, _STRLIT_CHAR("x-pvmf/net/"), 17); 3430 oscl_strncat(aParameters[j].key, DownloadManagerConfig_BaseKeys[j].iString, oscl_strlen(DownloadManagerConfig_BaseKeys[j].iString)); 3431 oscl_strncat(aParameters[j].key, _STRLIT_CHAR(";type="), 6); 3432 switch (DownloadManagerConfig_BaseKeys[j].iType) 3433 { 3434 case PVMI_KVPTYPE_AGGREGATE: 3435 oscl_strncat(aParameters[j].key, _STRLIT_CHAR(PVMI_KVPTYPE_AGGREGATE_STRING), oscl_strlen(PVMI_KVPTYPE_AGGREGATE_STRING)); 3436 break; 3437 3438 case PVMI_KVPTYPE_POINTER: 3439 oscl_strncat(aParameters[j].key, _STRLIT_CHAR(PVMI_KVPTYPE_POINTER_STRING), oscl_strlen(PVMI_KVPTYPE_POINTER_STRING)); 3440 break; 3441 3442 case PVMI_KVPTYPE_VALUE: 3443 default: 3444 oscl_strncat(aParameters[j].key, _STRLIT_CHAR(PVMI_KVPTYPE_VALUE_STRING), oscl_strlen(PVMI_KVPTYPE_VALUE_STRING)); 3445 break; 3446 } 3447 oscl_strncat(aParameters[j].key, _STRLIT_CHAR(";valtype="), 9); 3448 switch (DownloadManagerConfig_BaseKeys[j].iValueType) 3449 { 3450 case PVMI_KVPVALTYPE_RANGE_INT32: 3451 oscl_strncat(aParameters[j].key, _STRLIT_CHAR(PVMI_KVPVALTYPE_RANGE_INT32_STRING), oscl_strlen(PVMI_KVPVALTYPE_RANGE_INT32_STRING)); 3452 break; 3453 3454 case PVMI_KVPVALTYPE_KSV: 3455 oscl_strncat(aParameters[j].key, _STRLIT_CHAR(PVMI_KVPVALTYPE_KSV_STRING), oscl_strlen(PVMI_KVPVALTYPE_KSV_STRING)); 3456 break; 3457 3458 case PVMI_KVPVALTYPE_CHARPTR: 3459 oscl_strncat(aParameters[j].key, _STRLIT_CHAR(PVMI_KVPVALTYPE_CHARPTR_STRING), oscl_strlen(PVMI_KVPVALTYPE_CHARPTR_STRING)); 3460 break; 3461 3462 case PVMI_KVPVALTYPE_WCHARPTR: 3463 oscl_strncat(aParameters[j].key, _STRLIT_CHAR(PVMI_KVPVALTYPE_WCHARPTR_STRING), oscl_strlen(PVMI_KVPVALTYPE_WCHARPTR_STRING)); 3464 break; 3465 3466 case PVMI_KVPVALTYPE_BOOL: 3467 oscl_strncat(aParameters[j].key, _STRLIT_CHAR(PVMI_KVPVALTYPE_BOOL_STRING), oscl_strlen(PVMI_KVPVALTYPE_BOOL_STRING)); 3468 break; 3469 3470 case PVMI_KVPVALTYPE_UINT32: 3471 default: 3472 oscl_strncat(aParameters[j].key, _STRLIT_CHAR(PVMI_KVPVALTYPE_UINT32_STRING), oscl_strlen(PVMI_KVPVALTYPE_UINT32_STRING)); 3473 break; 3474 } 3475 aParameters[j].key[DLMCONFIG_KEYSTRING_SIZE-1] = 0; 3476 } 3477 3478 aNumParamElements = DownloadManagerConfig_NumBaseKeys; 3479 } 3480 else if (compcount == 3) 3481 { 3482 pv_mime_string_extract_type(2, aIdentifier, compstr); 3483 3484 // Determine what is requested 3485 PvmiKvpAttr reqattr = GetAttrTypeFromKeyString(aIdentifier); 3486 if (reqattr == PVMI_KVPATTR_UNKNOWN) 3487 { 3488 reqattr = PVMI_KVPATTR_CUR; 3489 } 3490 uint i; 3491 for (i = 0; i < DownloadManagerConfig_NumBaseKeys; i++) 3492 { 3493 if (pv_mime_strcmp(compstr, (char*)(DownloadManagerConfig_BaseKeys[i].iString)) >= 0) 3494 { 3495 break; 3496 } 3497 } 3498 3499 if (i == DownloadManagerConfig_NumBaseKeys) 3500 { 3501 // no match found 3502 PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_ERR, 3503 (0, "PVMFDownloadManagerNode::getParametersSync() Unsupported key")); 3504 return PVMFErrNoMemory; 3505 } 3506 } 3507 else 3508 { 3509 oscl_free(aParameters); 3510 PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_ERR, (0, "PVMFDownloadManagerNode::getParametersSync() Unsupported key")); 3511 return PVMFErrNoMemory; 3512 } 3513 3514 return PVMFSuccess; 3515} 3516 3517 3518PVMFStatus PVMFDownloadManagerNode::releaseParameters(PvmiMIOSession aSession, 3519 PvmiKvp* aParameters, 3520 int num_elements) 3521{ 3522 OSCL_UNUSED_ARG(aSession); 3523 3524 PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE, 3525 (0, "PVMFDownloadManagerNode::releaseParameters() In")); 3526 3527 if (aParameters == NULL || num_elements < 1) 3528 { 3529 PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_ERR, 3530 (0, "PVMFDownloadManagerNode::releaseParameters() KVP list is NULL or number of elements is 0")); 3531 return PVMFErrArgument; 3532 } 3533 3534 // Count the number of components and parameters in the key 3535 int compcount = pv_mime_string_compcnt(aParameters[0].key); 3536 // Retrieve the first component from the key string 3537 char* compstr = NULL; 3538 pv_mime_string_extract_type(0, aParameters[0].key, compstr); 3539 3540 if ((pv_mime_strcmp(compstr, _STRLIT_CHAR("x-pvmf")) < 0) || compcount < 2) 3541 { 3542 // First component should be "x-pvmf" and there must 3543 // be at least two components to go past x-pvmf 3544 PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_ERR, 3545 (0, "PVMFDownloadManagerNode::releaseParameters() Unsupported key")); 3546 return PVMFErrArgument; 3547 } 3548 3549 // Retrieve the second component from the key string 3550 pv_mime_string_extract_type(1, aParameters[0].key, compstr); 3551 3552 // Assume all the parameters come from the same component so the base components are the same 3553 if (pv_mime_strcmp(compstr, _STRLIT_CHAR("net")) >= 0) 3554 { 3555 // Go through each KVP and release memory for value if allocated from heap 3556 for (int32 i = 0; i < num_elements; ++i) 3557 { 3558 // Next check if it is a value type that allocated memory 3559 PvmiKvpType kvptype = GetTypeFromKeyString(aParameters[i].key); 3560 if (kvptype == PVMI_KVPTYPE_VALUE || kvptype == PVMI_KVPTYPE_UNKNOWN) 3561 { 3562 PvmiKvpValueType keyvaltype = GetValTypeFromKeyString(aParameters[i].key); 3563 if (keyvaltype == PVMI_KVPVALTYPE_UNKNOWN) 3564 { 3565 PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_ERR, 3566 (0, "PVMFDownloadManagerNode::releaseParameters() Valtype not specified in key string")); 3567 return PVMFErrArgument; 3568 } 3569 3570 if (keyvaltype == PVMI_KVPVALTYPE_CHARPTR && aParameters[i].value.pChar_value != NULL) 3571 { 3572 oscl_free(aParameters[i].value.pChar_value); 3573 aParameters[i].value.pChar_value = NULL; 3574 } 3575 else if (keyvaltype == PVMI_KVPVALTYPE_WCHARPTR && aParameters[i].value.pWChar_value != NULL) 3576 { 3577 oscl_free(aParameters[i].value.pWChar_value); 3578 aParameters[i].value.pWChar_value = NULL; 3579 } 3580 else if (keyvaltype == PVMI_KVPVALTYPE_CHARPTR && aParameters[i].value.pChar_value != NULL) 3581 { 3582 oscl_free(aParameters[i].value.pChar_value); 3583 aParameters[i].value.pChar_value = NULL; 3584 } 3585 else if (keyvaltype == PVMI_KVPVALTYPE_KSV && aParameters[i].value.key_specific_value != NULL) 3586 { 3587 oscl_free(aParameters[i].value.key_specific_value); 3588 aParameters[i].value.key_specific_value = NULL; 3589 } 3590 else if (keyvaltype == PVMI_KVPVALTYPE_RANGE_INT32 && aParameters[i].value.key_specific_value != NULL) 3591 { 3592 range_int32* ri32 = (range_int32*)aParameters[i].value.key_specific_value; 3593 aParameters[i].value.key_specific_value = NULL; 3594 oscl_free(ri32); 3595 } 3596 else if (keyvaltype == PVMI_KVPVALTYPE_RANGE_UINT32 && aParameters[i].value.key_specific_value != NULL) 3597 { 3598 range_uint32* rui32 = (range_uint32*)aParameters[i].value.key_specific_value; 3599 aParameters[i].value.key_specific_value = NULL; 3600 oscl_free(rui32); 3601 } 3602 } 3603 } 3604 3605 oscl_free(aParameters[0].key); 3606 3607 // Free memory for the parameter list 3608 oscl_free(aParameters); 3609 aParameters = NULL; 3610 } 3611 else 3612 { 3613 // Unknown key string 3614 return PVMFErrArgument; 3615 } 3616 3617 PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE, 3618 (0, "PVMFDownloadManagerNode::releaseParameters() Out")); 3619 return PVMFSuccess; 3620 3621} 3622 3623void PVMFDownloadManagerNode::createContext(PvmiMIOSession aSession, PvmiCapabilityContext& aContext) 3624{ 3625 OSCL_UNUSED_ARG(aSession); 3626 OSCL_UNUSED_ARG(aContext); 3627 // not supported 3628 OSCL_LEAVE(PVMFErrNotSupported); 3629} 3630 3631void PVMFDownloadManagerNode::setContextParameters(PvmiMIOSession aSession, PvmiCapabilityContext& aContext, 3632 PvmiKvp* aParameters, int num_parameter_elements) 3633{ 3634 OSCL_UNUSED_ARG(aSession); 3635 OSCL_UNUSED_ARG(aContext); 3636 OSCL_UNUSED_ARG(aParameters); 3637 OSCL_UNUSED_ARG(num_parameter_elements); 3638 // not supported 3639 OSCL_LEAVE(PVMFErrNotSupported); 3640} 3641 3642void PVMFDownloadManagerNode::DeleteContext(PvmiMIOSession aSession, 3643 PvmiCapabilityContext& aContext) 3644{ 3645 OSCL_UNUSED_ARG(aSession); 3646 OSCL_UNUSED_ARG(aContext); 3647 // not supported 3648 OSCL_LEAVE(PVMFErrNotSupported); 3649} 3650 3651void PVMFDownloadManagerNode::setParametersSync(PvmiMIOSession aSession, PvmiKvp* aParameters, 3652 int num_elements, PvmiKvp * & aRet_kvp) 3653{ 3654 OSCL_UNUSED_ARG(aSession); 3655 3656 PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE, 3657 (0, "PVMFDownloadManagerNode::setParametersSync() In")); 3658 3659 aRet_kvp = NULL; 3660 3661 // Go through each parameter 3662 for (int paramind = 0; paramind < num_elements; ++paramind) 3663 { 3664 // Count the number of components and parameters in the key 3665 int compcount = pv_mime_string_compcnt(aParameters[paramind].key); 3666 3667 // Retrieve the first component from the key string 3668 char* compstr = NULL; 3669 pv_mime_string_extract_type(0, aParameters[paramind].key, compstr); 3670 3671 if ((pv_mime_strcmp(compstr, _STRLIT_CHAR("x-pvmf")) < 0) || compcount < 2) 3672 { 3673 // First component should be "x-pvmf" and there must 3674 // be at least two components to go past x-pvmf 3675 aRet_kvp = &aParameters[paramind]; 3676 PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_ERR, 3677 (0, "PVMFDownloadManagerNode::setParametersSync() Unsupported key")); 3678 return; 3679 } 3680 3681 // Retrieve the second component from the key string 3682 pv_mime_string_extract_type(1, aParameters[paramind].key, compstr); 3683 3684 // First check if it is key string for the Download manager 3685 if (pv_mime_strcmp(compstr, _STRLIT_CHAR("net")) >= 0) 3686 { 3687 if (compcount == 3) 3688 { 3689 pv_mime_string_extract_type(2, aParameters[paramind].key, compstr); 3690 uint i; 3691 for (i = 0; i < DownloadManagerConfig_NumBaseKeys; i++) 3692 { 3693 if (pv_mime_strcmp(compstr, (char*)(DownloadManagerConfig_BaseKeys[i].iString)) >= 0) 3694 { 3695 break; 3696 } 3697 } 3698 3699 if (DownloadManagerConfig_NumBaseKeys == i) 3700 { 3701 // invalid third component 3702 aRet_kvp = &aParameters[paramind]; 3703 PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_ERR, 3704 (0, "PVMFDownloadManagerNode::setParametersSync() Unsupported key")); 3705 return; 3706 } 3707 3708 // Verify and set the passed-in setting 3709 switch (i) 3710 { 3711 case BASEKEY_SESSION_CONTROLLER_USER_AGENT: 3712 { 3713 if (IsDownloadExtensionHeaderValid(*aParameters)) 3714 { 3715 //setting KVP string for download when mode applied for download or not applied at all. 3716 OSCL_wHeapString<OsclMemAllocator> userAgent; 3717 userAgent = aParameters[paramind].value.pWChar_value; 3718 (iProtocolEngineNode.ProtocolEngineExtension())->SetUserAgent(userAgent, true); 3719 } 3720 } 3721 break; 3722 case BASEKEY_SESSION_CONTROLLER_HTTP_VERSION: 3723 { 3724 uint32 httpVersion; 3725 httpVersion = aParameters[paramind].value.uint32_value; 3726 (iProtocolEngineNode.ProtocolEngineExtension())->SetHttpVersion(httpVersion); 3727 3728 } 3729 break; 3730 case BASEKEY_SESSION_CONTROLLER_HTTP_TIMEOUT: 3731 { 3732 uint32 httpTimeout; 3733 httpTimeout = aParameters[paramind].value.uint32_value; 3734 (iProtocolEngineNode.ProtocolEngineExtension())->SetNetworkTimeout(httpTimeout); 3735 } 3736 break; 3737 case BASEKEY_SESSION_CONTROLLER_DOWNLOAD_PROGRESS_INFO: 3738 { 3739 OSCL_HeapString<OsclMemAllocator> downloadProgressInfo; 3740 downloadProgressInfo = aParameters[paramind].value.pChar_value; 3741 DownloadProgressMode aMode = DownloadProgressMode_TimeBased; 3742 if (IsByteBasedDownloadProgress(downloadProgressInfo)) aMode = DownloadProgressMode_ByteBased; 3743 (iProtocolEngineNode.ProtocolEngineExtension())->SetDownloadProgressMode(aMode); 3744 } 3745 break; 3746 case BASEKEY_SESSION_CONTROLLER_PROTOCOL_EXTENSION_HEADER: 3747 { 3748 if (IsDownloadExtensionHeaderValid(aParameters[paramind])) 3749 { 3750 OSCL_HeapString<OsclMemAllocator> extensionHeaderKey; 3751 OSCL_HeapString<OsclMemAllocator> extensionHeaderValue; 3752 HttpMethod httpMethod = HTTP_GET; 3753 bool aPurgeOnRedirect = false; 3754 if (GetHttpExtensionHeaderParams(aParameters[paramind], 3755 extensionHeaderKey, 3756 extensionHeaderValue, 3757 httpMethod, 3758 aPurgeOnRedirect)) 3759 { 3760 (iProtocolEngineNode.ProtocolEngineExtension())->SetHttpExtensionHeaderField(extensionHeaderKey, 3761 extensionHeaderValue, 3762 httpMethod, 3763 aPurgeOnRedirect); 3764 } 3765 } 3766 3767 } 3768 break; 3769 3770 case BASEKEY_SESSION_CONTROLLER_NUM_REDIRECT_ATTEMPTS: 3771 { 3772 if (IsDownloadExtensionHeaderValid(*aParameters)) 3773 { 3774 //setting KVP string for download when mode applied for download or not applied at all. 3775 uint32 numRedirects = aParameters[paramind].value.uint32_value; 3776 (iProtocolEngineNode.ProtocolEngineExtension())->SetNumRedirectTrials(numRedirects); 3777 } 3778 } 3779 break; 3780 3781 case BASEKEY_SESSION_CONTROLLER_NUM_HTTP_HEADER_REQUEST_DISABLED: 3782 { 3783 bool httpHeaderRequestDisabled = aParameters[paramind].value.bool_value; 3784 (iProtocolEngineNode.ProtocolEngineExtension())->DisableHttpHeadRequest(httpHeaderRequestDisabled); 3785 } 3786 break; 3787 3788 case BASEKEY_MAX_TCP_RECV_BUFFER_SIZE: 3789 { 3790 uint32 size = aParameters[paramind].value.uint32_value; 3791 PVMFSocketNode* socketNode = 3792 (PVMFSocketNode*)(iSocketNode.iNode); 3793 if (socketNode != NULL) 3794 { 3795 socketNode->SetMaxTCPRecvBufferSize(size); 3796 } 3797 } 3798 break; 3799 3800 case BASEKEY_MAX_TCP_RECV_BUFFER_COUNT: 3801 { 3802 uint32 size = aParameters[paramind].value.uint32_value; 3803 PVMFSocketNode* socketNode = 3804 (PVMFSocketNode*)(iSocketNode.iNode); 3805 if (socketNode != NULL) 3806 { 3807 socketNode->SetMaxTCPRecvBufferCount(size); 3808 } 3809 } 3810 break; 3811 3812 default: 3813 { 3814 aRet_kvp = &aParameters[paramind]; 3815 PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_ERR, 3816 (0, "PVMFDownloadManagerNode::setParametersSync() Setting " 3817 "parameter %d failed", paramind)); 3818 } 3819 break; 3820 } 3821 } 3822 else 3823 { 3824 // Do not support more than 3 components right now 3825 aRet_kvp = &aParameters[paramind]; 3826 PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_ERR, 3827 (0, "PVMFDownloadManagerNode::setParametersSync() Unsupported key")); 3828 return; 3829 } 3830 } 3831 else 3832 { 3833 // Unknown key string 3834 aRet_kvp = &aParameters[paramind]; 3835 PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_ERR, 3836 (0, "PVMFDownloadManagerNode::setParametersSync() Unsupported key")); 3837 return; 3838 } 3839 } 3840 3841 PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE, 3842 (0, "PVMFDownloadManagerNode::setParametersSync() Out")); 3843} 3844 3845bool PVMFDownloadManagerNode::IsByteBasedDownloadProgress(OSCL_String &aDownloadProgressInfo) 3846{ 3847 if (aDownloadProgressInfo.get_size() < 4) return false; // 4 => byte 3848 char *ptr = (char*)aDownloadProgressInfo.get_cstr(); 3849 uint32 len = aDownloadProgressInfo.get_size(); 3850 3851 while (!(((ptr[0] | OSCL_ASCII_CASE_MAGIC_BIT) == 'b') && 3852 ((ptr[1] | OSCL_ASCII_CASE_MAGIC_BIT) == 'y') && 3853 ((ptr[2] | OSCL_ASCII_CASE_MAGIC_BIT) == 't') && 3854 ((ptr[3] | OSCL_ASCII_CASE_MAGIC_BIT) == 'e')) && 3855 len >= 4) 3856 { 3857 ptr++; 3858 len--; 3859 } 3860 if (len < 4) return false; 3861 3862 return true; // find case-insentive string "byte" 3863} 3864 3865bool PVMFDownloadManagerNode::GetHttpExtensionHeaderParams(PvmiKvp &aParameter, 3866 OSCL_String &extensionHeaderKey, 3867 OSCL_String &extensionHeaderValue, 3868 HttpMethod &httpMethod, 3869 bool &aPurgeOnRedirect) 3870{ 3871 // check if the extension header is meant for download 3872 if (!IsHttpExtensionHeaderValid(aParameter)) return false; 3873 3874 // get aPurgeOnRedirect 3875 aPurgeOnRedirect = false; 3876 OSCL_StackString<32> purgeOnRedirect(_STRLIT_CHAR("purge-on-redirect")); 3877 if (oscl_strstr(aParameter.key, purgeOnRedirect.get_cstr()) != NULL) 3878 { 3879 aPurgeOnRedirect = true; 3880 } 3881 3882 // get key, value and http method of protocol extension header 3883 // the string value needs to be structured as follows: "key=app-feature-tag;value=xyz" 3884 char* extensionHeader = aParameter.value.pChar_value; 3885 if (!extensionHeader) return false; 3886 3887 // (1) extract the key 3888 OSCL_StackString<8> keyTag(_STRLIT_CHAR("key=")); 3889 3890 OSCL_StackString<8> valueTag(_STRLIT_CHAR("value=")); 3891 char *keyStart = OSCL_CONST_CAST(char*, oscl_strstr(extensionHeader, keyTag.get_cstr())); 3892 if (!keyStart) return false; 3893 3894 keyStart += keyTag.get_size(); 3895 char *keyEnd = OSCL_CONST_CAST(char*, oscl_strstr(extensionHeader, valueTag.get_cstr())); 3896 if (!keyEnd) return false; 3897 uint32 keyLen = getItemLen(keyStart, keyEnd); 3898 if (keyLen == 0) return false; 3899 extensionHeaderKey = OSCL_HeapString<OsclMemAllocator> (keyStart, keyLen); 3900 3901 // (2) extract the value 3902 char* valueStart = keyEnd; 3903 valueStart += valueTag.get_size(); 3904 3905 OSCL_StackString<8> methodTag(_STRLIT_CHAR("method=")); 3906 char* valueEnd = OSCL_CONST_CAST(char*, oscl_strstr(valueStart, methodTag.get_cstr())); 3907 if (!valueEnd) valueEnd = extensionHeader + aParameter.capacity; 3908 uint32 valueLen = getItemLen(valueStart, valueEnd); 3909 extensionHeaderValue = OSCL_HeapString<OsclMemAllocator> (valueStart, valueLen); 3910 3911 // (3) check for optional method 3912 const char *methodStart = oscl_strstr(extensionHeader, methodTag.get_cstr()); 3913 if (!methodStart) 3914 { 3915 httpMethod = HTTP_GET; 3916 return true; 3917 } 3918 methodStart += methodTag.get_size(); 3919 3920 OSCL_StackString<8> methodHttpGet(_STRLIT_CHAR("GET")); 3921 OSCL_StackString<8> methodHttpHead(_STRLIT_CHAR("HEAD")); 3922 OSCL_StackString<8> methodHttpPost(_STRLIT_CHAR("POST")); 3923 3924 const char* methodGet = oscl_strstr(methodStart, methodHttpGet.get_cstr()); 3925 const char* methodHead = oscl_strstr(methodStart, methodHttpHead.get_cstr()); 3926 const char* methodPost = oscl_strstr(methodStart, methodHttpPost.get_cstr()); 3927 3928 httpMethod = HTTP_GET; 3929 if (methodPost != NULL) httpMethod = HTTP_POST; 3930 if (methodGet != NULL) httpMethod = HTTP_GET; 3931 if (methodHead != NULL) httpMethod = HTTP_HEAD; 3932 if ((methodGet != NULL) && (methodHead != NULL)) httpMethod = HTTP_ALLMETHOD; 3933 3934 return true; 3935} 3936 3937bool PVMFDownloadManagerNode::IsHttpExtensionHeaderValid(PvmiKvp &aParameter) 3938{ 3939 OSCL_StackString<32> downloadMode(_STRLIT_CHAR("mode=download")); 3940 OSCL_StackString<32> streamingMode(_STRLIT_CHAR("mode=streaming")); 3941 3942 bool isDownloadMode = (oscl_strstr(aParameter.key, downloadMode.get_cstr()) != NULL); 3943 bool isStreamingMode = (oscl_strstr(aParameter.key, streamingMode.get_cstr()) != NULL); 3944 3945 // streaming mode only would fail, download mode specified or not specified will be viewed as true 3946 if (isStreamingMode && !isDownloadMode) return false; 3947 3948 return true; 3949} 3950 3951// remove the ending ';', ',' or ' ' and calulate value length 3952uint32 PVMFDownloadManagerNode::getItemLen(char *ptrItemStart, char *ptrItemEnd) 3953{ 3954 char *ptr = ptrItemEnd - 1; 3955 uint32 itemLen = ptr - ptrItemStart; 3956 for (uint32 i = 0; i < itemLen; i++) 3957 { 3958 if (*ptr == ';' || *ptr == ',' || *ptr == ' ') --ptr; 3959 else break; 3960 } 3961 itemLen = ptr - ptrItemStart + 1; 3962 return itemLen; 3963} 3964 3965 3966PVMFCommandId PVMFDownloadManagerNode::setParametersAsync(PvmiMIOSession aSession, 3967 PvmiKvp* aParameters, 3968 int num_elements, 3969 PvmiKvp*& aRet_kvp, 3970 OsclAny* context) 3971{ 3972 OSCL_UNUSED_ARG(aSession); 3973 OSCL_UNUSED_ARG(aParameters); 3974 OSCL_UNUSED_ARG(num_elements); 3975 OSCL_UNUSED_ARG(aRet_kvp); 3976 OSCL_UNUSED_ARG(context); 3977 // not supported 3978 OSCL_LEAVE(PVMFErrNotSupported); 3979 return 0; 3980} 3981 3982uint32 PVMFDownloadManagerNode::getCapabilityMetric(PvmiMIOSession aSession) 3983{ 3984 OSCL_UNUSED_ARG(aSession); 3985 return 0; 3986} 3987 3988PVMFStatus PVMFDownloadManagerNode::verifyParametersSync(PvmiMIOSession aSession, 3989 PvmiKvp* aParameters, 3990 int num_elements) 3991{ 3992 OSCL_UNUSED_ARG(aSession); 3993 OSCL_UNUSED_ARG(aParameters); 3994 OSCL_UNUSED_ARG(num_elements); 3995 // not supported 3996 OSCL_LEAVE(PVMFErrNotSupported); 3997 return 0; 3998} 3999 4000bool PVMFDownloadManagerNode::IsDownloadExtensionHeaderValid(PvmiKvp &aParameter) 4001{ 4002 OSCL_StackString<32> downloadMode(_STRLIT_CHAR("mode=download")); 4003 OSCL_StackString<32> streamingMode(_STRLIT_CHAR("mode=streaming")); 4004 OSCL_StackString<32> dlaMode(_STRLIT_CHAR("mode=dla")); 4005 4006 bool isDownloadMode = (oscl_strstr(aParameter.key, downloadMode.get_cstr()) != NULL); 4007 bool isStreamingMode = (oscl_strstr(aParameter.key, streamingMode.get_cstr()) != NULL); 4008 bool isDlaMode = (oscl_strstr(aParameter.key, dlaMode.get_cstr()) != NULL); 4009 4010 4011 // streaming mode only would fail, download mode specified or not specified will be viewed as true 4012 if (isStreamingMode && !isDownloadMode) return false; 4013 4014 // dla mode only would fail, download mode specified or not specified will be viewed as true 4015 if (isDlaMode && !isDownloadMode) return false; 4016 4017 return true; 4018} 4019 4020void PVMFDownloadManagerNode::NotificationsInterfaceDestroyed() 4021{ 4022 iClockNotificationsInf = NULL; 4023} 4024 4025void PVMFDownloadManagerNode::ClockStateUpdated() 4026{ 4027 if (!iDataReady) 4028 { 4029 // Don't let anyone start the clock while the source node is in underflow 4030 if (iPlayBackClock != NULL) 4031 { 4032 if (iPlayBackClock->GetState() == PVMFMediaClock::RUNNING) 4033 { 4034 iPlayBackClock->Pause(); 4035 } 4036 } 4037 } 4038} 4039