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