1 /* |
|
2 * Copyright (c) 2007 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 the License "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: Help methods for propriatary RTP format.* |
|
15 */ |
|
16 |
|
17 |
|
18 |
|
19 |
|
20 // INCLUDE FILES |
|
21 #include <pathinfo.h> |
|
22 #include <ipvideo/CRtpClipManager.h> |
|
23 #include "CRtpClipRepairer.h" |
|
24 #include <BaUtils.h> |
|
25 #include "videoserviceutilsLogger.h" |
|
26 |
|
27 // CONSTANTS |
|
28 const TInt EContentRightsRecordingAllowed( 0 ); |
|
29 const TInt EContentRightsLockToDevice( 2 ); |
|
30 const TInt KMaxProgramChars( 8 ); |
|
31 const TInt KFirstFileIndex( 1 ); |
|
32 const TInt KMaxFileIndex( 99 ); |
|
33 _LIT( KDvrClipExtension, ".rtp" ); |
|
34 _LIT( KIndexFormat, "(%02d)" ); |
|
35 |
|
36 // ============================ MEMBER FUNCTIONS =============================== |
|
37 |
|
38 // ----------------------------------------------------------------------------- |
|
39 // CRtpClipManager::NewL |
|
40 // Static two-phased constructor. |
|
41 // ----------------------------------------------------------------------------- |
|
42 // |
|
43 EXPORT_C CRtpClipManager* CRtpClipManager::NewL() |
|
44 { |
|
45 CRtpClipManager* self = CRtpClipManager::NewLC(); |
|
46 CleanupStack::Pop( self ); |
|
47 return self; |
|
48 } |
|
49 |
|
50 // ----------------------------------------------------------------------------- |
|
51 // CRtpClipManager::NewLC |
|
52 // Static two-phased constructor. |
|
53 // ----------------------------------------------------------------------------- |
|
54 // |
|
55 EXPORT_C CRtpClipManager* CRtpClipManager::NewLC() |
|
56 { |
|
57 CRtpClipManager* self = new( ELeave ) CRtpClipManager(); |
|
58 CleanupStack::PushL( self ); |
|
59 self->ConstructL(); |
|
60 return self; |
|
61 } |
|
62 |
|
63 // ----------------------------------------------------------------------------- |
|
64 // CRtpClipManager::CRtpClipManager |
|
65 // |
|
66 // ----------------------------------------------------------------------------- |
|
67 // |
|
68 CRtpClipManager::CRtpClipManager() |
|
69 { |
|
70 // None |
|
71 } |
|
72 |
|
73 // ----------------------------------------------------------------------------- |
|
74 // CRtpClipManager::ConstructL |
|
75 // Symbian 2nd phase constructor can leave. |
|
76 // ----------------------------------------------------------------------------- |
|
77 // |
|
78 void CRtpClipManager::ConstructL() |
|
79 { |
|
80 LOG( "CRtpClipManager::ConstructL() in" ); |
|
81 |
|
82 // IMEI |
|
83 TName buf( KNullDesC ); |
|
84 CRtpUtil::GetImeiL( buf ); |
|
85 iImei = buf.AllocL(); |
|
86 LOG1( "CRtpClipManager::ConstructL(), IMEI: %S", &*iImei ); |
|
87 |
|
88 // File server |
|
89 User::LeaveIfError( iFs.Connect() ); |
|
90 |
|
91 LOG( "CRtpClipManager::ConstructL() out" ); |
|
92 } |
|
93 |
|
94 // ----------------------------------------------------------------------------- |
|
95 // CRtpClipManager::~CRtpClipManager |
|
96 // |
|
97 // ----------------------------------------------------------------------------- |
|
98 // |
|
99 EXPORT_C CRtpClipManager::~CRtpClipManager() |
|
100 { |
|
101 LOG( "CRtpClipManager::~CRtpClipManager()" ); |
|
102 |
|
103 delete iImei; |
|
104 iRepairQueue.ResetAndDestroy(); |
|
105 delete iClipRepairer; |
|
106 iFile.Close(); |
|
107 iFs.Close(); |
|
108 } |
|
109 |
|
110 // ----------------------------------------------------------------------------- |
|
111 // CRtpClipManager::GetClipDetailsL |
|
112 // Getter for clip details. |
|
113 // ----------------------------------------------------------------------------- |
|
114 // |
|
115 EXPORT_C void CRtpClipManager::GetClipDetailsL( |
|
116 const TDesC& aClipPath, |
|
117 SRtpClipDetails& aDetails ) |
|
118 { |
|
119 iFile.Close(); |
|
120 TBool clipOpen( EFalse ); |
|
121 iFs.IsFileOpen( aClipPath, clipOpen ); |
|
122 User::LeaveIfError( iFile.Open( iFs, aClipPath, |
|
123 EFileShareAny | EFileStream | EFileRead ) ); |
|
124 CRtpMetaHeader* metaheader = CRtpMetaHeader::NewLC( |
|
125 iFile, CRtpMetaHeader::EMetaRead ); |
|
126 // Attributes |
|
127 CRtpMetaHeader::SAttributes att; |
|
128 metaheader->ReadAttributesL( att ); |
|
129 |
|
130 // Under version 2 clips not work any longer |
|
131 // Recording ongoing without file open indicates interrupted recording |
|
132 if ( att.iVersion < 2 || ( att.iOngoing && !clipOpen ) ) |
|
133 { |
|
134 LOG3( "CRtpClipManager::GetClipDetailsL(), iVersion: %d, iOngoing: %d, clipOpen: %d", |
|
135 att.iVersion, att.iOngoing, clipOpen ); |
|
136 iFile.Close(); |
|
137 User::Leave( KErrGeneral ); |
|
138 } |
|
139 |
|
140 // Details |
|
141 GetDetailsL( att, aDetails, metaheader ); |
|
142 CleanupStack::PopAndDestroy( metaheader ); |
|
143 iFile.Close(); |
|
144 } |
|
145 |
|
146 // ----------------------------------------------------------------------------- |
|
147 // CRtpClipManager::GetClipDetailsL |
|
148 // Getter for clip details. |
|
149 // ----------------------------------------------------------------------------- |
|
150 // |
|
151 EXPORT_C void CRtpClipManager::GetClipDetailsL( |
|
152 RFile& aFile, |
|
153 SRtpClipDetails& aDetails ) |
|
154 { |
|
155 CRtpMetaHeader* metaheader = CRtpMetaHeader::NewLC( |
|
156 aFile, CRtpMetaHeader::EMetaRead ); |
|
157 // Attributes |
|
158 CRtpMetaHeader::SAttributes att; |
|
159 metaheader->ReadAttributesL( att ); |
|
160 |
|
161 // Details |
|
162 GetDetailsL( att, aDetails, metaheader ); |
|
163 CleanupStack::PopAndDestroy( metaheader ); |
|
164 } |
|
165 |
|
166 // ----------------------------------------------------------------------------- |
|
167 // CRtpClipManager::ProtectClipL |
|
168 // Protects clip from deleting automatically during recording. |
|
169 // ----------------------------------------------------------------------------- |
|
170 // |
|
171 EXPORT_C void CRtpClipManager::ProtectClipL( |
|
172 const TDesC& aClipPath, |
|
173 const TBool aProtected ) |
|
174 { |
|
175 LOG1( "CRtpClipManager::ProtectClipL(), aClipPath: %S", &aClipPath ); |
|
176 LOG1( "CRtpClipManager::ProtectClipL(), aProtected: %d", aProtected ); |
|
177 |
|
178 iFile.Close(); |
|
179 User::LeaveIfError( iFile.Open( iFs, aClipPath, |
|
180 EFileShareExclusive | EFileStream | EFileWrite ) ); |
|
181 CRtpMetaHeader* metaheader = CRtpMetaHeader::NewLC( |
|
182 iFile, CRtpMetaHeader::EMetaUpdate ); |
|
183 // Read Attributes |
|
184 CRtpMetaHeader::SAttributes att; |
|
185 metaheader->ReadAttributesL( att ); |
|
186 // Update protected attribute |
|
187 if ( aProtected != att.iProtected ) |
|
188 { |
|
189 att.iProtected = aProtected; |
|
190 metaheader->WriteAttributesL( att ); |
|
191 } |
|
192 |
|
193 CleanupStack::PopAndDestroy( metaheader ); |
|
194 iFile.Close(); |
|
195 } |
|
196 |
|
197 // ----------------------------------------------------------------------------- |
|
198 // CRtpClipManager::FixMetaHeaderL |
|
199 // Fixes corrupted clip's meta header. |
|
200 // ----------------------------------------------------------------------------- |
|
201 // |
|
202 EXPORT_C void CRtpClipManager::FixMetaHeaderL( |
|
203 MRtpClipRepairObserver* aObs, |
|
204 const TDesC& aClipPath ) |
|
205 { |
|
206 LOG( "RM-CRtpClipManager::FixMetaHeaderL()" ); |
|
207 |
|
208 iFile.Close(); |
|
209 if ( !iClipRepairer ) |
|
210 { |
|
211 LOG1( "CRtpClipManager::FixMetaHeaderL(), Fix started: %S", &aClipPath ); |
|
212 AddClipToRepairQueueL( aClipPath ); |
|
213 iClipRepairer = CRtpClipRepairer::NewL( aObs ); |
|
214 iClipRepairer->CheckMetaHeaderL( aClipPath ); |
|
215 } |
|
216 else |
|
217 { |
|
218 // Verify that not exist in queue |
|
219 TInt loop( iRepairQueue.Count() - 1 ); |
|
220 for ( ; loop >= 0; loop-- ) |
|
221 { |
|
222 if ( !aClipPath.CompareC( iRepairQueue[loop]->Des() ) ) |
|
223 { |
|
224 break; |
|
225 } |
|
226 } |
|
227 |
|
228 // Add to queue |
|
229 if ( loop < 0 ) |
|
230 { |
|
231 LOG1( "CRtpClipManager::FixMetaHeaderL(), Fix queued: %S", &aClipPath ); |
|
232 AddClipToRepairQueueL( aClipPath ); |
|
233 } |
|
234 } |
|
235 } |
|
236 |
|
237 // ----------------------------------------------------------------------------- |
|
238 // CRtpClipManager::FixMetaHeaderL |
|
239 // Fixes corrupted clip's meta header syncronously. |
|
240 // ----------------------------------------------------------------------------- |
|
241 // |
|
242 EXPORT_C void CRtpClipManager::FixMetaHeaderL( const TDesC& aClipPath ) |
|
243 { |
|
244 LOG1( "CRtpClipManager::FixMetaHeaderL(), aClipPath: %S", &aClipPath ); |
|
245 |
|
246 iFile.Close(); |
|
247 delete iClipRepairer; iClipRepairer = NULL; |
|
248 iClipRepairer = CRtpClipRepairer::NewL( NULL ); |
|
249 iClipRepairer->CheckMetaHeaderL( aClipPath ); |
|
250 } |
|
251 |
|
252 // ----------------------------------------------------------------------------- |
|
253 // CRtpClipManager::DeleteRtpRepairer |
|
254 // Kills clip repairer after work done. |
|
255 // ----------------------------------------------------------------------------- |
|
256 // |
|
257 EXPORT_C void CRtpClipManager::DeleteRtpRepairer( MRtpClipRepairObserver* aObs ) |
|
258 { |
|
259 // Remove handled name from the queue first |
|
260 iFile.Close(); |
|
261 TInt last( iRepairQueue.Count() - 1 ); |
|
262 if ( last > KErrNotFound && iClipRepairer && |
|
263 !iRepairQueue[last]->Des().Compare( iClipRepairer->CurrentClipName() ) ) |
|
264 { |
|
265 delete iRepairQueue[last]; |
|
266 iRepairQueue[last] = NULL; |
|
267 iRepairQueue.Remove( last ); |
|
268 } |
|
269 |
|
270 // Repairer must be deleted in any case |
|
271 delete iClipRepairer; iClipRepairer = NULL; |
|
272 TInt err( KErrNotFound ); |
|
273 last = iRepairQueue.Count() - 1; |
|
274 LOG1( "CRtpClipManager::DeleteRtpRepairer(), queue count: %d", iRepairQueue.Count() ); |
|
275 |
|
276 while ( last > KErrNotFound && err ) |
|
277 { |
|
278 // Create new repairer and start it |
|
279 TPath path( iRepairQueue[last]->Des() ); |
|
280 TRAP( err, iClipRepairer = CRtpClipRepairer::NewL( aObs ) ); |
|
281 if ( !err ) |
|
282 { |
|
283 TRAP( err, iClipRepairer->CheckMetaHeaderL( path ) ); |
|
284 if ( err ) |
|
285 { |
|
286 LOG1( "CRtpClipManager::DeleteRtpRepairerL(), CheckMetaHeaderL Leaved: %d", err ); |
|
287 |
|
288 // Remove clip which can't be repaired from the queue |
|
289 delete iRepairQueue[last]; |
|
290 iRepairQueue[last] = NULL; |
|
291 iRepairQueue.Remove( last ); |
|
292 |
|
293 // Ready for the next clip |
|
294 last = iRepairQueue.Count() - 1; |
|
295 delete iClipRepairer; iClipRepairer = NULL; |
|
296 } |
|
297 } |
|
298 else |
|
299 { |
|
300 LOG1( "CRtpClipManager::DeleteRtpRepairerL(), No memory for new repairer: %d", err ); |
|
301 break; |
|
302 } |
|
303 } |
|
304 } |
|
305 |
|
306 // ----------------------------------------------------------------------------- |
|
307 // CRtpClipManager::VerifyPostRuleL |
|
308 // Verifies post acqusition rule of clip. |
|
309 // ----------------------------------------------------------------------------- |
|
310 // |
|
311 TInt CRtpClipManager::VerifyPostRuleL( |
|
312 const TUint8 aPostRule, |
|
313 CRtpMetaHeader* aMetaHeader ) |
|
314 { |
|
315 LOG( "CRtpClipManager::VerifyPostRule()" ); |
|
316 |
|
317 switch ( aPostRule ) |
|
318 { |
|
319 case EContentRightsRecordingAllowed: |
|
320 LOG( "CRtpClipManager::VerifyPostRule(), EContentRightsRecordingAllowed !" ); |
|
321 break; |
|
322 |
|
323 case EContentRightsLockToDevice: |
|
324 { |
|
325 TName imei( KNullDesC ); |
|
326 aMetaHeader->ReadDeviceInfoL( imei ); |
|
327 if ( !iImei || imei.Compare( iImei->Des() ) ) |
|
328 { |
|
329 LOG( "CRtpClipManager::VerifyPostRule(), EContentRightsLockToDevice" ); |
|
330 LOG1( "CRtpClipManager::VerifyPostRule(), ERmPlayDeviceLockError: %S", &imei ); |
|
331 LOG1( "CRtpClipManager::VerifyPostRule(), Phone's IMEI: %S", &*iImei ); |
|
332 return KErrAccessDenied; |
|
333 } |
|
334 } |
|
335 break; |
|
336 |
|
337 default: |
|
338 LOG1( "RM-CRtpClipManager::VerifyPostRule(), Default case: %d", aPostRule ); |
|
339 break; |
|
340 } |
|
341 |
|
342 return KErrNone; |
|
343 } |
|
344 |
|
345 // ----------------------------------------------------------------------------- |
|
346 // CRtpClipManager::GetDetailsL |
|
347 // Updates details from meta header attributes. |
|
348 // ----------------------------------------------------------------------------- |
|
349 // |
|
350 void CRtpClipManager::GetDetailsL( |
|
351 const CRtpMetaHeader::SAttributes& aAttributes, |
|
352 SRtpClipDetails& aDetails, |
|
353 CRtpMetaHeader* aMetaHeader ) |
|
354 { |
|
355 aDetails.iRecOngoing = aAttributes.iOngoing; |
|
356 aDetails.iCompleted = aAttributes.iCompleted; |
|
357 aDetails.iProtected = aAttributes.iProtected; |
|
358 aDetails.iFailed = aAttributes.iFailed; |
|
359 aDetails.iQuality = aAttributes.iQuality; |
|
360 aDetails.iPlayCount = aAttributes.iPlayCount; |
|
361 aDetails.iPlaySpot = aAttributes.iPlaySpot; |
|
362 aDetails.iParental = aAttributes.iParental; |
|
363 |
|
364 LOG1( "CRtpClipManager::GetDetailsL(), iRecOngoing: %d", aDetails.iRecOngoing ); |
|
365 LOG1( "CRtpClipManager::GetDetailsL(), iCompleted: %d", aDetails.iCompleted ); |
|
366 LOG1( "CRtpClipManager::GetDetailsL(), iProtected: %d", aDetails.iProtected ); |
|
367 LOG1( "CRtpClipManager::GetDetailsL(), iFailed: %d", aDetails.iFailed ); |
|
368 LOG1( "CRtpClipManager::GetDetailsL(), iQuality: %d", aDetails.iQuality ); |
|
369 LOG1( "CRtpClipManager::GetDetailsL(), iPlayCount: %d", aDetails.iPlayCount ); |
|
370 LOG1( "CRtpClipManager::GetDetailsL(), iPlaySpot: %d", aDetails.iPlaySpot ); |
|
371 LOG1( "CRtpClipManager::GetDetailsL(), iParental: %d", aDetails.iParental ); |
|
372 |
|
373 // ESG |
|
374 aMetaHeader->ReadEsgDataL( aDetails.iService, aDetails.iProgram ); |
|
375 LOG1( "CRtpClipManager::GetDetailsL(), iService: %S", &aDetails.iService ); |
|
376 LOG1( "CRtpClipManager::GetDetailsL(), iProgram: %S", &aDetails.iProgram ); |
|
377 |
|
378 // Start time |
|
379 aMetaHeader->ReadStartTimeL( aDetails.iStartTime ); |
|
380 |
|
381 // End time |
|
382 aMetaHeader->ReadEndTimeL( aDetails.iEndTime ); |
|
383 |
|
384 #if defined( LIVE_TV_RDEBUG_TRACE ) || defined( LIVE_TV_FILE_TRACE ) |
|
385 TName time( KNullDesC ); aDetails.iEndTime.FormatL( time, KTimeDateFormat ); |
|
386 LOG1( "CRtpClipManager::GetDetailsL(), End time: %S", &time ); |
|
387 #endif // LIVE_TV_RDEBUG_TRACE || LIVE_TV_FILE_TRACE |
|
388 |
|
389 // Duration |
|
390 aMetaHeader->ReadDurationL( aDetails.iDuration ); |
|
391 LOG1( "CRtpClipManager::GetDetailsL(), iDuration: %d", aDetails.iDuration ); |
|
392 aDetails.iDuration/= 1000; // convert to seconds |
|
393 |
|
394 // Post acquisition |
|
395 aDetails.iPostRuleOk = !VerifyPostRuleL( aAttributes.iPostRule, aMetaHeader ); |
|
396 LOG1( "CRtpClipManager::GetDetailsL(), iPostRuleOk: %d", aDetails.iPostRuleOk ); |
|
397 } |
|
398 |
|
399 // ----------------------------------------------------------------------------- |
|
400 // CRtpClipManager::NewClipRootL |
|
401 // Root path of the new clip, depends on user media setting. |
|
402 // If memory card is selected, but not available, default saving to phone memory. |
|
403 // ----------------------------------------------------------------------------- |
|
404 // |
|
405 void CRtpClipManager::NewClipRootL( TDes& aClipPath, const TDriveNumber aDrive ) |
|
406 { |
|
407 // Begin of the save path |
|
408 if ( aDrive == EDriveC ) |
|
409 { |
|
410 aClipPath = PathInfo::PhoneMemoryRootPath(); |
|
411 aClipPath.Append( PathInfo::VideosPath() ); |
|
412 } |
|
413 else |
|
414 { |
|
415 aClipPath = PathInfo::MemoryCardRootPath(); |
|
416 aClipPath.Append( PathInfo::VideosPath() ); |
|
417 } |
|
418 |
|
419 // Verify and create path if not exist |
|
420 if ( !BaflUtils::PathExists( iFs, aClipPath ) ) |
|
421 { |
|
422 TInt err( iFs.MkDirAll( aClipPath ) ); |
|
423 if ( err && aDrive != EDriveC ) |
|
424 { |
|
425 LOG1( "CRtpClipManager::NewClipRootL(), Forced to Use Phone Memory !", err ); |
|
426 |
|
427 // Memorycard not acceptable -> Use phone memory |
|
428 err = KErrNone; |
|
429 aClipPath = PathInfo::PhoneMemoryRootPath(); |
|
430 aClipPath.Append( PathInfo::VideosPath() ); |
|
431 BaflUtils::EnsurePathExistsL( iFs, aClipPath ); |
|
432 } |
|
433 |
|
434 User::LeaveIfError( err ); |
|
435 } |
|
436 } |
|
437 |
|
438 // ----------------------------------------------------------------------------- |
|
439 // CRtpClipManager::NewIndexNameL |
|
440 // Creates new clip name from program name (eigth first letters + index). |
|
441 // If program name allready in use, adds indexing to the end of name. |
|
442 // ----------------------------------------------------------------------------- |
|
443 // |
|
444 void CRtpClipManager::NewIndexNameL( TDes& aClipPath, const TDesC& aProgram ) |
|
445 { |
|
446 LOG1( "CRtpClipManager::NewIndexNameL(), aClipPath : %S", &aClipPath ); |
|
447 LOG1( "CRtpClipManager::NewIndexNameL(), aProgram : %S", &aProgram ); |
|
448 |
|
449 // Remove special characters |
|
450 TBuf<KMaxProgramChars> program( aProgram.Left( KMaxProgramChars ) ); |
|
451 for ( TInt i( program.Length() - 1 ); i >= 0; i-- ) |
|
452 { |
|
453 TChar letter( program[i] ); |
|
454 // Remove if not alpha nor space |
|
455 if ( !letter.IsAlphaDigit() && !letter.IsSpace() ) |
|
456 { |
|
457 program.Delete( i, 1 ); |
|
458 } |
|
459 } |
|
460 program.TrimRight(); |
|
461 |
|
462 TInt index( KFirstFileIndex ); |
|
463 |
|
464 // Test name for existing clip check |
|
465 TPath testName( aClipPath ); |
|
466 if ( program.Length() ) |
|
467 { |
|
468 testName.Append( program ); |
|
469 } |
|
470 else |
|
471 { |
|
472 // Zero length program name, start from "(01).rtp" |
|
473 testName.AppendFormat( KIndexFormat, index++ ); |
|
474 } |
|
475 |
|
476 // Name already used ? |
|
477 testName.Append( KDvrClipExtension ); |
|
478 if ( BaflUtils::FileExists( iFs, testName ) ) |
|
479 { |
|
480 do |
|
481 { |
|
482 LOG1( "CRtpClipManager::NewIndexNameL(), Clip exist: %S", &testName ); |
|
483 |
|
484 // Abort if file index exceeds "(99)" |
|
485 User::LeaveIfError( ( index > KMaxFileIndex ) * KErrOverflow ); |
|
486 |
|
487 // New test name |
|
488 testName.Copy( aClipPath ); |
|
489 testName.Append( program ); |
|
490 testName.AppendFormat( KIndexFormat, index++ ); |
|
491 testName.Append( KDvrClipExtension ); |
|
492 } |
|
493 while ( BaflUtils::FileExists( iFs, testName ) ); |
|
494 } |
|
495 |
|
496 // Return suitable filename |
|
497 aClipPath.Copy( testName ); |
|
498 } |
|
499 |
|
500 // ----------------------------------------------------------------------------- |
|
501 // CRtpClipManager::AddClipToRepairQueueL |
|
502 // Inserts new clip name to the first in queue. |
|
503 // ----------------------------------------------------------------------------- |
|
504 // |
|
505 void CRtpClipManager::AddClipToRepairQueueL( const TDesC& aClipPath ) |
|
506 { |
|
507 HBufC* clip = aClipPath.AllocLC(); |
|
508 User::LeaveIfError( iRepairQueue.Insert( clip, 0 ) ); |
|
509 CleanupStack::Pop( clip ); |
|
510 } |
|
511 |
|
512 // End of File |
|
513 |
|