• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 
PVMFDownloadManagerNode(int32 aPriority)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 
ConstructL()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 
~PVMFDownloadManagerNode()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.
ThreadLogon()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.
ThreadLogoff()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.
GetCapability(PVMFNodeCapability & aNodeCapability)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.
GetPorts(const PVMFPortFilter * aFilter)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.
QueryUUID(PVMFSessionId aSessionId,const PvmfMimeString & aMimeType,Oscl_Vector<PVUuid,OsclMemAllocator> & aUuids,bool aExactUuidsOnly,const OsclAny * aContext)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.
QueryInterface(PVMFSessionId aSessionId,const PVUuid & aUuid,PVInterface * & aInterfacePtr,const OsclAny * aContext)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.
RequestPort(PVMFSessionId aSessionId,int32 aPortTag,const PvmfMimeString * aPortConfig,const OsclAny * aContext)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.
ReleasePort(PVMFSessionId aSessionId,PVMFPortInterface & aPort,const OsclAny * aContext)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.
Init(PVMFSessionId aSessionId,const OsclAny * aContext)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.
Prepare(PVMFSessionId aSessionId,const OsclAny * aContext)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.
Start(PVMFSessionId aSessionId,const OsclAny * aContext)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.
Stop(PVMFSessionId aSessionId,const OsclAny * aContext)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.
Flush(PVMFSessionId aSessionId,const OsclAny * aContext)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.
Pause(PVMFSessionId aSessionId,const OsclAny * aContext)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.
Reset(PVMFSessionId aSessionId,const OsclAny * aContext)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.
CancelAllCommands(PVMFSessionId aSessionId,const OsclAny * aContext)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.
CancelCommand(PVMFSessionId aSessionId,PVMFCommandId aCmdId,const OsclAny * aContext)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
addRef()485 void PVMFDownloadManagerNode::addRef()
486 {
487     ++iExtensionRefCount;
488 }
489 
490 //public API from PVInterface
removeRef()491 void PVMFDownloadManagerNode::removeRef()
492 {
493     --iExtensionRefCount;
494 }
495 
496 //public API from PVInterface
queryInterface(const PVUuid & uuid,PVInterface * & iface)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
SetSourceInitializationData(OSCL_wString & aSourceURL,PVMFFormatType & aSourceFormat,OsclAny * aSourceData)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
SetClientPlayBackClock(PVMFMediaClock * aClientClock)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
SetEstimatedServerClock(PVMFMediaClock *)920 PVMFStatus PVMFDownloadManagerNode::SetEstimatedServerClock(PVMFMediaClock*)
921 {
922     //not needed for download.
923     return PVMFErrNotSupported;
924 }
925 
TrackSelectNode()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.
GetMediaPresentationInfo(PVMFMediaPresentationInfo & aInfo)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.
SelectTracks(PVMFMediaPresentationInfo & aInfo)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 
GetNumMetadataKeys(char * query_key)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 
GetNumMetadataValues(PVMFMetadataList & aKeyList)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 
GetNodeMetadataKeys(PVMFSessionId aSessionId,PVMFMetadataList & aKeyList,uint32 starting_index,int32 max_entries,char * query_key,const OsclAny * aContext)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 
GetNodeMetadataValues(PVMFSessionId aSessionId,PVMFMetadataList & aKeyList,Oscl_Vector<PvmiKvp,OsclMemAllocator> & aValueList,uint32 starting_index,int32 max_entries,const OsclAny * aContext)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
ReleaseNodeMetadataKeys(PVMFMetadataList & keys,uint32 start,uint32 end)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
ReleaseNodeMetadataValues(Oscl_Vector<PvmiKvp,OsclMemAllocator> & aValueList,uint32 start,uint32 end)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
SetDataSourcePosition(PVMFSessionId aSessionId,PVMFTimestamp aTargetNPT,PVMFTimestamp & aActualNPT,PVMFTimestamp & aActualMediaDataTS,bool aSeekToSyncPoint,uint32 aStreamID,OsclAny * aContext)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 
QueryDataSourcePosition(PVMFSessionId aSessionId,PVMFTimestamp aTargetNPT,PVMFTimestamp & aSeekPointBeforeTargetNPT,PVMFTimestamp & aSeekPointAfterTargetNPT,OsclAny * aContextData,bool aSeekToSyncPoint)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 
QueryDataSourcePosition(PVMFSessionId aSessionId,PVMFTimestamp aTargetNPT,PVMFTimestamp & aActualNPT,bool aSeekToSyncPoint,OsclAny * aContext)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 
SetDataSourceRate(PVMFSessionId aSessionId,int32 aRate,PVMFTimebase * aTimebase,OsclAny * aContext)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 
SetPlayerNodeRegistry(PVPlayerNodeRegistryInterface * aRegistry)1110 PVMFStatus PVMFDownloadManagerNode::SetPlayerNodeRegistry(PVPlayerNodeRegistryInterface* aRegistry)
1111 {
1112     iPlayerNodeRegistry = aRegistry;
1113     return PVMFSuccess;
1114 }
1115 
Run()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 
QueueCommandL(PVMFDownloadManagerNodeCommand & aCmd)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 
ProcessCommand()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 
CommandComplete(PVMFDownloadManagerNodeCmdQueue & aCmdQ,PVMFDownloadManagerNodeCommand & aCmd,PVMFStatus aStatus,PVInterface * aExtMsg,OsclAny * aEventData)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 
ReportErrorEvent(PVMFEventType aEventType,PVInterface * aExtMsg,OsclAny * aEventData)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 
ReportInfoEvent(PVMFAsyncEvent & aEvent)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 
GenerateDataReadyEvent()1422 void PVMFDownloadManagerNode::GenerateDataReadyEvent()
1423 {
1424     PVMFAsyncEvent info(PVMFInfoEvent, PVMFInfoDataReady, NULL, NULL);
1425     ReportInfoEvent(info);
1426     iDataReady = true;
1427 }
1428 
FilterPlaybackEventsFromSubNodes(const PVMFAsyncEvent & aEvent)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 
ChangeNodeState(TPVMFNodeInterfaceState aNewState)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 
DoQueryUuid(PVMFDownloadManagerNodeCommand & aCmd)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 
DoQueryInterface(PVMFDownloadManagerNodeCommand & aCmd)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 
DoRequestPort(PVMFDownloadManagerNodeCommand & aCmd)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 
DoReleasePort(PVMFDownloadManagerNodeCommand & aCmd)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 
DoInitNode(PVMFDownloadManagerNodeCommand & aCmd)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 
DoPrepareNode(PVMFDownloadManagerNodeCommand & aCmd)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 
DoStartNode(PVMFDownloadManagerNodeCommand & aCmd)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 
DoStopNode(PVMFDownloadManagerNodeCommand & aCmd)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 
DoFlushNode(PVMFDownloadManagerNodeCommand & aCmd)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 
DoPauseNode(PVMFDownloadManagerNodeCommand & aCmd)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 
DoResetNode(PVMFDownloadManagerNodeCommand & aCmd)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 
DoCancelAllCommands(PVMFDownloadManagerNodeCommand & aCmd)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 
DoCancelCommand(PVMFDownloadManagerNodeCommand & aCmd)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 
DoGetNodeMetadataKey(PVMFDownloadManagerNodeCommand & aCmd)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 
DoGetNodeMetadataValue(PVMFDownloadManagerNodeCommand & aCmd)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 
DoSetDataSourcePosition(PVMFDownloadManagerNodeCommand & aCmd)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 
DoQueryDataSourcePosition(PVMFDownloadManagerNodeCommand & aCmd)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 
ContinueInitAfterTrackSelectDecision()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 
ContinueFromDownloadTrackSelectionPoint()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.
ContinueAfterMovieAtom()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 
CreateParser()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 
ScheduleSubNodeCommands(PVMFDownloadManagerNodeCommand & aCmd)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 
Push(PVMFDownloadManagerSubNodeContainerBase & n,PVMFDownloadManagerSubNodeContainerBase::CmdType c)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
GetLicense(PVMFSessionId aSessionId,OSCL_wString & aContentName,OsclAny * aData,uint32 aDataSize,int32 aTimeoutMsec,OsclAny * aContextData)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
GetLicense(PVMFSessionId aSessionId,OSCL_String & aContentName,OsclAny * aData,uint32 aDataSize,int32 aTimeoutMsec,OsclAny * aContextData)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
CancelGetLicense(PVMFSessionId aSessionId,PVMFCommandId aCmdId,OsclAny * aContextData)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 
DoGetLicense(PVMFDownloadManagerNodeCommand & aCmd,bool aWideCharVersion)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 
CompleteGetLicense()2214 void PVMFDownloadManagerNode::CompleteGetLicense()
2215 {
2216     CommandComplete(iCurrentCommand,
2217                     iCurrentCommand.front(),
2218                     PVMFSuccess, NULL, NULL);
2219 }
2220 
DoCancelGetLicense(PVMFDownloadManagerNodeCommand & aCmd)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 
PVMFDownloadManagerSubNodeContainerBase()2243 PVMFDownloadManagerSubNodeContainerBase::PVMFDownloadManagerSubNodeContainerBase()
2244 {
2245     iCmdState = EIdle;
2246     iCancelCmdState = EIdle;
2247 }
2248 
Construct(NodeType t,PVMFDownloadManagerNode * c)2249 void PVMFDownloadManagerSubNodeContainerBase::Construct(NodeType t, PVMFDownloadManagerNode* c)
2250 {
2251     iContainer = c;
2252     iType = t;
2253 }
2254 
Cleanup()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 
Cleanup()2306 void PVMFDownloadManagerRecognizerContainer::Cleanup()
2307 {
2308     // Nothing to do here 'til recognizer is integrated
2309 }
2310 
Connect()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 
IssueCommand(int32 aCmd)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 
IssueCommand(int32 aCmd)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.
RecognizerCommandCompleted(const PVMFCmdResp & aResponse)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
HandleNodeErrorEvent(const PVMFAsyncEvent & aEvent)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
HandleNodeInformationalEvent(const PVMFAsyncEvent & aEvent)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 
CancelPendingCommand()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 
CancelPendingCommand()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 
CommandDone(PVMFStatus aStatus,PVInterface * aExtMsg,OsclAny * aEventData)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 
CancelCommandDone(PVMFStatus aStatus,PVInterface * aExtMsg,OsclAny * aEventData)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
NodeCommandCompleted(const PVMFCmdResp & aResponse)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
getParametersSync(PvmiMIOSession aSession,PvmiKeyType aIdentifier,PvmiKvp * & aParameters,int & aNumParamElements,PvmiCapabilityContext aContext)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 
releaseParameters(PvmiMIOSession aSession,PvmiKvp * aParameters,int num_elements)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 
createContext(PvmiMIOSession aSession,PvmiCapabilityContext & aContext)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 
setContextParameters(PvmiMIOSession aSession,PvmiCapabilityContext & aContext,PvmiKvp * aParameters,int num_parameter_elements)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 
DeleteContext(PvmiMIOSession aSession,PvmiCapabilityContext & aContext)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 
setParametersSync(PvmiMIOSession aSession,PvmiKvp * aParameters,int num_elements,PvmiKvp * & aRet_kvp)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 
IsByteBasedDownloadProgress(OSCL_String & aDownloadProgressInfo)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 
GetHttpExtensionHeaderParams(PvmiKvp & aParameter,OSCL_String & extensionHeaderKey,OSCL_String & extensionHeaderValue,HttpMethod & httpMethod,bool & aPurgeOnRedirect)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 
IsHttpExtensionHeaderValid(PvmiKvp & aParameter)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
getItemLen(char * ptrItemStart,char * ptrItemEnd)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 
setParametersAsync(PvmiMIOSession aSession,PvmiKvp * aParameters,int num_elements,PvmiKvp * & aRet_kvp,OsclAny * context)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 
getCapabilityMetric(PvmiMIOSession aSession)3982 uint32 PVMFDownloadManagerNode::getCapabilityMetric(PvmiMIOSession aSession)
3983 {
3984     OSCL_UNUSED_ARG(aSession);
3985     return 0;
3986 }
3987 
verifyParametersSync(PvmiMIOSession aSession,PvmiKvp * aParameters,int num_elements)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 
IsDownloadExtensionHeaderValid(PvmiKvp & aParameter)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 
NotificationsInterfaceDestroyed()4020 void PVMFDownloadManagerNode::NotificationsInterfaceDestroyed()
4021 {
4022     iClockNotificationsInf = NULL;
4023 }
4024 
ClockStateUpdated()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