@@ -51,10 +51,15 @@ MMF::AbstractMediaPlayer::AbstractMediaPlayer
51
51
, m_parent(parent)
52
52
, m_pending(NothingPending)
53
53
, m_positionTimer(new QTimer(this ))
54
+ , m_position(0 )
54
55
, m_bufferStatusTimer(new QTimer(this ))
55
56
, m_mmfMaxVolume(NullMaxVolume)
56
57
, m_prefinishMarkSent(false )
57
58
, m_aboutToFinishSent(false )
59
+ #ifdef PHONON_MMF_PROGRESSIVE_DOWNLOAD
60
+ , m_download(0 )
61
+ , m_downloadStalled(false )
62
+ #endif
58
63
{
59
64
connect (m_positionTimer.data (), SIGNAL (timeout ()), this , SLOT (positionTick ()));
60
65
connect (m_bufferStatusTimer.data (), SIGNAL (timeout ()), this , SLOT (bufferStatusTick ()));
@@ -183,6 +188,7 @@ void MMF::AbstractMediaPlayer::seek(qint64 ms)
183
188
}
184
189
185
190
doSeek (ms);
191
+ m_position = ms;
186
192
resetMarksIfRewound ();
187
193
188
194
if (wasPlaying && state () != ErrorState) {
@@ -207,6 +213,11 @@ bool MMF::AbstractMediaPlayer::isSeekable() const
207
213
return true ;
208
214
}
209
215
216
+ qint64 MMF::AbstractMediaPlayer::currentTime () const
217
+ {
218
+ return m_position;
219
+ }
220
+
210
221
void MMF::AbstractMediaPlayer::doSetTickInterval (qint32 interval)
211
222
{
212
223
TRACE_CONTEXT (AbstractMediaPlayer::doSetTickInterval, EAudioApi);
@@ -247,7 +258,19 @@ void MMF::AbstractMediaPlayer::open()
247
258
symbianErr = openFile (*file);
248
259
if (KErrNone != symbianErr)
249
260
errorMessage = tr (" Error opening file" );
250
- } else {
261
+ }
262
+ #ifdef PHONON_MMF_PROGRESSIVE_DOWNLOAD
263
+ else if (url.scheme () == QLatin1String (" http" )) {
264
+ Q_ASSERT (!m_download);
265
+ m_download = new Download (url, this );
266
+ connect (m_download, SIGNAL (lengthChanged (qint64)),
267
+ this , SLOT (downloadLengthChanged (qint64)));
268
+ connect (m_download, SIGNAL (stateChanged (Download::State)),
269
+ this , SLOT (downloadStateChanged (Download::State)));
270
+ m_download->start ();
271
+ }
272
+ #endif
273
+ else {
251
274
symbianErr = openUrl (url.toString ());
252
275
if (KErrNone != symbianErr)
253
276
errorMessage = tr (" Error opening URL" );
@@ -288,6 +311,16 @@ void MMF::AbstractMediaPlayer::open()
288
311
TRACE_EXIT_0 ();
289
312
}
290
313
314
+ void MMF::AbstractMediaPlayer::close ()
315
+ {
316
+ doClose ();
317
+ #ifdef PHONON_MMF_PROGRESSIVE_DOWNLOAD
318
+ delete m_download;
319
+ m_download = 0 ;
320
+ #endif
321
+ m_position = 0 ;
322
+ }
323
+
291
324
void MMF::AbstractMediaPlayer::volumeChanged (qreal volume)
292
325
{
293
326
TRACE_CONTEXT (AbstractMediaPlayer::volumeChanged, EAudioInternal);
@@ -374,7 +407,8 @@ void MMF::AbstractMediaPlayer::bufferingComplete()
374
407
{
375
408
stopBufferStatusTimer ();
376
409
emit MMF::AbstractPlayer::bufferStatus (100 );
377
- changeState (m_stateBeforeBuffering);
410
+ if (!progressiveDownloadStalled ())
411
+ changeState (m_stateBeforeBuffering);
378
412
}
379
413
380
414
void MMF::AbstractMediaPlayer::maxVolumeChanged (int mmfMaxVolume)
@@ -385,13 +419,30 @@ void MMF::AbstractMediaPlayer::maxVolumeChanged(int mmfMaxVolume)
385
419
386
420
void MMF::AbstractMediaPlayer::loadingComplete (int error)
387
421
{
388
- Q_ASSERT (Phonon::LoadingState == state ());
389
-
390
- if (KErrNone == error) {
391
- updateMetaData ();
392
- changeState (StoppedState);
422
+ TRACE_CONTEXT (AbstractMediaPlayer::loadingComplete, EAudioApi);
423
+ TRACE_ENTRY (" state %d error %d" , state (), error);
424
+ if (progressiveDownloadStalled ()) {
425
+ Q_ASSERT (Phonon::BufferingState == state ());
426
+ if (KErrNone == error) {
427
+ bufferingComplete ();
428
+ doSeek (m_position);
429
+ startPlayback ();
430
+ #ifdef PHONON_MMF_PROGRESSIVE_DOWNLOAD
431
+ m_downloadStalled = false ;
432
+ #endif
433
+ }
393
434
} else {
394
- setError (tr (" Loading clip failed" ), error);
435
+ Q_ASSERT (Phonon::LoadingState == state ());
436
+ if (KErrNone == error) {
437
+ updateMetaData ();
438
+ changeState (StoppedState);
439
+ } else {
440
+ if (isProgressiveDownload () && KErrCorrupt == error) {
441
+ setProgressiveDownloadStalled ();
442
+ } else {
443
+ setError (tr (" Loading clip failed" ), error);
444
+ }
445
+ }
395
446
}
396
447
}
397
448
@@ -415,8 +466,12 @@ void MMF::AbstractMediaPlayer::playbackComplete(int error)
415
466
QMetaObject::invokeMethod (m_parent, " switchToNextSource" , Qt::QueuedConnection);
416
467
}
417
468
else {
418
- setError (tr (" Playback complete" ), error);
419
- emit finished ();
469
+ if (isProgressiveDownload () && KErrCorrupt == error) {
470
+ setProgressiveDownloadStalled ();
471
+ } else {
472
+ setError (tr (" Playback complete" ), error);
473
+ emit finished ();
474
+ }
420
475
}
421
476
}
422
477
@@ -425,15 +480,36 @@ qint64 MMF::AbstractMediaPlayer::toMilliSeconds(const TTimeIntervalMicroSeconds
425
480
return in.Int64 () / 1000 ;
426
481
}
427
482
483
+ bool MMF::AbstractMediaPlayer::isProgressiveDownload () const
484
+ {
485
+ #ifdef PHONON_MMF_PROGRESSIVE_DOWNLOAD
486
+ return (0 != m_download);
487
+ #else
488
+ return false ;
489
+ #endif
490
+ }
491
+
492
+ bool MMF::AbstractMediaPlayer::progressiveDownloadStalled () const
493
+ {
494
+ #ifdef PHONON_MMF_PROGRESSIVE_DOWNLOAD
495
+ return m_downloadStalled;
496
+ #else
497
+ return false ;
498
+ #endif
499
+ }
500
+
428
501
// -----------------------------------------------------------------------------
429
502
// Slots
430
503
// -----------------------------------------------------------------------------
431
504
432
505
void MMF::AbstractMediaPlayer::positionTick ()
433
506
{
434
- const qint64 current = currentTime ();
435
- emitMarksIfReached (current);
436
- emit MMF::AbstractPlayer::tick (current);
507
+ const qint64 pos = getCurrentTime ();
508
+ if (pos > m_position) {
509
+ m_position = pos;
510
+ emitMarksIfReached (m_position);
511
+ emit MMF::AbstractPlayer::tick (m_position);
512
+ }
437
513
}
438
514
439
515
void MMF::AbstractMediaPlayer::emitMarksIfReached (qint64 current)
@@ -458,7 +534,7 @@ void MMF::AbstractMediaPlayer::emitMarksIfReached(qint64 current)
458
534
459
535
void MMF::AbstractMediaPlayer::resetMarksIfRewound ()
460
536
{
461
- const qint64 current = currentTime ();
537
+ const qint64 current = getCurrentTime ();
462
538
const qint64 total = totalTime ();
463
539
const qint64 remaining = total - current;
464
540
@@ -487,10 +563,74 @@ void MMF::AbstractMediaPlayer::startPlayback()
487
563
changeState (PlayingState);
488
564
}
489
565
566
+ void MMF::AbstractMediaPlayer::setProgressiveDownloadStalled ()
567
+ {
568
+ #ifdef PHONON_MMF_PROGRESSIVE_DOWNLOAD
569
+ TRACE_CONTEXT (AbstractMediaPlayer::setProgressiveDownloadStalled, EAudioApi);
570
+ TRACE_ENTRY (" state %d" , state ());
571
+ Q_ASSERT (isProgressiveDownload ());
572
+ m_downloadStalled = true ;
573
+ doClose ();
574
+ bufferingStarted ();
575
+ // Video player loses window handle when closed - need to reapply it here
576
+ videoOutputChanged ();
577
+ m_download->resume ();
578
+ #endif
579
+ }
580
+
490
581
void MMF::AbstractMediaPlayer::bufferStatusTick ()
491
582
{
492
- emit MMF::AbstractPlayer::bufferStatus (bufferStatus ());
583
+ // During progressive download, there is no way to detect the buffering status.
584
+ // Phonon does not support a "buffering; amount unknown" signal, therefore we
585
+ // return a buffering status of zero.
586
+ const int status = progressiveDownloadStalled () ? 0 : bufferStatus ();
587
+ emit MMF::AbstractPlayer::bufferStatus (status);
588
+ }
589
+
590
+ #ifdef PHONON_MMF_PROGRESSIVE_DOWNLOAD
591
+ void MMF::AbstractMediaPlayer::downloadLengthChanged (qint64 length)
592
+ {
593
+ TRACE_CONTEXT (AbstractMediaPlayer::downloadLengthChanged, EAudioApi);
594
+ TRACE_ENTRY (" length %Ld" , length);
595
+ Q_UNUSED (length)
596
+ if (m_downloadStalled) {
597
+ bufferingComplete ();
598
+ int err = m_parent->openFileHandle (m_download->targetFileName ());
599
+ if (KErrNone == err)
600
+ err = openFile (*m_parent->file ());
601
+ if (KErrNone != err)
602
+ setError (tr (" Error opening file" ));
603
+ }
604
+ }
605
+
606
+ void MMF::AbstractMediaPlayer::downloadStateChanged (Download::State state)
607
+ {
608
+ TRACE_CONTEXT (AbstractMediaPlayer::downloadStateChanged, EAudioApi);
609
+ TRACE_ENTRY (" state %d" , state);
610
+ switch (state) {
611
+ case Download::Idle:
612
+ case Download::Initializing:
613
+ break ;
614
+ case Download::Downloading:
615
+ {
616
+ int err = m_parent->openFileHandle (m_download->targetFileName ());
617
+ if (KErrNone == err)
618
+ err = openFile (*m_parent->file ());
619
+ else if (KErrCorrupt == err)
620
+ // Insufficient data downloaded - enter Buffering state
621
+ setProgressiveDownloadStalled ();
622
+ if (KErrNone != err)
623
+ setError (tr (" Error opening file" ));
624
+ }
625
+ break ;
626
+ case Download::Complete:
627
+ break ;
628
+ case Download::Error:
629
+ setError (tr (" Download error" ));
630
+ break ;
631
+ }
493
632
}
633
+ #endif // PHONON_MMF_PROGRESSIVE_DOWNLOAD
494
634
495
635
Phonon::State MMF::AbstractMediaPlayer::phononState (PrivateState state) const
496
636
{
0 commit comments