|
1 // Copyright (c) 2007-2009 Nokia Corporation and/or its subsidiary(-ies). |
|
2 // All rights reserved. |
|
3 // This component and the accompanying materials are made available |
|
4 // under the terms of "Eclipse Public License v1.0" |
|
5 // which accompanies this distribution, and is available |
|
6 // at the URL "http://www.eclipse.org/legal/epl-v10.html". |
|
7 // |
|
8 // Initial Contributors: |
|
9 // Nokia Corporation - initial contribution. |
|
10 // |
|
11 // Contributors: |
|
12 // |
|
13 // Description: |
|
14 // mmrcserverphysicaladaptation.cpp |
|
15 // |
|
16 // |
|
17 |
|
18 |
|
19 #include "mmrcadaptationproxy.h" |
|
20 #include "mmrcservercontroller.h" |
|
21 #include "mmrcserversession.h" |
|
22 #include "mlogicalchain.h" |
|
23 #include "audiostreamadaptation.h" |
|
24 |
|
25 #include <a3f/maudiocontext.h> |
|
26 |
|
27 |
|
28 |
|
29 //------------------------------------------------------------------------------------ |
|
30 // |
|
31 //------------------------------------------------------------------------------------ |
|
32 /** |
|
33 * By default Symbian 2nd phase constructor is private. |
|
34 * @param CMMRCServerController& A reference on the MMRC Server controller |
|
35 */ |
|
36 CMMRCClientSideServerRequestToAdaptationAO::CMMRCClientSideServerRequestToAdaptationAO() |
|
37 : CActive(EPriorityHigh) |
|
38 { |
|
39 TRACE_CREATE(); |
|
40 DP_CONTEXT(----> CMMRCClientSideServerRequestToAdaptationAO::CMMRCClientSideServerRequestToAdaptationAO *CD1*, CtxDevSound, DPLOCAL); |
|
41 DP_IN(); |
|
42 DP_OUT(); |
|
43 } |
|
44 |
|
45 /** |
|
46 * Destructor |
|
47 */ |
|
48 CMMRCClientSideServerRequestToAdaptationAO::~CMMRCClientSideServerRequestToAdaptationAO() |
|
49 { |
|
50 DP_CONTEXT(----> CMMRCClientSideServerRequestToAdaptationAO::~CMMRCClientSideServerRequestToAdaptationAO *CD1*, CtxDevSound, DPLOCAL); |
|
51 DP_IN(); |
|
52 |
|
53 Cancel(); |
|
54 TidyUp(); |
|
55 |
|
56 DP_OUT(); |
|
57 } |
|
58 |
|
59 /** |
|
60 * Constructs, and returns a pointer to, a new CMMRCClientSideServerRequestToAdaptationAO object. |
|
61 * Leaves on failure. |
|
62 * @param CMMRCServerController& A reference on the MMRC Server controller |
|
63 * @return CMMRCClientSideServerRequestToAdaptationAO* A pointer to newly created utlitly object. |
|
64 */ |
|
65 EXPORT_C CMMRCClientSideServerRequestToAdaptationAO* CMMRCClientSideServerRequestToAdaptationAO::NewL() |
|
66 { |
|
67 DP_STATIC_CONTEXT(----> CMMRCClientSideServerRequestToAdaptationAO::NewL *CD1*, CtxDevSound, DPLOCAL); |
|
68 DP_IN(); |
|
69 |
|
70 CMMRCClientSideServerRequestToAdaptationAO* self = new(ELeave) CMMRCClientSideServerRequestToAdaptationAO(); |
|
71 CleanupStack::PushL(self); |
|
72 self->ConstructL(); |
|
73 CleanupStack::Pop(self); |
|
74 |
|
75 DP0_RET(self, "self = 0x%x"); |
|
76 } |
|
77 |
|
78 void CMMRCClientSideServerRequestToAdaptationAO::Initialize(CMMRCServerSession* aServerSession, CMMRCServerSideAdaptationResponseAO* aCallback, |
|
79 RThread* aClientThread, const CFourCCConvertor& aFourCCConvertor) |
|
80 { |
|
81 DP_CONTEXT(----> CMMRCClientSideServerRequestToAdaptationAO::SetCallback *CD1*, CtxDevSound, DPLOCAL); |
|
82 DP_IN(); |
|
83 |
|
84 iMMRCServerSideAdaptationResponseAO = aCallback; |
|
85 iServerSession = aServerSession; |
|
86 iClientThread = aClientThread; |
|
87 |
|
88 iStreamAdaptation->SetFourCC(aFourCCConvertor); |
|
89 |
|
90 DP_OUT(); |
|
91 } |
|
92 |
|
93 /** |
|
94 CMMRCClientSideServerRequestToAdaptationAO::ConstructL |
|
95 Symbian 2nd phase constructor can leave. |
|
96 */ |
|
97 void CMMRCClientSideServerRequestToAdaptationAO::ConstructL() |
|
98 { |
|
99 DP_CONTEXT(----> CMMRCClientSideServerRequestToAdaptationAO::ConstructL *CD1*, CtxDevSound, DPLOCAL); |
|
100 DP_IN(); |
|
101 |
|
102 CActiveScheduler::Add(this); |
|
103 iStreamAdaptation = CAudioStreamAdaptation::NewL(TUid::Uid(0x10283461)) ; |
|
104 iStreamAdaptation->RegisterAudioStreamObserver(*this); |
|
105 |
|
106 iStatus = KRequestPending; |
|
107 SetActive(); |
|
108 |
|
109 DP_OUT(); |
|
110 } |
|
111 |
|
112 /** |
|
113 * Send a request to the resource manager |
|
114 * @param MLogicalChain* aOldChain the last committed chain |
|
115 * @param MLogicalChain* aNewChain the current committed chain |
|
116 * @param TRequestStatus& aStatus |
|
117 * @return KErrNone in case of success of the send |
|
118 */ |
|
119 void CMMRCClientSideServerRequestToAdaptationAO::Service(TUint aRequestType) |
|
120 { |
|
121 DP_CONTEXT(----> CMMRCClientSideServerRequestToAdaptationAO::Service *CD1*, CtxDevSound, DPLOCAL); |
|
122 DP_IN(); |
|
123 iRequestType = aRequestType; |
|
124 iAudioContext = const_cast<MAudioContext*>(iServerSession->AudioContext()); |
|
125 iLogicalChainLastCommited = iServerSession->LogicalChainLastCommited(); |
|
126 iLogicalChainRequested = iServerSession->LogicalChainRequested(); |
|
127 |
|
128 // Simulate an asyncronous response |
|
129 /* |
|
130 unsafe as checking a client-thread object from server thread. |
|
131 if (IsActive()) |
|
132 |
|
133 Rely on serversession making this call safe. |
|
134 */ |
|
135 |
|
136 { |
|
137 TRequestStatus* status = &iStatus; |
|
138 DP1(2,"clientsideAO event",status); |
|
139 iClientThread->RequestComplete(status, KErrNone); |
|
140 } |
|
141 /* else |
|
142 { |
|
143 DP0(2,"shouldneverhappen!!"); |
|
144 ASSERT(0); |
|
145 } |
|
146 */ |
|
147 DP_OUT(); |
|
148 } |
|
149 |
|
150 /** |
|
151 * Callback in case of timeout |
|
152 */ |
|
153 void CMMRCClientSideServerRequestToAdaptationAO::ResourceRequestAcknowledgmentTimeout( ) |
|
154 { |
|
155 DP_CONTEXT(----> CMMRCClientSideServerRequestToAdaptationAO::ResourceRequestAcknowledgmentTimeout *CD1*, CtxDevSound, DPLOCAL); |
|
156 DP_IN(); |
|
157 |
|
158 DP_OUT(); |
|
159 } |
|
160 |
|
161 void CMMRCClientSideServerRequestToAdaptationAO::TidyUp() |
|
162 { |
|
163 /* |
|
164 This is a place to put synchronous tidyup code. |
|
165 See below first attempt. |
|
166 */ |
|
167 |
|
168 /* if(iStreamAdaptation) |
|
169 { |
|
170 iStreamAdaptation->UnregisterAllAudioStreamObserver(); |
|
171 |
|
172 if (iLogicalChainLastCommited) |
|
173 { |
|
174 // never got past uninitialised. delete. |
|
175 CLogicalAudioStream* audiostream = static_cast<CLogicalAudioStream*>(iLogicalChainLastCommited); |
|
176 TAudioState state = audiostream->StreamState(); |
|
177 if (state != EUninitialized) && (iLogicalChainLastCommited)) |
|
178 { |
|
179 CLogicalAudioStream* audiostream = static_cast<CLogicalAudioStream*>(iLogicalChainRequested); |
|
180 TAudioState state = audiostream->StreamState(); |
|
181 audiostream->ResetMessage(); |
|
182 audiostream->SetMessageType(EComponentDestruction); |
|
183 switch(state) |
|
184 { |
|
185 case EActive: |
|
186 case EPrimed: |
|
187 { |
|
188 audiostream->Stop(); |
|
189 } // deliberate fallthru'. |
|
190 case EIdle: |
|
191 { |
|
192 audiostream->Unload(); |
|
193 } // deliberate fallthru'. |
|
194 case EInitialized: |
|
195 { |
|
196 audiostream->Uninitialize(); |
|
197 iStreamAdaptation->Message(*iLogicalChainLastCommited, *iLogicalChainRequested, *iAudioContext, ETrue); |
|
198 waitForAdaptationResponse=EFalse; |
|
199 } |
|
200 break; |
|
201 default: |
|
202 { |
|
203 // No need to wait until adaptation responds... just kill. |
|
204 waitForAdaptationResponse=EFalse; |
|
205 } |
|
206 break; |
|
207 } |
|
208 } |
|
209 } |
|
210 */ delete iStreamAdaptation; |
|
211 }; |
|
212 |
|
213 |
|
214 /** |
|
215 * CMMRCClientSideServerRequestToAdaptationAO::RunL |
|
216 */ |
|
217 |
|
218 void CMMRCClientSideServerRequestToAdaptationAO::RunL() |
|
219 { |
|
220 DP_CONTEXT(--------> CMMRCClientSideServerRequestToAdaptationAO::RunL *CD1*, CtxDevSound, DPLOCAL); |
|
221 DP_IN(); |
|
222 |
|
223 /* |
|
224 flag is safe to read in A.O as it is set synchronously by an A.O running |
|
225 in the same Active scheduler. |
|
226 */ |
|
227 // no shut down... regular call. |
|
228 iStatus = KRequestPending; |
|
229 SetActive(); |
|
230 iRequestsProcessed++; |
|
231 |
|
232 TUint flags = 0; |
|
233 if(iRequestType == EPreemptionRequest) |
|
234 { |
|
235 flags |= KPreemptionRequest; |
|
236 } |
|
237 |
|
238 iStreamAdaptation->Message(*iLogicalChainLastCommited, *iLogicalChainRequested, *iAudioContext, flags); |
|
239 DP_OUT(); |
|
240 } |
|
241 |
|
242 /** |
|
243 CMMFDevSoundServer::CDelayDevSoundShutDown::DoCancel |
|
244 Called by Active object framework when user cancels active object. |
|
245 (other items were commented in a header). |
|
246 */ |
|
247 void CMMRCClientSideServerRequestToAdaptationAO::DoCancel() |
|
248 { |
|
249 DP_CONTEXT(----> CMMRCClientSideServerRequestToAdaptationAO::DoCancel *CD1*, CtxDevSound, DPLOCAL); |
|
250 DP_IN(); |
|
251 /* This is "rather complicated" :-) |
|
252 |
|
253 This AO always sets itself active, and hence this method will be called |
|
254 under all deletion conditions. |
|
255 |
|
256 As AO and signaller are in different threads, and in Symbian there is |
|
257 no official manner by which to ascertain if you have been signalled, |
|
258 we have a synchronous call (across client and server threads) which |
|
259 simply sets a flag and completes. The flag prevents any further |
|
260 requests being sent to the adaptation. |
|
261 |
|
262 By this mechanism, it is possible to read the number of requests |
|
263 sent in the server thread as the number does not change after the |
|
264 sync call. This is necessary as if there was no outstanding request |
|
265 this A.O needs to self-signal. |
|
266 */ |
|
267 |
|
268 /* |
|
269 This assert ensures that the synchronous client->server call occurred |
|
270 and therefore it is safe to do the next comparison. Necessary in |
|
271 case someone re-orders the MMRC client deletion later. |
|
272 */ |
|
273 ASSERT(iServerSession->IsServerShuttingDown()); |
|
274 |
|
275 /* check to see if we have processed all of the requests that |
|
276 have been sent by the server - i.e. are there any pending requests |
|
277 |
|
278 if (no outstanding requests) |
|
279 we need to self-signal or this would hang. |
|
280 otherwise |
|
281 we need to signal the server-side A.O to terminate that. |
|
282 */ |
|
283 if (iServerSession->RequestsSent() != iRequestsProcessed) |
|
284 { |
|
285 // should throw an error, rather than KErrNone |
|
286 // iMMRCServerSideAdaptationResponseAO->ServiceL( EMMRCAdaptationToServerShutdown, KErrServerTerminated); |
|
287 iMMRCServerSideAdaptationResponseAO->Service( EMMRCAdaptationToServerShutdown, KErrNone); |
|
288 } |
|
289 else |
|
290 { |
|
291 /* no more requests will ever come... self signal. |
|
292 Don't notify MMRC server A.O. - it won't be expecting one |
|
293 */ |
|
294 TRequestStatus* status(&iStatus); |
|
295 User::RequestComplete(status, KErrNone); |
|
296 } |
|
297 DP_OUT(); |
|
298 } |
|
299 |
|
300 /** |
|
301 * |
|
302 */ |
|
303 void CMMRCClientSideServerRequestToAdaptationAO::PhysicalAdaptationEvent(TPhysicalEvent aEvent, TInt aError) |
|
304 { |
|
305 DP_CONTEXT(----> CMMRCClientSideServerRequestToAdaptationAO::PhysicalAdaptationEvent *CD1*, CtxDevSound, DPLOCAL); |
|
306 DP_IN(); |
|
307 |
|
308 switch (aEvent) |
|
309 { |
|
310 case EOperationComplete: |
|
311 if(iMMRCServerSideAdaptationResponseAO) |
|
312 { |
|
313 iMMRCServerSideAdaptationResponseAO->Service( EMMRCAdaptationToServerResourceComplete, aError); |
|
314 } |
|
315 break; |
|
316 |
|
317 case EOperationIncomplete: |
|
318 if(iMMRCServerSideAdaptationResponseAO) |
|
319 { |
|
320 iMMRCServerSideAdaptationResponseAO->Service( EMMRCAdaptationToServerResourceIncomplete, aError); |
|
321 } |
|
322 break; |
|
323 |
|
324 default: |
|
325 break; |
|
326 } |
|
327 |
|
328 DP_OUT(); |
|
329 } |
|
330 |
|
331 /** |
|
332 * |
|
333 */ |
|
334 void CMMRCClientSideServerRequestToAdaptationAO::StateEvent(TInt /*aReason*/, TAudioState /*aNewState*/) |
|
335 { |
|
336 DP_CONTEXT(----> CMMRCClientSideServerRequestToAdaptationAO::StateEvent *CD1*, CtxDevSound, DPLOCAL); |
|
337 DP_IN(); |
|
338 |
|
339 DP_OUT(); |
|
340 } |
|
341 |
|
342 /** |
|
343 * |
|
344 */ |
|
345 void CMMRCClientSideServerRequestToAdaptationAO::AddProcessingUnitComplete(TUid /*aType*/, TInt /*aError*/) |
|
346 { |
|
347 DP_CONTEXT(----> CMMRCClientSideServerRequestToAdaptationAO::AddProcessingUnitComplete *CD1*, CtxDevSound, DPLOCAL); |
|
348 DP_IN(); |
|
349 |
|
350 DP_OUT(); |
|
351 } |
|
352 |
|
353 /** |
|
354 * |
|
355 */ |
|
356 void CMMRCClientSideServerRequestToAdaptationAO::RemoveProcessingUnitComplete(TUid /*aType*/, TInt /*aError*/) |
|
357 { |
|
358 DP_CONTEXT(----> CMMRCClientSideServerRequestToAdaptationAO::RemoveProcessingUnitComplete *CD1*, CtxDevSound, DPLOCAL); |
|
359 DP_IN(); |
|
360 |
|
361 DP_OUT(); |
|
362 } |
|
363 |
|
364 /** |
|
365 * |
|
366 */ |
|
367 void CMMRCClientSideServerRequestToAdaptationAO::ProcessingFinished() |
|
368 { |
|
369 DP_CONTEXT(----> CMMRCClientSideServerRequestToAdaptationAO::ProcessingFinished *CD1*, CtxDevSound, DPLOCAL); |
|
370 DP_IN(); |
|
371 |
|
372 DP_OUT(); |
|
373 } |
|
374 |
|
375 /** |
|
376 * |
|
377 */ |
|
378 void CMMRCClientSideServerRequestToAdaptationAO::FlushComplete(TInt /*aError*/) |
|
379 { |
|
380 DP_CONTEXT(----> CMMRCClientSideServerRequestToAdaptationAO::FlushComplete *CD1*, CtxDevSound, DPLOCAL); |
|
381 DP_IN(); |
|
382 |
|
383 DP_OUT(); |
|
384 } |
|
385 |
|
386 |
|
387 //------------------------------------------------------------------------------------ |
|
388 // |
|
389 //------------------------------------------------------------------------------------ |
|
390 /** |
|
391 */ |
|
392 CMMRCServerSideAdaptationResponseAO::CMMRCServerSideAdaptationResponseAO() |
|
393 : CActive(EPriorityHigh) |
|
394 { |
|
395 TRACE_CREATE(); |
|
396 DP_CONTEXT(----> CMMRCServerSideAdaptationResponseAO::CMMRCServerSideAdaptationResponseAO *CD1*, CtxDevSound, DPLOCAL); |
|
397 DP_IN(); |
|
398 DP_OUT(); |
|
399 } |
|
400 |
|
401 /** |
|
402 */ |
|
403 CMMRCServerSideAdaptationResponseAO::~CMMRCServerSideAdaptationResponseAO() |
|
404 { |
|
405 DP_CONTEXT(----> CMMRCServerSideAdaptationResponseAO::~CMMRCServerSideAdaptationResponseAO *CD1*, CtxDevSound, DPLOCAL); |
|
406 DP_IN(); |
|
407 |
|
408 Cancel(); |
|
409 |
|
410 DP_OUT(); |
|
411 } |
|
412 |
|
413 /** |
|
414 */ |
|
415 CMMRCServerSideAdaptationResponseAO* CMMRCServerSideAdaptationResponseAO::NewL() |
|
416 { |
|
417 DP_STATIC_CONTEXT(----> CMMRCServerSideAdaptationResponseAO::NewL *CD1*, CtxDevSound, DPLOCAL); |
|
418 DP_IN(); |
|
419 |
|
420 CMMRCServerSideAdaptationResponseAO* self = new(ELeave) CMMRCServerSideAdaptationResponseAO(); |
|
421 CleanupStack::PushL( self ); |
|
422 self->ConstructL(); |
|
423 CleanupStack::Pop(self); |
|
424 |
|
425 DP0_RET(self, "self = 0x%x"); |
|
426 } |
|
427 |
|
428 /** |
|
429 */ |
|
430 void CMMRCServerSideAdaptationResponseAO::ConstructL() |
|
431 { |
|
432 DP_CONTEXT(----> CMMRCServerSideAdaptationResponseAO::ConstructL *CD1*, CtxDevSound, DPLOCAL); |
|
433 DP_IN(); |
|
434 |
|
435 CActiveScheduler::Add (this ); |
|
436 |
|
437 DP_OUT(); |
|
438 } |
|
439 |
|
440 /** |
|
441 */ |
|
442 void CMMRCServerSideAdaptationResponseAO::Initialize(CMMRCServerSession* aServerSession, RThread* aServerThread ) |
|
443 { |
|
444 DP_CONTEXT(----> CMMRCServerSideAdaptationResponseAO::SetServerSession *CD1*, CtxDevSound, DPLOCAL); |
|
445 DP_IN(); |
|
446 |
|
447 iMMRCServerSession = aServerSession; |
|
448 ASSERT(iMMRCServerSession!=0); |
|
449 iServerThread = aServerThread; |
|
450 ASSERT(iServerThread!=0); |
|
451 DP_OUT(); |
|
452 } |
|
453 |
|
454 /** |
|
455 These are rather misleading convenience functions which are called |
|
456 from the context of the caller (i.e. a different thread context) |
|
457 |
|
458 Be very cautious with what you rely on. |
|
459 */ |
|
460 void CMMRCServerSideAdaptationResponseAO::Service(TMMRCAdaptationToServerRequestResults aEvent, TInt aError) |
|
461 { |
|
462 DP_CONTEXT(----> CMMRCServerSideAdaptationResponseAO::Service *CD1*, CtxDevSound, DPLOCAL); |
|
463 DP_IN(); |
|
464 |
|
465 iEvent = aEvent; |
|
466 iError = aError; |
|
467 |
|
468 // Simulate an asynchronous response on correct thread. |
|
469 TRequestStatus* status = &iStatus; |
|
470 iServerThread->RequestComplete(status, KErrNone); |
|
471 DP_OUT(); |
|
472 } |
|
473 /** |
|
474 */ |
|
475 void CMMRCServerSideAdaptationResponseAO::DoCancel( ) |
|
476 { |
|
477 DP_CONTEXT(----> CMMRCServerSideAdaptationResponseAO::DoCancel *CD1*, CtxDevSound, DPLOCAL); |
|
478 DP_IN(); |
|
479 /* this should only happen if there is a pending request. |
|
480 client-side will send a response before closing. |
|
481 |
|
482 See DoCancel in CMMRCClientSideServerRequestToAdaptationAO for details. |
|
483 */ |
|
484 DP_OUT(); |
|
485 } |
|
486 |
|
487 /** |
|
488 server-side A.O. used to observe the outcome. |
|
489 |
|
490 Calls back AdaptationRequestAcknowledgment on MMRC server session |
|
491 from server thread context. |
|
492 */ |
|
493 void CMMRCServerSideAdaptationResponseAO::RunL() |
|
494 { |
|
495 DP_CONTEXT(--------> CMMRCServerSideAdaptationResponseAO::RunL *CD1*, CtxDevSound, DPLOCAL); |
|
496 DP_IN(); |
|
497 iMMRCServerSession->AdaptationRequestAcknowledgment( iEvent, iError ); |
|
498 DP_OUT(); |
|
499 } |
|
500 |
|
501 void CMMRCServerSideAdaptationResponseAO::StartAdaptationListening() |
|
502 { |
|
503 /* wrapper functio to set up the A.O */ |
|
504 iStatus = KRequestPending; |
|
505 SetActive(); |
|
506 } |
|
507 //EOF |