/* * Copyright (C) 2011, 2012 Apple Inc. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #include "config.h" #if ENABLE(VIDEO_TRACK) #include "TrackListBase.h" #include "EventNames.h" #include "HTMLMediaElement.h" #include "ScriptExecutionContext.h" #include "TrackEvent.h" using namespace WebCore; TrackListBase::TrackListBase(HTMLMediaElement* element, ScriptExecutionContext* context) : m_context(context) , m_element(element) , m_asyncEventQueue(*this) { ASSERT(context->isDocument()); } TrackListBase::~TrackListBase() { } Element* TrackListBase::element() const { return m_element; } unsigned TrackListBase::length() const { return m_inbandTracks.size(); } void TrackListBase::remove(TrackBase* track, bool scheduleEvent) { size_t index = m_inbandTracks.find(track); ASSERT(index != notFound); ASSERT(track->mediaElement() == m_element); track->setMediaElement(0); RefPtr<TrackBase> trackRef = m_inbandTracks[index]; m_inbandTracks.remove(index); if (scheduleEvent) scheduleRemoveTrackEvent(trackRef.release()); } bool TrackListBase::contains(TrackBase* track) const { return m_inbandTracks.find(track) != notFound; } void TrackListBase::scheduleTrackEvent(const AtomicString& eventName, PassRefPtr<TrackBase> track) { TrackEventInit initializer; initializer.track = track; initializer.bubbles = false; initializer.cancelable = false; m_asyncEventQueue.enqueueEvent(TrackEvent::create(eventName, initializer)); } void TrackListBase::scheduleAddTrackEvent(PassRefPtr<TrackBase> track) { // 4.8.10.5 Loading the media resource // ... // Fire a trusted event with the name addtrack, that does not bubble and is // not cancelable, and that uses the TrackEvent interface, with the track // attribute initialized to the new AudioTrack object, at this // AudioTrackList object. // ... // Fire a trusted event with the name addtrack, that does not bubble and is // not cancelable, and that uses the TrackEvent interface, with the track // attribute initialized to the new VideoTrack object, at this // VideoTrackList object. // 4.8.10.12.3 Sourcing out-of-band text tracks // 4.8.10.12.4 Text track API // ... then queue a task to fire an event with the name addtrack, that does not // bubble and is not cancelable, and that uses the TrackEvent interface, with // the track attribute initialized to the text track's TextTrack object, at // the media element's textTracks attribute's TextTrackList object. scheduleTrackEvent(eventNames().addtrackEvent, track); } void TrackListBase::scheduleRemoveTrackEvent(PassRefPtr<TrackBase> track) { // 4.8.10.6 Offsets into the media resource // If at any time the user agent learns that an audio or video track has // ended and all media data relating to that track corresponds to parts of // the media timeline that are before the earliest possible position, the // user agent may queue a task to remove the track from the audioTracks // attribute's AudioTrackList object or the videoTracks attribute's // VideoTrackList object as appropriate and then fire a trusted event // with the name removetrack, that does not bubble and is not cancelable, // and that uses the TrackEvent interface, with the track attribute // initialized to the AudioTrack or VideoTrack object representing the // track, at the media element's aforementioned AudioTrackList or // VideoTrackList object. // 4.8.10.12.3 Sourcing out-of-band text tracks // When a track element's parent element changes and the old parent was a // media element, then the user agent must remove the track element's // corresponding text track from the media element's list of text tracks, // and then queue a task to fire a trusted event with the name removetrack, // that does not bubble and is not cancelable, and that uses the TrackEvent // interface, with the track attribute initialized to the text track's // TextTrack object, at the media element's textTracks attribute's // TextTrackList object. scheduleTrackEvent(eventNames().removetrackEvent, track); } void TrackListBase::scheduleChangeEvent() { // 4.8.10.6 Offsets into the media resource // Whenever an audio track in an AudioTrackList is enabled or disabled, the // user agent must queue a task to fire a simple event named change at the // AudioTrackList object. // ... // Whenever a track in a VideoTrackList that was previously not selected is // selected, the user agent must queue a task to fire a simple event named // change at the VideoTrackList object. EventInit initializer; initializer.bubbles = false; initializer.cancelable = false; m_asyncEventQueue.enqueueEvent(Event::create(eventNames().changeEvent, initializer)); } bool TrackListBase::isAnyTrackEnabled() const { for (size_t i = 0; i < m_inbandTracks.size(); ++i) { TrackBase* track = m_inbandTracks[i].get(); if (track->enabled()) return true; } return false; } #endif