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 "pv_2way_proxy_adapter.h"
20#include "pvlogger.h"
21#include "pvt_common.h"
22#include "pv_2way_engine_factory.h"
23#include "oscl_error_trapcleanup.h"
24
25#define DEFAULT_2WAY_STACK_SIZE 8192
26
27void PVCmnCmdRespMsg::Set(PVCommandId aId,
28                          void *aContext,
29                          PVMFStatus aStatus,
30                          OsclAny* aEventData,
31                          int32 aEventDataSize)
32{
33    OSCL_UNUSED_ARG(aEventDataSize);
34    iId = aId;
35    iContext = aContext;
36    iStatus = aStatus;
37    iEventData = aEventData;
38    //iEventDataSize = aEventDataSize;
39}
40
41void PVCmnAsyncEventMsg::Set(const PVAsyncInformationalEvent& aEvent, PVEventType aType,
42                             PVExclusivePtr aPtr,
43                             uint8 *aBuffer,
44                             uint32 aBufferSize)
45{
46    iEventType = aType;
47    iEventData = aPtr;
48    iEventExtInterface = aEvent.GetEventExtensionInterface();
49    if (iEventExtInterface)
50    {
51        iEventExtInterface->addRef();
52    }
53    if (aBuffer)
54    {
55        if (aBufferSize > PV_COMMON_ASYNC_EVENT_LOCAL_BUF_SIZE)
56        {
57            oscl_memcpy(iLocalBuffer, aBuffer, PV_COMMON_ASYNC_EVENT_LOCAL_BUF_SIZE);
58        }
59        else
60        {
61            oscl_memcpy(iLocalBuffer, aBuffer, aBufferSize);
62        }
63    }
64}
65
66void PVCmnAsyncErrorEvent::Set(PVEventType aEventType,
67                               PVExclusivePtr aEventData,
68                               uint8* aLocalBuffer,
69                               int32 aLocalBufferSize)
70{
71    iEventType = aEventType;
72    iEventData = aEventData;
73    if (aLocalBuffer)
74    {
75        if (aLocalBufferSize > PV_COMMON_ASYNC_EVENT_LOCAL_BUF_SIZE)
76        {
77            oscl_memcpy(iLocalBuffer, aLocalBuffer, PV_COMMON_ASYNC_EVENT_LOCAL_BUF_SIZE);
78        }
79        else
80        {
81            oscl_memcpy(iLocalBuffer, aLocalBuffer, aLocalBufferSize);
82        }
83    }
84}
85
86CPV2WayProxyAdapter *CPV2WayProxyAdapter::New(TPVTerminalType aTerminalType,
87        PVCommandStatusObserver* aCmdStatusObserver,
88        PVInformationalEventObserver *aInfoEventObserver,
89        PVErrorEventObserver *aErrorEventObserver)
90//called by the factory to create a new proxied 2way interface.
91{
92    int32 error;
93    CPV2WayProxyAdapter* aRet = OSCL_NEW(CPV2WayProxyAdapter, ());
94    if (aRet)
95    {
96        error = Construct(aRet, aTerminalType, aCmdStatusObserver,
97                          aInfoEventObserver,
98                          aErrorEventObserver);
99        if (error)
100        {
101            OSCL_DELETE(aRet);
102            aRet = NULL;
103            OSCL_LEAVE(error);
104        }
105    }
106    else
107    {
108        OSCL_LEAVE(PVMFErrNoMemory);
109    }
110
111    return aRet;
112}
113
114int32 CPV2WayProxyAdapter::Construct(CPV2WayProxyAdapter*& aRet,
115                                     TPVTerminalType aTerminalType,
116                                     PVCommandStatusObserver* aCmdStatusObserver,
117                                     PVInformationalEventObserver *aInfoEventObserver,
118                                     PVErrorEventObserver *aErrorEventObserver)
119{
120    int32 error;
121    OSCL_TRY(error, aRet->ConstructL(aTerminalType,
122                                     aCmdStatusObserver,
123                                     aInfoEventObserver,
124                                     aErrorEventObserver));
125    return error;
126}
127
128OsclAny CPV2WayProxyAdapter::ConstructL(TPVTerminalType aTerminalType,
129                                        PVCommandStatusObserver* aCmdStatusObserver,
130                                        PVInformationalEventObserver *aInfoEventObserver,
131                                        PVErrorEventObserver *aErrorEventObserver)
132{
133    OSCL_UNUSED_ARG(aTerminalType);
134    iCmdStatusObserver = aCmdStatusObserver;
135    iInfoEventObserver = aInfoEventObserver;
136    iErrorEventObserver = aErrorEventObserver;
137
138    int32 i;
139    for (i = 0; i < MAX_PENDING_2WAY_COMMANDS; i++)
140    {
141        iFreeCmdMsg.push_back(&iCmdMsg[i]);
142    }
143
144    for (i = 0; i < MAX_PENDING_2WAY_EVENTS; i++)
145    {
146        iFreeEventMsg.push_back(&iEventMsg[i]);
147    }
148
149    for (i = 0; i < MAX_PENDING_2WAY_ERRORS; i++)
150    {
151        iFreeErrorMsg.push_back(&iErrorMsg[i]);
152    }
153
154    //Create proxy
155    iPVProxy = CPVInterfaceProxy::NewL(*this, NULL, 2 * DEFAULT_2WAY_STACK_SIZE);
156    //Register ourself as a proxied interface
157    iProxyId = iPVProxy->RegisterProxiedInterface(*this, *this);
158    //Start the proxy thread.
159    iPVProxy->StartPVThread();
160}
161
162
163// Called by the factory to delete 2way interface.
164CPV2WayProxyAdapter::~CPV2WayProxyAdapter()
165{
166    PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_STACK_TRACE, (0, "CPV2WayProxyAdapter::~CPV2WayProxyAdapter iterminalEngine(%x)", iterminalEngine));
167    if (iPVProxy)
168    {
169        iPVProxy->StopPVThread();
170        iPVProxy->Delete();
171    }
172    PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_STACK_TRACE, (0, "CPV2WayProxyAdapter::~CPV2WayProxyAdapter - done"));
173}
174
175//
176// Pure virtuals from Oscl proxy base class.
177//
178
179OSCL_EXPORT_REF void CPV2WayProxyAdapter::DeleteTerminal(PVLogger *aLogger)
180//called by proxy base class to delete terminal under the PV thread.
181{
182    PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, aLogger, PVLOGMSG_STACK_TRACE, (0, "CPV2WayProxyAdapter::DeleteTerminal-in"));
183    if (iterminalEngine)
184        CPV2WayEngineFactory::DeleteTerminal(iterminalEngine);
185    iterminalEngine = NULL;
186    PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, aLogger, PVLOGMSG_STACK_TRACE, (0, "CPV2WayProxyAdapter::DeleteTerminal-out"));
187}
188
189OSCL_EXPORT_REF void CPV2WayProxyAdapter::CreateTerminal(PVLogger *aLogger)
190//called by proxy base class to create terminal under the PV thread.
191{
192    OSCL_UNUSED_ARG(aLogger);
193    iterminalEngine =  CPV2WayEngineFactory::CreateTerminal(PV_324M,
194                       this,//observers
195                       this,
196                       this);
197}
198
199OSCL_EXPORT_REF void CPV2WayProxyAdapter::CreateLoggerAppenders()
200{
201}
202
203OSCL_EXPORT_REF void CPV2WayProxyAdapter::PVThreadLogon(PVMainProxy &proxy)
204{
205    OSCL_UNUSED_ARG(proxy);
206    CreateTerminal();
207}
208
209OSCL_EXPORT_REF void CPV2WayProxyAdapter::PVThreadLogoff(PVMainProxy &proxy)
210{
211    OSCL_UNUSED_ARG(proxy);
212    DeleteTerminal();
213}
214
215OSCL_EXPORT_REF void CPV2WayProxyAdapter::CleanupMessage(CPVCmnInterfaceCmdMessage *cmdMsg, PVLogger *aLogger)
216//Cleanup an un-processed command message that was passed to SendAPI.
217{
218    OSCL_UNUSED_ARG(aLogger);
219    if (cmdMsg)
220        OSCL_DELETE(cmdMsg);
221}
222
223OSCL_EXPORT_REF void CPV2WayProxyAdapter::CleanupNotification(CPVCmnInterfaceObserverMessage *obsMsg, PVLogger *aLogger)
224//Cleanup an un-processed notifier message that was passed to NotifyCaller
225{
226    OSCL_UNUSED_ARG(aLogger);
227    OSCL_UNUSED_ARG(obsMsg);
228}
229
230OSCL_EXPORT_REF void CPV2WayProxyAdapter::ProcessMessage(CPVCmnInterfaceCmdMessage *aMsg, PVLogger *aLogger)
231//called in the PV thread to field a command.
232{
233    OSCL_UNUSED_ARG(aLogger);
234    if (!aMsg)
235        return;
236
237    int32 err = ProcessMessageLTry(aMsg);
238
239    //if ProcessMessage did a leave, create
240    //a response here...
241    if (err)
242    {
243        int32 tmp_err;
244        PVCmnCmdRespMsg *msg = NULL;
245        OSCL_TRY(tmp_err, msg = GetCmdMsgL());
246        if (tmp_err) return;
247
248        msg->Set(aMsg->GetCommandId() , //id
249                 aMsg, //context data
250                 err, //status
251                 NULL, 0); //response data
252
253        iPVProxy->SendNotification(iProxyId, (OsclAny*)msg);
254    }
255}
256
257int CPV2WayProxyAdapter::ProcessMessageLTry(CPVCmnInterfaceCmdMessage* aMsg)
258{
259    // this function exists to get rid of compiler warnings
260    int32 err = 0;
261    OSCL_TRY(err, ProcessMessageL(aMsg););
262    return err;
263}
264
265OSCL_EXPORT_REF void CPV2WayProxyAdapter::HandleCommand(TPVProxyMsgId aMsgId, OsclAny* aMsg)
266{
267    CPVCmnInterfaceCmdMessage *msg = (CPVCmnInterfaceCmdMessage*)aMsg;
268    msg->SetId(aMsgId);
269    ProcessMessage(msg);
270}
271
272OSCL_EXPORT_REF void CPV2WayProxyAdapter::CleanupNotification(TPVProxyMsgId aId,
273        OsclAny* aMsg)
274{
275    OSCL_UNUSED_ARG(aId);
276    OSCL_UNUSED_ARG(aMsg);
277    //CleanupMessage((CCPVCmnInterfaceCmdMessage*)aMsg);
278}
279
280OSCL_EXPORT_REF void CPV2WayProxyAdapter::ProcessNotification(CPVCmnInterfaceObserverMessage *aMsg, PVLogger *aLogger)
281//called in the app thread to notify observer.
282{
283    int32 err = 0;
284    OSCL_TRY(err, ProcessNotificationL(aMsg););
285    if (err)
286    {
287        //not really sure what to do with this...
288        PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, aLogger, PVLOGMSG_NONFATAL_ERROR, (0, "PV2WAYPROXY:Error! ProcessNotificationL %d", err));
289    }
290}
291
292OSCL_EXPORT_REF void CPV2WayProxyAdapter::HandleNotification(TPVProxyMsgId aId, OsclAny* aMsg)
293{
294    OSCL_UNUSED_ARG(aId);
295    ProcessNotification((CPVCmnInterfaceObserverMessage*)aMsg);
296}
297
298OSCL_EXPORT_REF void CPV2WayProxyAdapter::CleanupCommand(TPVProxyMsgId aId, OsclAny* aMsg)
299{
300    OSCL_UNUSED_ARG(aId);
301    CleanupNotification((CPVCmnInterfaceObserverMessage*)aMsg);
302}
303
304//
305// proxied 2way API implementation.
306//
307
308PVCommandId CPV2WayProxyAdapter::GetSDKInfo(PVSDKInfo &aSDKInfo, OsclAny* aContextData)
309{
310    PV2WayMessageGetSDKInfo *msg = OSCL_NEW(PV2WayMessageGetSDKInfo, (aSDKInfo, aContextData));
311    if (msg == NULL)
312    {
313        OSCL_LEAVE(PVMFErrNoMemory);
314    }
315    return iPVProxy->SendCommand(iProxyId, (OsclAny*)msg);
316}
317
318PVCommandId CPV2WayProxyAdapter::GetSDKModuleInfo(PVSDKModuleInfo &aSDKModuleInfo, OsclAny* aContextData)
319{
320    PV2WayMessageGetSDKModuleInfo *msg = OSCL_NEW(PV2WayMessageGetSDKModuleInfo, (aSDKModuleInfo, aContextData));
321    if (msg == NULL)
322    {
323        OSCL_LEAVE(PVMFErrNoMemory);
324    }
325    return iPVProxy->SendCommand(iProxyId, (OsclAny*)msg);
326}
327
328PVCommandId CPV2WayProxyAdapter::Init(PV2WayInitInfo& aInitInfo, OsclAny* aContextData)
329{
330    PV2WayMessageInit *msg = OSCL_NEW(PV2WayMessageInit, (aInitInfo, aContextData));
331    if (msg == NULL)
332    {
333        OSCL_LEAVE(PVMFErrNoMemory);
334    }
335    return iPVProxy->SendCommand(iProxyId, (OsclAny*)msg);
336}
337
338
339PVCommandId CPV2WayProxyAdapter::Reset(OsclAny* aContextData)
340{
341    PV2WayMessageReset *msg = OSCL_NEW(PV2WayMessageReset, (aContextData));
342    if (msg == NULL)
343    {
344        OSCL_LEAVE(PVMFErrNoMemory);
345    }
346    return iPVProxy->SendCommand(iProxyId, (OsclAny*)msg);
347}
348
349PVCommandId CPV2WayProxyAdapter::AddDataSource(PVTrackId aTrackId,
350        PVMFNodeInterface& aDataSource,
351        OsclAny* aContextData)
352{
353    PV2WayMessageAddDataSource *msg = OSCL_NEW(PV2WayMessageAddDataSource, (aTrackId, aDataSource, aContextData));
354    if (msg == NULL)
355    {
356        OSCL_LEAVE(PVMFErrNoMemory);
357    }
358    return iPVProxy->SendCommand(iProxyId, (OsclAny*)msg);
359}
360
361PVCommandId CPV2WayProxyAdapter::RemoveDataSource(PVMFNodeInterface& aDataSource, OsclAny* aContextData)
362{
363    PV2WayMessageRemoveDataSource *msg = OSCL_NEW(PV2WayMessageRemoveDataSource, (aDataSource, aContextData));
364    if (msg == NULL)
365    {
366        OSCL_LEAVE(PVMFErrNoMemory);
367    }
368    return iPVProxy->SendCommand(iProxyId, (OsclAny*)msg);
369}
370
371PVCommandId CPV2WayProxyAdapter::AddDataSink(PVTrackId aTrackId,
372        PVMFNodeInterface& aDataSink,
373        OsclAny* aContextData)
374{
375    PV2WayMessageAddDataSink *msg = OSCL_NEW(PV2WayMessageAddDataSink, (aTrackId, aDataSink, aContextData));
376    if (msg == NULL)
377    {
378        OSCL_LEAVE(PVMFErrNoMemory);
379    }
380    return iPVProxy->SendCommand(iProxyId, (OsclAny*)msg);
381}
382
383PVCommandId CPV2WayProxyAdapter::RemoveDataSink(PVMFNodeInterface& aDataSink, OsclAny* aContextData)
384{
385    PV2WayMessageRemoveDataSink *msg = OSCL_NEW(PV2WayMessageRemoveDataSink, (aDataSink, aContextData));
386    if (msg == NULL)
387    {
388        OSCL_LEAVE(PVMFErrNoMemory);
389    }
390    return iPVProxy->SendCommand(iProxyId, (OsclAny*)msg);
391}
392
393PVCommandId CPV2WayProxyAdapter::Connect(const PV2WayConnectOptions& aOptions,
394        PVMFNodeInterface* aCommServer,
395        OsclAny* aContextData)
396{
397    PV2WayMessageConnect *msg = OSCL_NEW(PV2WayMessageConnect, (aOptions, aCommServer, aContextData));
398    if (msg == NULL)
399    {
400        OSCL_LEAVE(PVMFErrNoMemory);
401    }
402    return iPVProxy->SendCommand(iProxyId, (OsclAny*)msg);
403}
404
405PVCommandId CPV2WayProxyAdapter::Disconnect(OsclAny* aContextData)
406{
407    PV2WayMessageDisconnect *msg = OSCL_NEW(PV2WayMessageDisconnect, (aContextData));
408    if (msg == NULL)
409    {
410        OSCL_LEAVE(PVMFErrNoMemory);
411    }
412    return iPVProxy->SendCommand(iProxyId, (OsclAny*)msg);
413}
414
415PVCommandId CPV2WayProxyAdapter::GetState(PV2WayState& aState, OsclAny* aContextData)
416{
417    PV2WayMessageGetPV2WayState *msg = OSCL_NEW(PV2WayMessageGetPV2WayState, (aState, aContextData));
418    if (msg == NULL)
419    {
420        OSCL_LEAVE(PVMFErrNoMemory);
421    }
422    return iPVProxy->SendCommand(iProxyId, (OsclAny*)msg);
423}
424
425PVCommandId CPV2WayProxyAdapter::Pause(PV2WayDirection aDirection,
426                                       PVTrackId aTrackId,
427                                       OsclAny* aContextData)
428{
429    PV2WayMessagePause *msg = OSCL_NEW(PV2WayMessagePause, (aDirection, aTrackId, aContextData));
430    if (msg == NULL)
431    {
432        OSCL_LEAVE(PVMFErrNoMemory);
433    }
434    return iPVProxy->SendCommand(iProxyId, (OsclAny*)msg);
435}
436
437PVCommandId CPV2WayProxyAdapter::Resume(PV2WayDirection aDirection,
438                                        PVTrackId aTrackId,
439                                        OsclAny* aContextData)
440{
441    PV2WayMessageResume *msg = OSCL_NEW(PV2WayMessageResume, (aDirection, aTrackId, aContextData));
442    if (msg == NULL)
443    {
444        OSCL_LEAVE(PVMFErrNoMemory);
445    }
446    return iPVProxy->SendCommand(iProxyId, (OsclAny*)msg);
447}
448
449PVCommandId CPV2WayProxyAdapter::SetLogAppender(const char* aTag, OsclSharedPtr<PVLoggerAppender>& aAppender, OsclAny* aContextData)
450{
451    ////// copy tag string //////
452    Oscl_TAlloc<uint8, OsclMemAllocator> myAlloc;
453    typedef OsclRefCounterSA<Oscl_TAlloc<uint8, OsclMemAllocator> > refcount_type;
454
455    uint32 allocSize = sizeof(refcount_type) + (sizeof(char) * (oscl_strlen(aTag) + 1));
456    uint8 * mem = (uint8*)myAlloc.allocate(allocSize);
457    OsclError::PushL(mem);
458
459    char* tag = (char*)(mem + sizeof(refcount_type));
460    oscl_strncpy(tag, aTag, oscl_strlen(aTag) + 1);
461
462    refcount_type *tagRefCounter = OSCL_PLACEMENT_NEW(mem, refcount_type(mem));
463
464    OsclSharedPtr<char> tagPtr(tag, tagRefCounter);
465
466
467    PV2WayMessageSetLogAppender *msg = OSCL_NEW(PV2WayMessageSetLogAppender , (tagPtr, aAppender, aContextData));
468    if (msg == NULL)
469    {
470        OSCL_LEAVE(PVMFErrNoMemory);
471    }
472
473    OsclError::Pop();
474
475    return iPVProxy->SendCommand(iProxyId, (OsclAny*)msg);
476}
477
478PVCommandId CPV2WayProxyAdapter::RemoveLogAppender(const char* aTag, OsclSharedPtr<PVLoggerAppender>& aAppender, OsclAny* aContextData)
479{
480    ////// copy tag string //////
481    Oscl_TAlloc<uint8, OsclMemAllocator> myAlloc;
482    typedef OsclRefCounterSA<Oscl_TAlloc<uint8, OsclMemAllocator> > refcount_type;
483
484    uint32 allocSize = sizeof(refcount_type) + (sizeof(char) * (oscl_strlen(aTag) + 1));
485    uint8 * mem = (uint8*)myAlloc.allocate(allocSize);
486    OsclError::PushL(mem);
487
488    char* tag = (char*)(mem + sizeof(refcount_type));
489    oscl_strncpy(tag, aTag, oscl_strlen(aTag) + 1);
490
491    refcount_type *tagRefCounter =  OSCL_PLACEMENT_NEW(mem, refcount_type(mem));
492
493    OsclSharedPtr<char> tagPtr(tag, tagRefCounter);
494
495
496    PV2WayMessageRemoveLogAppender *msg = OSCL_NEW(PV2WayMessageRemoveLogAppender , (tagPtr, aAppender, aContextData));
497    if (msg == NULL)
498    {
499        OSCL_LEAVE(PVMFErrNoMemory);
500    }
501
502    OsclError::Pop();
503
504    return iPVProxy->SendCommand(iProxyId, (OsclAny*)msg);
505}
506
507PVCommandId CPV2WayProxyAdapter::SetLogLevel(const char *aTag, int32 aLevel, bool aSetSubtree, OsclAny* aContextData)
508{
509    // set the log level in this thread
510    PVLogger *logger = PVLogger::GetLoggerObject(aTag);
511    logger->SetLogLevel(aLevel);
512
513    ////// copy tag string //////
514    Oscl_TAlloc<uint8, OsclMemAllocator> myAlloc;
515    typedef OsclRefCounterSA<Oscl_TAlloc<uint8, OsclMemAllocator> > refcount_type;
516
517    uint32 allocSize = sizeof(refcount_type) + (sizeof(char) * (oscl_strlen(aTag) + 1));
518    uint8 * mem = (uint8*)myAlloc.allocate(allocSize);
519    OsclError::PushL(mem);
520
521    char* tag = (char*)(mem + sizeof(refcount_type));
522    oscl_strncpy(tag, aTag, oscl_strlen(aTag) + 1);
523
524    refcount_type *tagRefCounter = OSCL_PLACEMENT_NEW(mem, refcount_type(mem));
525
526    OsclSharedPtr<char> tagPtr(tag, tagRefCounter);
527
528
529    PV2WayMessageSetLogLevel *msg = OSCL_NEW(PV2WayMessageSetLogLevel, (tagPtr, aLevel, aSetSubtree, aContextData));
530    if (msg == NULL)
531    {
532        OSCL_LEAVE(PVMFErrNoMemory);
533    }
534
535    OsclError::Pop();
536
537    return iPVProxy->SendCommand(iProxyId, (OsclAny*)msg);
538}
539
540PVCommandId CPV2WayProxyAdapter::GetLogLevel(const char *aTag, int32 &aLogLevel, OsclAny* aContextData)
541{
542    ////// copy tag string //////
543    Oscl_TAlloc<uint8, OsclMemAllocator> myAlloc;
544    typedef OsclRefCounterSA<Oscl_TAlloc<uint8, OsclMemAllocator> > refcount_type;
545
546    uint32 allocSize = sizeof(refcount_type) + (sizeof(char) * (oscl_strlen(aTag) + 1));
547    uint8 * mem = (uint8*)myAlloc.allocate(allocSize);
548    OsclError::PushL(mem);
549
550    char* tag = (char*)(mem + sizeof(refcount_type));
551    oscl_strncpy(tag, aTag, oscl_strlen(aTag) + 1);
552
553    refcount_type *tagRefCounter =  OSCL_PLACEMENT_NEW(mem, refcount_type(mem));
554
555    OsclSharedPtr<char> tagPtr(tag, tagRefCounter);
556
557
558    PV2WayMessageGetLogLevel *msg = OSCL_NEW(PV2WayMessageGetLogLevel, (tagPtr, aLogLevel, aContextData));
559    if (msg == NULL)
560    {
561        OSCL_LEAVE(PVMFErrNoMemory);
562    }
563
564    OsclError::Pop();
565
566    return iPVProxy->SendCommand(iProxyId, (OsclAny*)msg);
567}
568
569
570PVCommandId CPV2WayProxyAdapter::QueryUUID(const PvmfMimeString& aMimeType, Oscl_Vector<PVUuid, BasicAlloc>& aUuids,
571        bool aExactUuidsOnly, OsclAny* aContextData)
572{
573    PV2WayMessageQueryUUID *msg = OSCL_NEW(PV2WayMessageQueryUUID, (aMimeType, aUuids, aExactUuidsOnly, aContextData));
574    if (msg == NULL)
575    {
576        OSCL_LEAVE(PVMFErrNoMemory);
577    }
578    return iPVProxy->SendCommand(iProxyId, (OsclAny*)msg);
579}
580
581PVCommandId CPV2WayProxyAdapter::QueryInterface(const PVUuid& aUuid, PVInterface*& aInterfacePtr, OsclAny* aContextData)
582{
583    PV2WayMessageQueryInterface *msg = OSCL_NEW(PV2WayMessageQueryInterface, (aUuid, aInterfacePtr, aContextData));
584    if (msg == NULL)
585    {
586        OSCL_LEAVE(PVMFErrNoMemory);
587    }
588    return iPVProxy->SendCommand(iProxyId, (OsclAny*)msg);
589
590    // proxiedinterface->QueryProxiedInterface(uuid, iface);
591
592}
593
594PVCommandId CPV2WayProxyAdapter::CancelAllCommands(OsclAny* aContextData)
595{
596    PV2WayMessageCancelAllCommands *msg = OSCL_NEW(PV2WayMessageCancelAllCommands, (aContextData));
597    if (msg == NULL)
598    {
599        OSCL_LEAVE(PVMFErrNoMemory);
600    }
601    return iPVProxy->SendCommand(iProxyId, (OsclAny*)msg);
602}
603
604//
605// 2way engine observer implementation.
606//
607
608void CPV2WayProxyAdapter::HandleErrorEvent(const PVAsyncErrorEvent& aEvent)
609{
610    PVCmnAsyncErrorEvent *msg;
611    TPVCmnExclusivePtr aExclusivePtr;
612    aEvent.GetEventData(aExclusivePtr);
613
614    msg = GetErrorMsgL();
615
616    msg->Set(aEvent.GetEventType(),
617             aExclusivePtr,
618             aEvent.GetLocalBuffer(),
619             PV_COMMON_ASYNC_EVENT_LOCAL_BUF_SIZE);
620
621    iPVProxy->SendNotification(iProxyId, (OsclAny*)msg);
622}
623
624void CPV2WayProxyAdapter::HandleInformationalEvent(const PVAsyncInformationalEvent& aEvent)
625{
626    PVCmnAsyncEventMsg *msg;
627    TPVCmnExclusivePtr aExclusivePtr;
628    aEvent.GetEventData(aExclusivePtr);
629    msg = GetEventMsgL();
630
631    msg->Set(aEvent, aEvent.GetEventType(),
632             aExclusivePtr,
633             aEvent.GetLocalBuffer(),
634             PV_COMMON_ASYNC_EVENT_LOCAL_BUF_SIZE);
635
636    iPVProxy->SendNotification(iProxyId, (OsclAny*)msg);
637}
638
639void CPV2WayProxyAdapter::CommandCompleted(const PVCmdResponse& aResponse)
640{
641    // if command is query interface, we need to get the proxied interface for the response
642    CPVCmnInterfaceCmdMessage *iface_msg = (CPVCmnInterfaceCmdMessage *)aResponse.GetContext();
643    PVMFStatus status = aResponse.GetCmdStatus();
644
645    if (iface_msg->GetType() == PVT_COMMAND_QUERY_INTERFACE)
646    {
647        status = PVMFFailure;
648        /* Handle query interface*/
649        PVUuid uuid = OSCL_STATIC_CAST(PV2WayMessageQueryInterface*, iface_msg)->iUuid;
650        PVInterface *iface = OSCL_STATIC_CAST(PV2WayMessageQueryInterface*, iface_msg)->iInterfacePtr;
651
652        if (iface != NULL && aResponse.GetCmdStatus() == PVMFSuccess)
653        {
654            PVProxiedInterface *proxiedinterface = NULL;
655            PVInterface * tempInterface = NULL;
656
657            bool success = iface->queryInterface(PVUidProxiedInterface, tempInterface);
658            proxiedinterface = OSCL_STATIC_CAST(PVProxiedInterface*, tempInterface) ;
659            iface->removeRef();
660            OSCL_STATIC_CAST(PV2WayMessageQueryInterface*, iface_msg)->iInterfacePtr = iface = NULL;
661
662            if (success && proxiedinterface)
663            {
664                proxiedinterface->SetMainProxy(iPVProxy);
665                proxiedinterface->QueryProxiedInterface(uuid, iface);
666                proxiedinterface->removeRef();
667                OSCL_STATIC_CAST(PV2WayMessageQueryInterface*, iface_msg)->iInterfacePtr = iface;
668                if (iface != NULL)
669                {
670                    status = PVMFSuccess;
671                }
672            }
673        }
674    }
675
676    PVCmnCmdRespMsg *msg;
677    msg = GetCmdMsgL();
678
679    msg->Set(aResponse.GetCmdId(), //id
680             iface_msg, //context
681             status,
682             aResponse.GetResponseData(),
683             aResponse.GetResponseDataSize());//response data
684
685    iPVProxy->SendNotification(iProxyId, (OsclAny*)msg);
686}
687
688//
689// server side processing
690//
691
692void CPV2WayProxyAdapter::ProcessMessageL(CPVCmnInterfaceCmdMessage *aMsg)
693//called in the PV thread to field a command.
694{
695    int32 error = 0;
696    //Call the engine, passing the command message pointer as the context data.
697    //We will need the command message later in the response processing,
698    //so we can restore the original command ID and context data that the
699    //app sees.
700
701    switch (aMsg->GetType())
702    {
703        case PVT_COMMAND_INIT:
704        {
705            OSCL_TRY(error, iterminalEngine->Init(
706                         OSCL_STATIC_CAST(PV2WayMessageInit *, aMsg)->iInitInfo,
707                         aMsg));
708        }
709        break;
710        case PVT_COMMAND_GET_SDK_INFO:
711        {
712            OSCL_TRY(error, iterminalEngine->GetSDKInfo(
713                         OSCL_STATIC_CAST(PV2WayMessageGetSDKInfo *, aMsg)->iSDKInfo,
714                         aMsg));
715        }
716        break;
717
718        case PVT_COMMAND_GET_SDK_MODULE_INFO:
719        {
720            OSCL_TRY(error, iterminalEngine->GetSDKModuleInfo(
721                         OSCL_STATIC_CAST(PV2WayMessageGetSDKModuleInfo* , aMsg)->iSDKModuleInfo,
722                         aMsg));
723        }
724        break;
725
726        case PVT_COMMAND_GET_PV2WAY_STATE:
727        {
728            OSCL_TRY(error, iterminalEngine->GetState(
729                         OSCL_STATIC_CAST(PV2WayMessageGetPV2WayState*, aMsg)->iState,
730                         aMsg));
731        }
732        break;
733
734        case PVT_COMMAND_RESET:
735            OSCL_TRY(error, iterminalEngine->Reset(aMsg));
736            break;
737
738        case PVT_COMMAND_ADD_DATA_SOURCE:
739            OSCL_TRY(error, iterminalEngine->AddDataSource(
740                         OSCL_STATIC_CAST(PV2WayMessageAddDataSource *, aMsg)->iTrackId,
741                         OSCL_STATIC_CAST(PV2WayMessageAddDataSource *, aMsg)->iDataSource,
742                         aMsg));
743            break;
744
745        case PVT_COMMAND_REMOVE_DATA_SOURCE:
746            OSCL_TRY(error, iterminalEngine->RemoveDataSource(
747                         OSCL_STATIC_CAST(PV2WayMessageRemoveDataSource*, aMsg)->iDataSource,
748                         aMsg));
749            break;
750
751        case PVT_COMMAND_ADD_DATA_SINK:
752            OSCL_TRY(error, iterminalEngine->AddDataSink(
753                         OSCL_STATIC_CAST(PV2WayMessageAddDataSink *, aMsg)->iTrackId,
754                         OSCL_STATIC_CAST(PV2WayMessageAddDataSink *, aMsg)->iDataSink,
755                         aMsg));
756            break;
757
758        case PVT_COMMAND_REMOVE_DATA_SINK:
759            OSCL_TRY(error, iterminalEngine->RemoveDataSink(
760                         OSCL_STATIC_CAST(PV2WayMessageRemoveDataSink* , aMsg)->iDataSink,
761                         aMsg));
762            break;
763
764        case PVT_COMMAND_CONNECT:
765            OSCL_TRY(error, iterminalEngine->Connect(
766                         OSCL_STATIC_CAST(PV2WayMessageConnect *, aMsg)->iConnectOptions,
767                         OSCL_STATIC_CAST(PV2WayMessageConnect *, aMsg)->iCommServer,
768                         aMsg));
769            break;
770
771        case PVT_COMMAND_DISCONNECT:
772            OSCL_TRY(error, iterminalEngine->Disconnect(aMsg));
773            break;
774
775        case PVT_COMMAND_PAUSE:
776            OSCL_TRY(error, iterminalEngine->Pause(
777                         OSCL_STATIC_CAST(PV2WayMessagePause* , aMsg)->iDirection,
778                         OSCL_STATIC_CAST(PV2WayMessagePause* , aMsg)->iTrackId,
779                         aMsg));
780            break;
781
782        case PVT_COMMAND_RESUME:
783            OSCL_TRY(error, iterminalEngine->Resume(
784                         OSCL_STATIC_CAST(PV2WayMessagePause* , aMsg)->iDirection,
785                         OSCL_STATIC_CAST(PV2WayMessagePause* , aMsg)->iTrackId,
786                         aMsg));
787            break;
788
789        case PVT_COMMAND_SET_LOG_APPENDER:
790        {
791            OSCL_TRY(error, iterminalEngine->SetLogAppender(
792                         OSCL_STATIC_CAST(PV2WayMessageSetLogAppender*, aMsg)->iTag,
793                         OSCL_STATIC_CAST(PV2WayMessageSetLogAppender*, aMsg)->iAppender,
794                         aMsg));
795        }
796        break;
797
798        case PVT_COMMAND_REMOVE_LOG_APPENDER:
799        {
800            OSCL_TRY(error, iterminalEngine->RemoveLogAppender(
801                         OSCL_STATIC_CAST(PV2WayMessageRemoveLogAppender*, aMsg)->iTag,
802                         OSCL_STATIC_CAST(PV2WayMessageRemoveLogAppender*, aMsg)->iAppender,
803                         aMsg));
804        }
805        break;
806
807        case PVT_COMMAND_SET_LOG_LEVEL:
808            OSCL_TRY(error, iterminalEngine->SetLogLevel(
809                         OSCL_STATIC_CAST(PV2WayMessageSetLogLevel*, aMsg)->iTag,
810                         OSCL_STATIC_CAST(PV2WayMessageSetLogLevel*, aMsg)->iLevel,
811                         OSCL_STATIC_CAST(PV2WayMessageSetLogLevel*, aMsg)->iSetSubtree,
812                         aMsg));
813            break;
814
815        case PVT_COMMAND_GET_LOG_LEVEL:
816            OSCL_TRY(error, iterminalEngine->GetLogLevel(
817                         OSCL_STATIC_CAST(PV2WayMessageGetLogLevel*, aMsg)->iTag,
818                         OSCL_STATIC_CAST(PV2WayMessageGetLogLevel*, aMsg)->iLogLevel,
819                         aMsg));
820            break;
821
822        case PVT_COMMAND_QUERY_UUID:
823            OSCL_TRY(error, iterminalEngine->QueryUUID(
824                         OSCL_STATIC_CAST(PV2WayMessageQueryUUID*, aMsg)->iMimeType,
825                         OSCL_STATIC_CAST(PV2WayMessageQueryUUID*, aMsg)->iUuids,
826                         OSCL_STATIC_CAST(PV2WayMessageQueryUUID*, aMsg)->iExactUuidsOnly,
827                         aMsg));
828            break;
829
830        case PVT_COMMAND_QUERY_INTERFACE:
831            OSCL_TRY(error, iterminalEngine->QueryInterface(
832                         OSCL_STATIC_CAST(PV2WayMessageQueryInterface*, aMsg)->iUuid,
833                         OSCL_STATIC_CAST(PV2WayMessageQueryInterface*, aMsg)->iInterfacePtr,
834                         aMsg));
835            break;
836
837        case PVT_COMMAND_CANCEL_ALL_COMMANDS:
838            OSCL_TRY(error, iterminalEngine->CancelAllCommands(
839                         aMsg));
840            break;
841    }
842
843    if (error)
844    {
845        //create response to go across proxy.
846        PVCmnCmdRespMsg *msg = GetCmdMsgL();
847
848        msg->Set(aMsg->GetCommandId(), //id
849                 aMsg, //context
850                 error, //status
851                 NULL, 0); //response data
852
853        iPVProxy->SendNotification(iProxyId, (OsclAny*)msg);
854    }
855}
856
857//
858// client side processing
859//
860
861void CPV2WayProxyAdapter::ProcessNotificationL(CPVCmnInterfaceObserverMessage *aMsg)
862//called in the app thread to notify observer.
863{
864    int32 err = 0;
865
866    if (!aMsg)
867        return;
868
869    switch (aMsg->GetResponseType())
870    {
871        case 0:
872        {
873            PVCmnCmdRespMsg *resp = (PVCmnCmdRespMsg*)aMsg;
874
875            //Get the command message that prompted this
876            //response.  The pointer is in the context data.
877            CPVCmnInterfaceCmdMessage *cmd = (CPVCmnInterfaceCmdMessage*)resp->GetContext();
878
879            //Create a new response with the original command ID and
880            //original context data.
881            resp->SetId(cmd->GetCommandId());
882            resp->SetContextData(cmd->GetContextData());
883            OSCL_TRY(err, iCmdStatusObserver->CommandCompleted(*resp));
884            //ignore any leave from the observer function.
885
886            //discard command message.
887            OSCL_DELETE(cmd);
888
889            FreeCmdMsg(resp);
890        }
891        break;
892
893        case 1:
894        {
895            PVCmnAsyncEventMsg *event = (PVCmnAsyncEventMsg*) aMsg;
896
897            OSCL_TRY(err, iInfoEventObserver->HandleInformationalEvent(*event););
898            //ignore any leave from the observer function.
899
900            FreeEventMsg((PVCmnAsyncEventMsg *) aMsg);
901
902        }
903        break;
904
905        case 2:
906        {
907            PVCmnAsyncErrorEvent *event = (PVCmnAsyncErrorEvent *) aMsg;
908
909            OSCL_TRY(err, iErrorEventObserver->HandleErrorEvent(*event););
910            //ignore any leave from the observer function.
911
912            FreeErrorMsg((PVCmnAsyncErrorEvent *) aMsg);
913        }
914        break;
915
916        default:
917            PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_ERR, (0, "CPV2WayProxyAdapter::ProcessNotificationL unknown response (%d)", aMsg->GetResponseType()));
918            //Assume command message.
919            FreeCmdMsg((PVCmnCmdRespMsg *) aMsg);
920            break;
921    }
922}
923
924
925PVCmnCmdRespMsg *CPV2WayProxyAdapter::GetCmdMsgL()
926{
927    if (iFreeCmdMsg.empty())
928    {
929        OSCL_LEAVE(PVMFErrNoMemory);
930    }
931    else
932    {
933        PVCmnCmdRespMsg *cmd = (PVCmnCmdRespMsg *)iFreeCmdMsg[0];
934        iFreeCmdMsg.erase(iFreeCmdMsg.begin());
935        return cmd;
936    }
937
938    return NULL;
939}
940
941PVCmnAsyncEventMsg *CPV2WayProxyAdapter::GetEventMsgL()
942{
943    if (iFreeEventMsg.empty())
944    {
945        OSCL_LEAVE(PVMFErrNoMemory);
946    }
947    else
948    {
949        PVCmnAsyncEventMsg *cmd = (PVCmnAsyncEventMsg *)iFreeEventMsg[0];
950        iFreeEventMsg.erase(iFreeEventMsg.begin());
951        return cmd;
952    }
953
954    return NULL;
955}
956
957PVCmnAsyncErrorEvent* CPV2WayProxyAdapter::GetErrorMsgL()
958{
959    if (iFreeErrorMsg.empty())
960    {
961        OSCL_LEAVE(PVMFErrNoMemory);
962    }
963    else
964    {
965        PVCmnAsyncErrorEvent *cmd = (PVCmnAsyncErrorEvent *)iFreeErrorMsg[0];
966        iFreeErrorMsg.erase(iFreeErrorMsg.begin());
967        return cmd;
968    }
969
970    return NULL;
971}
972