|
1 /* |
|
2 * Copyright (c) 2008 Nokia Corporation and/or its subsidiary(-ies). |
|
3 * All rights reserved. |
|
4 * This component and the accompanying materials are made available |
|
5 * under the terms of "Eclipse Public License v1.0" |
|
6 * which accompanies this distribution, and is available |
|
7 * at the URL "http://www.eclipse.org/legal/epl-v10.html". |
|
8 * |
|
9 * Initial Contributors: |
|
10 * Nokia Corporation - initial contribution. |
|
11 * |
|
12 * Contributors: |
|
13 * |
|
14 * Description: Interthread synchronization object |
|
15 * |
|
16 */ |
|
17 |
|
18 |
|
19 |
|
20 #include <e32debug.h> |
|
21 #include <coemain.h> |
|
22 #include "alfstreamerbridge.h" |
|
23 #include "alfstreamerserver.h" |
|
24 #include "alflogger.h" |
|
25 |
|
26 #ifdef ALF_DEBUG_TRACK_DRAWING |
|
27 #include "alfcommanddebug.h" |
|
28 #endif |
|
29 |
|
30 |
|
31 // #define EGL_TALKS_TO_WINDOW_SERVER |
|
32 |
|
33 // --------------------------------------------------------------------------- |
|
34 // constructor |
|
35 // |
|
36 // --------------------------------------------------------------------------- |
|
37 // |
|
38 |
|
39 // The priority is EActivePriorityWsEvents+1 instead of CActive::EPriorityHigh to prevent a deadlock |
|
40 // when AlfredServerThread calling iWsSession.GetEvent(event); from inside CCoeEnv::RunL() while |
|
41 // wserv was waiting inside CWindowServer::CDefaultAnimationScheduler::DoRedrawNow for Alf to |
|
42 // complete the TRequestStatus passed to CAlfRenderStage::End. |
|
43 |
|
44 CAlfStreamerBridge::CAlfStreamerBridge(MAlfStreamerListener* aObserver):CActive(EActivePriorityWsEvents+1),iObserver(aObserver), iBatchObserver(0), iThread(RThread().Id()) |
|
45 { |
|
46 CActiveScheduler::Add(this); |
|
47 iStatus = KRequestPending; |
|
48 SetActive(); |
|
49 TInt err = iQueueSema.CreateLocal(); |
|
50 |
|
51 if (err) |
|
52 { |
|
53 // Device startup ends here. |
|
54 __ALFLOGSTRING("Stop the music, we are running without synchronization"); |
|
55 User::Panic(_L("UI Accelerator"), 1); |
|
56 } |
|
57 } |
|
58 |
|
59 // --------------------------------------------------------------------------- |
|
60 // NewL |
|
61 // |
|
62 // --------------------------------------------------------------------------- |
|
63 // |
|
64 CAlfStreamerBridge* CAlfStreamerBridge::NewL( MAlfStreamerListener* aObserver ) |
|
65 { |
|
66 CAlfStreamerBridge* self = new(ELeave)CAlfStreamerBridge( aObserver ); |
|
67 CleanupStack::PushL( self ); |
|
68 self->ConstructL(); |
|
69 CleanupStack::Pop( self ); |
|
70 return self; |
|
71 } |
|
72 |
|
73 // --------------------------------------------------------------------------- |
|
74 // ConstructL |
|
75 // |
|
76 // --------------------------------------------------------------------------- |
|
77 // |
|
78 void CAlfStreamerBridge::ConstructL() |
|
79 { |
|
80 iDataBuf.Create( KInitialVariableBufferSize ); |
|
81 iDataBuf.SetLength(0); |
|
82 iStreamerServer = NULL; |
|
83 #ifdef ALF_DEBUG_TRACK_DRAWING |
|
84 iCommandDebugger = CAlfCommandDebug::NewL(); |
|
85 #endif |
|
86 CHuiEnv::Static()->iSwapObserver = this; |
|
87 } |
|
88 |
|
89 // --------------------------------------------------------------------------- |
|
90 // destructor |
|
91 // |
|
92 // --------------------------------------------------------------------------- |
|
93 // |
|
94 CAlfStreamerBridge::~CAlfStreamerBridge() |
|
95 { |
|
96 CHuiEnv::Static()->iSwapObserver = 0; |
|
97 iDataBuf.Close(); |
|
98 iQueueSema.Close(); |
|
99 #ifdef ALF_DEBUG_TRACK_DRAWING |
|
100 delete iCommandDebugger; |
|
101 #endif |
|
102 } |
|
103 |
|
104 // --------------------------------------------------------------------------- |
|
105 // SetBatchObserver |
|
106 // |
|
107 // --------------------------------------------------------------------------- |
|
108 // |
|
109 void CAlfStreamerBridge::SetBatchObserver(MAlfBatchObs* aBatchObserver) |
|
110 { |
|
111 iBatchObserver = aBatchObserver; |
|
112 } |
|
113 |
|
114 // --------------------------------------------------------------------------- |
|
115 // Activate |
|
116 // |
|
117 // --------------------------------------------------------------------------- |
|
118 // |
|
119 void CAlfStreamerBridge::Activate() |
|
120 { |
|
121 iStatus = KRequestPending; |
|
122 SetActive(); |
|
123 } |
|
124 |
|
125 // --------------------------------------------------------------------------- |
|
126 // Trigger |
|
127 // |
|
128 // --------------------------------------------------------------------------- |
|
129 // |
|
130 TInt CAlfStreamerBridge::Trigger(TInt aStatus) |
|
131 { |
|
132 TInt err = KErrNone; |
|
133 if (!iVarDataAddedButNotPosted) |
|
134 { |
|
135 iQueueSema.Wait(); |
|
136 } |
|
137 iVarDataAddedButNotPosted = EFalse; // after this point, data may just be lost if posting fails |
|
138 __ALFLOGSTRING2("CAlfStreamerBridge::Trigger status %d, own request status %d", aStatus, iStatus.Int() ); |
|
139 if (IsActive() && iStatus == KRequestPending) |
|
140 { |
|
141 RThread t; |
|
142 TInt err = t.Open(iThread); |
|
143 if (err) |
|
144 { |
|
145 __ALFLOGSTRING1( "CAlfStreamerBridge::Trigger() ignore RThread::Open() error: %d", err ); |
|
146 } |
|
147 TRequestStatus* status = &iStatus; |
|
148 __ALFLOGSTRING("CAlfStreamerBridge::Trigger - completing CAlfStreamerBridge"); |
|
149 t.RequestComplete(status, aStatus); |
|
150 t.Close(); |
|
151 } |
|
152 else |
|
153 { |
|
154 #ifdef _DEBUG |
|
155 if ( IsActive() ) |
|
156 { |
|
157 __ALFLOGSTRING("CAlfStreamerBridge::Trigger - already active"); |
|
158 } |
|
159 __ALFLOGSTRING("CAlfStreamerBridge::Trigger - appending data"); |
|
160 #endif |
|
161 err = iQueue.Append(aStatus); |
|
162 } |
|
163 |
|
164 iQueueSema.Signal(); |
|
165 __ALFLOGSTRING1("CAlfStreamerBridge::Trigger request status %d", iStatus.Int() ); |
|
166 return err; |
|
167 } |
|
168 |
|
169 // --------------------------------------------------------------------------- |
|
170 // AddData |
|
171 // |
|
172 // --------------------------------------------------------------------------- |
|
173 // |
|
174 TInt CAlfStreamerBridge::AddData( TAlfDecoderServerBindings aOp,TInt aI1,TInt aI2 ,TAny* aPtr ) |
|
175 { |
|
176 if (iSwapActive && aOp == EAlfRequestCommitBatch) |
|
177 { |
|
178 __ALFLOGSTRING("CAlfStreamerBridge::AddData() just release window server"); |
|
179 iBatchObserver->BridgerCallback(KRELEASEWINDOWSERVER,KRELEASEDBEFOREQUEUE); |
|
180 return KErrNone; |
|
181 } |
|
182 |
|
183 TInt err = KErrNotFound; |
|
184 { |
|
185 #ifdef ALF_DEBUG_TRACK_DRAWING |
|
186 iCommandDebugger->SetDescription( aOp, R_ALF_BRIDGE_COMMAND_DESCRIPTION_ARRAY ); |
|
187 __ALFLOGSTRING2("CAlfStreamerBridge::AddData op %S, iQueue.Length = %d", &iCommandDebugger->Text(), iQueue.Count()); |
|
188 #else |
|
189 __ALFLOGSTRING2("CAlfStreamerBridge::AddData op %d, iQueue.Length = %d", aOp, iQueue.Count()); |
|
190 #endif |
|
191 err = KErrNone; |
|
192 for(TInt i = 0; i < iMessages.Count(); i++ ) |
|
193 { |
|
194 if (iMessages[i].IsEmpty()) |
|
195 { |
|
196 iMessages[i].Set(aOp,aI1,aI2,aPtr); |
|
197 err = Trigger(i); |
|
198 return err; |
|
199 } |
|
200 } |
|
201 |
|
202 // No existing (empty) cell was available for recycling, add new cell to array |
|
203 TAlfBridgerData data; |
|
204 data.Set(aOp,aI1,aI2,aPtr); |
|
205 err = iMessages.Append(data); |
|
206 } |
|
207 if (!err) |
|
208 { |
|
209 err = Trigger(iMessages.Count()-1); |
|
210 } |
|
211 else |
|
212 { |
|
213 iQueueSema.Signal(); |
|
214 } |
|
215 return err; |
|
216 } |
|
217 |
|
218 // --------------------------------------------------------------------------- |
|
219 // GetData |
|
220 // |
|
221 // Note, that this method frees the message entry for reuse. |
|
222 // --------------------------------------------------------------------------- |
|
223 // |
|
224 TAlfBridgerData CAlfStreamerBridge::GetData(TInt aIndex) |
|
225 { |
|
226 TAlfBridgerData data; |
|
227 ASSERT(aIndex <= iMessages.Count()-1); |
|
228 data = iMessages[aIndex]; |
|
229 return data; |
|
230 } |
|
231 |
|
232 void CAlfStreamerBridge::PrepareSwap() |
|
233 { |
|
234 #ifdef EGL_TALKS_TO_WINDOW_SERVER |
|
235 __ALFLOGSTRING("CAlfStreamerBridge:: Prepare swap, flush the queue"); |
|
236 iSwapActive = ETrue; |
|
237 if (iStatus.Int() >=0 && iMessages.Count() > iStatus.Int() ) |
|
238 { |
|
239 Cancel(); // remove from scheduler |
|
240 RunL(); // run manually (and activate) |
|
241 } |
|
242 __ALFLOGSTRING("CAlfStreamerBridge:: Prepare swap, the queue emptied"); |
|
243 #endif //#ifdef EGL_TALKS_TO_WINDOW_SERVER |
|
244 } |
|
245 |
|
246 void CAlfStreamerBridge::SwapComplete() |
|
247 { |
|
248 #ifdef EGL_TALKS_TO_WINDOW_SERVER |
|
249 __ALFLOGSTRING("CAlfStreamerBridge:: Swap buffers complete"); |
|
250 iSwapActive = EFalse; |
|
251 #endif // #ifdef EGL_TALKS_TO_WINDOW_SERVER |
|
252 |
|
253 } |
|
254 |
|
255 #ifdef EGL_TALKS_TO_WINDOW_SERVER |
|
256 void CAlfStreamerBridge::ReleaseWindowServer(TBool aRelease) |
|
257 { |
|
258 __ALFLOGSTRING1("CAlfStreamerBridge::ReleaseWindowServer: %d",aRelease); |
|
259 if (aRelease) |
|
260 { |
|
261 iMakeCurrentActive = ETrue; |
|
262 if (iBatchObserver && !iSwapActive) |
|
263 { |
|
264 iBatchObserver->BridgerCallback(KRELEASEWINDOWSERVER); |
|
265 } |
|
266 } |
|
267 else |
|
268 { |
|
269 iMakeCurrentActive = EFalse; |
|
270 } |
|
271 #else |
|
272 void CAlfStreamerBridge::ReleaseWindowServer(TBool) |
|
273 { |
|
274 #endif |
|
275 } |
|
276 |
|
277 void CAlfStreamerBridge::SetWgIdArray(TInt* aArray) |
|
278 { |
|
279 iWgArray = aArray; |
|
280 } |
|
281 |
|
282 EXPORT_C TUid CAlfStreamerBridge::FindAppUidForWgId(TInt aWgId) |
|
283 { |
|
284 if (iWgArray) |
|
285 {TInt* ptr = iWgArray; |
|
286 for (TInt i=0; i<39; i=i+2) // magic |
|
287 { |
|
288 if (ptr[i] == aWgId) |
|
289 { |
|
290 return TUid::Uid(ptr[i+1]); |
|
291 } |
|
292 if (!ptr[i]) |
|
293 { |
|
294 break; |
|
295 } |
|
296 } |
|
297 } |
|
298 return KNullUid; |
|
299 } |
|
300 |
|
301 EXPORT_C TInt CAlfStreamerBridge::FindWgForAppUid(TUid aAppUid) |
|
302 { |
|
303 if (iWgArray) |
|
304 {TInt* ptr = iWgArray; |
|
305 for (TInt i=0; i<39; i=i+2) // magic |
|
306 { |
|
307 if (ptr[i+1] == aAppUid.iUid) |
|
308 { |
|
309 return ptr[i]; |
|
310 } |
|
311 if (!ptr[i]) |
|
312 { |
|
313 break; |
|
314 } |
|
315 } |
|
316 } |
|
317 return 0; |
|
318 } |
|
319 |
|
320 // --------------------------------------------------------------------------- |
|
321 // RunL |
|
322 // |
|
323 // --------------------------------------------------------------------------- |
|
324 // |
|
325 void CAlfStreamerBridge::RunL() |
|
326 { |
|
327 TInt operation = iMessages[iStatus.Int()].iOp; |
|
328 |
|
329 #ifdef ALF_DEBUG_TRACK_DRAWING |
|
330 iCommandDebugger->SetDescription( operation, R_ALF_BRIDGE_COMMAND_DESCRIPTION_ARRAY ); |
|
331 __ALFLOGSTRING1("CAlfStreamerBridge::RunL: First op %S", &iCommandDebugger->Text() ); |
|
332 #else |
|
333 __ALFLOGSTRING1("CAlfStreamerBridge::RunL: First op %d", operation); |
|
334 #endif |
|
335 switch ( operation ) |
|
336 { |
|
337 // Just call back to Alf decoder thread |
|
338 case EAlfRequestCommitBatch: |
|
339 case EAlfRequestCommandReadNotification: |
|
340 case EAlfReleaseTemporaryChunk: |
|
341 { |
|
342 if (iBatchObserver) |
|
343 { |
|
344 iBatchObserver->BridgerCallback( operation, iMessages[iStatus.Int()].iInt1 ); |
|
345 } |
|
346 iMessages[iStatus.Int()].ResetEntry(); |
|
347 break; |
|
348 } |
|
349 default: |
|
350 { |
|
351 // Handle command |
|
352 __ALFLOGSTRING("CAlfStreamerBridge:: calling observer callback"); |
|
353 iObserver->HandleCallback(iStatus.Int()); |
|
354 |
|
355 // For "getters" also call back to Alf decoder thread |
|
356 if ((operation > EAlfDSGetCommandsStart) && (operation < EAlfDSGetCommandsEnd)) |
|
357 { |
|
358 if (iBatchObserver) |
|
359 { |
|
360 iBatchObserver->BridgerCallback( operation, iMessages[iStatus.Int()].iInt1 ); |
|
361 } |
|
362 } |
|
363 |
|
364 iMessages[iStatus.Int()].ResetEntry(); // mark the cell free |
|
365 } |
|
366 } |
|
367 |
|
368 // Todo: is this kind of burst mode ok, it should be.. |
|
369 iQueueSema.Wait(); |
|
370 while (iQueue.Count()) |
|
371 { |
|
372 TInt operation2 = iMessages[iQueue[0]].iOp; |
|
373 #ifdef ALF_DEBUG_TRACK_DRAWING |
|
374 iCommandDebugger->SetDescription( operation2, R_ALF_BRIDGE_COMMAND_DESCRIPTION_ARRAY ); |
|
375 __ALFLOGSTRING1("CAlfStreamerBridge:: Queue op %S", &iCommandDebugger->Text() ); |
|
376 #else |
|
377 __ALFLOGSTRING1("CAlfStreamerBridge:: Queue op %d", operation2 ); |
|
378 #endif |
|
379 switch ( operation2 ) |
|
380 { |
|
381 case EAlfRequestCommitBatch: |
|
382 case EAlfRequestCommandReadNotification: |
|
383 case EAlfReleaseTemporaryChunk: |
|
384 { |
|
385 if (iBatchObserver) |
|
386 { |
|
387 __ALFLOGSTRING("CAlfStreamerBridge:: calling BATCH observer callback"); |
|
388 iBatchObserver->BridgerCallback( operation2, iMessages[iQueue[0]].iInt1 ); |
|
389 } |
|
390 iMessages[iQueue[0]].ResetEntry(); |
|
391 break; |
|
392 } |
|
393 default: |
|
394 { |
|
395 // Handle command |
|
396 __ALFLOGSTRING("CAlfStreamerBridge:: calling observer callback"); |
|
397 iObserver->HandleCallback(iQueue[0]); |
|
398 |
|
399 // For "getters" also call back to Alf decoder thread |
|
400 if ((operation2 > EAlfDSGetCommandsStart) && (operation2 < EAlfDSGetCommandsEnd)) |
|
401 { |
|
402 if (iBatchObserver) |
|
403 { |
|
404 iBatchObserver->BridgerCallback( operation2, iMessages[iQueue[0]].iInt1 ); |
|
405 } |
|
406 } |
|
407 iMessages[iQueue[0]].ResetEntry(); // mark the cell free |
|
408 } |
|
409 } |
|
410 iQueue.Remove(0); |
|
411 } |
|
412 if ( !iItemsInBuffer ) |
|
413 { |
|
414 iDataBuf.SetLength(0); |
|
415 } |
|
416 |
|
417 __ALFLOGSTRING1("CAlfStreamerBridge::RunL - activating", iItemsInBuffer); |
|
418 Activate(); |
|
419 iQueueSema.Signal(); |
|
420 __ALFLOGSTRING1("CAlfStreamerBridge::RunL - really really ending", iItemsInBuffer); |
|
421 } |
|
422 |
|
423 // --------------------------------------------------------------------------- |
|
424 // DoCancel |
|
425 // |
|
426 // --------------------------------------------------------------------------- |
|
427 // |
|
428 void CAlfStreamerBridge::DoCancel() |
|
429 { |
|
430 if (iBatchObserver) |
|
431 { |
|
432 iBatchObserver->BridgerCanceled(); |
|
433 } |
|
434 } |
|
435 |
|
436 // --------------------------------------------------------------------------- |
|
437 // StartNewBlock |
|
438 // |
|
439 // --------------------------------------------------------------------------- |
|
440 // |
|
441 void CAlfStreamerBridge::StartNewBlock() |
|
442 { |
|
443 // Queue marker. Basically we could use one new member to assert that there can |
|
444 // be only one marker |
|
445 __ALFLOGSTRING1("CAlfStreamerBridge:: Request command read notification, swap active: %d", iSwapActive ); |
|
446 if ( iSwapActive || iMakeCurrentActive ) |
|
447 { |
|
448 __ALFLOGSTRING("CAlfStreamerBridge::StartNewBlock() just release window server"); |
|
449 iBatchObserver->BridgerCallback(KRELEASEWINDOWSERVER,KRELEASEDBEFOREQUEUE); |
|
450 return; |
|
451 } |
|
452 AddData(EAlfRequestCommitBatch,0,0,0); |
|
453 } |
|
454 |
|
455 // --------------------------------------------------------------------------- |
|
456 // RequestCommandReadNotification |
|
457 // |
|
458 // --------------------------------------------------------------------------- |
|
459 // |
|
460 void CAlfStreamerBridge::RequestCommandReadNotification( TInt aLastReadOffset, TAlfDecoderServerBindings aCommand ) |
|
461 { |
|
462 AddData( aCommand, aLastReadOffset, 0, 0); |
|
463 } |
|
464 |
|
465 // --------------------------------------------------------------------------- |
|
466 // AppendVarDataL |
|
467 // |
|
468 // Note, that memory allocation is done only if current buffer is not large enough |
|
469 // to add an item. |
|
470 // TODO: The buffers added are not the buffer in optimal way. |
|
471 // --------------------------------------------------------------------------- |
|
472 // |
|
473 EXPORT_C const TAny* CAlfStreamerBridge::AppendVarDataL( TInt aSize, TInt& aIndex ) |
|
474 { |
|
475 iQueueSema.Wait(); |
|
476 // Make sure the length of the allocated data is always divisible by 8 |
|
477 if ( aSize % 8 != 0 ) |
|
478 { |
|
479 __ALFLOGSTRING1("CAlfStreamerBridge::AppendVarDataL, size not multiple of 8: %d", aSize ); |
|
480 aSize = aSize + ( 8 - aSize % 8 ); |
|
481 } |
|
482 if ( iDataBuf.Length() + aSize >= iDataBuf.MaxLength() ) |
|
483 { |
|
484 TRAPD(err, iDataBuf.ReAllocL( iDataBuf.MaxLength() + KInitialVariableBufferSize )); |
|
485 if ( err ) |
|
486 { |
|
487 __ALFLOGSTRING("CAlfStreamerBridge::AppendVarDataL, realloc failed"); |
|
488 iQueueSema.Signal(); |
|
489 return NULL; |
|
490 } |
|
491 __ALFLOGSTRING1("CAlfStreamerBridge::AppendVarDataL, new max size: %d", iDataBuf.MaxLength() ); |
|
492 } |
|
493 aIndex = iDataBuf.Length(); |
|
494 iDataBuf.SetLength( iDataBuf.Length() + aSize); |
|
495 iItemsInBuffer++; |
|
496 __ALFLOGSTRING1("CAlfStreamerBridge::AppendVarDataL: buflength %d", iDataBuf.Length()); |
|
497 iVarDataAddedButNotPosted = ETrue; |
|
498 return iDataBuf.MidTPtr( aIndex ).Ptr(); |
|
499 } |
|
500 |
|
501 // --------------------------------------------------------------------------- |
|
502 // GetVarDataL |
|
503 // |
|
504 // Note, that data is not removed at any point. However it should not be accessed again |
|
505 // with this method, because that would confuse iItemsInBuffer counter. |
|
506 // --------------------------------------------------------------------------- |
|
507 // |
|
508 const TAny* CAlfStreamerBridge::GetVarDataL( TInt aIndex ) |
|
509 { |
|
510 ASSERT( aIndex >= 0 && aIndex < iDataBuf.MaxLength() ); |
|
511 ASSERT( iItemsInBuffer ); |
|
512 iItemsInBuffer--; |
|
513 return iDataBuf.MidTPtr( aIndex ).Ptr(); |
|
514 } |
|
515 |
|
516 EXPORT_C const TAny* CAlfStreamerBridge::AppendEffectsDataL( TInt aSize, TInt& aIndex ) |
|
517 { |
|
518 return AppendVarDataL( aSize, aIndex ); |
|
519 } |
|
520 |
|
521 // --------------------------------------------------------------------------- |
|
522 // GetVarDataL |
|
523 // |
|
524 // Note, that data is not removed at any point. However it should not be accessed again |
|
525 // with this method, because that would confuse iItemsInBuffer counter. |
|
526 // --------------------------------------------------------------------------- |
|
527 // |
|
528 const TAny* CAlfStreamerBridge::GetEffectsDataL( TInt aIndex ) |
|
529 { |
|
530 return GetVarDataL(aIndex); |
|
531 } |
|
532 |
|
533 // --------------------------------------------------------------------------- |
|
534 // SetStreamerServer |
|
535 // --------------------------------------------------------------------------- |
|
536 // |
|
537 void CAlfStreamerBridge::SetStreamerServer( CAlfStreamerServer& aStreamerServer ) |
|
538 { |
|
539 iStreamerServer = &aStreamerServer; |
|
540 } |
|
541 |
|
542 // --------------------------------------------------------------------------- |
|
543 // StreamerServer |
|
544 // --------------------------------------------------------------------------- |
|
545 // |
|
546 CAlfStreamerServer* CAlfStreamerBridge::StreamerServer() |
|
547 { |
|
548 return iStreamerServer; |
|
549 } |