| OLD | NEW |
| 1 /* | 1 /* |
| 2 * Copyright (C) 2007, 2008, 2009 Apple Inc. All rights reserved. | 2 * Copyright (C) 2007, 2008, 2009 Apple Inc. All rights reserved. |
| 3 * | 3 * |
| 4 * Redistribution and use in source and binary forms, with or without | 4 * Redistribution and use in source and binary forms, with or without |
| 5 * modification, are permitted provided that the following conditions | 5 * modification, are permitted provided that the following conditions |
| 6 * are met: | 6 * are met: |
| 7 * 1. Redistributions of source code must retain the above copyright | 7 * 1. Redistributions of source code must retain the above copyright |
| 8 * notice, this list of conditions and the following disclaimer. | 8 * notice, this list of conditions and the following disclaimer. |
| 9 * 2. Redistributions in binary form must reproduce the above copyright | 9 * 2. Redistributions in binary form must reproduce the above copyright |
| 10 * notice, this list of conditions and the following disclaimer in the | 10 * notice, this list of conditions and the following disclaimer in the |
| (...skipping 58 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 69 : HTMLElement(tagName, doc) | 69 : HTMLElement(tagName, doc) |
| 70 , m_loadTimer(this, &HTMLMediaElement::loadTimerFired) | 70 , m_loadTimer(this, &HTMLMediaElement::loadTimerFired) |
| 71 , m_asyncEventTimer(this, &HTMLMediaElement::asyncEventTimerFired) | 71 , m_asyncEventTimer(this, &HTMLMediaElement::asyncEventTimerFired) |
| 72 , m_progressEventTimer(this, &HTMLMediaElement::progressEventTimerFired) | 72 , m_progressEventTimer(this, &HTMLMediaElement::progressEventTimerFired) |
| 73 , m_defaultPlaybackRate(1.0f) | 73 , m_defaultPlaybackRate(1.0f) |
| 74 , m_networkState(EMPTY) | 74 , m_networkState(EMPTY) |
| 75 , m_readyState(DATA_UNAVAILABLE) | 75 , m_readyState(DATA_UNAVAILABLE) |
| 76 , m_begun(false) | 76 , m_begun(false) |
| 77 , m_loadedFirstFrame(false) | 77 , m_loadedFirstFrame(false) |
| 78 , m_autoplaying(true) | 78 , m_autoplaying(true) |
| 79 , m_currentLoop(0) | |
| 80 , m_volume(1.0f) | 79 , m_volume(1.0f) |
| 81 , m_muted(false) | 80 , m_muted(false) |
| 82 , m_paused(true) | 81 , m_paused(true) |
| 83 , m_seeking(false) | 82 , m_seeking(false) |
| 84 , m_currentTimeDuringSeek(0) | 83 , m_currentTimeDuringSeek(0) |
| 85 , m_previousProgress(0) | 84 , m_previousProgress(0) |
| 86 , m_previousProgressTime(numeric_limits<double>::max()) | 85 , m_previousProgressTime(numeric_limits<double>::max()) |
| 87 , m_sentStalledEvent(false) | 86 , m_sentStalledEvent(false) |
| 88 , m_bufferingRate(0) | |
| 89 , m_loadNestingLevel(0) | 87 , m_loadNestingLevel(0) |
| 90 , m_terminateLoadBelowNestingLevel(0) | 88 , m_terminateLoadBelowNestingLevel(0) |
| 91 , m_pausedInternal(false) | 89 , m_pausedInternal(false) |
| 92 , m_inActiveDocument(true) | 90 , m_inActiveDocument(true) |
| 93 , m_player(0) | 91 , m_player(0) |
| 94 , m_restrictions(NoRestrictions) | 92 , m_restrictions(NoRestrictions) |
| 95 , m_processingMediaPlayerCallback(0) | 93 , m_processingMediaPlayerCallback(0) |
| 96 , m_sendProgressEvents(true) | 94 , m_sendProgressEvents(true) |
| 97 #if ENABLE(PLUGIN_PROXY_FOR_VIDEO) | 95 #if ENABLE(PLUGIN_PROXY_FOR_VIDEO) |
| 98 , m_needWidgetUpdate(false) | 96 , m_needWidgetUpdate(false) |
| (...skipping 193 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 292 String HTMLMediaElement::currentSrc() const | 290 String HTMLMediaElement::currentSrc() const |
| 293 { | 291 { |
| 294 return m_currentSrc; | 292 return m_currentSrc; |
| 295 } | 293 } |
| 296 | 294 |
| 297 HTMLMediaElement::NetworkState HTMLMediaElement::networkState() const | 295 HTMLMediaElement::NetworkState HTMLMediaElement::networkState() const |
| 298 { | 296 { |
| 299 return m_networkState; | 297 return m_networkState; |
| 300 } | 298 } |
| 301 | 299 |
| 302 float HTMLMediaElement::bufferingRate() | |
| 303 { | |
| 304 if (!m_player) | |
| 305 return 0; | |
| 306 return m_bufferingRate; | |
| 307 //return m_player->dataRate(); | |
| 308 } | |
| 309 | |
| 310 String HTMLMediaElement::canPlayType(const String& mimeType) const | 300 String HTMLMediaElement::canPlayType(const String& mimeType) const |
| 311 { | 301 { |
| 312 MediaPlayer::SupportsType support = MediaPlayer::supportsType(ContentType(mi
meType)); | 302 MediaPlayer::SupportsType support = MediaPlayer::supportsType(ContentType(mi
meType)); |
| 313 String canPlay; | 303 String canPlay; |
| 314 | 304 |
| 315 // 4.8.10.3 | 305 // 4.8.10.3 |
| 316 switch (support) | 306 switch (support) |
| 317 { | 307 { |
| 318 case MediaPlayer::IsNotSupported: | 308 case MediaPlayer::IsNotSupported: |
| 319 canPlay = "no"; | 309 canPlay = "no"; |
| (...skipping 25 matching lines...) Expand all Loading... |
| 345 ContentType contentType(""); | 335 ContentType contentType(""); |
| 346 | 336 |
| 347 // 3.14.9.4. Loading the media resource | 337 // 3.14.9.4. Loading the media resource |
| 348 // 1 | 338 // 1 |
| 349 // if an event generated during load() ends up re-entering load(), terminate
previous instances | 339 // if an event generated during load() ends up re-entering load(), terminate
previous instances |
| 350 m_loadNestingLevel++; | 340 m_loadNestingLevel++; |
| 351 m_terminateLoadBelowNestingLevel = m_loadNestingLevel; | 341 m_terminateLoadBelowNestingLevel = m_loadNestingLevel; |
| 352 | 342 |
| 353 m_progressEventTimer.stop(); | 343 m_progressEventTimer.stop(); |
| 354 m_sentStalledEvent = false; | 344 m_sentStalledEvent = false; |
| 355 m_bufferingRate = 0; | |
| 356 | 345 |
| 357 m_loadTimer.stop(); | 346 m_loadTimer.stop(); |
| 358 | 347 |
| 359 // 2 | 348 // 2 |
| 360 if (m_begun) { | 349 if (m_begun) { |
| 361 m_begun = false; | 350 m_begun = false; |
| 362 m_error = MediaError::create(MediaError::MEDIA_ERR_ABORTED); | 351 m_error = MediaError::create(MediaError::MEDIA_ERR_ABORTED); |
| 363 if (m_sendProgressEvents) | 352 if (m_sendProgressEvents) |
| 364 initAndDispatchProgressEvent(eventNames().abortEvent); | 353 initAndDispatchProgressEvent(eventNames().abortEvent); |
| 365 if (m_loadNestingLevel < m_terminateLoadBelowNestingLevel) | 354 if (m_loadNestingLevel < m_terminateLoadBelowNestingLevel) |
| (...skipping 11 matching lines...) Expand all Loading... |
| 377 // 5 | 366 // 5 |
| 378 if (networkState() != EMPTY) { | 367 if (networkState() != EMPTY) { |
| 379 m_networkState = EMPTY; | 368 m_networkState = EMPTY; |
| 380 m_readyState = DATA_UNAVAILABLE; | 369 m_readyState = DATA_UNAVAILABLE; |
| 381 m_paused = true; | 370 m_paused = true; |
| 382 m_seeking = false; | 371 m_seeking = false; |
| 383 if (m_player) { | 372 if (m_player) { |
| 384 m_player->pause(); | 373 m_player->pause(); |
| 385 m_player->seek(0); | 374 m_player->seek(0); |
| 386 } | 375 } |
| 387 m_currentLoop = 0; | |
| 388 dispatchEventForType(eventNames().emptiedEvent, false, true); | 376 dispatchEventForType(eventNames().emptiedEvent, false, true); |
| 389 if (m_loadNestingLevel < m_terminateLoadBelowNestingLevel) | 377 if (m_loadNestingLevel < m_terminateLoadBelowNestingLevel) |
| 390 goto end; | 378 goto end; |
| 391 } | 379 } |
| 392 | 380 |
| 393 // 6 | 381 // 6 |
| 394 mediaSrc = selectMediaURL(contentType); | 382 mediaSrc = selectMediaURL(contentType); |
| 395 if (mediaSrc.isEmpty()) { | 383 if (mediaSrc.isEmpty()) { |
| 396 ec = INVALID_STATE_ERR; | 384 ec = INVALID_STATE_ERR; |
| 397 goto end; | 385 goto end; |
| (...skipping 66 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 464 | 452 |
| 465 // 3.14.9.4. Loading the media resource | 453 // 3.14.9.4. Loading the media resource |
| 466 // 14 | 454 // 14 |
| 467 if (state == MediaPlayer::LoadFailed) { | 455 if (state == MediaPlayer::LoadFailed) { |
| 468 //delete m_player; | 456 //delete m_player; |
| 469 //m_player = 0; | 457 //m_player = 0; |
| 470 // FIXME better error handling | 458 // FIXME better error handling |
| 471 m_error = MediaError::create(MediaError::MEDIA_ERR_NETWORK); | 459 m_error = MediaError::create(MediaError::MEDIA_ERR_NETWORK); |
| 472 m_begun = false; | 460 m_begun = false; |
| 473 m_progressEventTimer.stop(); | 461 m_progressEventTimer.stop(); |
| 474 m_bufferingRate = 0; | |
| 475 | 462 |
| 476 initAndDispatchProgressEvent(eventNames().errorEvent); | 463 initAndDispatchProgressEvent(eventNames().errorEvent); |
| 477 if (m_loadNestingLevel < m_terminateLoadBelowNestingLevel) | 464 if (m_loadNestingLevel < m_terminateLoadBelowNestingLevel) |
| 478 return; | 465 return; |
| 479 | 466 |
| 480 m_networkState = EMPTY; | 467 m_networkState = EMPTY; |
| 481 | 468 |
| 482 if (isVideo()) | 469 if (isVideo()) |
| 483 static_cast<HTMLVideoElement*>(this)->updatePosterImage(); | 470 static_cast<HTMLVideoElement*>(this)->updatePosterImage(); |
| 484 | 471 |
| 485 dispatchEventForType(eventNames().emptiedEvent, false, true); | 472 dispatchEventForType(eventNames().emptiedEvent, false, true); |
| 486 return; | 473 return; |
| 487 } | 474 } |
| 488 | 475 |
| 489 if (state >= MediaPlayer::Loading && m_networkState < LOADING) | 476 if (state >= MediaPlayer::Loading && m_networkState < LOADING) |
| 490 m_networkState = LOADING; | 477 m_networkState = LOADING; |
| 491 | 478 |
| 492 if (state >= MediaPlayer::LoadedMetaData && m_networkState < LOADED_METADATA
) { | 479 if (state >= MediaPlayer::LoadedMetaData && m_networkState < LOADED_METADATA
) { |
| 493 m_player->seek(effectiveStart()); | |
| 494 m_networkState = LOADED_METADATA; | 480 m_networkState = LOADED_METADATA; |
| 495 | 481 |
| 496 dispatchEventForType(eventNames().durationchangeEvent, false, true); | 482 dispatchEventForType(eventNames().durationchangeEvent, false, true); |
| 497 if (m_loadNestingLevel < m_terminateLoadBelowNestingLevel) | 483 if (m_loadNestingLevel < m_terminateLoadBelowNestingLevel) |
| 498 return; | 484 return; |
| 499 | 485 |
| 500 dispatchEventForType(eventNames().loadedmetadataEvent, false, true); | 486 dispatchEventForType(eventNames().loadedmetadataEvent, false, true); |
| 501 if (m_loadNestingLevel < m_terminateLoadBelowNestingLevel) | 487 if (m_loadNestingLevel < m_terminateLoadBelowNestingLevel) |
| 502 return; | 488 return; |
| 503 } | 489 } |
| (...skipping 24 matching lines...) Expand all Loading... |
| 528 dispatchEventForType(eventNames().canshowcurrentframeEvent, false, true)
; | 514 dispatchEventForType(eventNames().canshowcurrentframeEvent, false, true)
; |
| 529 if (m_loadNestingLevel < m_terminateLoadBelowNestingLevel) | 515 if (m_loadNestingLevel < m_terminateLoadBelowNestingLevel) |
| 530 return; | 516 return; |
| 531 } | 517 } |
| 532 | 518 |
| 533 // 15 | 519 // 15 |
| 534 if (state == MediaPlayer::Loaded && m_networkState < LOADED) { | 520 if (state == MediaPlayer::Loaded && m_networkState < LOADED) { |
| 535 m_begun = false; | 521 m_begun = false; |
| 536 m_networkState = LOADED; | 522 m_networkState = LOADED; |
| 537 m_progressEventTimer.stop(); | 523 m_progressEventTimer.stop(); |
| 538 m_bufferingRate = 0; | |
| 539 initAndDispatchProgressEvent(eventNames().loadEvent); | 524 initAndDispatchProgressEvent(eventNames().loadEvent); |
| 540 } | 525 } |
| 541 } | 526 } |
| 542 | 527 |
| 543 void HTMLMediaElement::mediaPlayerReadyStateChanged(MediaPlayer*) | 528 void HTMLMediaElement::mediaPlayerReadyStateChanged(MediaPlayer*) |
| 544 { | 529 { |
| 545 beginProcessingMediaPlayerCallback(); | 530 beginProcessingMediaPlayerCallback(); |
| 546 | 531 |
| 547 MediaPlayer::ReadyState state = m_player->readyState(); | 532 MediaPlayer::ReadyState state = m_player->readyState(); |
| 548 setReadyState((ReadyState)state); | 533 setReadyState((ReadyState)state); |
| (...skipping 40 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 589 } | 574 } |
| 590 updatePlayState(); | 575 updatePlayState(); |
| 591 } | 576 } |
| 592 | 577 |
| 593 void HTMLMediaElement::progressEventTimerFired(Timer<HTMLMediaElement>*) | 578 void HTMLMediaElement::progressEventTimerFired(Timer<HTMLMediaElement>*) |
| 594 { | 579 { |
| 595 ASSERT(m_player); | 580 ASSERT(m_player); |
| 596 unsigned progress = m_player->bytesLoaded(); | 581 unsigned progress = m_player->bytesLoaded(); |
| 597 double time = WTF::currentTime(); | 582 double time = WTF::currentTime(); |
| 598 double timedelta = time - m_previousProgressTime; | 583 double timedelta = time - m_previousProgressTime; |
| 599 if (timedelta) | |
| 600 m_bufferingRate = (float)(0.8 * m_bufferingRate + 0.2 * ((float)(progres
s - m_previousProgress)) / timedelta); | |
| 601 | 584 |
| 602 if (progress == m_previousProgress) { | 585 if (progress == m_previousProgress) { |
| 603 if (timedelta > 3.0 && !m_sentStalledEvent) { | 586 if (timedelta > 3.0 && !m_sentStalledEvent) { |
| 604 m_bufferingRate = 0; | |
| 605 initAndDispatchProgressEvent(eventNames().stalledEvent); | 587 initAndDispatchProgressEvent(eventNames().stalledEvent); |
| 606 m_sentStalledEvent = true; | 588 m_sentStalledEvent = true; |
| 607 } | 589 } |
| 608 } else { | 590 } else { |
| 609 initAndDispatchProgressEvent(eventNames().progressEvent); | 591 initAndDispatchProgressEvent(eventNames().progressEvent); |
| 610 m_previousProgress = progress; | 592 m_previousProgress = progress; |
| 611 m_previousProgressTime = time; | 593 m_previousProgressTime = time; |
| 612 m_sentStalledEvent = false; | 594 m_sentStalledEvent = false; |
| 613 } | 595 } |
| 614 } | 596 } |
| 615 | 597 |
| 616 void HTMLMediaElement::seek(float time, ExceptionCode& ec) | 598 void HTMLMediaElement::seek(float time, ExceptionCode& ec) |
| 617 { | 599 { |
| 618 // 3.14.9.8. Seeking | 600 // 3.14.9.8. Seeking |
| 619 // 1 | 601 // 1 |
| 620 if (networkState() < LOADED_METADATA) { | 602 if (networkState() < LOADED_METADATA) { |
| 621 ec = INVALID_STATE_ERR; | 603 ec = INVALID_STATE_ERR; |
| 622 return; | 604 return; |
| 623 } | 605 } |
| 624 | 606 |
| 625 // 2 | 607 time = min(time, duration()); |
| 626 float minTime; | 608 time = max(time, 0.0f); |
| 627 if (currentLoop() == 0) | |
| 628 minTime = effectiveStart(); | |
| 629 else | |
| 630 minTime = effectiveLoopStart(); | |
| 631 | |
| 632 // 3 | |
| 633 float maxTime = currentLoop() == playCount() - 1 ? effectiveEnd() : effectiv
eLoopEnd(); | |
| 634 | |
| 635 // 4 | |
| 636 time = min(time, maxTime); | |
| 637 | |
| 638 // 5 | |
| 639 time = max(time, minTime); | |
| 640 | 609 |
| 641 // 6 | 610 // 6 |
| 642 RefPtr<TimeRanges> seekableRanges = seekable(); | 611 RefPtr<TimeRanges> seekableRanges = seekable(); |
| 643 if (!seekableRanges->contain(time)) { | 612 if (!seekableRanges->contain(time)) { |
| 644 ec = INDEX_SIZE_ERR; | 613 ec = INDEX_SIZE_ERR; |
| 645 return; | 614 return; |
| 646 } | 615 } |
| 647 | 616 |
| 648 // 7 | 617 // 7 |
| 649 m_currentTimeDuringSeek = time; | 618 m_currentTimeDuringSeek = time; |
| 650 | 619 |
| 651 // 8 | 620 // 8 |
| 652 m_seeking = true; | 621 m_seeking = true; |
| 653 | 622 |
| 654 // 9 | 623 // 9 |
| 655 dispatchEventForType(eventNames().timeupdateEvent, false, true); | 624 dispatchEventForType(eventNames().timeupdateEvent, false, true); |
| 656 | 625 |
| 657 // 10 | 626 // 10 |
| 658 // As soon as the user agent has established whether or not the media data f
or the new playback position is available, | 627 // As soon as the user agent has established whether or not the media data f
or the new playback position is available, |
| 659 // and, if it is, decoded enough data to play back that position, the seekin
g DOM attribute must be set to false. | 628 // and, if it is, decoded enough data to play back that position, the seekin
g DOM attribute must be set to false. |
| 660 if (m_player) { | 629 if (m_player) |
| 661 m_player->setEndTime(maxTime); | |
| 662 m_player->seek(time); | 630 m_player->seek(time); |
| 663 } | |
| 664 } | 631 } |
| 665 | 632 |
| 666 HTMLMediaElement::ReadyState HTMLMediaElement::readyState() const | 633 HTMLMediaElement::ReadyState HTMLMediaElement::readyState() const |
| 667 { | 634 { |
| 668 return m_readyState; | 635 return m_readyState; |
| 669 } | 636 } |
| 670 | 637 |
| 671 bool HTMLMediaElement::seeking() const | 638 bool HTMLMediaElement::seeking() const |
| 672 { | 639 { |
| 673 return m_seeking; | 640 return m_seeking; |
| (...skipping 87 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 761 { | 728 { |
| 762 // 3.14.9.7. Playing the media resource | 729 // 3.14.9.7. Playing the media resource |
| 763 if (!m_player || networkState() == EMPTY) { | 730 if (!m_player || networkState() == EMPTY) { |
| 764 ec = 0; | 731 ec = 0; |
| 765 load(ec); | 732 load(ec); |
| 766 if (ec) | 733 if (ec) |
| 767 return; | 734 return; |
| 768 } | 735 } |
| 769 ExceptionCode unused; | 736 ExceptionCode unused; |
| 770 if (endedPlayback()) { | 737 if (endedPlayback()) { |
| 771 m_currentLoop = 0; | 738 seek(0, unused); |
| 772 seek(effectiveStart(), unused); | |
| 773 } | 739 } |
| 774 setPlaybackRate(defaultPlaybackRate(), unused); | 740 setPlaybackRate(defaultPlaybackRate(), unused); |
| 775 | 741 |
| 776 if (m_paused) { | 742 if (m_paused) { |
| 777 m_paused = false; | 743 m_paused = false; |
| 778 dispatchEventAsync(eventNames().playEvent); | 744 dispatchEventAsync(eventNames().playEvent); |
| 779 } | 745 } |
| 780 | 746 |
| 781 m_autoplaying = false; | 747 m_autoplaying = false; |
| 782 | 748 |
| (...skipping 25 matching lines...) Expand all Loading... |
| 808 m_paused = true; | 774 m_paused = true; |
| 809 dispatchEventAsync(eventNames().timeupdateEvent); | 775 dispatchEventAsync(eventNames().timeupdateEvent); |
| 810 dispatchEventAsync(eventNames().pauseEvent); | 776 dispatchEventAsync(eventNames().pauseEvent); |
| 811 } | 777 } |
| 812 | 778 |
| 813 m_autoplaying = false; | 779 m_autoplaying = false; |
| 814 | 780 |
| 815 updatePlayState(); | 781 updatePlayState(); |
| 816 } | 782 } |
| 817 | 783 |
| 818 unsigned HTMLMediaElement::playCount() const | 784 bool HTMLMediaElement::loop() const |
| 819 { | 785 { |
| 820 bool ok; | 786 return hasAttribute(loopAttr); |
| 821 unsigned count = getAttribute(playcountAttr).string().toUInt(&ok); | |
| 822 return (count > 0 && ok) ? count : 1; | |
| 823 } | 787 } |
| 824 | 788 |
| 825 void HTMLMediaElement::setPlayCount(unsigned count, ExceptionCode& ec) | 789 void HTMLMediaElement::setLoop(bool b) |
| 826 { | 790 { |
| 827 if (!count) { | 791 setBooleanAttribute(loopAttr, b); |
| 828 ec = INDEX_SIZE_ERR; | |
| 829 return; | |
| 830 } | |
| 831 setAttribute(playcountAttr, String::number(count)); | |
| 832 checkIfSeekNeeded(); | |
| 833 } | |
| 834 | |
| 835 float HTMLMediaElement::start() const | |
| 836 { | |
| 837 return getTimeOffsetAttribute(startAttr, 0); | |
| 838 } | |
| 839 | |
| 840 void HTMLMediaElement::setStart(float time) | |
| 841 { | |
| 842 setTimeOffsetAttribute(startAttr, time); | |
| 843 checkIfSeekNeeded(); | |
| 844 } | |
| 845 | |
| 846 float HTMLMediaElement::end() const | |
| 847 { | |
| 848 return getTimeOffsetAttribute(endAttr, std::numeric_limits<float>::infinity(
)); | |
| 849 } | |
| 850 | |
| 851 void HTMLMediaElement::setEnd(float time) | |
| 852 { | |
| 853 setTimeOffsetAttribute(endAttr, time); | |
| 854 checkIfSeekNeeded(); | |
| 855 } | |
| 856 | |
| 857 float HTMLMediaElement::loopStart() const | |
| 858 { | |
| 859 return getTimeOffsetAttribute(loopstartAttr, start()); | |
| 860 } | |
| 861 | |
| 862 void HTMLMediaElement::setLoopStart(float time) | |
| 863 { | |
| 864 setTimeOffsetAttribute(loopstartAttr, time); | |
| 865 checkIfSeekNeeded(); | |
| 866 } | |
| 867 | |
| 868 float HTMLMediaElement::loopEnd() const | |
| 869 { | |
| 870 return getTimeOffsetAttribute(loopendAttr, end()); | |
| 871 } | |
| 872 | |
| 873 void HTMLMediaElement::setLoopEnd(float time) | |
| 874 { | |
| 875 setTimeOffsetAttribute(loopendAttr, time); | |
| 876 checkIfSeekNeeded(); | |
| 877 } | |
| 878 | |
| 879 unsigned HTMLMediaElement::currentLoop() const | |
| 880 { | |
| 881 return m_currentLoop; | |
| 882 } | |
| 883 | |
| 884 void HTMLMediaElement::setCurrentLoop(unsigned currentLoop) | |
| 885 { | |
| 886 m_currentLoop = currentLoop; | |
| 887 } | 792 } |
| 888 | 793 |
| 889 bool HTMLMediaElement::controls() const | 794 bool HTMLMediaElement::controls() const |
| 890 { | 795 { |
| 891 Frame* frame = document()->frame(); | 796 Frame* frame = document()->frame(); |
| 892 | 797 |
| 893 // always show controls when scripting is disabled | 798 // always show controls when scripting is disabled |
| 894 if (frame && !frame->script()->isEnabled()) | 799 if (frame && !frame->script()->isEnabled()) |
| 895 return true; | 800 return true; |
| 896 | 801 |
| (...skipping 104 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1001 mediaSrc = source->src().string(); | 906 mediaSrc = source->src().string(); |
| 1002 break; | 907 break; |
| 1003 } | 908 } |
| 1004 } | 909 } |
| 1005 } | 910 } |
| 1006 if (!mediaSrc.isEmpty()) | 911 if (!mediaSrc.isEmpty()) |
| 1007 mediaSrc = document()->completeURL(mediaSrc).string(); | 912 mediaSrc = document()->completeURL(mediaSrc).string(); |
| 1008 return mediaSrc; | 913 return mediaSrc; |
| 1009 } | 914 } |
| 1010 | 915 |
| 1011 void HTMLMediaElement::checkIfSeekNeeded() | |
| 1012 { | |
| 1013 // 3.14.9.5. Offsets into the media resource | |
| 1014 // 1 | |
| 1015 if (playCount() <= m_currentLoop) | |
| 1016 m_currentLoop = playCount() - 1; | |
| 1017 | |
| 1018 // 2 | |
| 1019 if (networkState() <= LOADING) | |
| 1020 return; | |
| 1021 | |
| 1022 // 3 | |
| 1023 ExceptionCode ec; | |
| 1024 float time = currentTime(); | |
| 1025 if (!m_currentLoop && time < effectiveStart()) | |
| 1026 seek(effectiveStart(), ec); | |
| 1027 | |
| 1028 // 4 | |
| 1029 if (m_currentLoop && time < effectiveLoopStart()) | |
| 1030 seek(effectiveLoopStart(), ec); | |
| 1031 | |
| 1032 // 5 | |
| 1033 if (m_currentLoop < playCount() - 1 && time > effectiveLoopEnd()) { | |
| 1034 seek(effectiveLoopStart(), ec); | |
| 1035 m_currentLoop++; | |
| 1036 } | |
| 1037 | |
| 1038 // 6 | |
| 1039 if (m_currentLoop == playCount() - 1 && time > effectiveEnd()) | |
| 1040 seek(effectiveEnd(), ec); | |
| 1041 | |
| 1042 updatePlayState(); | |
| 1043 } | |
| 1044 | |
| 1045 void HTMLMediaElement::mediaPlayerTimeChanged(MediaPlayer*) | 916 void HTMLMediaElement::mediaPlayerTimeChanged(MediaPlayer*) |
| 1046 { | 917 { |
| 1047 beginProcessingMediaPlayerCallback(); | 918 beginProcessingMediaPlayerCallback(); |
| 1048 | 919 |
| 1049 if (readyState() >= CAN_PLAY) | 920 if (readyState() >= CAN_PLAY) |
| 1050 m_seeking = false; | 921 m_seeking = false; |
| 1051 | 922 |
| 1052 float now = currentTime(); | 923 float now = currentTime(); |
| 1053 if (m_currentLoop < playCount() - 1 && now >= effectiveLoopEnd()) { | 924 if (now >= duration()) { |
| 1054 ExceptionCode ec; | 925 if (loop()) { |
| 1055 seek(effectiveLoopStart(), ec); | 926 ExceptionCode ec; |
| 1056 m_currentLoop++; | 927 seek(0, ec); |
| 1057 dispatchEventForType(eventNames().timeupdateEvent, false, true); | 928 dispatchEventForType(eventNames().timeupdateEvent, false, true); |
| 1058 } | 929 } else { |
| 1059 | 930 dispatchEventForType(eventNames().timeupdateEvent, false, true); |
| 1060 if (m_currentLoop == playCount() - 1 && now >= effectiveEnd()) { | 931 dispatchEventForType(eventNames().endedEvent, false, true); |
| 1061 dispatchEventForType(eventNames().timeupdateEvent, false, true); | 932 } |
| 1062 dispatchEventForType(eventNames().endedEvent, false, true); | |
| 1063 } | 933 } |
| 1064 | 934 |
| 1065 updatePlayState(); | 935 updatePlayState(); |
| 1066 | 936 |
| 1067 endProcessingMediaPlayerCallback(); | 937 endProcessingMediaPlayerCallback(); |
| 1068 } | 938 } |
| 1069 | 939 |
| 1070 void HTMLMediaElement::mediaPlayerRepaint(MediaPlayer*) | 940 void HTMLMediaElement::mediaPlayerRepaint(MediaPlayer*) |
| 1071 { | 941 { |
| 1072 beginProcessingMediaPlayerCallback(); | 942 beginProcessingMediaPlayerCallback(); |
| (...skipping 24 matching lines...) Expand all Loading... |
| 1097 } | 967 } |
| 1098 | 968 |
| 1099 PassRefPtr<TimeRanges> HTMLMediaElement::seekable() const | 969 PassRefPtr<TimeRanges> HTMLMediaElement::seekable() const |
| 1100 { | 970 { |
| 1101 // FIXME real ranges support | 971 // FIXME real ranges support |
| 1102 if (!m_player || !m_player->maxTimeSeekable()) | 972 if (!m_player || !m_player->maxTimeSeekable()) |
| 1103 return TimeRanges::create(); | 973 return TimeRanges::create(); |
| 1104 return TimeRanges::create(0, m_player->maxTimeSeekable()); | 974 return TimeRanges::create(0, m_player->maxTimeSeekable()); |
| 1105 } | 975 } |
| 1106 | 976 |
| 1107 float HTMLMediaElement::effectiveStart() const | |
| 1108 { | |
| 1109 if (!m_player) | |
| 1110 return 0; | |
| 1111 return min(start(), m_player->duration()); | |
| 1112 } | |
| 1113 | |
| 1114 float HTMLMediaElement::effectiveEnd() const | |
| 1115 { | |
| 1116 if (!m_player) | |
| 1117 return 0; | |
| 1118 return min(max(end(), max(start(), loopStart())), m_player->duration()); | |
| 1119 } | |
| 1120 | |
| 1121 float HTMLMediaElement::effectiveLoopStart() const | |
| 1122 { | |
| 1123 if (!m_player) | |
| 1124 return 0; | |
| 1125 return min(loopStart(), m_player->duration()); | |
| 1126 } | |
| 1127 | |
| 1128 float HTMLMediaElement::effectiveLoopEnd() const | |
| 1129 { | |
| 1130 if (!m_player) | |
| 1131 return 0; | |
| 1132 return min(max(start(), max(loopStart(), loopEnd())), m_player->duration()); | |
| 1133 } | |
| 1134 | |
| 1135 bool HTMLMediaElement::activelyPlaying() const | 977 bool HTMLMediaElement::activelyPlaying() const |
| 1136 { | 978 { |
| 1137 return !paused() && readyState() >= CAN_PLAY && !endedPlayback(); // && !sto
ppedDueToErrors() && !pausedForUserInteraction(); | 979 return !paused() && readyState() >= CAN_PLAY && !endedPlayback(); // && !sto
ppedDueToErrors() && !pausedForUserInteraction(); |
| 1138 } | 980 } |
| 1139 | 981 |
| 1140 bool HTMLMediaElement::endedPlayback() const | 982 bool HTMLMediaElement::endedPlayback() const |
| 1141 { | 983 { |
| 1142 return networkState() >= LOADED_METADATA && currentTime() >= effectiveEnd()
&& currentLoop() == playCount() - 1; | 984 return networkState() >= LOADED_METADATA && currentTime() >= duration() && !
loop(); |
| 1143 } | 985 } |
| 1144 | 986 |
| 1145 void HTMLMediaElement::updateVolume() | 987 void HTMLMediaElement::updateVolume() |
| 1146 { | 988 { |
| 1147 if (!m_player) | 989 if (!m_player) |
| 1148 return; | 990 return; |
| 1149 | 991 |
| 1150 // Avoid recursion when the player reports volume changes. | 992 // Avoid recursion when the player reports volume changes. |
| 1151 if (!processingMediaPlayerCallback()) { | 993 if (!processingMediaPlayerCallback()) { |
| 1152 Page* page = document()->page(); | 994 Page* page = document()->page(); |
| (...skipping 10 matching lines...) Expand all Loading... |
| 1163 { | 1005 { |
| 1164 if (!m_player) | 1006 if (!m_player) |
| 1165 return; | 1007 return; |
| 1166 | 1008 |
| 1167 if (m_pausedInternal) { | 1009 if (m_pausedInternal) { |
| 1168 if (!m_player->paused()) | 1010 if (!m_player->paused()) |
| 1169 m_player->pause(); | 1011 m_player->pause(); |
| 1170 return; | 1012 return; |
| 1171 } | 1013 } |
| 1172 | 1014 |
| 1173 m_player->setEndTime(currentLoop() == playCount() - 1 ? effectiveEnd() : eff
ectiveLoopEnd()); | 1015 bool shouldBePlaying = activelyPlaying(); |
| 1174 | |
| 1175 bool shouldBePlaying = activelyPlaying() && currentTime() < effectiveEnd(); | |
| 1176 if (shouldBePlaying && m_player->paused()) | 1016 if (shouldBePlaying && m_player->paused()) |
| 1177 m_player->play(); | 1017 m_player->play(); |
| 1178 else if (!shouldBePlaying && !m_player->paused()) | 1018 else if (!shouldBePlaying && !m_player->paused()) |
| 1179 m_player->pause(); | 1019 m_player->pause(); |
| 1180 | 1020 |
| 1181 if (renderer()) | 1021 if (renderer()) |
| 1182 renderer()->updateFromElement(); | 1022 renderer()->updateFromElement(); |
| 1183 } | 1023 } |
| 1184 | 1024 |
| 1185 void HTMLMediaElement::setPausedInternal(bool b) | 1025 void HTMLMediaElement::setPausedInternal(bool b) |
| (...skipping 112 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1298 | 1138 |
| 1299 document()->updateRendering(); | 1139 document()->updateRendering(); |
| 1300 if (m_needWidgetUpdate && renderer()) | 1140 if (m_needWidgetUpdate && renderer()) |
| 1301 static_cast<RenderPartObject*>(renderer())->updateWidget(true); | 1141 static_cast<RenderPartObject*>(renderer())->updateWidget(true); |
| 1302 } | 1142 } |
| 1303 #endif | 1143 #endif |
| 1304 | 1144 |
| 1305 } | 1145 } |
| 1306 | 1146 |
| 1307 #endif | 1147 #endif |
| OLD | NEW |