@@ -51,10 +51,13 @@ 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
+ , m_download(0 )
60
+ , m_downloadStalled(false )
58
61
{
59
62
connect (m_positionTimer.data (), SIGNAL (timeout ()), this , SLOT (positionTick ()));
60
63
connect (m_bufferStatusTimer.data (), SIGNAL (timeout ()), this , SLOT (bufferStatusTick ()));
@@ -183,6 +186,7 @@ void MMF::AbstractMediaPlayer::seek(qint64 ms)
183
186
}
184
187
185
188
doSeek (ms);
189
+ m_position = ms;
186
190
resetMarksIfRewound ();
187
191
188
192
if (wasPlaying && state () != ErrorState) {
@@ -207,6 +211,11 @@ bool MMF::AbstractMediaPlayer::isSeekable() const
207
211
return true ;
208
212
}
209
213
214
+ qint64 MMF::AbstractMediaPlayer::currentTime () const
215
+ {
216
+ return m_position;
217
+ }
218
+
210
219
void MMF::AbstractMediaPlayer::doSetTickInterval (qint32 interval)
211
220
{
212
221
TRACE_CONTEXT (AbstractMediaPlayer::doSetTickInterval, EAudioApi);
@@ -247,6 +256,14 @@ void MMF::AbstractMediaPlayer::open()
247
256
symbianErr = openFile (*file);
248
257
if (KErrNone != symbianErr)
249
258
errorMessage = tr (" Error opening file" );
259
+ } else if (url.scheme () == QLatin1String (" http" )) {
260
+ Q_ASSERT (!m_download);
261
+ m_download = new Download (url, this );
262
+ connect (m_download, SIGNAL (lengthChanged (qint64)),
263
+ this , SLOT (downloadLengthChanged (qint64)));
264
+ connect (m_download, SIGNAL (stateChanged (Download::State)),
265
+ this , SLOT (downloadStateChanged (Download::State)));
266
+ m_download->start ();
250
267
} else {
251
268
symbianErr = openUrl (url.toString ());
252
269
if (KErrNone != symbianErr)
@@ -288,6 +305,14 @@ void MMF::AbstractMediaPlayer::open()
288
305
TRACE_EXIT_0 ();
289
306
}
290
307
308
+ void MMF::AbstractMediaPlayer::close ()
309
+ {
310
+ doClose ();
311
+ delete m_download;
312
+ m_download = 0 ;
313
+ m_position = 0 ;
314
+ }
315
+
291
316
void MMF::AbstractMediaPlayer::volumeChanged (qreal volume)
292
317
{
293
318
TRACE_CONTEXT (AbstractMediaPlayer::volumeChanged, EAudioInternal);
@@ -374,7 +399,8 @@ void MMF::AbstractMediaPlayer::bufferingComplete()
374
399
{
375
400
stopBufferStatusTimer ();
376
401
emit MMF::AbstractPlayer::bufferStatus (100 );
377
- changeState (m_stateBeforeBuffering);
402
+ if (!progressiveDownloadStalled ())
403
+ changeState (m_stateBeforeBuffering);
378
404
}
379
405
380
406
void MMF::AbstractMediaPlayer::maxVolumeChanged (int mmfMaxVolume)
@@ -385,13 +411,28 @@ void MMF::AbstractMediaPlayer::maxVolumeChanged(int mmfMaxVolume)
385
411
386
412
void MMF::AbstractMediaPlayer::loadingComplete (int error)
387
413
{
388
- Q_ASSERT (Phonon::LoadingState == state ());
389
-
390
- if (KErrNone == error) {
391
- updateMetaData ();
392
- changeState (StoppedState);
414
+ TRACE_CONTEXT (AbstractMediaPlayer::loadingComplete, EAudioApi);
415
+ TRACE_ENTRY (" state %d error %d" , state (), error);
416
+ if (progressiveDownloadStalled ()) {
417
+ Q_ASSERT (Phonon::BufferingState == state ());
418
+ if (KErrNone == error) {
419
+ bufferingComplete ();
420
+ doSeek (m_position);
421
+ startPlayback ();
422
+ m_downloadStalled = false ;
423
+ }
393
424
} else {
394
- setError (tr (" Loading clip failed" ), error);
425
+ Q_ASSERT (Phonon::LoadingState == state ());
426
+ if (KErrNone == error) {
427
+ updateMetaData ();
428
+ changeState (StoppedState);
429
+ } else {
430
+ if (isProgressiveDownload () && KErrCorrupt == error) {
431
+ setProgressiveDownloadStalled ();
432
+ } else {
433
+ setError (tr (" Loading clip failed" ), error);
434
+ }
435
+ }
395
436
}
396
437
}
397
438
@@ -415,8 +456,12 @@ void MMF::AbstractMediaPlayer::playbackComplete(int error)
415
456
QMetaObject::invokeMethod (m_parent, " switchToNextSource" , Qt::QueuedConnection);
416
457
}
417
458
else {
418
- setError (tr (" Playback complete" ), error);
419
- emit finished ();
459
+ if (isProgressiveDownload () && KErrCorrupt == error) {
460
+ setProgressiveDownloadStalled ();
461
+ } else {
462
+ setError (tr (" Playback complete" ), error);
463
+ emit finished ();
464
+ }
420
465
}
421
466
}
422
467
@@ -425,15 +470,28 @@ qint64 MMF::AbstractMediaPlayer::toMilliSeconds(const TTimeIntervalMicroSeconds
425
470
return in.Int64 () / 1000 ;
426
471
}
427
472
473
+ bool MMF::AbstractMediaPlayer::isProgressiveDownload () const
474
+ {
475
+ return (0 != m_download);
476
+ }
477
+
478
+ bool MMF::AbstractMediaPlayer::progressiveDownloadStalled () const
479
+ {
480
+ return m_downloadStalled;
481
+ }
482
+
428
483
// -----------------------------------------------------------------------------
429
484
// Slots
430
485
// -----------------------------------------------------------------------------
431
486
432
487
void MMF::AbstractMediaPlayer::positionTick ()
433
488
{
434
- const qint64 current = currentTime ();
435
- emitMarksIfReached (current);
436
- emit MMF::AbstractPlayer::tick (current);
489
+ const qint64 pos = getCurrentTime ();
490
+ if (pos > m_position) {
491
+ m_position = pos;
492
+ emitMarksIfReached (m_position);
493
+ emit MMF::AbstractPlayer::tick (m_position);
494
+ }
437
495
}
438
496
439
497
void MMF::AbstractMediaPlayer::emitMarksIfReached (qint64 current)
@@ -458,7 +516,7 @@ void MMF::AbstractMediaPlayer::emitMarksIfReached(qint64 current)
458
516
459
517
void MMF::AbstractMediaPlayer::resetMarksIfRewound ()
460
518
{
461
- const qint64 current = currentTime ();
519
+ const qint64 current = getCurrentTime ();
462
520
const qint64 total = totalTime ();
463
521
const qint64 remaining = total - current;
464
522
@@ -487,9 +545,71 @@ void MMF::AbstractMediaPlayer::startPlayback()
487
545
changeState (PlayingState);
488
546
}
489
547
548
+ void MMF::AbstractMediaPlayer::setProgressiveDownloadStalled ()
549
+ {
550
+ TRACE_CONTEXT (AbstractMediaPlayer::setProgressiveDownloadStalled, EAudioApi);
551
+ TRACE_ENTRY (" state %d" , state ());
552
+ Q_ASSERT (isProgressiveDownload ());
553
+ m_downloadStalled = true ;
554
+ doClose ();
555
+ bufferingStarted ();
556
+ // Video player loses window handle when closed - need to reapply it here
557
+ videoOutputChanged ();
558
+ #ifdef QT_PHONON_MMF_DOWNLOAD_DUMMY
559
+ m_download->resume ();
560
+ #endif
561
+ }
562
+
490
563
void MMF::AbstractMediaPlayer::bufferStatusTick ()
491
564
{
492
- emit MMF::AbstractPlayer::bufferStatus (bufferStatus ());
565
+ // During progressive download, there is no way to detect the buffering status.
566
+ // Phonon does not support a "buffering; amount unknown" signal, therefore we
567
+ // return a buffering status of zero.
568
+ const int status = progressiveDownloadStalled () ? 0 : bufferStatus ();
569
+ emit MMF::AbstractPlayer::bufferStatus (status);
570
+ }
571
+
572
+ void MMF::AbstractMediaPlayer::downloadLengthChanged (qint64 length)
573
+ {
574
+ TRACE_CONTEXT (AbstractMediaPlayer::downloadLengthChanged, EAudioApi);
575
+ TRACE_ENTRY (" length %Ld" , length);
576
+ Q_UNUSED (length)
577
+ if (m_downloadStalled) {
578
+ bufferingComplete ();
579
+ int err = m_parent->openFileHandle (m_download->targetFileName ());
580
+ if (KErrNone == err)
581
+ err = openFile (*m_parent->file ());
582
+ if (KErrNone != err)
583
+ setError (tr (" Error opening file" ));
584
+ }
585
+ }
586
+
587
+ void MMF::AbstractMediaPlayer::downloadStateChanged (Download::State state)
588
+ {
589
+ TRACE_CONTEXT (AbstractMediaPlayer::downloadStateChanged, EAudioApi);
590
+ TRACE_ENTRY (" state %d" , state);
591
+ switch (state) {
592
+ case Download::Idle:
593
+ case Download::Initializing:
594
+ break ;
595
+ case Download::Downloading:
596
+ {
597
+ int err = m_parent->openFileHandle (m_download->targetFileName ());
598
+ if (KErrNone == err)
599
+ err = openFile (*m_parent->file ());
600
+ else if (KErrCorrupt == err)
601
+ // Insufficient data downloaded - enter Buffering state
602
+ setProgressiveDownloadStalled ();
603
+ if (KErrNone != err)
604
+ setError (tr (" Error opening file" ));
605
+ }
606
+ break ;
607
+ case Download::Complete:
608
+ break ;
609
+ case Download::Error:
610
+ setError (tr (" Download error" ));
611
+ break ;
612
+ }
493
613
}
494
614
495
615
Phonon::State MMF::AbstractMediaPlayer::phononState (PrivateState state) const
0 commit comments