|
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: Singleton class for main upnp related services |
|
15 * |
|
16 */ |
|
17 |
|
18 |
|
19 |
|
20 |
|
21 |
|
22 |
|
23 // INCLUDES |
|
24 #include <badesca.h> |
|
25 #include "upnpavcontrollerfactory.h" |
|
26 #include "upnpavcontroller.h" |
|
27 #include "upnpavdevice.h" |
|
28 #include "upnpavdevicelist.h" |
|
29 #include "upnprendererselectorobserver.h" |
|
30 #include "upnpsingleton.h" |
|
31 |
|
32 // CONSTANTS |
|
33 const TInt KDefaultGranularity = 5; |
|
34 const TInt32 KRendererRequestTimeOut = 5000000; |
|
35 |
|
36 _LIT( KComponentLogfile, "musicplugins.txt"); |
|
37 #include "upnplog.h" |
|
38 |
|
39 // -------------------------------------------------------------------------- |
|
40 // Static members of CUPnPSingleton |
|
41 // -------------------------------------------------------------------------- |
|
42 // |
|
43 |
|
44 // reference count |
|
45 TInt CUPnPSingleton::iInstanceCount = 0; |
|
46 |
|
47 // reference count |
|
48 CUPnPSingleton* CUPnPSingleton::iInstance = 0; |
|
49 |
|
50 // default device index |
|
51 TInt CUPnPSingleton::iDefaultRendererIndex; |
|
52 |
|
53 |
|
54 // -------------------------------------------------------------------------- |
|
55 // CUPnPSingleton::GetInstanceL |
|
56 // singleton constructor |
|
57 // -------------------------------------------------------------------------- |
|
58 // |
|
59 CUPnPSingleton* CUPnPSingleton::GetInstanceL() |
|
60 { |
|
61 if( iInstanceCount == 0 ) |
|
62 { |
|
63 CUPnPSingleton* self = new(ELeave) CUPnPSingleton(); |
|
64 CleanupStack::PushL( self ); |
|
65 self->ConstructL(); |
|
66 CleanupStack::Pop( self ); |
|
67 iInstance = self; |
|
68 } |
|
69 |
|
70 ++iInstanceCount; |
|
71 return iInstance; |
|
72 } |
|
73 |
|
74 // -------------------------------------------------------------------------- |
|
75 // CUPnPSingleton::CUPnPSingleton |
|
76 // Default constructor. |
|
77 // -------------------------------------------------------------------------- |
|
78 // |
|
79 CUPnPSingleton::CUPnPSingleton() |
|
80 { |
|
81 } |
|
82 |
|
83 // -------------------------------------------------------------------------- |
|
84 // CUPnPSingleton::ConstructL |
|
85 // ConstructL. |
|
86 // -------------------------------------------------------------------------- |
|
87 // |
|
88 void CUPnPSingleton::ConstructL() |
|
89 { |
|
90 // Create timer for observing play time out. |
|
91 iPeriodizer = CUPnPMusicPeriodizer::NewL( *this, |
|
92 KRendererRequestTimeOut ); |
|
93 |
|
94 // Create handle to AVController |
|
95 iAVController = UPnPAVControllerFactory::NewUPnPAVControllerL(); |
|
96 iAVController->SetDeviceObserver( *this ); |
|
97 CacheRendererListL(); |
|
98 if ( iMediaRenderers.Count() > 0 ) |
|
99 { |
|
100 iSelectorState = EStateReady; |
|
101 } |
|
102 else |
|
103 { |
|
104 iSelectorState = EStateWaiting; |
|
105 iPeriodizer->Start(); |
|
106 } |
|
107 |
|
108 } |
|
109 |
|
110 // -------------------------------------------------------------------------- |
|
111 // CUPnPSingleton::LoseInstance |
|
112 // singleton desctuctor |
|
113 // -------------------------------------------------------------------------- |
|
114 // |
|
115 void CUPnPSingleton::LoseInstance( CUPnPSingleton* aInstance ) |
|
116 { |
|
117 if( aInstance != 0 ) |
|
118 { |
|
119 __ASSERTD( aInstance == iInstance,__FILE__, __LINE__ ); |
|
120 __ASSERTD( iInstanceCount > 0,__FILE__, __LINE__ ); |
|
121 --iInstanceCount; |
|
122 if( iInstanceCount == 0 ) |
|
123 { |
|
124 delete iInstance; |
|
125 iInstance = 0; |
|
126 } |
|
127 } |
|
128 } |
|
129 |
|
130 // -------------------------------------------------------------------------- |
|
131 // CUPnPSingleton::~CUPnPSingleton |
|
132 // Destructor. |
|
133 // -------------------------------------------------------------------------- |
|
134 // |
|
135 CUPnPSingleton::~CUPnPSingleton() |
|
136 { |
|
137 __LOG("CUPnPSingleton::~CUPnPSingleton()"); |
|
138 iMediaRenderers.ResetAndDestroy(); |
|
139 delete iPeriodizer; |
|
140 if( iAVController ) |
|
141 { |
|
142 iAVController->Release(); |
|
143 } |
|
144 } |
|
145 |
|
146 // -------------------------------------------------------------------------- |
|
147 // CUPnPSingleton::GetRendererNamesL |
|
148 // Get renderes from AVController and return the renderer names. |
|
149 // -------------------------------------------------------------------------- |
|
150 // |
|
151 void CUPnPSingleton::GetRendererNamesL( |
|
152 MUPnPRendererSelectorObserver& aObserver ) |
|
153 { |
|
154 __ASSERTD( iRendererselectorObserver == 0,__FILE__, __LINE__ ); |
|
155 iRendererselectorObserver = &aObserver; |
|
156 |
|
157 switch( iSelectorState ) |
|
158 { |
|
159 case EStateWaiting: |
|
160 { |
|
161 __LOG("GetRendererNames: waiting"); |
|
162 // wait for something to happen |
|
163 } |
|
164 break; |
|
165 case EStateComplete: |
|
166 { |
|
167 __LOG("GetRendererNames: complete->ready"); |
|
168 DeliverNamesToObserverL( ETrue ); |
|
169 iSelectorState = EStateReady; |
|
170 } |
|
171 break; |
|
172 case EStateReady: |
|
173 { |
|
174 CacheRendererListL(); |
|
175 if ( iMediaRenderers.Count() > 0 ) |
|
176 { |
|
177 __LOG("GetRendererNames: ready"); |
|
178 DeliverNamesToObserverL( ETrue ); |
|
179 } |
|
180 else |
|
181 { |
|
182 __LOG("GetRendererNames: ready->waiting"); |
|
183 iSelectorState = EStateWaiting; |
|
184 iPeriodizer->Start(); |
|
185 } |
|
186 } |
|
187 break; |
|
188 case EStateError: |
|
189 { |
|
190 __LOG("GetRendererNames: error"); |
|
191 DeliverNamesToObserverL( ETrue, KErrDisconnected ); |
|
192 } |
|
193 break; |
|
194 default: |
|
195 { |
|
196 __PANICD(__FILE__, __LINE__ ); |
|
197 } |
|
198 break; |
|
199 } |
|
200 } |
|
201 |
|
202 // -------------------------------------------------------------------------- |
|
203 // CUPnPSingleton::CancelGetRendererNames |
|
204 // -------------------------------------------------------------------------- |
|
205 // |
|
206 void CUPnPSingleton::CancelGetRendererNames() |
|
207 { |
|
208 // just clear the observer -> no callbacks will occur. |
|
209 iRendererselectorObserver = 0; |
|
210 } |
|
211 |
|
212 // -------------------------------------------------------------------------- |
|
213 // CUPnPSingleton::SelectRendererByIndexL |
|
214 // Select renderer by given index. |
|
215 // -------------------------------------------------------------------------- |
|
216 // |
|
217 const CUpnpAVDevice* CUPnPSingleton::SelectRendererByIndexL( TInt aIndex ) |
|
218 { |
|
219 if( iMediaRenderers.Count() <= aIndex || aIndex < 0 ) |
|
220 { |
|
221 __LOG("CUPnPSingl::SelectRendererByIndexL error: Wrong index"); |
|
222 User::Leave( KErrArgument ); |
|
223 } |
|
224 |
|
225 if ( iRendererselectorObserver != 0 ) |
|
226 { |
|
227 DeliverNamesToObserverL( ETrue ); |
|
228 } |
|
229 |
|
230 if ( !IsAvailable( *iMediaRenderers[aIndex] ) ) |
|
231 { |
|
232 __LOG("CUPnPSingl::SelectRendererByIndexL error: disconnected"); |
|
233 User::Leave( KErrDisconnected ); |
|
234 } |
|
235 |
|
236 iDefaultRendererIndex = aIndex; |
|
237 |
|
238 return iMediaRenderers[aIndex]; |
|
239 } |
|
240 |
|
241 // -------------------------------------------------------------------------- |
|
242 // CUPnPSingleton::DefaultDevice |
|
243 // Return return pointer of current renderer |
|
244 // -------------------------------------------------------------------------- |
|
245 // |
|
246 const CUpnpAVDevice* CUPnPSingleton::DefaultDevice() |
|
247 { |
|
248 if ( iDefaultRendererIndex >= 0 ) |
|
249 { |
|
250 return iMediaRenderers[iDefaultRendererIndex]; |
|
251 } |
|
252 else |
|
253 { |
|
254 return 0; |
|
255 } |
|
256 } |
|
257 |
|
258 // -------------------------------------------------------------------------- |
|
259 // CUPnPSingleton::AVC |
|
260 // Provides reference to the AVController resource |
|
261 // -------------------------------------------------------------------------- |
|
262 // |
|
263 MUPnPAVController& CUPnPSingleton::AVC() |
|
264 { |
|
265 return *iAVController; |
|
266 } |
|
267 |
|
268 |
|
269 // -------------------------------------------------------------------------- |
|
270 // Method from MUPnPAVMediaObserver |
|
271 // -------------------------------------------------------------------------- |
|
272 |
|
273 // -------------------------------------------------------------------------- |
|
274 // CUPnPSingleton::UPnPDeviceDiscovered |
|
275 // Inform that new renderer device has discovered. |
|
276 // -------------------------------------------------------------------------- |
|
277 // |
|
278 void CUPnPSingleton::UPnPDeviceDiscovered( const CUpnpAVDevice& aDevice ) |
|
279 { |
|
280 // Check if device is media renderer |
|
281 if( aDevice.DeviceType() == CUpnpAVDevice::EMediaRenderer |
|
282 && aDevice.AudioCapability() ) |
|
283 { |
|
284 if ( iSelectorState == EStateWaiting || |
|
285 iSelectorState == EStateComplete ) |
|
286 { |
|
287 CUpnpAVDevice* dev = 0; |
|
288 TRAP_IGNORE( dev = CUpnpAVDevice::NewL( aDevice ) ); |
|
289 if( dev ) |
|
290 { |
|
291 iMediaRenderers.Append( dev ); |
|
292 if ( iRendererselectorObserver != 0 ) |
|
293 { |
|
294 TRAP_IGNORE( DeliverNamesToObserverL( EFalse ) ); |
|
295 } |
|
296 } |
|
297 } |
|
298 } |
|
299 else |
|
300 { |
|
301 // Do nothing with media servers |
|
302 } |
|
303 } |
|
304 |
|
305 // -------------------------------------------------------------------------- |
|
306 // CUPnPSingleton::UPnPDeviceDisappeared |
|
307 // Inform that renderer device has disappeared. |
|
308 // -------------------------------------------------------------------------- |
|
309 // |
|
310 void CUPnPSingleton::UPnPDeviceDisappeared( const CUpnpAVDevice& aDevice ) |
|
311 { |
|
312 // Check if device is media renderer |
|
313 if( aDevice.DeviceType() == CUpnpAVDevice::EMediaRenderer |
|
314 && aDevice.AudioCapability() ) |
|
315 { |
|
316 if ( iSelectorState == EStateWaiting || |
|
317 iSelectorState == EStateComplete ) |
|
318 { |
|
319 // In monitoring state. Remove the renderer from cache. |
|
320 TInt count = iMediaRenderers.Count(); |
|
321 for( TInt i = 0; i < count; i++ ) |
|
322 { |
|
323 if( aDevice.Uuid().Compare( |
|
324 iMediaRenderers[i]->Uuid() ) == 0 ) |
|
325 { |
|
326 iMediaRenderers.Remove(i); |
|
327 // we removed an renderer from the list so we want to |
|
328 // continue the loop with the same i. |
|
329 // Could break here if absolutely sure that there are |
|
330 // no duplicates in iMediaRenderers. |
|
331 count--; |
|
332 i--; |
|
333 } |
|
334 } |
|
335 if ( iRendererselectorObserver != 0 ) |
|
336 { |
|
337 TRAP_IGNORE( DeliverNamesToObserverL( EFalse ) ); |
|
338 } |
|
339 } |
|
340 else if ( iSelectorState == EStateReady ) |
|
341 { |
|
342 // Device disappears in ready state. Can't remove from cache |
|
343 // (because we use indexing to select to renderers) |
|
344 // instead mark the renderer unusable. |
|
345 __LOG( "Singleton: renderer disappeared in Ready state" ); |
|
346 TInt count = iMediaRenderers.Count(); |
|
347 TBool done = EFalse; |
|
348 for( TInt i = 0; i < count && !done; i++ ) |
|
349 { |
|
350 if( aDevice.Uuid().Compare( |
|
351 iMediaRenderers[i]->Uuid() ) == 0 ) |
|
352 { |
|
353 SetAvailable( *iMediaRenderers[i], EFalse ); |
|
354 done = ETrue; |
|
355 } |
|
356 } |
|
357 } |
|
358 } |
|
359 else |
|
360 { |
|
361 // Do nothing with media servers |
|
362 } |
|
363 } |
|
364 |
|
365 // -------------------------------------------------------------------------- |
|
366 // CUPnPSingleton::WLANConnectionLost |
|
367 // Inform that renderer device has disappeared. |
|
368 // -------------------------------------------------------------------------- |
|
369 // |
|
370 void CUPnPSingleton::WLANConnectionLost() |
|
371 { |
|
372 iMediaRenderers.ResetAndDestroy(); |
|
373 if ( iSelectorState == EStateWaiting ) |
|
374 { |
|
375 iPeriodizer->Stop(); |
|
376 } |
|
377 |
|
378 iSelectorState = EStateError; |
|
379 |
|
380 if ( iRendererselectorObserver != 0 ) |
|
381 { |
|
382 TRAP_IGNORE( DeliverNamesToObserverL( ETrue, KErrDisconnected ) ); |
|
383 } |
|
384 } |
|
385 |
|
386 // -------------------------------------------------------------------------- |
|
387 // Methods of MUPnPMusicPeriodizerObserver |
|
388 // -------------------------------------------------------------------------- |
|
389 |
|
390 // -------------------------------------------------------------------------- |
|
391 // CUPnPSingleton::HandlePeriod |
|
392 // Action when timer has expired. |
|
393 // -------------------------------------------------------------------------- |
|
394 // |
|
395 void CUPnPSingleton::HandlePeriod() |
|
396 { |
|
397 __ASSERTD( iSelectorState == EStateWaiting,__FILE__, __LINE__ ); |
|
398 |
|
399 if ( iMediaRenderers.Count() > 0 ) |
|
400 { |
|
401 __LOG("GetRendererNames: timeout->complete"); |
|
402 iSelectorState = EStateComplete; |
|
403 if ( iRendererselectorObserver != 0 ) |
|
404 { |
|
405 __LOG("GetRendererNames: complete->ready"); |
|
406 iSelectorState = EStateReady; |
|
407 TRAP_IGNORE( DeliverNamesToObserverL( ETrue ) ); |
|
408 } |
|
409 } |
|
410 else |
|
411 { |
|
412 __LOG("GetRendererNames: timeout->continue timer"); |
|
413 iPeriodizer->Continue(); |
|
414 if ( iRendererselectorObserver != 0 ) |
|
415 { |
|
416 TRAP_IGNORE( DeliverNamesToObserverL( ETrue ) ); |
|
417 } |
|
418 } |
|
419 } |
|
420 |
|
421 // -------------------------------------------------------------------------- |
|
422 // Private methods of CUPnPRendererSelector |
|
423 // -------------------------------------------------------------------------- |
|
424 |
|
425 // -------------------------------------------------------------------------- |
|
426 // CUPnPSingleton::CacheRendererListL |
|
427 // Refreshes the renderer cache from AVController |
|
428 // -------------------------------------------------------------------------- |
|
429 // |
|
430 void CUPnPSingleton::CacheRendererListL() |
|
431 { |
|
432 // Clean old devices array and device names |
|
433 iDefaultRendererIndex = KErrNotFound; |
|
434 |
|
435 // Get media renderers |
|
436 CUpnpAVDeviceList* devices = iAVController->GetMediaRenderersL(); |
|
437 CleanupStack::PushL( devices ); |
|
438 |
|
439 // go through current renderer list |
|
440 for ( TInt i = 0; i < iMediaRenderers.Count(); ++i ) |
|
441 { |
|
442 CUpnpAVDevice* renderer = iMediaRenderers[ i ]; |
|
443 TBool exists = EFalse; |
|
444 for ( TInt j = 0; j < devices->Count() && !exists; ++j ) |
|
445 { |
|
446 CUpnpAVDevice* device = (*devices)[j]; |
|
447 if ( renderer->Uuid() == device->Uuid()) |
|
448 { |
|
449 // renderer still exists. |
|
450 delete device; |
|
451 devices->Remove( j ); |
|
452 SetAvailable( *renderer, ETrue ); |
|
453 --j; |
|
454 exists = ETrue; |
|
455 } |
|
456 } |
|
457 if ( !exists ) |
|
458 { |
|
459 // renderer has disappeared |
|
460 delete renderer; |
|
461 iMediaRenderers.Remove( i ); |
|
462 --i; |
|
463 } |
|
464 } |
|
465 |
|
466 // Remaining devices are all new. Add them to end of the list. |
|
467 while ( devices->Count() > 0 ) |
|
468 { |
|
469 __LOG("CacheRendererListL::Remaining devices are all new."); |
|
470 CUpnpAVDevice* device = (*devices)[ 0 ]; |
|
471 if( device->AudioCapability() ) |
|
472 { |
|
473 iMediaRenderers.Append( device ); |
|
474 } |
|
475 devices->Remove( 0 ); |
|
476 } |
|
477 |
|
478 CleanupStack::PopAndDestroy( devices ); |
|
479 } |
|
480 |
|
481 // -------------------------------------------------------------------------- |
|
482 // CUPnPSingleton::DeliverNamesToObserverL |
|
483 // Delivers current names in cached list to observer |
|
484 // -------------------------------------------------------------------------- |
|
485 // |
|
486 void CUPnPSingleton::DeliverNamesToObserverL( TBool aCompleted, |
|
487 TInt aError ) |
|
488 { |
|
489 __ASSERTD( iRendererselectorObserver != 0,__FILE__, __LINE__ ); |
|
490 |
|
491 // Create an array for names |
|
492 CDesCArrayFlat* deviceNames = new(ELeave) CDesCArrayFlat( |
|
493 KDefaultGranularity ); |
|
494 CleanupStack::PushL( deviceNames ); |
|
495 |
|
496 TInt count = iMediaRenderers.Count(); |
|
497 for( TInt i = 0; i < count; i++ ) |
|
498 { |
|
499 HBufC* buf = HBufC::NewL( |
|
500 iMediaRenderers[i]->FriendlyName().Length() ); |
|
501 CleanupStack::PushL( buf ); |
|
502 buf->Des().Copy( iMediaRenderers[i]->FriendlyName() ); |
|
503 deviceNames->AppendL( *buf ); // Transfer ownership |
|
504 CleanupStack::PopAndDestroy( buf ); |
|
505 } |
|
506 |
|
507 // Call back current renderer names |
|
508 __LOG1( "DeliverNamesToObserver: count=%d", count ); |
|
509 MUPnPRendererSelectorObserver& obs = *iRendererselectorObserver; |
|
510 iRendererselectorObserver = 0; |
|
511 obs.HandleSubPlayerNames( deviceNames, aCompleted, aError ); |
|
512 |
|
513 CleanupStack::PopAndDestroy( deviceNames ); |
|
514 } |
|
515 |
|
516 // -------------------------------------------------------------------------- |
|
517 // CUPnPSingleton::IsAvailable |
|
518 // checks if the device type is renderer |
|
519 // -------------------------------------------------------------------------- |
|
520 // |
|
521 TBool CUPnPSingleton::IsAvailable( const CUpnpAVDevice& aDevice ) const |
|
522 { |
|
523 return aDevice.DeviceType() == CUpnpAVDevice::EMediaRenderer; |
|
524 } |
|
525 |
|
526 // -------------------------------------------------------------------------- |
|
527 // CUPnPSingleton::SetAvailable |
|
528 // sets the device type to an illegal unrecognized type |
|
529 // -------------------------------------------------------------------------- |
|
530 // |
|
531 void CUPnPSingleton::SetAvailable( |
|
532 CUpnpAVDevice& aDevice, TBool aAvailable ) const |
|
533 { |
|
534 if ( aAvailable && !IsAvailable( aDevice ) ) |
|
535 { |
|
536 __LOG1( "CUPnPSingleton: renderer available: %S", |
|
537 &aDevice.FriendlyName() ); |
|
538 aDevice.SetDeviceType( |
|
539 CUpnpAVDevice::EMediaRenderer ); |
|
540 } |
|
541 else if ( !aAvailable && IsAvailable ( aDevice ) ) |
|
542 { |
|
543 __LOG1( "CUPnPSingleton: renderer not available: %S", |
|
544 &aDevice.FriendlyName() ); |
|
545 aDevice.SetDeviceType( |
|
546 (CUpnpAVDevice::TUpnpAVDeviceType)KErrUnknown ); |
|
547 } |
|
548 } |