Not all subtitle tracks are SDH
[WebKit-https.git] / Source / WebCore / html / track / InbandTextTrack.cpp
1 /*
2  * Copyright (C) 2012 Apple Inc.  All rights reserved.
3  *
4  * Redistribution and use in source and binary forms, with or without
5  * modification, are permitted provided that the following conditions
6  * are met:
7  * 1. Redistributions of source code must retain the above copyright
8  *    notice, this list of conditions and the following disclaimer.
9  * 2. Redistributions in binary form must reproduce the above copyright
10  *    notice, this list of conditions and the following disclaimer in the
11  *    documentation and/or other materials provided with the distribution.
12  *
13  * THIS SOFTWARE IS PROVIDED BY APPLE COMPUTER, INC. ``AS IS'' AND ANY
14  * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
15  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
16  * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL APPLE COMPUTER, INC. OR
17  * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
18  * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
19  * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
20  * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
21  * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
22  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
23  * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
24  */
25
26 #include "config.h"
27
28 #if ENABLE(VIDEO_TRACK)
29
30 #include "InbandTextTrack.h"
31
32 #include "Document.h"
33 #include "Event.h"
34 #include "ExceptionCodePlaceholder.h"
35 #include "HTMLMediaElement.h"
36 #include "InbandTextTrackPrivate.h"
37 #include "Logging.h"
38 #include "TextTrackCueGeneric.h"
39 #include "TextTrackCueList.h"
40 #include <math.h>
41
42 namespace WebCore {
43
44 void TextTrackCueMap::add(GenericCueData* cueData, TextTrackCueGeneric* cue)
45 {
46     m_dataToCueMap.add(cueData, cue);
47     m_cueToDataMap.add(cue, cueData);
48 }
49
50 PassRefPtr<TextTrackCueGeneric> TextTrackCueMap::find(GenericCueData* cueData)
51 {
52     GenericCueDataToCueMap::iterator iter = m_dataToCueMap.find(cueData);
53     if (iter == m_dataToCueMap.end())
54         return 0;
55     
56     return iter->value;
57 }
58
59 PassRefPtr<GenericCueData> TextTrackCueMap::find(TextTrackCueGeneric* cue)
60 {
61     GenericCueToCueDataMap::iterator iter = m_cueToDataMap.find(cue);
62     if (iter == m_cueToDataMap.end())
63         return 0;
64     
65     return iter->value;
66 }
67
68 void TextTrackCueMap::remove(GenericCueData* cueData)
69 {
70     RefPtr<TextTrackCueGeneric> cue = find(cueData);
71
72     if (cue)
73         m_cueToDataMap.remove(cue);
74     m_dataToCueMap.remove(cueData);
75 }
76
77 void TextTrackCueMap::remove(TextTrackCueGeneric* cue)
78 {
79     RefPtr<GenericCueData> cueData = find(cue);
80
81     if (cueData)
82         m_dataToCueMap.remove(cueData);
83     m_cueToDataMap.remove(cue);
84 }
85
86
87 PassRefPtr<InbandTextTrack> InbandTextTrack::create(ScriptExecutionContext* context, TextTrackClient* client, PassRefPtr<InbandTextTrackPrivate> playerPrivate)
88 {
89     return adoptRef(new InbandTextTrack(context, client, playerPrivate));
90 }
91
92 InbandTextTrack::InbandTextTrack(ScriptExecutionContext* context, TextTrackClient* client, PassRefPtr<InbandTextTrackPrivate> tracksPrivate)
93     : TextTrack(context, client, emptyString(), tracksPrivate->label(), tracksPrivate->language(), InBand)
94     , m_private(tracksPrivate)
95 {
96     m_private->setClient(this);
97     
98     switch (m_private->kind()) {
99     case InbandTextTrackPrivate::Subtitles:
100         setKind(TextTrack::subtitlesKeyword());
101         break;
102     case InbandTextTrackPrivate::Captions:
103         setKind(TextTrack::captionsKeyword());
104         break;
105     case InbandTextTrackPrivate::Descriptions:
106         setKind(TextTrack::descriptionsKeyword());
107         break;
108     case InbandTextTrackPrivate::Chapters:
109         setKind(TextTrack::chaptersKeyword());
110         break;
111     case InbandTextTrackPrivate::Metadata:
112         setKind(TextTrack::metadataKeyword());
113         break;
114     case InbandTextTrackPrivate::Forced:
115         setKind(TextTrack::forcedKeyword());
116         break;
117     case InbandTextTrackPrivate::None:
118     default:
119         ASSERT_NOT_REACHED();
120         break;
121     }
122 }
123
124 InbandTextTrack::~InbandTextTrack()
125 {
126     m_private->setClient(0);
127 }
128
129 void InbandTextTrack::setMode(const AtomicString& mode)
130 {
131     TextTrack::setMode(mode);
132
133     if (mode == TextTrack::disabledKeyword())
134         m_private->setMode(InbandTextTrackPrivate::Disabled);
135     else if (mode == TextTrack::hiddenKeyword())
136         m_private->setMode(InbandTextTrackPrivate::Hidden);
137     else if (mode == TextTrack::showingKeyword())
138         m_private->setMode(InbandTextTrackPrivate::Showing);
139     else
140         ASSERT_NOT_REACHED();
141 }
142
143 bool InbandTextTrack::isClosedCaptions() const
144 {
145     if (!m_private)
146         return false;
147
148     return m_private->isClosedCaptions();
149 }
150
151 bool InbandTextTrack::isSDH() const
152 {
153     if (!m_private)
154         return false;
155     
156     return m_private->isSDH();
157 }
158
159 bool InbandTextTrack::containsOnlyForcedSubtitles() const
160 {
161     if (!m_private)
162         return false;
163     
164     return m_private->containsOnlyForcedSubtitles();
165 }
166
167 bool InbandTextTrack::isMainProgramContent() const
168 {
169     if (!m_private)
170         return false;
171     
172     return m_private->isMainProgramContent();
173 }
174
175 bool InbandTextTrack::isEasyToRead() const
176 {
177     if (!m_private)
178         return false;
179     
180     return m_private->isEasyToRead();
181 }
182     
183 size_t InbandTextTrack::inbandTrackIndex()
184 {
185     ASSERT(m_private);
186     return m_private->textTrackIndex();
187 }
188
189 void InbandTextTrack::updateCueFromCueData(TextTrackCueGeneric* cue, GenericCueData* cueData)
190 {
191     cue->willChange();
192
193     cue->setStartTime(cueData->startTime(), IGNORE_EXCEPTION);
194     double endTime = cueData->endTime();
195     if (std::isinf(endTime) && mediaElement())
196         endTime = mediaElement()->duration();
197     cue->setEndTime(endTime, IGNORE_EXCEPTION);
198     cue->setText(cueData->content());
199     cue->setId(cueData->id());
200     cue->setBaseFontSizeRelativeToVideoHeight(cueData->baseFontSize());
201     cue->setFontSizeMultiplier(cueData->relativeFontSize());
202     cue->setFontName(cueData->fontName());
203
204     if (cueData->position() > 0)
205         cue->setPosition(lround(cueData->position()), IGNORE_EXCEPTION);
206     if (cueData->line() > 0)
207         cue->setLine(lround(cueData->line()), IGNORE_EXCEPTION);
208     if (cueData->size() > 0)
209         cue->setSize(lround(cueData->size()), IGNORE_EXCEPTION);
210     if (cueData->backgroundColor().isValid())
211         cue->setBackgroundColor(cueData->backgroundColor().rgb());
212     if (cueData->foregroundColor().isValid())
213         cue->setForegroundColor(cueData->foregroundColor().rgb());
214     if (cueData->highlightColor().isValid())
215         cue->setHighlightColor(cueData->highlightColor().rgb());
216
217     if (cueData->align() == GenericCueData::Start)
218         cue->setAlign(ASCIILiteral("start"), IGNORE_EXCEPTION);
219     else if (cueData->align() == GenericCueData::Middle)
220         cue->setAlign(ASCIILiteral("middle"), IGNORE_EXCEPTION);
221     else if (cueData->align() == GenericCueData::End)
222         cue->setAlign(ASCIILiteral("end"), IGNORE_EXCEPTION);
223     cue->setSnapToLines(false);
224
225     cue->didChange();
226 }
227     
228 void InbandTextTrack::addGenericCue(InbandTextTrackPrivate* trackPrivate, PassRefPtr<GenericCueData> prpCueData)
229 {
230     UNUSED_PARAM(trackPrivate);
231     ASSERT(trackPrivate == m_private);
232
233     RefPtr<GenericCueData> cueData = prpCueData;
234     if (m_cueMap.find(cueData.get()))
235         return;
236
237     RefPtr<TextTrackCueGeneric> cue = TextTrackCueGeneric::create(scriptExecutionContext(), cueData->startTime(), cueData->endTime(), cueData->content());
238     updateCueFromCueData(cue.get(), cueData.get());
239     if (hasCue(cue.get(), TextTrackCue::IgnoreDuration)) {
240         LOG(Media, "InbandTextTrack::addGenericCue ignoring already added cue: start=%.2f, end=%.2f, content=\"%s\"\n", cueData->startTime(), cueData->endTime(), cueData->content().utf8().data());
241         return;
242     }
243
244     if (cueData->status() != GenericCueData::Complete)
245         m_cueMap.add(cueData.get(), cue.get());
246
247     addCue(cue);
248 }
249
250 void InbandTextTrack::updateGenericCue(InbandTextTrackPrivate*, GenericCueData* cueData)
251 {
252     RefPtr<TextTrackCueGeneric> cue = m_cueMap.find(cueData);
253     if (!cue)
254         return;
255
256     updateCueFromCueData(cue.get(), cueData);
257     
258     if (cueData->status() == GenericCueData::Complete)
259         m_cueMap.remove(cueData);
260 }
261
262 void InbandTextTrack::removeGenericCue(InbandTextTrackPrivate*, GenericCueData* cueData)
263 {
264     RefPtr<TextTrackCueGeneric> cue = m_cueMap.find(cueData);
265     if (cue) {
266         LOG(Media, "InbandTextTrack::removeGenericCue removing cue: start=%.2f, end=%.2f, content=\"%s\"\n", cueData->startTime(), cueData->endTime(), cueData->content().utf8().data());
267         removeCue(cue.get(), IGNORE_EXCEPTION);
268     } else
269         m_cueMap.remove(cueData);
270 }
271
272 void InbandTextTrack::removeCue(TextTrackCue* cue, ExceptionCode& ec)
273 {
274     m_cueMap.remove(static_cast<TextTrackCueGeneric*>(cue));
275     TextTrack::removeCue(cue, ec);
276 }
277
278 void InbandTextTrack::willRemoveTextTrackPrivate(InbandTextTrackPrivate* trackPrivate)
279 {
280     UNUSED_PARAM(trackPrivate);
281     ASSERT(trackPrivate == m_private);
282     mediaElement()->removeTextTrack(this);
283 }
284
285 } // namespace WebCore
286
287 #endif