1/*
2 * Copyright (C) 2012, 2013 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 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 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#import "config.h"
27
28#if ENABLE(VIDEO) && USE(AVFOUNDATION) && HAVE(AVFOUNDATION_MEDIA_SELECTION_GROUP)
29
30#import "InbandTextTrackPrivateAVFObjC.h"
31
32#import "BlockExceptions.h"
33#import "FloatConversion.h"
34#import "InbandTextTrackPrivate.h"
35#import "InbandTextTrackPrivateAVF.h"
36#import "Logging.h"
37#import "SoftLinking.h"
38#import <AVFoundation/AVFoundation.h>
39#import <objc/runtime.h>
40
41SOFT_LINK_FRAMEWORK_OPTIONAL(AVFoundation)
42
43#define AVPlayer getAVPlayerClass()
44#define AVPlayerItem getAVPlayerItemClass()
45
46SOFT_LINK_CLASS(AVFoundation, AVPlayer)
47SOFT_LINK_CLASS(AVFoundation, AVPlayerItem)
48SOFT_LINK_CLASS(AVFoundation, AVMetadataItem)
49SOFT_LINK_CLASS(AVFoundation, AVPlayerItemLegibleOutput)
50#define AVMediaCharacteristicVisual getAVMediaCharacteristicVisual()
51#define AVMediaCharacteristicAudible getAVMediaCharacteristicAudible()
52#define AVMediaTypeClosedCaption getAVMediaTypeClosedCaption()
53#define AVMediaCharacteristicContainsOnlyForcedSubtitles getAVMediaCharacteristicContainsOnlyForcedSubtitles()
54#define AVMediaCharacteristicIsMainProgramContent getAVMediaCharacteristicIsMainProgramContent()
55#define AVMediaCharacteristicEasyToRead getAVMediaCharacteristicEasyToRead()
56
57SOFT_LINK_POINTER(AVFoundation, AVMediaTypeClosedCaption, NSString *)
58SOFT_LINK_POINTER(AVFoundation, AVMediaCharacteristicLegible, NSString *)
59SOFT_LINK_POINTER(AVFoundation, AVMetadataCommonKeyTitle, NSString *)
60SOFT_LINK_POINTER(AVFoundation, AVMetadataKeySpaceCommon, NSString *)
61SOFT_LINK_POINTER(AVFoundation, AVMediaTypeSubtitle, NSString *)
62SOFT_LINK_POINTER(AVFoundation, AVMediaCharacteristicTranscribesSpokenDialogForAccessibility, NSString *)
63SOFT_LINK_POINTER(AVFoundation, AVMediaCharacteristicDescribesMusicAndSoundForAccessibility, NSString *)
64SOFT_LINK_POINTER(AVFoundation, AVMediaCharacteristicContainsOnlyForcedSubtitles, NSString *)
65SOFT_LINK_POINTER(AVFoundation, AVMediaCharacteristicIsMainProgramContent, NSString *)
66SOFT_LINK_POINTER(AVFoundation, AVMediaCharacteristicEasyToRead, NSString *)
67
68#define AVMetadataItem getAVMetadataItemClass()
69#define AVPlayerItemLegibleOutput getAVPlayerItemLegibleOutputClass()
70#define AVMediaCharacteristicLegible getAVMediaCharacteristicLegible()
71#define AVMetadataCommonKeyTitle getAVMetadataCommonKeyTitle()
72#define AVMetadataKeySpaceCommon getAVMetadataKeySpaceCommon()
73#define AVMediaTypeSubtitle getAVMediaTypeSubtitle()
74#define AVMediaCharacteristicTranscribesSpokenDialogForAccessibility getAVMediaCharacteristicTranscribesSpokenDialogForAccessibility()
75#define AVMediaCharacteristicDescribesMusicAndSoundForAccessibility getAVMediaCharacteristicDescribesMusicAndSoundForAccessibility()
76
77namespace WebCore {
78
79InbandTextTrackPrivateAVFObjC::InbandTextTrackPrivateAVFObjC(AVFInbandTrackParent* player, AVMediaSelectionOption *selection, InbandTextTrackPrivate::CueFormat format)
80    : InbandTextTrackPrivateAVF(player, format)
81    , m_mediaSelectionOption(selection)
82{
83}
84
85void InbandTextTrackPrivateAVFObjC::disconnect()
86{
87    m_mediaSelectionOption = 0;
88    InbandTextTrackPrivateAVF::disconnect();
89}
90
91InbandTextTrackPrivate::Kind InbandTextTrackPrivateAVFObjC::kind() const
92{
93    if (!m_mediaSelectionOption)
94        return InbandTextTrackPrivate::None;
95
96    NSString *mediaType = [m_mediaSelectionOption mediaType];
97
98    if ([mediaType isEqualToString:AVMediaTypeClosedCaption])
99        return InbandTextTrackPrivate::Captions;
100    if ([mediaType isEqualToString:AVMediaTypeSubtitle]) {
101
102        if ([m_mediaSelectionOption hasMediaCharacteristic:AVMediaCharacteristicContainsOnlyForcedSubtitles])
103            return InbandTextTrackPrivate::Forced;
104
105        // An "SDH" track is a subtitle track created for the deaf or hard-of-hearing. "captions" in WebVTT are
106        // "labeled as appropriate for the hard-of-hearing", so tag SDH sutitles as "captions".
107        if ([m_mediaSelectionOption hasMediaCharacteristic:AVMediaCharacteristicTranscribesSpokenDialogForAccessibility])
108            return InbandTextTrackPrivate::Captions;
109        if ([m_mediaSelectionOption hasMediaCharacteristic:AVMediaCharacteristicDescribesMusicAndSoundForAccessibility])
110            return InbandTextTrackPrivate::Captions;
111
112        return InbandTextTrackPrivate::Subtitles;
113    }
114
115    return InbandTextTrackPrivate::Captions;
116}
117
118bool InbandTextTrackPrivateAVFObjC::isClosedCaptions() const
119{
120    if (!m_mediaSelectionOption)
121        return false;
122
123    return [[m_mediaSelectionOption mediaType] isEqualToString:AVMediaTypeClosedCaption];
124}
125
126bool InbandTextTrackPrivateAVFObjC::isSDH() const
127{
128    if (!m_mediaSelectionOption)
129        return false;
130
131    if (![[m_mediaSelectionOption mediaType] isEqualToString:AVMediaTypeSubtitle])
132        return false;
133
134    if ([m_mediaSelectionOption hasMediaCharacteristic:AVMediaCharacteristicTranscribesSpokenDialogForAccessibility] && [m_mediaSelectionOption hasMediaCharacteristic:AVMediaCharacteristicDescribesMusicAndSoundForAccessibility])
135        return true;
136
137    return false;
138}
139
140bool InbandTextTrackPrivateAVFObjC::containsOnlyForcedSubtitles() const
141{
142    if (!m_mediaSelectionOption)
143        return false;
144
145    return [m_mediaSelectionOption hasMediaCharacteristic:AVMediaCharacteristicContainsOnlyForcedSubtitles];
146}
147
148bool InbandTextTrackPrivateAVFObjC::isMainProgramContent() const
149{
150    if (!m_mediaSelectionOption)
151        return false;
152
153    return [m_mediaSelectionOption hasMediaCharacteristic:AVMediaCharacteristicIsMainProgramContent];
154}
155
156bool InbandTextTrackPrivateAVFObjC::isEasyToRead() const
157{
158    if (!m_mediaSelectionOption)
159        return false;
160
161    return [m_mediaSelectionOption hasMediaCharacteristic:AVMediaCharacteristicEasyToRead];
162}
163
164AtomicString InbandTextTrackPrivateAVFObjC::label() const
165{
166    if (!m_mediaSelectionOption)
167        return emptyAtom;
168
169    NSString *title = 0;
170
171    NSArray *titles = [AVMetadataItem metadataItemsFromArray:[m_mediaSelectionOption.get() commonMetadata] withKey:AVMetadataCommonKeyTitle keySpace:AVMetadataKeySpaceCommon];
172    if ([titles count]) {
173        // If possible, return a title in one of the user's preferred languages.
174        NSArray *titlesForPreferredLanguages = [AVMetadataItem metadataItemsFromArray:titles filteredAndSortedAccordingToPreferredLanguages:[NSLocale preferredLanguages]];
175        if ([titlesForPreferredLanguages count])
176            title = [[titlesForPreferredLanguages objectAtIndex:0] stringValue];
177
178        if (!title)
179            title = [[titles objectAtIndex:0] stringValue];
180    }
181
182    return title ? AtomicString(title) : emptyAtom;
183}
184
185AtomicString InbandTextTrackPrivateAVFObjC::language() const
186{
187    if (!m_mediaSelectionOption)
188        return emptyAtom;
189
190    return [[m_mediaSelectionOption.get() locale] localeIdentifier];
191}
192
193bool InbandTextTrackPrivateAVFObjC::isDefault() const
194{
195    return false;
196}
197
198} // namespace WebCore
199
200#endif
201