示例#1
0
void MediaControls::disableShowingTextTracks() {
  TextTrackList* trackList = mediaElement().textTracks();
  for (unsigned i = 0; i < trackList->length(); ++i) {
    TextTrack* track = trackList->anonymousIndexedGetter(i);
    if (track->mode() == TextTrack::showingKeyword())
      track->setMode(TextTrack::disabledKeyword());
  }
}
示例#2
0
void MediaControls::showTextTrackAtIndex(unsigned indexToEnable) {
  TextTrackList* trackList = mediaElement().textTracks();
  if (indexToEnable >= trackList->length())
    return;
  TextTrack* track = trackList->anonymousIndexedGetter(indexToEnable);
  if (track && track->canBeRendered())
    track->setMode(TextTrack::showingKeyword());
}
void MediaControlClosedCaptionsTrackListElement::updateDisplay()
{
#if ENABLE(VIDEO_TRACK)
    DEFINE_STATIC_LOCAL(AtomicString, selectedClassValue, ("selected", AtomicString::ConstructFromLiteral));

    if (!mediaController()->hasClosedCaptions())
        return;

    if (!document()->page())
        return;
    CaptionUserPreferences::CaptionDisplayMode displayMode = document()->page()->group().captionPreferences()->captionDisplayMode();
    bool trackIsSelected = displayMode != CaptionUserPreferences::Automatic && displayMode != CaptionUserPreferences::ForcedOnly;

    HTMLMediaElement* mediaElement = toParentMediaElement(this);
    if (!mediaElement)
        return;

    TextTrackList* trackList = mediaElement->textTracks();
    if (!trackList || !trackList->length())
        return;

    rebuildTrackListMenu();

    for (unsigned i = 0, length = m_menuItems.size(); i < length; ++i) {
        RefPtr<Element> trackItem = m_menuItems[i];

        RefPtr<TextTrack> textTrack;
        MenuItemToTrackMap::iterator iter = m_menuToTrackMap.find(trackItem.get());
        if (iter == m_menuToTrackMap.end())
            continue;
        textTrack = iter->value;
        if (!textTrack)
            continue;

        if (textTrack == TextTrack::captionMenuOffItem()) {
            if (displayMode == CaptionUserPreferences::ForcedOnly)
                trackItem->classList()->add(selectedClassValue, ASSERT_NO_EXCEPTION);
            else
                trackItem->classList()->remove(selectedClassValue, ASSERT_NO_EXCEPTION);
            continue;
        }

        if (textTrack == TextTrack::captionMenuAutomaticItem()) {
            if (displayMode == CaptionUserPreferences::Automatic)
                trackItem->classList()->add(selectedClassValue, ASSERT_NO_EXCEPTION);
            else
                trackItem->classList()->remove(selectedClassValue, ASSERT_NO_EXCEPTION);
            continue;
        }

        if (trackIsSelected && textTrack->mode() == TextTrack::showingKeyword())
            trackItem->classList()->add(selectedClassValue, ASSERT_NO_EXCEPTION);
        else
            trackItem->classList()->remove(selectedClassValue, ASSERT_NO_EXCEPTION);
    }
#endif
}
void AutomaticTrackSelection::perform(TextTrackList& textTracks)
{
    TrackGroup captionAndSubtitleTracks(TrackGroup::CaptionsAndSubtitles);
    TrackGroup descriptionTracks(TrackGroup::Description);
    TrackGroup chapterTracks(TrackGroup::Chapter);
    TrackGroup metadataTracks(TrackGroup::Metadata);

    for (size_t i = 0; i < textTracks.length(); ++i) {
        TextTrack* textTrack = textTracks.item(i);
        if (!textTrack)
            continue;

        String kind = textTrack->kind();
        TrackGroup* currentGroup;
        if (kind == TextTrack::subtitlesKeyword() || kind == TextTrack::captionsKeyword()) {
            currentGroup = &captionAndSubtitleTracks;
        } else if (kind == TextTrack::descriptionsKeyword()) {
            currentGroup = &descriptionTracks;
        } else if (kind == TextTrack::chaptersKeyword()) {
            currentGroup = &chapterTracks;
        } else {
            ASSERT(kind == TextTrack::metadataKeyword());
            currentGroup = &metadataTracks;
        }

        if (!currentGroup->visibleTrack && textTrack->mode() == TextTrack::showingKeyword())
            currentGroup->visibleTrack = textTrack;
        if (!currentGroup->defaultTrack && textTrack->isDefault())
            currentGroup->defaultTrack = textTrack;

        // Do not add this track to the group if it has already been automatically configured
        // as we only want to perform selection once per track so that adding another track
        // after the initial configuration doesn't reconfigure every track - only those that
        // should be changed by the new addition. For example all metadata tracks are
        // disabled by default, and we don't want a track that has been enabled by script
        // to be disabled automatically when a new metadata track is added later.
        if (textTrack->hasBeenConfigured())
            continue;

        if (textTrack->language().length())
            currentGroup->hasSrcLang = true;
        currentGroup->tracks.append(textTrack);
    }

    if (captionAndSubtitleTracks.tracks.size())
        performAutomaticTextTrackSelection(captionAndSubtitleTracks);
    if (descriptionTracks.tracks.size())
        performAutomaticTextTrackSelection(descriptionTracks);
    if (chapterTracks.tracks.size())
        performAutomaticTextTrackSelection(chapterTracks);
    if (metadataTracks.tracks.size())
        enableDefaultMetadataTextTracks(metadataTracks);
}
void JSTextTrackList::visitChildren(JSCell* cell, SlotVisitor& visitor)
{
    JSTextTrackList* jsTextTrackList = jsCast<JSTextTrackList*>(cell);
    ASSERT_GC_OBJECT_INHERITS(jsTextTrackList, info());
    COMPILE_ASSERT(StructureFlags & OverridesVisitChildren, OverridesVisitChildrenWithoutSettingFlag);
    ASSERT(jsTextTrackList->structure()->typeInfo().overridesVisitChildren());
    Base::visitChildren(jsTextTrackList, visitor);
    
    TextTrackList* textTrackList = static_cast<TextTrackList*>(jsTextTrackList->impl());
    visitor.addOpaqueRoot(root(textTrackList->element()));
    textTrackList->visitJSEventListeners(visitor);
}
示例#6
0
void MediaControlClosedCaptionsTrackListElement::updateDisplay()
{
#if ENABLE(VIDEO_TRACK)
    DEFINE_STATIC_LOCAL(AtomicString, selectedClassValue, ("selected", AtomicString::ConstructFromLiteral));

    if (!mediaController()->hasClosedCaptions())
        return;

    HTMLMediaElement* mediaElement = toParentMediaElement(this);
    if (!mediaElement)
        return;

    TextTrackList* trackList = mediaElement->textTracks();

    if (!trackList || !trackList->length())
        return;

    if (m_trackListHasChanged)
        rebuildTrackListMenu();

    bool captionsVisible = mediaElement->closedCaptionsVisible();
    for (unsigned i = 0, length = m_menuItems.size(); i < length; ++i) {
        RefPtr<Element> trackItem = m_menuItems[i];
        int trackIndex = trackListIndexForElement(trackItem.get());
        if (trackIndex != HTMLMediaElement::textTracksIndexNotFound()) {
            if (trackIndex == HTMLMediaElement::textTracksOffIndex()) {
                if (captionsVisible)
                    trackItem->classList()->remove(selectedClassValue, ASSERT_NO_EXCEPTION);
                else
                    trackItem->classList()->add(selectedClassValue, ASSERT_NO_EXCEPTION);
            } else {
                TextTrack* track = trackList->item(trackIndex);
                if (!track)
                    continue;
                if (track->mode() == TextTrack::showingKeyword())
                    trackItem->classList()->add(selectedClassValue, ASSERT_NO_EXCEPTION);
                else
                    trackItem->classList()->remove(selectedClassValue, ASSERT_NO_EXCEPTION);
            }
        }
    }
#endif
}
void MediaControlClosedCaptionsTrackListElement::rebuildTrackListMenu()
{
#if ENABLE(VIDEO_TRACK)
    // Remove any existing content.
    removeChildren();
    m_menuItems.clear();
    m_menuToTrackMap.clear();

    if (!mediaController()->hasClosedCaptions())
        return;

    HTMLMediaElement* mediaElement = toParentMediaElement(this);
    if (!mediaElement)
        return;

    TextTrackList* trackList = mediaElement->textTracks();
    if (!trackList || !trackList->length())
        return;

    Document* doc = document();
    if (!document()->page())
        return;
    CaptionUserPreferences* captionPreferences = document()->page()->group().captionPreferences();
    Vector<RefPtr<TextTrack> > tracksForMenu = captionPreferences->sortedTrackListForMenu(trackList);

    RefPtr<Element> captionsHeader = doc->createElement(h3Tag, ASSERT_NO_EXCEPTION);
    captionsHeader->appendChild(doc->createTextNode(textTrackSubtitlesText()));
    appendChild(captionsHeader);
    RefPtr<Element> captionsMenuList = doc->createElement(ulTag, ASSERT_NO_EXCEPTION);

    for (unsigned i = 0, length = tracksForMenu.size(); i < length; ++i) {
        RefPtr<TextTrack> textTrack = tracksForMenu[i];
        RefPtr<Element> menuItem = doc->createElement(liTag, ASSERT_NO_EXCEPTION);
        menuItem->appendChild(doc->createTextNode(captionPreferences->displayNameForTrack(textTrack.get())));
        captionsMenuList->appendChild(menuItem);
        m_menuItems.append(menuItem);
        m_menuToTrackMap.add(menuItem, textTrack);
    }

    appendChild(captionsMenuList);
#endif
}
void MediaControlTextTrackListElement::refreshTextTrackListMenu()
{
    if (!mediaElement().hasClosedCaptions() || !mediaElement().textTracksAreReady())
        return;

    EventDispatchForbiddenScope::AllowUserAgentEvents allowEvents;
    removeChildren(OmitSubtreeModifiedEvent);

    // Construct a menu for subtitles and captions
    // Pass in a nullptr to createTextTrackListItem to create the "Off" track item.
    appendChild(createTextTrackListItem(nullptr));

    TextTrackList* trackList = mediaElement().textTracks();
    for (unsigned i = 0; i < trackList->length(); i++) {
        TextTrack* track = trackList->anonymousIndexedGetter(i);
        if (!track->canBeRendered())
            continue;
        appendChild(createTextTrackListItem(track));
    }
}
示例#9
0
void MediaControlClosedCaptionsTrackListElement::rebuildTrackListMenu()
{
#if ENABLE(VIDEO_TRACK)
    // Remove any existing content.
    removeChildren();
    m_menuItems.clear();

    m_trackListHasChanged = false;

    if (!mediaController()->hasClosedCaptions())
        return;

    HTMLMediaElement* mediaElement = toParentMediaElement(this);
    if (!mediaElement)
        return;

    TextTrackList* trackList = mediaElement->textTracks();

    if (!trackList || !trackList->length())
        return;

    Document* doc = document();

    RefPtr<Element> captionsSection = doc->createElement(sectionTag, ASSERT_NO_EXCEPTION);
    RefPtr<Element> captionsHeader = doc->createElement(h3Tag, ASSERT_NO_EXCEPTION);
    captionsHeader->appendChild(doc->createTextNode(textTrackClosedCaptionsText()));
    captionsSection->appendChild(captionsHeader);
    RefPtr<Element> captionsMenuList = doc->createElement(ulTag, ASSERT_NO_EXCEPTION);

    RefPtr<Element> subtitlesSection = doc->createElement(sectionTag, ASSERT_NO_EXCEPTION);
    RefPtr<Element> subtitlesHeader = doc->createElement(h3Tag, ASSERT_NO_EXCEPTION);
    subtitlesHeader->appendChild(doc->createTextNode(textTrackSubtitlesText()));
    subtitlesSection->appendChild(subtitlesHeader);
    RefPtr<Element> subtitlesMenuList = doc->createElement(ulTag, ASSERT_NO_EXCEPTION);

    RefPtr<Element> trackItem;

    trackItem = doc->createElement(liTag, ASSERT_NO_EXCEPTION);
    trackItem->appendChild(doc->createTextNode(textTrackOffText()));
    trackItem->setAttribute(trackIndexAttributeName(), textTracksOffAttrValue, ASSERT_NO_EXCEPTION);
    captionsMenuList->appendChild(trackItem);
    m_menuItems.append(trackItem);

    trackItem = doc->createElement(liTag, ASSERT_NO_EXCEPTION);
    trackItem->appendChild(doc->createTextNode(textTrackOffText()));
    trackItem->setAttribute(trackIndexAttributeName(), textTracksOffAttrValue, ASSERT_NO_EXCEPTION);
    subtitlesMenuList->appendChild(trackItem);
    m_menuItems.append(trackItem);

    bool hasCaptions = false;
    bool hasSubtitles = false;

    for (unsigned i = 0, length = trackList->length(); i < length; ++i) {
        TextTrack* track = trackList->item(i);
        trackItem = doc->createElement(liTag, ASSERT_NO_EXCEPTION);

        // Add a custom attribute to the <li> element which will allow
        // us to easily associate the user tapping here with the
        // track. Since this list is rebuilt if the tracks change, we
        // should always be in sync.
        trackItem->setAttribute(trackIndexAttributeName(), String::number(i), ASSERT_NO_EXCEPTION);

        AtomicString labelText = track->label();
        if (labelText.isNull() || labelText.isEmpty())
            labelText = displayNameForLanguageLocale(track->language());
        if (labelText.isNull() || labelText.isEmpty())
            labelText = textTrackNoLabelText();
        trackItem->appendChild(doc->createTextNode(labelText));

        if (track->kind() == track->captionsKeyword()) {
            hasCaptions = true;
            insertTextTrackMenuItemIntoSortedContainer(trackItem, captionsMenuList);
        }
        if (track->kind() == track->subtitlesKeyword()) {
            hasSubtitles = true;
            insertTextTrackMenuItemIntoSortedContainer(trackItem, subtitlesMenuList);
        }
        m_menuItems.append(trackItem);
    }

    captionsSection->appendChild(captionsMenuList);
    subtitlesSection->appendChild(subtitlesMenuList);

    if (hasCaptions)
        appendChild(captionsSection);
    if (hasSubtitles)
        appendChild(subtitlesSection);

    updateDisplay();
#endif
}
示例#10
0
  bool LessThan(SimpleTextTrackEvent* aOne, SimpleTextTrackEvent* aTwo) const {
    // TimeMarchesOn step 13.1.
    if (aOne->mTime < aTwo->mTime) {
      return true;
    } else if (aOne->mTime > aTwo->mTime) {
      return false;
    }

    // TimeMarchesOn step 13.2 text track cue order.
    // TextTrack position in TextTrackList
    TextTrack* t1 = aOne->mTrack;
    TextTrack* t2 = aTwo->mTrack;
    MOZ_ASSERT(t1, "CompareSimpleTextTrackEvents t1 is null");
    MOZ_ASSERT(t2, "CompareSimpleTextTrackEvents t2 is null");
    if (t1 != t2) {
      TextTrackList* tList = t1->GetTextTrackList();
      MOZ_ASSERT(tList, "CompareSimpleTextTrackEvents tList is null");
      nsTArray<RefPtr<TextTrack>>& textTracks = tList->GetTextTrackArray();
      auto index1 = textTracks.IndexOf(t1);
      auto index2 = textTracks.IndexOf(t2);
      if (index1 < index2) {
        return true;
      } else if (index1 > index2) {
        return false;
      }
    }

    MOZ_ASSERT(t1 == t2, "CompareSimpleTextTrackEvents t1 != t2");
    // c1 and c2 are both belongs to t1.
    TextTrackCue* c1 = aOne->mCue;
    TextTrackCue* c2 = aTwo->mCue;
    if (c1 != c2) {
      if (c1->StartTime() < c2->StartTime()) {
        return true;
      } else if (c1->StartTime() > c2->StartTime()) {
        return false;
      }
      if (c1->EndTime() < c2->EndTime()) {
        return true;
      } else if (c1->EndTime() > c2->EndTime()) {
        return false;
      }

      TextTrackCueList* cueList = t1->GetCues();
      MOZ_ASSERT(cueList);
      nsTArray<RefPtr<TextTrackCue>>& cues = cueList->GetCuesArray();
      auto index1 = cues.IndexOf(c1);
      auto index2 = cues.IndexOf(c2);
      if (index1 < index2) {
        return true;
      } else if (index1 > index2) {
        return false;
      }
    }

    // TimeMarchesOn step 13.3.
    if (aOne->mName.EqualsLiteral("enter") ||
        aTwo->mName.EqualsLiteral("exit")) {
      return true;
    }
    return false;
  }