|
1 /* |
|
2 * Copyright (c) 2006 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: Implementation of the ClientStreamControl class. |
|
15 * |
|
16 */ |
|
17 |
|
18 |
|
19 #include <mmf/common/mmfdrmcustomcommands.h> |
|
20 #include <StreamControlEvents.h> |
|
21 #include <DataBufferSource.h> |
|
22 #include <EffectControl.h> |
|
23 #include <SinkControl.h> |
|
24 #include <SourceControl.h> |
|
25 #include <ProgDLSource.h> |
|
26 #include <FileSource.h> |
|
27 #include <DescriptorSource.h> |
|
28 #include <SCCustomInterfaceUIDs.h> |
|
29 |
|
30 #include "ClientStreamControl.h" |
|
31 #include "EventNotifier.h" |
|
32 #include "EventBase.h" |
|
33 #include "ErrorCode.h" |
|
34 #include "StateChangedEvent.h" |
|
35 #include "CMCustomCommand.h" |
|
36 #include "SourceBase.h" |
|
37 #include "SinkBase.h" |
|
38 #include "tracemacros.h" |
|
39 |
|
40 #define RETURN_IF_ERROR(x) if(x != KErrNone) return x |
|
41 |
|
42 #ifdef __WINDOWS_MEDIA |
|
43 #ifndef RD_PD_FOR_AUDIO_CONTENT_VIA_HELIX_ENGINE |
|
44 _LIT8(KWMAMimeType,"audio/x-ms-wma"); |
|
45 #endif |
|
46 #endif |
|
47 |
|
48 const TInt KMaxMimeLength = 256; |
|
49 |
|
50 using namespace multimedia; |
|
51 |
|
52 CStreamControl::CStreamControl() : |
|
53 iStreamState(EStreamClosed), iStreamControlCustomCommands(iController) |
|
54 { |
|
55 // No impl yet |
|
56 iError = KErrNone; |
|
57 } |
|
58 |
|
59 CStreamControl::~CStreamControl() |
|
60 { |
|
61 EMC_TRACE1(_L("CStreamControl::~CStreamControl")); |
|
62 // Don't have to send events to observers. |
|
63 Close(); |
|
64 delete iCMCustomCommand; |
|
65 delete iEventNotifier; |
|
66 delete iEventNotifierForEffects; |
|
67 delete iControllerEventMonitor; |
|
68 delete iFindAndOpenController; |
|
69 // Signal associated effects that this instance is closed |
|
70 TInt index(0); |
|
71 CEffectControlBase* effectBase(NULL); |
|
72 for (; index < iAssociatedEffects.Count(); index++) |
|
73 { |
|
74 effectBase = iAssociatedEffects[index]; |
|
75 effectBase->StreamControlDeleted( *this); |
|
76 } |
|
77 iAssociatedEffects.Close(); |
|
78 REComSession::FinalClose(); |
|
79 } |
|
80 |
|
81 TInt CStreamControl::PostConstructor() |
|
82 { |
|
83 TInt status(KErrNone); |
|
84 if (!iControllerEventMonitor) |
|
85 { |
|
86 TRAP(status, iControllerEventMonitor = CMMFControllerEventMonitor::NewL(*this, iController)); |
|
87 } |
|
88 RETURN_IF_ERROR(status); |
|
89 |
|
90 if (!iFindAndOpenController) |
|
91 { |
|
92 TRAP(status, iFindAndOpenController = CMMFFindAndOpenController::NewL(*this)); |
|
93 } |
|
94 RETURN_IF_ERROR(status); |
|
95 |
|
96 if (!iEventNotifier) |
|
97 { |
|
98 TRAP(status, iEventNotifier = CEventNotifier::NewL()); |
|
99 } |
|
100 if ( !iEventNotifierForEffects) |
|
101 { |
|
102 TRAP(status, iEventNotifierForEffects = CEventNotifier::NewL()); |
|
103 } |
|
104 |
|
105 if (!iCMCustomCommand) |
|
106 { |
|
107 iCMCustomCommand = new CMCustomCommand(iController); |
|
108 if ( !iCMCustomCommand) |
|
109 status = KErrNoMemory; |
|
110 } |
|
111 return status; |
|
112 } |
|
113 |
|
114 TInt CStreamControl::AddObserver(MControlObserver& aObserver) |
|
115 { |
|
116 return iEventNotifier->AddObserver(aObserver); |
|
117 } |
|
118 |
|
119 TInt CStreamControl::RemoveObserver(MControlObserver& aObserver) |
|
120 { |
|
121 return iEventNotifier->RemoveObserver(aObserver); |
|
122 } |
|
123 |
|
124 TUid CStreamControl::Type() |
|
125 { |
|
126 return KStreamControl; |
|
127 } |
|
128 |
|
129 TControlType CStreamControl::ControlType() |
|
130 { |
|
131 return EStreamControl; |
|
132 } |
|
133 |
|
134 TInt CStreamControl::AddSource(MSourceControl& aSource) |
|
135 { |
|
136 TInt status(KErrNotReady); |
|
137 switch (iStreamState) |
|
138 { |
|
139 case EStreamClosed: |
|
140 status = KErrAlreadyExists; |
|
141 if ( !iSourceControl) |
|
142 { |
|
143 iSourceControl = &aSource; |
|
144 status = KErrNone; |
|
145 } |
|
146 break; |
|
147 default: |
|
148 break; |
|
149 }; |
|
150 return status; |
|
151 } |
|
152 |
|
153 TInt CStreamControl::RemoveSource(MSourceControl& aSource) |
|
154 { |
|
155 TInt status(KErrLocked); |
|
156 switch (iStreamState) |
|
157 { |
|
158 case EStreamClosed: |
|
159 status = KErrBadHandle; |
|
160 if (iSourceControl == &aSource) |
|
161 { |
|
162 iSourceControl = NULL; |
|
163 status = KErrNone; |
|
164 } |
|
165 break; |
|
166 default: |
|
167 break; |
|
168 }; |
|
169 return status; |
|
170 } |
|
171 |
|
172 TInt CStreamControl::AddSink(MSinkControl& aSink) |
|
173 { |
|
174 TInt status(KErrNotReady); |
|
175 switch (iStreamState) |
|
176 { |
|
177 case EStreamClosed: |
|
178 status = KErrAlreadyExists; |
|
179 if ( !iSinkControl) |
|
180 { |
|
181 iSinkControl = &aSink; |
|
182 status = KErrNone; |
|
183 } |
|
184 break; |
|
185 default: |
|
186 break; |
|
187 }; |
|
188 return status; |
|
189 } |
|
190 |
|
191 TInt CStreamControl::RemoveSink(MSinkControl& aSink) |
|
192 { |
|
193 TInt status(KErrLocked); |
|
194 switch (iStreamState) |
|
195 { |
|
196 case EStreamClosed: |
|
197 status = KErrBadHandle; |
|
198 if (iSinkControl == &aSink) |
|
199 { |
|
200 iSinkControl = NULL; |
|
201 status = KErrNone; |
|
202 } |
|
203 break; |
|
204 default: |
|
205 break; |
|
206 }; |
|
207 return status; |
|
208 } |
|
209 |
|
210 TInt CStreamControl::RemoveEffect(MEffectControl& aEffect) |
|
211 { |
|
212 TInt status(KErrNotReady); |
|
213 // Get the observer from effect |
|
214 CEffectControlBase* effectBase = |
|
215 dynamic_cast<CEffectControlBase*>(&aEffect); |
|
216 |
|
217 // Remove the effect from the array |
|
218 TInt index(KErrNotFound); |
|
219 index = iAssociatedEffects.Find(effectBase); |
|
220 if (index != KErrNotFound) |
|
221 { |
|
222 MControlObserver* observer; |
|
223 status = effectBase->GetControlObserver(observer); |
|
224 RETURN_IF_ERROR( status ); |
|
225 |
|
226 status = iEventNotifierForEffects->RemoveObserver( *observer); |
|
227 RETURN_IF_ERROR( status ); |
|
228 |
|
229 iAssociatedEffects.Remove(index); |
|
230 status = effectBase->RemovedFromStreamControl(*this); |
|
231 RETURN_IF_ERROR( status ); |
|
232 } |
|
233 |
|
234 return status; |
|
235 } |
|
236 |
|
237 TInt CStreamControl::AddEffect(MEffectControl& aEffect) |
|
238 { |
|
239 TInt status(KErrNotReady); |
|
240 |
|
241 // Get the observer from effect |
|
242 CEffectControlBase* effectBase = |
|
243 dynamic_cast<CEffectControlBase*>(&aEffect); |
|
244 |
|
245 MControlObserver* observer; |
|
246 if (effectBase) |
|
247 { |
|
248 status = effectBase->GetControlObserver(observer); |
|
249 } |
|
250 RETURN_IF_ERROR( status ); |
|
251 |
|
252 if (iEventNotifierForEffects) |
|
253 { |
|
254 status = iEventNotifierForEffects->AddObserver( *observer); |
|
255 } |
|
256 RETURN_IF_ERROR( status ); |
|
257 |
|
258 // Add effect to array to notify Effects if user destroys Stream Control |
|
259 // before removing all Effect Controls from this instance. |
|
260 status = iAssociatedEffects.Append(effectBase); |
|
261 RETURN_IF_ERROR( status ); |
|
262 |
|
263 status = effectBase->AddedToStreamControl( *this, *iCMCustomCommand, |
|
264 aEffect); |
|
265 |
|
266 // If there was any error adding, undo operations and send error code to user. |
|
267 if (status != KErrNone) |
|
268 { |
|
269 // Remove the effect from the array |
|
270 TInt index(KErrNotFound); |
|
271 index = iAssociatedEffects.Find(effectBase); |
|
272 if (index != KErrNotFound) |
|
273 { |
|
274 iAssociatedEffects.Remove(index); |
|
275 } |
|
276 iEventNotifierForEffects->RemoveObserver( *observer); |
|
277 } |
|
278 |
|
279 return status; |
|
280 |
|
281 } |
|
282 |
|
283 // Sets the current position microseconds |
|
284 TInt CStreamControl::SetPosition(TInt64& aPos) |
|
285 { |
|
286 TInt status(KErrNone); |
|
287 TTimeIntervalMicroSeconds timePos(aPos); |
|
288 status = iController.SetPosition(timePos); |
|
289 return status; |
|
290 } |
|
291 |
|
292 TInt CStreamControl::SetPriority(TInt aPriority, TInt aPreference) |
|
293 { |
|
294 TInt status(KErrNone); |
|
295 iPrioritySettings.iPriority = aPriority; |
|
296 iPrioritySettings.iPref = TMdaPriorityPreference(aPreference); |
|
297 |
|
298 if (iStreamState != EStreamClosed) |
|
299 { |
|
300 status = iController.SetPrioritySettings(iPrioritySettings); |
|
301 } |
|
302 return status; |
|
303 } |
|
304 |
|
305 TInt CStreamControl::GetDuration(TInt64& aDuration) |
|
306 { |
|
307 TInt status(KErrUnknown); |
|
308 TTimeIntervalMicroSeconds duration; |
|
309 status = iController.GetDuration(duration); |
|
310 if (status == KErrNone) |
|
311 { |
|
312 aDuration = duration.Int64(); |
|
313 } |
|
314 return status; |
|
315 } |
|
316 |
|
317 TInt CStreamControl::GetPosition(TInt64& aPos) |
|
318 { |
|
319 TInt status(KErrUnknown); |
|
320 TTimeIntervalMicroSeconds posInTime; |
|
321 status = iController.GetPosition(posInTime); |
|
322 if (status == KErrNone) |
|
323 { |
|
324 aPos = posInTime.Int64(); |
|
325 } |
|
326 return status; |
|
327 } |
|
328 |
|
329 TInt CStreamControl::GetSeekingSupport(TBool& aFlag) |
|
330 { |
|
331 TInt status(KErrNone); |
|
332 status = iStreamControlCustomCommands.GetSeekingSupported(aFlag); |
|
333 return status; |
|
334 } |
|
335 |
|
336 TInt CStreamControl::GetRandomSeekingSupport(TBool& aFlag) |
|
337 { |
|
338 TInt status(KErrNone); |
|
339 status = iStreamControlCustomCommands.GetRandomSeekingSupported(aFlag); |
|
340 return status; |
|
341 } |
|
342 |
|
343 MStreamControl::TStreamState CStreamControl::GetState() |
|
344 { |
|
345 return iState; |
|
346 } |
|
347 |
|
348 TAny* CStreamControl::CustomInterface(TUid aCIUid) |
|
349 { |
|
350 TAny* retVal(NULL); |
|
351 |
|
352 // This function should only be called after the StreamControl |
|
353 // is Initialized |
|
354 if (aCIUid == KUidInterfaceMMFDRMControl) |
|
355 { |
|
356 RMMFDRMCustomCommands* drmCustCommand = new RMMFDRMCustomCommands(iController); |
|
357 if (drmCustCommand && drmCustCommand->IsSupported()) |
|
358 { |
|
359 retVal = drmCustCommand; |
|
360 } |
|
361 else |
|
362 { |
|
363 delete drmCustCommand; |
|
364 } |
|
365 } |
|
366 else |
|
367 if (aCIUid == KUidSCControllerRef) |
|
368 { |
|
369 retVal = &iController; |
|
370 EMC_TRACE2(_L("CStreamControl::CustomInterface [%x]"), retVal); |
|
371 |
|
372 } |
|
373 else |
|
374 if (aCIUid == KUidSCControllerUid) |
|
375 { |
|
376 retVal = &iControllerUid; |
|
377 } |
|
378 return retVal; |
|
379 } |
|
380 |
|
381 TInt CStreamControl::Open() |
|
382 { |
|
383 EMC_TRACE1(_L("CStreamControl::Open")); |
|
384 TInt status(KErrNotReady); |
|
385 |
|
386 switch (iStreamState) |
|
387 { |
|
388 case EStreamClosed: |
|
389 if (iSourceControl) |
|
390 { // Launch the controller |
|
391 iStreamState = EStreamOpening; |
|
392 status = LaunchController(); |
|
393 } |
|
394 break; |
|
395 default: |
|
396 break; |
|
397 }; |
|
398 return status; |
|
399 } |
|
400 |
|
401 TInt CStreamControl::Prime() |
|
402 { |
|
403 EMC_TRACE1(_L("CStreamControl::Prime")); |
|
404 TInt status(KErrNotReady); |
|
405 switch (iStreamState) |
|
406 { |
|
407 case EStreamOpened: |
|
408 iStreamState = EStreamPriming; |
|
409 status = iController.Prime(); |
|
410 iPrimeController = EFalse; |
|
411 break; |
|
412 case EStreamPriming: |
|
413 status = KErrNone; |
|
414 break; |
|
415 default: |
|
416 break; |
|
417 }; |
|
418 return status; |
|
419 } |
|
420 |
|
421 TInt CStreamControl::Start() |
|
422 { |
|
423 EMC_TRACE1(_L("CStreamControl::Start")); |
|
424 TInt status(KErrNotReady); |
|
425 switch (iStreamState) |
|
426 { |
|
427 case EStreamOpened: |
|
428 case EStreamPrimed: |
|
429 case EStreamPaused: |
|
430 case EStreamPriming: |
|
431 case EStreamStartingPlaying://added for bug #ESLM-7X8A88 |
|
432 iStreamState = EStreamStartingPlaying; |
|
433 // If EOF prime controller before calling Play(). |
|
434 if (iPrimeController) |
|
435 { |
|
436 status = iController.Prime(); |
|
437 iPrimeController = EFalse; |
|
438 } |
|
439 else |
|
440 { |
|
441 // This is the case where Play a file, EOF reached and app calls |
|
442 // Play() again. |
|
443 status = iController.Play(); |
|
444 } |
|
445 break; |
|
446 default: |
|
447 break; |
|
448 }; |
|
449 return status; |
|
450 } |
|
451 |
|
452 TInt CStreamControl::Pause() |
|
453 { |
|
454 EMC_TRACE1(_L("CStreamControl::Pause")); |
|
455 TInt status(KErrNotReady); |
|
456 switch (iStreamState) |
|
457 { |
|
458 case EStreamPlaying: |
|
459 case EStreamBuffering: |
|
460 case EStreamPrimed: |
|
461 case EStreamPriming: |
|
462 iStreamState = EStreamPausing; |
|
463 status = iController.Pause(); |
|
464 break; |
|
465 case EStreamPaused: |
|
466 status = KErrNone; |
|
467 default: |
|
468 break; |
|
469 }; |
|
470 return status; |
|
471 } |
|
472 |
|
473 |
|
474 TInt CStreamControl::Stop() |
|
475 { |
|
476 EMC_TRACE1(_L("CStreamControl::Stop")); |
|
477 TInt status(KErrNotReady); |
|
478 switch (iStreamState) |
|
479 { |
|
480 case EStreamOpened: |
|
481 case EStreamPrimed: |
|
482 case EStreamPlaying: |
|
483 case EStreamPaused: |
|
484 iStreamState = EStreamPriming; |
|
485 status = iController.Stop(); |
|
486 break; |
|
487 default: |
|
488 break; |
|
489 }; |
|
490 return status; |
|
491 } |
|
492 |
|
493 TInt CStreamControl::Close() |
|
494 { |
|
495 EMC_TRACE1(_L("CStreamControl::Close")); |
|
496 TInt status(KErrNotReady); |
|
497 |
|
498 // Disconnect All Effects. This makes sure that Effects |
|
499 // delete their MessageHandlers before the Controller is Closed. |
|
500 // This is done to Support AudioEffects in EMC. |
|
501 // This is done because if Controller tries to delete MessageHandlers |
|
502 // after deleting DevSound in the Destructor, there is a NULL pointer |
|
503 // Exception. Untill that problem is fixed in DevSound this is the fix. |
|
504 |
|
505 TInt count = iAssociatedEffects.Count(); |
|
506 for (TInt i = 0; i < count; i++) |
|
507 { |
|
508 iAssociatedEffects[i]->Disconnect(); |
|
509 } |
|
510 |
|
511 if (iControllerEventMonitor) |
|
512 { |
|
513 iControllerEventMonitor->Cancel(); |
|
514 } |
|
515 |
|
516 iController.Stop(); |
|
517 iController.Close(); |
|
518 |
|
519 if (iFindAndOpenController) |
|
520 { |
|
521 iFindAndOpenController->Close(); |
|
522 } |
|
523 |
|
524 // Signal the source that server side source is unloaded |
|
525 if (iSourceControl) |
|
526 { |
|
527 CSourceBase* sourcebase = dynamic_cast<CSourceBase*>(iSourceControl); |
|
528 sourcebase->ServerSourceDeleted(); |
|
529 } |
|
530 |
|
531 SetStreamState(EStreamClosed, KErrNone); |
|
532 status = KErrNone; |
|
533 return status; |
|
534 } |
|
535 |
|
536 void CStreamControl::HandleEvent(const TMMFEvent& aEvent) |
|
537 { |
|
538 EMC_TRACE3(_L("CStreamControl::HandleEvent:Evt[%d]Err[%d]"), aEvent.iErrorCode, aEvent.iEventType); |
|
539 |
|
540 if (aEvent.iEventType == KStreamControlEventStateChangedStopped) |
|
541 { |
|
542 iPrimeController = ETrue; |
|
543 SetStreamState(EStreamOpened, aEvent.iErrorCode); |
|
544 // If playback is stopped due to EOF, set flag to prime controller when |
|
545 // client calls Play() to play the same file/clip. |
|
546 |
|
547 } |
|
548 else |
|
549 if (aEvent.iEventType == KStreamControlEventStateChangedPrimed) |
|
550 { |
|
551 if (iStreamState == EStreamStartingPlaying) |
|
552 { |
|
553 iController.Play(); |
|
554 } |
|
555 else |
|
556 { |
|
557 SetStreamState(EStreamPrimed, KErrNone); |
|
558 } |
|
559 } |
|
560 else |
|
561 if (aEvent.iEventType == KStreamControlEventStateChangedPlaying) |
|
562 { |
|
563 SetStreamState(EStreamPlaying, KErrNone); |
|
564 } |
|
565 else |
|
566 if (aEvent.iEventType |
|
567 == KStreamControlEventStateChangedPaused) |
|
568 { |
|
569 SetStreamState(EStreamPaused, KErrNone); |
|
570 } |
|
571 else |
|
572 if (aEvent.iEventType |
|
573 == KStreamControlEventStateChangedAutoPaused) |
|
574 { |
|
575 SetStreamState(EStreamBuffering, KErrNone); |
|
576 } |
|
577 else |
|
578 if (aEvent.iEventType |
|
579 == KStreamControlEventDurationChanged) |
|
580 { |
|
581 SendEventToClient( |
|
582 MStreamControlObserver::KDurationChangedEvent, |
|
583 NULL); |
|
584 } |
|
585 else |
|
586 if (aEvent.iEventType |
|
587 == KStreamControlEventSeekingSupportChanged) |
|
588 { |
|
589 SendEventToClient( |
|
590 MStreamControlObserver::KSeekingSupportChangedEvent, |
|
591 NULL); |
|
592 } |
|
593 else |
|
594 if (aEvent.iEventType |
|
595 == KStreamControlEventRandomSeekingSupportChanged) |
|
596 { |
|
597 SendEventToClient( |
|
598 MStreamControlObserver::KRandomSeekingSupportChangedEvent, |
|
599 NULL); |
|
600 } |
|
601 else |
|
602 if (aEvent.iEventType |
|
603 == KMMFEventCategoryPlaybackComplete) |
|
604 { // KMMFEventCategoryPlaybackComplete will no longer be needed once |
|
605 // controller start sending state changed events. |
|
606 SetStreamState(EStreamOpened, KErrEof); |
|
607 iPrimeController = ETrue; |
|
608 } |
|
609 } |
|
610 |
|
611 void CStreamControl::MfaocComplete(TInt& aError, |
|
612 RMMFController* /*aController*/, TUid aControllerUid, |
|
613 TMMFMessageDestination* aSourceHandle, TMMFMessageDestination* /*aSinkHandle*/) |
|
614 { |
|
615 EMC_TRACE3(_L("CStreamControl::MfaocComplete:Err[%d]aSourceHandle[0x%x]"), aError, aSourceHandle); |
|
616 if (aError == KErrNone) |
|
617 { |
|
618 iControllerLoaded = ETrue; |
|
619 // Configure the controller to send state change events. |
|
620 TInt error = iStreamControlCustomCommands.EnableEvents(ETrue); |
|
621 if (error != KErrNone) |
|
622 { |
|
623 // We should error out and not let apps to continue. This player |
|
624 // only works with controllers that send state events. |
|
625 |
|
626 // The same sequence occurs in Close() also. May be move this a |
|
627 // seperate function and call function here... |
|
628 |
|
629 // Signal the source that server side source is unloaded |
|
630 CSourceBase* sourcebase = |
|
631 dynamic_cast<CSourceBase*>(iSourceControl); |
|
632 sourcebase->ServerSourceDeleted(); |
|
633 |
|
634 if (iControllerEventMonitor) |
|
635 { |
|
636 iControllerEventMonitor->Cancel(); |
|
637 } |
|
638 |
|
639 iController.Stop(); |
|
640 iController.Close(); |
|
641 |
|
642 if (iFindAndOpenController) |
|
643 { |
|
644 iFindAndOpenController->Close(); |
|
645 } |
|
646 // If the stream is already in CLOSED state |
|
647 // send an error event. |
|
648 if (iState == CLOSED) |
|
649 { |
|
650 /*EError*/ |
|
651 EMC_TRACE1(_L("CStreamControl::MfaocComplete:ERROR[KErrNotSupported]")); |
|
652 } |
|
653 else |
|
654 { |
|
655 SetStreamState(EStreamClosed, KErrNotSupported); |
|
656 } |
|
657 } |
|
658 else |
|
659 { |
|
660 |
|
661 if (!iControllerEventMonitor->IsActive()) |
|
662 { |
|
663 iControllerEventMonitor->Start(); |
|
664 } |
|
665 |
|
666 // Save the uid of controller loaded. |
|
667 iControllerUid = aControllerUid; |
|
668 // Signal the source that server side source is loaded |
|
669 CSourceBase* sourcebase = |
|
670 dynamic_cast<CSourceBase*>(iSourceControl); |
|
671 sourcebase->ServerSourceCreated( *iCMCustomCommand, |
|
672 *aSourceHandle); |
|
673 |
|
674 if (iStreamState == EStreamOpening) |
|
675 { |
|
676 iPrimeController = ETrue; |
|
677 SetStreamState(EStreamOpened, KErrNone); |
|
678 //FIX ME we need to do this even when the controller is closed |
|
679 CErrorCode* eventforEffects = new CErrorCode( KErrNone ); |
|
680 SendEventToEffectControls( |
|
681 CEffectControlBase::ECIBuilderCreated, |
|
682 eventforEffects); |
|
683 } |
|
684 } |
|
685 } |
|
686 else |
|
687 { |
|
688 SetStreamState(EStreamClosed, aError); |
|
689 } |
|
690 } |
|
691 |
|
692 void CStreamControl::ConfigureControllerLoader(TUid aMediaType, |
|
693 CMMFFindAndOpenController::TControllerMode aMode) |
|
694 { |
|
695 iFindAndOpenController->Configure(aMediaType, iPrioritySettings); |
|
696 iFindAndOpenController->ConfigureController(iController, |
|
697 *iControllerEventMonitor, aMode); |
|
698 } |
|
699 |
|
700 TInt CStreamControl::LaunchController() |
|
701 { |
|
702 TInt status(KErrNone); |
|
703 // KUidMediaTypeAudio need to be part of source |
|
704 ConfigureControllerLoader(KUidMediaTypeAudio, |
|
705 CMMFFindAndOpenController::EPlayback); |
|
706 // if Streaming case |
|
707 |
|
708 if (!iSourceControl || !iSinkControl) |
|
709 return KErrNotReady; |
|
710 |
|
711 TUid sourceUID = (dynamic_cast<CSourceBase*>(iSourceControl))->GetSourceUid(); |
|
712 TUid sinkUID = (dynamic_cast<CSinkBase*>(iSinkControl))->GetSinkUid(); |
|
713 |
|
714 if (iSourceControl->Type() == KDataBufferSourceControl) |
|
715 { |
|
716 MDataBufferSource* streamingSource = |
|
717 static_cast<MDataBufferSource*>(iSourceControl); |
|
718 iFindAndOpenController->ConfigureSourceSink( |
|
719 CMMFFindAndOpenController::TSourceSink( /*TUid::Uid(0x10207AF3)*/sourceUID), |
|
720 CMMFFindAndOpenController::TSourceSink( /*KUidMmfAudioOutput*/sinkUID) ); |
|
721 TBuf8<KMaxMimeLength> mimeType; |
|
722 status = streamingSource->GetMimeType(mimeType); |
|
723 if (status == KErrNone) |
|
724 { |
|
725 |
|
726 // This Flag is defined so that if the Helix Controller Supports |
|
727 // the playback of Local Media for WMA, then the HTTP Streaming still |
|
728 // goes through the Old WMA Controller( AdvancedAudioController) |
|
729 // We are launching the Old WMA Controller using the UID. |
|
730 |
|
731 #ifdef __WINDOWS_MEDIA |
|
732 #ifndef RD_PD_FOR_AUDIO_CONTENT_VIA_HELIX_ENGINE |
|
733 if(!mimeType.Compare(KWMAMimeType())) |
|
734 { |
|
735 iFindAndOpenController->OpenByControllerUid(TUid::Uid(0x10207A9B),KNullUid); |
|
736 } |
|
737 else |
|
738 #endif |
|
739 #endif |
|
740 { |
|
741 iFindAndOpenController->OpenByMimeType(mimeType); |
|
742 } |
|
743 } |
|
744 } |
|
745 else |
|
746 if (iSourceControl->Type() == KProgDLSourceControl) |
|
747 { |
|
748 MProgDLSource* progDLSource = |
|
749 static_cast<MProgDLSource*>(iSourceControl); |
|
750 HBufC* fileName = HBufC::NewLC(KMaxPath); |
|
751 TPtr fileNamePtr = fileName->Des(); |
|
752 |
|
753 TInt err = progDLSource->FileName(fileNamePtr); |
|
754 |
|
755 HBufC8* mimeType = HBufC8::NewLC(KMaxMimeLength); |
|
756 TPtr8 mimeTypePtr = mimeType->Des(); |
|
757 |
|
758 TInt status = iSourceControl->GetMimeType(mimeTypePtr); |
|
759 |
|
760 iFindAndOpenController->ConfigureSourceSink( |
|
761 TMMFileSource(fileNamePtr, |
|
762 ContentAccess::KDefaultContentObject, |
|
763 ContentAccess::EPlay), |
|
764 CMMFFindAndOpenController::TSourceSink(/*KUidMmfAudioOutput*/sinkUID/*,fileHandle*/)); |
|
765 |
|
766 TMMFileSource source(fileNamePtr, |
|
767 ContentAccess::KDefaultContentObject, |
|
768 ContentAccess::EPlay); |
|
769 |
|
770 // This Flag is defined so that if the Helix Controller Supports |
|
771 // the playback of Local Media for WMA, then the Progressive Download |
|
772 // for WMA still goes through the Old WMA Controller( AdvancedAudioController) |
|
773 // We are launching the Old WMA Controller using the UID. |
|
774 |
|
775 #ifdef __WINDOWS_MEDIA |
|
776 #ifndef RD_PD_FOR_AUDIO_CONTENT_VIA_HELIX_ENGINE |
|
777 if(!mimeTypePtr.Compare(KWMAMimeType())) |
|
778 { |
|
779 iFindAndOpenController->OpenByControllerUid(TUid::Uid(0x10207A9B),KNullUid); |
|
780 } |
|
781 else |
|
782 #endif |
|
783 #endif |
|
784 { |
|
785 iFindAndOpenController->OpenByFileSource(source); |
|
786 } |
|
787 |
|
788 CleanupStack::PopAndDestroy(mimeType); // mimeType |
|
789 CleanupStack::PopAndDestroy(fileName); // fileName |
|
790 //fileHandle.Close(); |
|
791 } |
|
792 |
|
793 if (iSourceControl->Type() == KFileSourceControl) |
|
794 { |
|
795 MFileSource* fileSource = static_cast<MFileSource*>(iSourceControl); |
|
796 |
|
797 HBufC* fileName = HBufC::NewLC(KMaxPath); |
|
798 TPtr fileNamePtr = fileName->Des(); |
|
799 |
|
800 TInt err = fileSource->GetFileName(fileNamePtr); |
|
801 |
|
802 HBufC8* fileName1 = HBufC8::NewLC(KMaxPath); |
|
803 TPtr8 fileNamePtr1 = fileName1->Des(); |
|
804 fileNamePtr1.Copy(fileNamePtr); |
|
805 |
|
806 HBufC8* mimeType = HBufC8::NewLC(KMaxMimeLength); |
|
807 TPtr8 mimeTypePtr = mimeType->Des(); |
|
808 |
|
809 TInt status = iSourceControl->GetMimeType(mimeTypePtr); |
|
810 |
|
811 iFindAndOpenController->ConfigureSourceSink( |
|
812 CMMFFindAndOpenController::TSourceSink(sourceUID, |
|
813 fileNamePtr1), |
|
814 CMMFFindAndOpenController::TSourceSink(sinkUID)); |
|
815 |
|
816 TMMFileSource source(fileNamePtr, |
|
817 ContentAccess::KDefaultContentObject, ContentAccess::EPlay); |
|
818 iFindAndOpenController->OpenByFileSource(source); |
|
819 |
|
820 CleanupStack::PopAndDestroy(mimeType); // mimeType |
|
821 CleanupStack::PopAndDestroy(fileName1); // fileName |
|
822 CleanupStack::PopAndDestroy(fileName); // fileName |
|
823 } |
|
824 |
|
825 if (iSourceControl->Type() == KDescriptorSourceControl) |
|
826 { |
|
827 MDescriptorSource* descriptorSource = |
|
828 static_cast<MDescriptorSource*>(iSourceControl); |
|
829 iFindAndOpenController->ConfigureSourceSink( |
|
830 CMMFFindAndOpenController::TSourceSink( /*TUid::Uid(0x10207AF3)*/sourceUID), |
|
831 CMMFFindAndOpenController::TSourceSink( /*KUidMmfAudioOutput*/sinkUID) ); |
|
832 TBuf8<KMaxMimeLength> mimeType; |
|
833 status = descriptorSource->GetMimeType(mimeType); |
|
834 if (status == KErrNone) |
|
835 { |
|
836 // This Flag is defined so that if the Helix Controller Supports |
|
837 // the playback of Local Media for WMA, then the HTTP Streaming still |
|
838 // goes through the Old WMA Controller( AdvancedAudioController) |
|
839 // We are launching the Old WMA Controller using the UID. |
|
840 |
|
841 iFindAndOpenController->OpenByMimeType(mimeType); |
|
842 } |
|
843 } |
|
844 return status; |
|
845 } |
|
846 |
|
847 void CStreamControl::SetStreamState(TStreamControlState aState, TInt aReason) |
|
848 { |
|
849 EMC_TRACE4(_L("CStreamControl::SetStreamState:aState[%d]aReason[%d]iState[%d]"), \ |
|
850 aState, aReason, iState); |
|
851 TStreamState prevState = iState; |
|
852 TInt prevError = iError; |
|
853 iError = aReason; |
|
854 switch (aState) |
|
855 { |
|
856 case EStreamClosed: |
|
857 iStreamState = EStreamClosed; |
|
858 iState = CLOSED; |
|
859 break; |
|
860 case EStreamOpened: |
|
861 iStreamState = EStreamOpened; |
|
862 iState = INITIALIZED; |
|
863 break; |
|
864 case EStreamPrimed: |
|
865 iStreamState = EStreamPrimed; |
|
866 iState = PRIMED; |
|
867 break; |
|
868 case EStreamPlaying: |
|
869 iStreamState = EStreamPlaying; |
|
870 iState = EXECUTING; |
|
871 break; |
|
872 case EStreamPaused: |
|
873 iStreamState = EStreamPaused; |
|
874 iState = PAUSED; |
|
875 break; |
|
876 case EStreamBuffering: |
|
877 iStreamState = EStreamBuffering; |
|
878 iState = BUFFERING; |
|
879 break; |
|
880 default: |
|
881 break; |
|
882 }; |
|
883 // If there is a change in state notify client |
|
884 if (prevState != iState || iError != prevError) |
|
885 { |
|
886 CStateChangedEvent* event(NULL); |
|
887 //EMC_TRACE3(_L("CStreamControl::SetStreamState Before iState [%d] prevState [%d]"), |
|
888 // iState,prevState); |
|
889 //EMC_TRACE3(_L("CStreamControl::SetStreamState Before iError [%d] prevError [%d]"), iError,prevError); |
|
890 event = new CStateChangedEvent( iState, aReason ); |
|
891 //EMC_TRACE3(_L("CStreamControl::SetStreamState After iState [%d] iReason [%d]"), event->GetState() ,event->GetErrorCode()); |
|
892 SendEventToClient(MStreamControlObserver::KStateChangedEvent, event); |
|
893 } |
|
894 } |
|
895 |
|
896 void CStreamControl::SendEventToClient(TUint aEvent, CEventBase* aEventObject) |
|
897 { |
|
898 iEventNotifier->Event(this, aEvent, aEventObject); |
|
899 } |
|
900 |
|
901 void CStreamControl::SendEventToEffectControls(TUint aEvent, |
|
902 CEventBase* aEventObject) |
|
903 { |
|
904 iEventNotifierForEffects->Event( this, aEvent, aEventObject); |
|
905 } |
|
906 // End of file |