|
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: Fills MPX playlist by browsing media server content |
|
15 * |
|
16 */ |
|
17 |
|
18 |
|
19 // INCLUDE FILES |
|
20 // upnp stack api |
|
21 #include <upnpobject.h> |
|
22 |
|
23 // MPX framework api |
|
24 #include <mpxcollectionutility.h> |
|
25 #include <mpxmediaarray.h> |
|
26 #include <mpxmediageneraldefs.h> |
|
27 #include <mpxmediacontainerdefs.h> |
|
28 |
|
29 // upnpframework / avcontroller api |
|
30 #include "upnpavcontroller.h" |
|
31 #include "upnpavdevice.h" |
|
32 #include "upnpavbrowsingsession.h" |
|
33 |
|
34 // upnpframework / avcontroller helper api |
|
35 #include "upnpconstantdefs.h" // for browse filters |
|
36 |
|
37 // upnpframework / xmlparser api |
|
38 #include "upnpxmlparser.h" |
|
39 |
|
40 // musicadapter internal |
|
41 #include "upnpmusicadapter.h" |
|
42 #include "upnpbrowseplaylistfiller.h" |
|
43 |
|
44 // debug |
|
45 _LIT16( KComponentLogfile, "musicadapter.txt" ); |
|
46 #include "upnplog.h" |
|
47 |
|
48 // CONSTANTS |
|
49 const TInt KBrowseRequestedCount = 100; |
|
50 const TUid KHostAppUid = { 0x10208A0A }; // Host app UID |
|
51 const TInt KMaxPlaylistSize = 500; // MAX container size to play |
|
52 const TInt KBrowsePeriod = 5000000; // 5 seconds |
|
53 |
|
54 // ======== MEMBER FUNCTIONS ======== |
|
55 |
|
56 // -------------------------------------------------------------------------- |
|
57 // CUPnPBrowsePlaylistFiller::NewL |
|
58 // static constructor. |
|
59 // -------------------------------------------------------------------------- |
|
60 // |
|
61 EXPORT_C CUPnPBrowsePlaylistFiller* CUPnPBrowsePlaylistFiller::NewL( |
|
62 const TDesC8& aContainerId, |
|
63 TInt aCachedStartIndex, |
|
64 TInt aTotalContainerSize ) |
|
65 { |
|
66 __LOG( "CUPnPBrowsePlaylistFiller::NewL" ); |
|
67 |
|
68 CUPnPBrowsePlaylistFiller* self = new(ELeave) |
|
69 CUPnPBrowsePlaylistFiller(); |
|
70 CleanupStack::PushL( self ); |
|
71 self->ConstructL( aContainerId, aCachedStartIndex, aTotalContainerSize ); |
|
72 CleanupStack::Pop( self ); |
|
73 return self; |
|
74 } |
|
75 |
|
76 // -------------------------------------------------------------------------- |
|
77 // CUPnPBrowsePlaylistFiller::CUPnPBrowsePlaylistFiller |
|
78 // 1st phase constructor. |
|
79 // -------------------------------------------------------------------------- |
|
80 // |
|
81 CUPnPBrowsePlaylistFiller::CUPnPBrowsePlaylistFiller() |
|
82 : CUPnPPlayListFiller() |
|
83 { |
|
84 } |
|
85 |
|
86 // -------------------------------------------------------------------------- |
|
87 // CUPnPBrowsePlaylistFiller::ConstructL |
|
88 // 2nd phase constructor. |
|
89 // -------------------------------------------------------------------------- |
|
90 // |
|
91 void CUPnPBrowsePlaylistFiller::ConstructL( |
|
92 const TDesC8& aContainerId, |
|
93 TInt aCachedStartIndex, |
|
94 TInt aTotalContainerSize ) |
|
95 { |
|
96 // Create timer for continue browse after short period. |
|
97 iBrowseTimer = CUPnPBrowseTimer::NewL( *this, KBrowsePeriod ); |
|
98 iBlocksize = KBrowseRequestedCount; |
|
99 |
|
100 iContainerId = HBufC8::NewL( aContainerId.Length() ); |
|
101 iContainerId->Des().Copy( aContainerId ); |
|
102 iCachedStartIndex = aCachedStartIndex; |
|
103 |
|
104 iPlaylistInitialSize = KErrUnknown; |
|
105 if ( aTotalContainerSize >= 0 ) |
|
106 { |
|
107 iPlaylistInitialSize = Min( |
|
108 aTotalContainerSize - iCachedStartIndex, |
|
109 KMaxPlaylistSize ); |
|
110 } |
|
111 iPlaylistActualSize = 0; |
|
112 } |
|
113 |
|
114 // -------------------------------------------------------------------------- |
|
115 // CUPnPBrowsePlaylistFiller::~CUPnPBrowsePlaylistFiller |
|
116 // Destructor. |
|
117 // -------------------------------------------------------------------------- |
|
118 // |
|
119 EXPORT_C CUPnPBrowsePlaylistFiller::~CUPnPBrowsePlaylistFiller() |
|
120 { |
|
121 delete iBrowseTimer; |
|
122 iBrowseTimer = 0; |
|
123 |
|
124 __LOG( "CUPnPBrowsePlaylistFiller::~CUPnPBrowsePlaylistFiller" ); |
|
125 if ( iBrowsingSession ) |
|
126 { |
|
127 Host().AVController().StopBrowsingSession( *iBrowsingSession ); |
|
128 iBrowsingSession = 0; |
|
129 } |
|
130 delete iContainerId; |
|
131 } |
|
132 |
|
133 // -------------------------------------------------------------------------- |
|
134 // CUPnPBrowsePlaylistFiller::FillL |
|
135 // Fill track data into the playlist and continue browsing |
|
136 // -------------------------------------------------------------------------- |
|
137 // |
|
138 void CUPnPBrowsePlaylistFiller::FillL( |
|
139 CUPnPMusicAdapter& aHost, |
|
140 CMPXMediaArray& aPlaylist ) |
|
141 { |
|
142 __LOG( "CUPnPBrowsePlaylistFiller::Fill" ); |
|
143 |
|
144 SetHost( aHost ); |
|
145 |
|
146 // fill the initial items, increase the index |
|
147 iCurrentIndex = iCachedStartIndex; |
|
148 iPlaylistActualSize = DoFillL( aPlaylist, ObjectArray() ); |
|
149 iCurrentIndex += ObjectArray().Count(); |
|
150 |
|
151 if ( iPlaylistActualSize < iPlaylistInitialSize ) |
|
152 { |
|
153 // Start doing more browse requests after short waiting period |
|
154 iBrowseTimer->Start(); |
|
155 } |
|
156 else |
|
157 { |
|
158 __LOG( "CUPnPBrowsePlaylistFiller::Fill - \ |
|
159 No need to browse" ); |
|
160 DoComplete(); |
|
161 } |
|
162 } |
|
163 |
|
164 // -------------------------------------------------------------------------- |
|
165 // CUPnPBrowsePlaylistFiller::CancelFill |
|
166 // Fill track data into the playlist and continue browsing |
|
167 // -------------------------------------------------------------------------- |
|
168 // |
|
169 void CUPnPBrowsePlaylistFiller::CancelFill() |
|
170 { |
|
171 if ( iBrowsingSession ) |
|
172 { |
|
173 iBrowsingSession->CancelBrowse(); |
|
174 } |
|
175 } |
|
176 |
|
177 // -------------------------------------------------------------------------- |
|
178 // CUPnPPlayListFiller::PlaylistSize |
|
179 // Returns the total playlist size |
|
180 // -------------------------------------------------------------------------- |
|
181 // |
|
182 TInt CUPnPBrowsePlaylistFiller::PlaylistSize() |
|
183 { |
|
184 if ( iPlaylistInitialSize >= 0 ) |
|
185 { |
|
186 return iPlaylistInitialSize; |
|
187 } |
|
188 else |
|
189 { |
|
190 return ObjectArray().Count(); |
|
191 } |
|
192 } |
|
193 |
|
194 // -------------------------------------------------------------------------- |
|
195 // Methods from MUPnPAVBrowsingSessionObserver |
|
196 // -------------------------------------------------------------------------- |
|
197 |
|
198 // -------------------------------------------------------------------------- |
|
199 // CUPnPBrowsePlaylistFiller::BrowseResponse |
|
200 // -------------------------------------------------------------------------- |
|
201 // |
|
202 void CUPnPBrowsePlaylistFiller::BrowseResponse( |
|
203 const TDesC8& aBrowseResponse, TInt aError, TInt /*aMatches*/, |
|
204 TInt aTotalCount, const TDesC8& /*aUpdateId*/ ) |
|
205 { |
|
206 __LOG( "CUPnPBrowsePlaylistFiller::BrowseResponse" ); |
|
207 TBool continueBrowse = ETrue; |
|
208 |
|
209 // Stop browsing if any error in previous browse |
|
210 if( aError != KErrNone ) |
|
211 { |
|
212 // Browse stops to an error - do not continue playlist. |
|
213 __LOG( "CUPnPBrowsePlaylistFiller::BrowseResponse ->error!" ); |
|
214 continueBrowse = EFalse; |
|
215 DoComplete(); |
|
216 } |
|
217 else |
|
218 { |
|
219 __LOG( "CUPnPBrowsePlaylistFiller::BrowseResponse - \ |
|
220 Error None" ); |
|
221 |
|
222 TInt error = KErrNone; |
|
223 TRAP( error, AddMediaToCollectionL( aBrowseResponse ) ); |
|
224 if( error != KErrNone ) |
|
225 { |
|
226 __LOG( "CUPnPBrowsePlaylistFiller::BrowseResponse - \ |
|
227 AddMediaToCollectionL leaves!" ); |
|
228 continueBrowse = EFalse; |
|
229 DoComplete(); |
|
230 } |
|
231 else |
|
232 { |
|
233 if ( iPlaylistActualSize >= iPlaylistInitialSize ) |
|
234 { |
|
235 // browse is complete |
|
236 __LOG( "CUPnPBrowsePlaylistFiller::BrowseResult - \ |
|
237 ->playlist size reached." ); |
|
238 continueBrowse = EFalse; |
|
239 DoComplete(); |
|
240 } |
|
241 |
|
242 if ( iCurrentIndex >= aTotalCount ) |
|
243 { |
|
244 // browse is complete |
|
245 __LOG( "CUPnPBrowsePlaylistFiller::BrowseResult - \ |
|
246 ->end of data." ); |
|
247 continueBrowse = EFalse; |
|
248 DoComplete(); |
|
249 } |
|
250 } |
|
251 } |
|
252 |
|
253 if ( continueBrowse ) |
|
254 { |
|
255 // Calculate item count to be browsed. |
|
256 iBlocksize = KBrowseRequestedCount; |
|
257 if ( iPlaylistActualSize + iBlocksize > iPlaylistInitialSize ) |
|
258 { |
|
259 iBlocksize = iPlaylistInitialSize - iPlaylistActualSize; |
|
260 } |
|
261 |
|
262 // Continue the browse request |
|
263 iBrowseTimer->Continue(); |
|
264 } |
|
265 } |
|
266 |
|
267 // -------------------------------------------------------------------------- |
|
268 // CUPnPBrowsePlaylistFiller::AddMediaToCollectionL |
|
269 // Adds media to collection |
|
270 // -------------------------------------------------------------------------- |
|
271 // |
|
272 void CUPnPBrowsePlaylistFiller::AddMediaToCollectionL( |
|
273 const TDesC8& aBrowseResponse ) |
|
274 { |
|
275 CUPnPXMLParser* parser = NULL; |
|
276 parser = CUPnPXMLParser::NewL(); |
|
277 CleanupStack::PushL( parser ); |
|
278 RPointerArray<CUpnpObject> array; |
|
279 parser->ParseResultDataL( array, aBrowseResponse ); |
|
280 |
|
281 // Update playlist counter |
|
282 iCurrentIndex += KBrowseRequestedCount; |
|
283 |
|
284 TInt count = array.Count(); |
|
285 if( count > 0 ) |
|
286 { |
|
287 // Create new media object |
|
288 CMPXMedia* media = CMPXMedia::NewL(); |
|
289 CleanupStack::PushL( media ); |
|
290 // Set collection Uid |
|
291 media->SetTObjectValueL<TUid>( |
|
292 KMPXMediaGeneralCollectionId, |
|
293 Host().PlaylistCollectionId() ); |
|
294 // Set type |
|
295 media->SetTObjectValueL<TMPXGeneralType>( |
|
296 KMPXMediaGeneralType, EMPXItem ); |
|
297 // Set category |
|
298 media->SetTObjectValueL<TMPXGeneralCategory>( |
|
299 KMPXMediaGeneralCategory, EMPXPlaylist ); |
|
300 // Set playlist ID |
|
301 media->SetTObjectValueL<TMPXItemId>( |
|
302 KMPXMediaGeneralId, KHostAppUid.iUid ); |
|
303 // Add playlist into media object |
|
304 CMPXMediaArray* playlist = CMPXMediaArray::NewL(); |
|
305 CleanupStack::PushL( playlist ); |
|
306 iPlaylistActualSize += DoFillL( *playlist, array ); |
|
307 media->SetCObjectValueL( |
|
308 KMPXMediaArrayContents, playlist ); |
|
309 // Add count of items in playlist |
|
310 media->SetTObjectValueL( |
|
311 KMPXMediaArrayCount, |
|
312 playlist->Count() ); |
|
313 CleanupStack::PopAndDestroy( playlist ); |
|
314 |
|
315 __LOG( "CUPnPBrowsePlaylistFiller::AddMediaToCollectionL - \ |
|
316 Collection->SetSyncL" ); |
|
317 // Add new playlist to the collection |
|
318 Host().CollectionUtility().Collection().SetSyncL( *media ); |
|
319 CleanupStack::PopAndDestroy( media ); |
|
320 } |
|
321 else |
|
322 { |
|
323 __LOG( "CUPnPBrowsePlaylistFiller::AddMediaToCollectionL - \ |
|
324 No items received!" ); |
|
325 User::Leave( KErrNotFound ); |
|
326 } |
|
327 array.ResetAndDestroy(); |
|
328 CleanupStack::PopAndDestroy( parser ); |
|
329 } |
|
330 |
|
331 // -------------------------------------------------------------------------- |
|
332 // CUPnPBrowsePlaylistFiller::MediaServerDisappeared |
|
333 // The media server has vanished |
|
334 // -------------------------------------------------------------------------- |
|
335 // |
|
336 void CUPnPBrowsePlaylistFiller::MediaServerDisappeared( |
|
337 TUPnPDeviceDisconnectedReason /*aReason*/ ) |
|
338 { |
|
339 __LOG( "CUPnPBrowsePlaylistFiller::MediaServerDisappeared" ); |
|
340 DoComplete(); |
|
341 } |
|
342 |
|
343 // -------------------------------------------------------------------------- |
|
344 // Unused callback methods from the interface |
|
345 // -------------------------------------------------------------------------- |
|
346 // |
|
347 |
|
348 void CUPnPBrowsePlaylistFiller::SearchResponse( |
|
349 const TDesC8& /*aSearchResponse*/, TInt /*aError*/, TInt /*aMatches*/, |
|
350 TInt /*aTotalCount*/, const TDesC8& /*aUpdateId*/ ) {} |
|
351 void CUPnPBrowsePlaylistFiller::SearchCapabilitiesResponse( TInt /*aError*/, |
|
352 const TDesC8& /*aSearchCapabilities*/ ) {} |
|
353 void CUPnPBrowsePlaylistFiller::CreateContainerResponse( TInt /*aError*/, |
|
354 const TDesC8& /*aObjectId*/ ) {} |
|
355 void CUPnPBrowsePlaylistFiller::DeleteObjectResponse( TInt /*aError*/ ) {} |
|
356 void CUPnPBrowsePlaylistFiller::ReserveLocalMSServicesCompleted( TInt |
|
357 /*aError*/ ) {} |
|
358 |
|
359 // -------------------------------------------------------------------------- |
|
360 // CUPnPBrowsePlaylistFiller::HandlePeriod |
|
361 // Action when timer has expired. |
|
362 // -------------------------------------------------------------------------- |
|
363 // |
|
364 void CUPnPBrowsePlaylistFiller::HandlePeriod() |
|
365 { |
|
366 __LOG( "CUPnPBrowsePlaylistFiller::HandlePeriod" ); |
|
367 |
|
368 TRAP_IGNORE( |
|
369 // start a browsing session if not already started |
|
370 if( iBrowsingSession == 0 ) |
|
371 { |
|
372 __LOG( "Start a browsing session" ); |
|
373 iBrowsingSession = &Host().AVController() |
|
374 .StartBrowsingSessionL( SourceDevice() ); |
|
375 iBrowsingSession->SetObserver( *this ); |
|
376 } |
|
377 |
|
378 __LOG( "Start doing more browse requests" ); |
|
379 // Start doing more browse requests |
|
380 iBrowsingSession->BrowseL( *iContainerId, KFilterMin, |
|
381 MUPnPAVBrowsingSession::EDirectChildren, iCurrentIndex, |
|
382 iBlocksize, KSortNone ); |
|
383 ); |
|
384 } |
|
385 |
|
386 |