Home | History | Annotate | Download | only in src
      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 
     47 static 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 
     60 static const uint DownloadManagerConfig_NumBaseKeys =
     61     (sizeof(DownloadManagerConfig_BaseKeys) /
     62      sizeof(DownloadManagerKeyStringData));
     63 
     64 enum 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 
     79 PVMFDownloadManagerNode::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 
    101 void 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 
    182 PVMFDownloadManagerNode::~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.
    264 PVMFStatus 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.
    290 PVMFStatus 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.
    317 PVMFStatus 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.
    328 PVMFPortIter* 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.
    339 PVMFCommandId 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.
    352 PVMFCommandId 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.
    364 PVMFCommandId 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.
    376 PVMFStatus 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.
    387 PVMFCommandId 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.
    398 PVMFCommandId 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.
    409 PVMFCommandId 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.
    420 PVMFCommandId 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.
    431 PVMFCommandId 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.
    442 PVMFCommandId 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.
    453 PVMFCommandId 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.
    464 PVMFCommandId 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.
    475 PVMFCommandId 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
    485 void PVMFDownloadManagerNode::addRef()
    486 {
    487     ++iExtensionRefCount;
    488 }
    489 
    490 //public API from PVInterface
    491 void PVMFDownloadManagerNode::removeRef()
    492 {
    493     --iExtensionRefCount;
    494 }
    495 
    496 //public API from PVInterface
    497 bool 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
    548 PVMFStatus 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
    895 PVMFStatus 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
    920 PVMFStatus PVMFDownloadManagerNode::SetEstimatedServerClock(PVMFMediaClock*)
    921 {
    922     //not needed for download.
    923     return PVMFErrNotSupported;
    924 }
    925 
    926 PVMFDownloadManagerSubNodeContainer& 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.
    953 PVMFStatus 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.
    966 PVMFStatus 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 
    979 uint32 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 
    989 uint32 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 
   1000 PVMFCommandId 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 
   1010 PVMFCommandId 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
   1020 PVMFStatus 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
   1033 PVMFStatus 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
   1047 PVMFCommandId 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 
   1064 PVMFCommandId 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 
   1084 PVMFCommandId 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 
   1100 PVMFCommandId 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 
   1110 PVMFStatus PVMFDownloadManagerNode::SetPlayerNodeRegistry(PVPlayerNodeRegistryInterface* aRegistry)
   1111 {
   1112     iPlayerNodeRegistry = aRegistry;
   1113     return PVMFSuccess;
   1114 }
   1115 
   1116 void 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 
   1135 PVMFCommandId 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 
   1149 void 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 
   1300 void 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 
   1386 void 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 
   1397 void 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 
   1422 void PVMFDownloadManagerNode::GenerateDataReadyEvent()
   1423 {
   1424     PVMFAsyncEvent info(PVMFInfoEvent, PVMFInfoDataReady, NULL, NULL);
   1425     ReportInfoEvent(info);
   1426     iDataReady = true;
   1427 }
   1428 
   1429 bool 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 
   1468 void 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 
   1478 PVMFStatus 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 
   1501 PVMFStatus 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 
   1524 PVMFStatus 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 
   1536 PVMFStatus 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 
   1545 PVMFStatus 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 
   1557 PVMFStatus 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 
   1569 PVMFStatus 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 
   1582 PVMFStatus 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 
   1596 PVMFStatus 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 
   1609 PVMFStatus 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 
   1621 PVMFStatus 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 
   1641 PVMFStatus 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 
   1672 PVMFStatus 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 
   1713 PVMFStatus 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 
   1724 PVMFStatus 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 
   1735 PVMFStatus 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 
   1745 PVMFStatus 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 
   1754 void 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 
   1777 void 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.
   1844 void 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 
   1874 PVMFNodeInterface* 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 
   1895 PVMFStatus 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 
   2129 void 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 
   2138 PVMFCommandId
   2139 PVMFDownloadManagerNode::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 
   2158 PVMFCommandId
   2159 PVMFDownloadManagerNode::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 
   2179 PVMFCommandId
   2180 PVMFDownloadManagerNode::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 
   2193 PVMFStatus 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 
   2214 void PVMFDownloadManagerNode::CompleteGetLicense()
   2215 {
   2216     CommandComplete(iCurrentCommand,
   2217                     iCurrentCommand.front(),
   2218                     PVMFSuccess, NULL, NULL);
   2219 }
   2220 
   2221 PVMFStatus 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 
   2243 PVMFDownloadManagerSubNodeContainerBase::PVMFDownloadManagerSubNodeContainerBase()
   2244 {
   2245     iCmdState = EIdle;
   2246     iCancelCmdState = EIdle;
   2247 }
   2248 
   2249 void PVMFDownloadManagerSubNodeContainerBase::Construct(NodeType t, PVMFDownloadManagerNode* c)
   2250 {
   2251     iContainer = c;
   2252     iType = t;
   2253 }
   2254 
   2255 void 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 
   2306 void PVMFDownloadManagerRecognizerContainer::Cleanup()
   2307 {
   2308     // Nothing to do here 'til recognizer is integrated
   2309 }
   2310 
   2311 void 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 
   2327 PVMFStatus 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 
   2772 PVMFStatus 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.
   2830 void 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
   2999 void 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
   3033 void 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 
   3140 bool 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 
   3159 bool 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 
   3176 void 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 
   3286 void 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
   3324 void 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
   3360 PVMFStatus 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 
   3518 PVMFStatus 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 
   3623 void 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 
   3631 void 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 
   3642 void 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 
   3651 void 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 
   3845 bool 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 
   3865 bool 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 
   3937 bool 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
   3952 uint32 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 
   3966 PVMFCommandId 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 
   3982 uint32 PVMFDownloadManagerNode::getCapabilityMetric(PvmiMIOSession aSession)
   3983 {
   3984     OSCL_UNUSED_ARG(aSession);
   3985     return 0;
   3986 }
   3987 
   3988 PVMFStatus 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 
   4000 bool 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 
   4020 void PVMFDownloadManagerNode::NotificationsInterfaceDestroyed()
   4021 {
   4022     iClockNotificationsInf = NULL;
   4023 }
   4024 
   4025 void 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