Changeset 174402 in webkit


Ignore:
Timestamp:
Oct 7, 2014 12:11:53 PM (9 years ago)
Author:
jer.noble@apple.com
Message:

[Media] Expose AudioTracks in the "captions" menu.
https://bugs.webkit.org/show_bug.cgi?id=137472

Reviewed by Brent Fulgham.

Source/WebCore:

Test: media/video-controls-audiotracks-trackmenu.html

If more than one AudioTrack is present in the video element, add those tracks to the
captions menu:

  • English.lproj/mediaControlsLocalizedStrings.js:
  • Modules/mediacontrols/mediaControlsApple.js:

(Controller.prototype.addVideoListeners):
(Controller.prototype.removeVideoListeners):
(Controller.prototype.handleAudioTrackChange):
(Controller.prototype.handleAudioTrackAdd):
(Controller.prototype.handleAudioTrackRemove):
(Controller.prototype.updateCaptionButton):
(Controller.prototype.buildCaptionMenu):
(Controller.prototype.handleCaptionItemKeyUp):
(Controller.prototype.audioTrackItemSelected):
(Controller.prototype.focusSiblingAudioTrackItem):
(Controller.prototype.handleAudioTrackItemKeyUp):

Add support to MediaControlHost for retrieving the sorted audio track list, and the
localized names for every audio track:

  • Modules/mediacontrols/MediaControlsHost.cpp:

(WebCore::MediaControlsHost::sortedTrackListForMenu):
(WebCore::MediaControlsHost::displayNameForTrack):

  • Modules/mediacontrols/MediaControlsHost.h:
  • Modules/mediacontrols/MediaControlsHost.idl:
  • page/CaptionUserPreferences.cpp:

(WebCore::trackDisplayName):
(WebCore::CaptionUserPreferences::displayNameForTrack):
(WebCore::CaptionUserPreferences::sortedTrackListForMenu):

  • page/CaptionUserPreferences.h:
  • platform/LocalizedStrings.cpp:

(WebCore::audioTrackNoLabelText):

  • platform/LocalizedStrings.h:
  • platform/efl/LocalizedStringsEfl.cpp:

(WebCore::audioTrackNoLabelText):

  • platform/gtk/LocalizedStringsGtk.cpp:

(WebCore::audioTrackNoLabelText):

Drive-by fix; do not recurse into AudioTrackPrivate->setEnabled() when the enabled
state changes.

  • html/track/AudioTrack.cpp:

(WebCore::AudioTrack::enabledChanged):

Fix possible out-of-bounds Vector access when adding tracks to a track list by
sorting the list at insert time, rather than inserting into the track's reported
position in the Vector:

  • html/track/AudioTrackList.cpp:

(AudioTrackList::append):

  • html/track/VideoTrackList.cpp:

(VideoTrackList::append):

Correctly report the trackIndex of audio and video tracks from AVFoundation:

  • platform/graphics/avfoundation/AudioTrackPrivateAVF.h:

(WebCore::AudioTrackPrivateAVF::trackIndex):
(WebCore::AudioTrackPrivateAVF::setTrackIndex):
(WebCore::AudioTrackPrivateAVF::AudioTrackPrivateAVF):

  • platform/graphics/avfoundation/VideoTrackPrivateAVF.h:

(WebCore::VideoTrackPrivateAVF::trackIndex):
(WebCore::VideoTrackPrivateAVF::setTrackIndex):
(WebCore::VideoTrackPrivateAVF::VideoTrackPrivateAVF):

  • platform/graphics/avfoundation/objc/AudioTrackPrivateAVFObjC.mm:

(WebCore::AudioTrackPrivateAVFObjC::resetPropertiesFromTrack):

  • platform/graphics/avfoundation/objc/VideoTrackPrivateAVFObjC.cpp:

(WebCore::VideoTrackPrivateAVFObjC::resetPropertiesFromTrack):

LayoutTests:

  • media/content/audio-tracks.mp4: Added.
  • media/content/audio-tracks.ogg: Added.
  • media/content/audio-tracks.webm: Added.
  • media/video-controls-audiotracks-trackmenu-expected.txt: Added.
  • media/video-controls-audiotracks-trackmenu.html: Added.
Location:
trunk
Files:
5 added
20 edited

Legend:

Unmodified
Added
Removed
  • trunk/LayoutTests/ChangeLog

    r174370 r174402  
     12014-10-07  Jer Noble  <jer.noble@apple.com>
     2
     3        [Media] Expose AudioTracks in the "captions" menu.
     4        https://bugs.webkit.org/show_bug.cgi?id=137472
     5
     6        Reviewed by Brent Fulgham.
     7
     8        * media/content/audio-tracks.mp4: Added.
     9        * media/content/audio-tracks.ogg: Added.
     10        * media/content/audio-tracks.webm: Added.
     11        * media/video-controls-audiotracks-trackmenu-expected.txt: Added.
     12        * media/video-controls-audiotracks-trackmenu.html: Added.
     13
    1142014-10-06  David Hyatt  <hyatt@apple.com>
    215
  • trunk/Source/WebCore/ChangeLog

    r174400 r174402  
     12014-10-07  Jer Noble  <jer.noble@apple.com>
     2
     3        [Media] Expose AudioTracks in the "captions" menu.
     4        https://bugs.webkit.org/show_bug.cgi?id=137472
     5
     6        Reviewed by Brent Fulgham.
     7
     8        Test: media/video-controls-audiotracks-trackmenu.html
     9
     10        If more than one AudioTrack is present in the video element, add those tracks to the
     11        captions menu:
     12        * English.lproj/mediaControlsLocalizedStrings.js:
     13        * Modules/mediacontrols/mediaControlsApple.js:
     14        (Controller.prototype.addVideoListeners):
     15        (Controller.prototype.removeVideoListeners):
     16        (Controller.prototype.handleAudioTrackChange):
     17        (Controller.prototype.handleAudioTrackAdd):
     18        (Controller.prototype.handleAudioTrackRemove):
     19        (Controller.prototype.updateCaptionButton):
     20        (Controller.prototype.buildCaptionMenu):
     21        (Controller.prototype.handleCaptionItemKeyUp):
     22        (Controller.prototype.audioTrackItemSelected):
     23        (Controller.prototype.focusSiblingAudioTrackItem):
     24        (Controller.prototype.handleAudioTrackItemKeyUp):
     25
     26        Add support to MediaControlHost for retrieving the sorted audio track list, and the
     27        localized names for every audio track:
     28        * Modules/mediacontrols/MediaControlsHost.cpp:
     29        (WebCore::MediaControlsHost::sortedTrackListForMenu):
     30        (WebCore::MediaControlsHost::displayNameForTrack):
     31        * Modules/mediacontrols/MediaControlsHost.h:
     32        * Modules/mediacontrols/MediaControlsHost.idl:
     33        * page/CaptionUserPreferences.cpp:
     34        (WebCore::trackDisplayName):
     35        (WebCore::CaptionUserPreferences::displayNameForTrack):
     36        (WebCore::CaptionUserPreferences::sortedTrackListForMenu):
     37        * page/CaptionUserPreferences.h:
     38        * platform/LocalizedStrings.cpp:
     39        (WebCore::audioTrackNoLabelText):
     40        * platform/LocalizedStrings.h:
     41        * platform/efl/LocalizedStringsEfl.cpp:
     42        (WebCore::audioTrackNoLabelText):
     43        * platform/gtk/LocalizedStringsGtk.cpp:
     44        (WebCore::audioTrackNoLabelText):
     45
     46        Drive-by fix; do not recurse into AudioTrackPrivate->setEnabled() when the enabled
     47        state changes.
     48        * html/track/AudioTrack.cpp:
     49        (WebCore::AudioTrack::enabledChanged):
     50
     51        Fix possible out-of-bounds Vector access when adding tracks to a track list by
     52        sorting the list at insert time, rather than inserting into the track's reported
     53        position in the Vector:
     54        * html/track/AudioTrackList.cpp:
     55        (AudioTrackList::append):
     56        * html/track/VideoTrackList.cpp:
     57        (VideoTrackList::append):
     58
     59        Correctly report the trackIndex of audio and video tracks from AVFoundation:
     60        * platform/graphics/avfoundation/AudioTrackPrivateAVF.h:
     61        (WebCore::AudioTrackPrivateAVF::trackIndex):
     62        (WebCore::AudioTrackPrivateAVF::setTrackIndex):
     63        (WebCore::AudioTrackPrivateAVF::AudioTrackPrivateAVF):
     64        * platform/graphics/avfoundation/VideoTrackPrivateAVF.h:
     65        (WebCore::VideoTrackPrivateAVF::trackIndex):
     66        (WebCore::VideoTrackPrivateAVF::setTrackIndex):
     67        (WebCore::VideoTrackPrivateAVF::VideoTrackPrivateAVF):
     68        * platform/graphics/avfoundation/objc/AudioTrackPrivateAVFObjC.mm:
     69        (WebCore::AudioTrackPrivateAVFObjC::resetPropertiesFromTrack):
     70        * platform/graphics/avfoundation/objc/VideoTrackPrivateAVFObjC.cpp:
     71        (WebCore::VideoTrackPrivateAVFObjC::resetPropertiesFromTrack):
     72
    1732014-10-07  Christophe Dumez  <cdumez@apple.com>
    274
  • trunk/Source/WebCore/English.lproj/mediaControlsLocalizedStrings.js

    r169183 r174402  
    77
    88    'Aborted': 'Aborted',
     9    'Audio': 'Audio',
    910    'Audio Playback': 'Audio Playback',
    1011    'Captions': 'Captions',
  • trunk/Source/WebCore/Modules/mediacontrols/MediaControlsHost.cpp

    r170920 r174402  
    8989}
    9090
     91Vector<RefPtr<AudioTrack>> MediaControlsHost::sortedTrackListForMenu(AudioTrackList* trackList)
     92{
     93    if (!trackList)
     94        return Vector<RefPtr<AudioTrack>>();
     95
     96    Page* page = m_mediaElement->document().page();
     97    if (!page)
     98        return Vector<RefPtr<AudioTrack>>();
     99
     100    CaptionUserPreferences* captionPreferences = page->group().captionPreferences();
     101    return captionPreferences->sortedTrackListForMenu(trackList);
     102}
     103
    91104String MediaControlsHost::displayNameForTrack(TextTrack* track)
     105{
     106    if (!track)
     107        return emptyString();
     108
     109    Page* page = m_mediaElement->document().page();
     110    if (!page)
     111        return emptyString();
     112
     113    CaptionUserPreferences* captionPreferences = page->group().captionPreferences();
     114    return captionPreferences->displayNameForTrack(track);
     115}
     116
     117String MediaControlsHost::displayNameForTrack(AudioTrack* track)
    92118{
    93119    if (!track)
  • trunk/Source/WebCore/Modules/mediacontrols/MediaControlsHost.h

    r170920 r174402  
    3737namespace WebCore {
    3838
     39class AudioTrack;
     40class AudioTrackList;
    3941class Element;
    4042class HTMLMediaElement;
     
    5355
    5456    Vector<RefPtr<TextTrack>> sortedTrackListForMenu(TextTrackList*);
     57    Vector<RefPtr<AudioTrack>> sortedTrackListForMenu(AudioTrackList*);
    5558    String displayNameForTrack(TextTrack*);
     59    String displayNameForTrack(AudioTrack*);
    5660    TextTrack* captionMenuOffItem();
    5761    TextTrack* captionMenuAutomaticItem();
  • trunk/Source/WebCore/Modules/mediacontrols/MediaControlsHost.idl

    r170920 r174402  
    3636] interface MediaControlsHost {
    3737    TextTrack[] sortedTrackListForMenu(TextTrackList trackList);
     38    AudioTrack[] sortedTrackListForMenu(AudioTrackList trackList);
    3839    DOMString displayNameForTrack(TextTrack track);
     40    DOMString displayNameForTrack(AudioTrack track);
    3941    readonly attribute TextTrack captionMenuOffItem;
    4042    readonly attribute TextTrack captionMenuAutomaticItem;
  • trunk/Source/WebCore/Modules/mediacontrols/mediaControlsApple.js

    r173790 r174402  
    163163
    164164        /* audio tracks */
    165         this.listenFor(this.video.audioTracks, 'change', this.updateHasAudio);
    166         this.listenFor(this.video.audioTracks, 'addtrack', this.updateHasAudio);
    167         this.listenFor(this.video.audioTracks, 'removetrack', this.updateHasAudio);
     165        this.listenFor(this.video.audioTracks, 'change', this.handleAudioTrackChange);
     166        this.listenFor(this.video.audioTracks, 'addtrack', this.handleAudioTrackAdd);
     167        this.listenFor(this.video.audioTracks, 'removetrack', this.handleAudioTrackRemove);
    168168
    169169        /* video tracks */
     
    189189
    190190        /* audio tracks */
    191         this.stopListeningFor(this.video.audioTracks, 'change', this.updateHasAudio);
    192         this.stopListeningFor(this.video.audioTracks, 'addtrack', this.updateHasAudio);
    193         this.stopListeningFor(this.video.audioTracks, 'removetrack', this.updateHasAudio);
     191        this.stopListeningFor(this.video.audioTracks, 'change', this.handleAudioTrackChange);
     192        this.stopListeningFor(this.video.audioTracks, 'addtrack', this.handleAudioTrackAdd);
     193        this.stopListeningFor(this.video.audioTracks, 'removetrack', this.handleAudioTrackRemove);
    194194
    195195        /* video tracks */
     
    616616    },
    617617
     618    handleAudioTrackChange: function(event)
     619    {
     620        this.updateHasAudio();
     621    },
     622
     623    handleAudioTrackAdd: function(event)
     624    {
     625        this.updateHasAudio();
     626        this.updateCaptionButton();
     627    },
     628
     629    handleAudioTrackRemove: function(event)
     630    {
     631        this.updateHasAudio();
     632        this.updateCaptionButton();
     633    },
     634
    618635    isFullScreen: function()
    619636    {
     
    10891106    updateCaptionButton: function()
    10901107    {
    1091         if (this.video.webkitHasClosedCaptions)
     1108        if (this.video.webkitHasClosedCaptions || this.video.audioTracks.length > 1)
    10921109            this.controls.captionButton.classList.remove(this.ClassNames.hidden);
    10931110        else
     
    11141131    buildCaptionMenu: function()
    11151132    {
    1116         var tracks = this.host.sortedTrackListForMenu(this.video.textTracks);
    1117         if (!tracks || !tracks.length)
     1133        var audioTracks = this.host.sortedTrackListForMenu(this.video.audioTracks);
     1134        var textTracks = this.host.sortedTrackListForMenu(this.video.textTracks);
     1135
     1136        if ((!textTracks || !textTracks.length) && (!audioTracks || !audioTracks.length))
    11181137            return;
    11191138
     
    11311150        list.classList.add(this.ClassNames.list);
    11321151
    1133         var heading = document.createElement('h3');
    1134         heading.id = 'webkitMediaControlsClosedCaptionsHeading'; // for AX menu label
    1135         list.appendChild(heading);
    1136         heading.innerText = this.UIString('Subtitles');
    1137 
    1138         var ul = document.createElement('ul');
    1139         ul.setAttribute('role', 'menu');
    1140         ul.setAttribute('aria-labelledby', 'webkitMediaControlsClosedCaptionsHeading');
    1141         list.appendChild(ul);
    1142 
    1143         for (var i = 0; i < tracks.length; ++i) {
    1144             var menuItem = document.createElement('li');
    1145             menuItem.setAttribute('role', 'menuitemradio');
    1146             menuItem.setAttribute('tabindex', '-1');
    1147             this.captionMenuItems.push(menuItem);
    1148             this.listenFor(menuItem, 'click', this.captionItemSelected);
    1149             this.listenFor(menuItem, 'keyup', this.handleCaptionItemKeyUp);
    1150             ul.appendChild(menuItem);
    1151 
    1152             var track = tracks[i];
    1153             menuItem.innerText = this.host.displayNameForTrack(track);
    1154             menuItem.track = track;
    1155 
    1156             if (track === offItem) {
    1157                 var offMenu = menuItem;
    1158                 continue;
    1159             }
    1160 
    1161             if (track === automaticItem) {
    1162                 if (displayMode === 'automatic') {
     1152        if (audioTracks && audioTracks.length > 1) {
     1153            var heading = document.createElement('h3');
     1154            heading.id = 'webkitMediaControlsAudioTrackHeading'; // for AX menu label
     1155            list.appendChild(heading);
     1156            heading.innerText = this.UIString('Audio');
     1157
     1158            var ul = document.createElement('ul');
     1159            ul.setAttribute('role', 'menu');
     1160            ul.setAttribute('aria-labelledby', 'webkitMediaControlsAudioTrackHeading');
     1161            list.appendChild(ul);
     1162
     1163            for (var i = 0; i < audioTracks.length; ++i) {
     1164                var menuItem = document.createElement('li');
     1165                menuItem.setAttribute('role', 'menuitemradio');
     1166                menuItem.setAttribute('tabindex', '-1');
     1167                this.captionMenuItems.push(menuItem);
     1168                this.listenFor(menuItem, 'click', this.audioTrackItemSelected);
     1169                this.listenFor(menuItem, 'keyup', this.handleAudioTrackItemKeyUp);
     1170                ul.appendChild(menuItem);
     1171
     1172                var track = audioTracks[i];
     1173                menuItem.innerText = this.host.displayNameForTrack(track);
     1174                menuItem.track = track;
     1175
     1176                if (track.enabled) {
     1177                    var trackMenuItemSelected = true;
    11631178                    menuItem.classList.add(this.ClassNames.selected);
    11641179                    menuItem.setAttribute('tabindex', '0');
    11651180                    menuItem.setAttribute('aria-checked', 'true');
    11661181                }
    1167                 continue;
    11681182            }
    11691183
    1170             if (displayMode != 'automatic' && track.mode === 'showing') {
    1171                 var trackMenuItemSelected = true;
    1172                 menuItem.classList.add(this.ClassNames.selected);
     1184            if (offMenu && displayMode === 'forced-only' && !trackMenuItemSelected) {
     1185                offMenu.classList.add(this.ClassNames.selected);
    11731186                menuItem.setAttribute('tabindex', '0');
    11741187                menuItem.setAttribute('aria-checked', 'true');
    11751188            }
    1176 
    1177         }
    1178 
    1179         if (offMenu && displayMode === 'forced-only' && !trackMenuItemSelected) {
    1180             offMenu.classList.add(this.ClassNames.selected);
    1181             menuItem.setAttribute('tabindex', '0');
    1182             menuItem.setAttribute('aria-checked', 'true');
     1189        }
     1190
     1191        if (textTracks && textTracks.length > 2) {
     1192            var heading = document.createElement('h3');
     1193            heading.id = 'webkitMediaControlsClosedCaptionsHeading'; // for AX menu label
     1194            list.appendChild(heading);
     1195            heading.innerText = this.UIString('Subtitles');
     1196
     1197            var ul = document.createElement('ul');
     1198            ul.setAttribute('role', 'menu');
     1199            ul.setAttribute('aria-labelledby', 'webkitMediaControlsClosedCaptionsHeading');
     1200            list.appendChild(ul);
     1201
     1202            for (var i = 0; i < textTracks.length; ++i) {
     1203                var menuItem = document.createElement('li');
     1204                menuItem.setAttribute('role', 'menuitemradio');
     1205                menuItem.setAttribute('tabindex', '-1');
     1206                this.captionMenuItems.push(menuItem);
     1207                this.listenFor(menuItem, 'click', this.captionItemSelected);
     1208                this.listenFor(menuItem, 'keyup', this.handleCaptionItemKeyUp);
     1209                ul.appendChild(menuItem);
     1210
     1211                var track = textTracks[i];
     1212                menuItem.innerText = this.host.displayNameForTrack(track);
     1213                menuItem.track = track;
     1214
     1215                if (track === offItem) {
     1216                    var offMenu = menuItem;
     1217                    continue;
     1218                }
     1219
     1220                if (track === automaticItem) {
     1221                    if (displayMode === 'automatic') {
     1222                        menuItem.classList.add(this.ClassNames.selected);
     1223                        menuItem.setAttribute('tabindex', '0');
     1224                        menuItem.setAttribute('aria-checked', 'true');
     1225                    }
     1226                    continue;
     1227                }
     1228
     1229                if (displayMode != 'automatic' && track.mode === 'showing') {
     1230                    var trackMenuItemSelected = true;
     1231                    menuItem.classList.add(this.ClassNames.selected);
     1232                    menuItem.setAttribute('tabindex', '0');
     1233                    menuItem.setAttribute('aria-checked', 'true');
     1234                }
     1235
     1236            }
     1237
     1238            if (offMenu && displayMode === 'forced-only' && !trackMenuItemSelected) {
     1239                offMenu.classList.add(this.ClassNames.selected);
     1240                menuItem.setAttribute('tabindex', '0');
     1241                menuItem.setAttribute('aria-checked', 'true');
     1242            }
    11831243        }
    11841244       
     
    12451305    },
    12461306
     1307    audioTrackItemSelected: function(event)
     1308    {
     1309        for (var i = 0; i < this.video.audioTracks.length; ++i) {
     1310            var track = this.video.audioTracks[i];
     1311            track.enabled = (track == event.target.track);
     1312        }
     1313
     1314        this.destroyCaptionMenu();
     1315    },
     1316
     1317    focusSiblingAudioTrackItem: function(event)
     1318    {
     1319        var currentItem = event.target;
     1320        var pendingItem = false;
     1321        switch(event.keyCode) {
     1322            case this.KeyCodes.left:
     1323            case this.KeyCodes.up:
     1324                pendingItem = currentItem.previousSibling;
     1325                break;
     1326            case this.KeyCodes.right:
     1327            case this.KeyCodes.down:
     1328                pendingItem = currentItem.nextSibling;
     1329                break;
     1330        }
     1331        if (pendingItem) {
     1332            currentItem.setAttribute('tabindex', '-1');
     1333            pendingItem.setAttribute('tabindex', '0');
     1334            pendingItem.focus();
     1335        }
     1336    },
     1337
     1338    handleAudioTrackItemKeyUp: function(event)
     1339    {
     1340        switch (event.keyCode) {
     1341            case this.KeyCodes.enter:
     1342            case this.KeyCodes.space:
     1343                this.audioTrackItemSelected(event);
     1344                break;
     1345            case this.KeyCodes.escape:
     1346                this.destroyCaptionMenu();
     1347                break;
     1348            case this.KeyCodes.left:
     1349            case this.KeyCodes.up:
     1350            case this.KeyCodes.right:
     1351            case this.KeyCodes.down:
     1352                this.focusSiblingAudioTrackItem(event);
     1353                break;
     1354            default:
     1355                return;
     1356        }
     1357        // handled
     1358        event.stopPropagation();
     1359        event.preventDefault();
     1360    },
     1361
    12471362    destroyCaptionMenu: function()
    12481363    {
  • trunk/Source/WebCore/html/track/AudioTrack.cpp

    r167440 r174402  
    148148{
    149149    ASSERT_UNUSED(trackPrivate, trackPrivate == m_private);
    150     setEnabled(enabled);
     150    m_enabled = enabled;
     151
     152    if (m_client)
     153        m_client->audioTrackEnabledChanged(this);
    151154}
    152155
  • trunk/Source/WebCore/html/track/AudioTrackList.cpp

    r165676 r174402  
    5050    // Insert tracks in the media file order.
    5151    size_t index = track->inbandTrackIndex();
    52     m_inbandTracks.insert(index, track);
     52    size_t insertionIndex;
     53    for (insertionIndex = 0; insertionIndex < m_inbandTracks.size(); ++insertionIndex) {
     54        AudioTrack* otherTrack = static_cast<AudioTrack*>(m_inbandTracks[insertionIndex].get());
     55        if (otherTrack->inbandTrackIndex() > index)
     56            break;
     57    }
     58    m_inbandTracks.insert(insertionIndex, track);
     59
    5360
    5461    ASSERT(!track->mediaElement() || track->mediaElement() == mediaElement());
  • trunk/Source/WebCore/html/track/VideoTrackList.cpp

    r165676 r174402  
    5050    // Insert tracks in the media file order.
    5151    size_t index = track->inbandTrackIndex();
    52     m_inbandTracks.insert(index, track);
     52    size_t insertionIndex;
     53    for (insertionIndex = 0; insertionIndex < m_inbandTracks.size(); ++insertionIndex) {
     54        VideoTrack* otherTrack = static_cast<VideoTrack*>(m_inbandTracks[insertionIndex].get());
     55        if (otherTrack->inbandTrackIndex() > index)
     56            break;
     57    }
     58    m_inbandTracks.insert(insertionIndex, track);
    5359
    5460    ASSERT(!track->mediaElement() || track->mediaElement() == mediaElement());
  • trunk/Source/WebCore/page/CaptionUserPreferences.cpp

    r171746 r174402  
    2525
    2626#include "config.h"
     27#include "CaptionUserPreferences.h"
    2728
    2829#if ENABLE(VIDEO_TRACK)
    2930
    30 #include "CaptionUserPreferences.h"
     31#include "AudioTrackList.h"
    3132#include "DOMWrapperWorld.h"
    3233#include "Page.h"
     
    198199}
    199200
     201static String trackDisplayName(AudioTrack* track)
     202{
     203    if (track->label().isEmpty() && track->language().isEmpty())
     204        return audioTrackNoLabelText();
     205    if (!track->label().isEmpty())
     206        return track->label();
     207    return track->language();
     208}
     209
     210String CaptionUserPreferences::displayNameForTrack(AudioTrack* track) const
     211{
     212    return trackDisplayName(track);
     213}
     214
     215Vector<RefPtr<AudioTrack>> CaptionUserPreferences::sortedTrackListForMenu(AudioTrackList* trackList)
     216{
     217    ASSERT(trackList);
     218
     219    Vector<RefPtr<AudioTrack>> tracksForMenu;
     220
     221    for (unsigned i = 0, length = trackList->length(); i < length; ++i) {
     222        AudioTrack* track = trackList->item(i);
     223        tracksForMenu.append(track);
     224    }
     225
     226    std::sort(tracksForMenu.begin(), tracksForMenu.end(), [](const RefPtr<AudioTrack>& a, const RefPtr<AudioTrack>& b) {
     227        return codePointCompare(trackDisplayName(a.get()), trackDisplayName(b.get())) < 0;
     228    });
     229
     230    return tracksForMenu;
     231}
     232
    200233int CaptionUserPreferences::textTrackSelectionScore(TextTrack* track, HTMLMediaElement*) const
    201234{
  • trunk/Source/WebCore/page/CaptionUserPreferences.h

    r167594 r174402  
    2929#if ENABLE(VIDEO_TRACK)
    3030
     31#include "AudioTrack.h"
    3132#include "Language.h"
    3233#include "LocalizedStrings.h"
     
    3940class HTMLMediaElement;
    4041class PageGroup;
     42class AudioTrackList;
    4143class TextTrackList;
    4244
     
    8183    virtual Vector<RefPtr<TextTrack>> sortedTrackListForMenu(TextTrackList*);
    8284
     85    virtual String displayNameForTrack(AudioTrack*) const;
     86    virtual Vector<RefPtr<AudioTrack>> sortedTrackListForMenu(AudioTrackList*);
     87
    8388    void setPrimaryAudioTrackLanguageOverride(const String& language) { m_primaryAudioTrackLanguageOverride = language;  }
    8489    String primaryAudioTrackLanguageOverride() const;
  • trunk/Source/WebCore/platform/LocalizedStrings.cpp

    r166175 r174402  
    10801080    return WEB_UI_STRING_KEY("Unknown", "Unknown (text track)", "Menu item label for a text track that has no other name");
    10811081}
    1082    
     1082
     1083String audioTrackNoLabelText()
     1084{
     1085    return WEB_UI_STRING_KEY("Unknown", "Unknown (audio track)", "Menu item label for an audio track that has no other name");
     1086}
     1087
    10831088#if PLATFORM(COCOA) || PLATFORM(WIN)
    10841089String textTrackCountryAndLanguageMenuItemText(const String& title, const String& country, const String& language)
  • trunk/Source/WebCore/platform/LocalizedStrings.h

    r173176 r174402  
    251251    String textTrackAutomaticMenuItemText();
    252252    String textTrackNoLabelText();
     253    String audioTrackNoLabelText();
    253254#if PLATFORM(COCOA) || PLATFORM(WIN)
    254255    String textTrackCountryAndLanguageMenuItemText(const String& title, const String& country, const String& language);
  • trunk/Source/WebCore/platform/efl/LocalizedStringsEfl.cpp

    r165676 r174402  
    685685    return String::fromUTF8("No label");
    686686}
     687
     688String audioTrackNoLabelText()
     689{
     690    return String::fromUTF8("No label");
     691}
    687692#endif
    688693
  • trunk/Source/WebCore/platform/graphics/avfoundation/AudioTrackPrivateAVF.h

    r156652 r174402  
    4141    virtual AtomicString label() const { return m_label; }
    4242    virtual AtomicString language() const { return m_language; }
     43    virtual int trackIndex() const { return m_index; }
    4344
    4445protected:
     
    4748    void setLabel(AtomicString label) { m_label = label; }
    4849    void setLanguage(AtomicString language) { m_language = language; }
     50    void setTrackIndex(int index) { m_index = index; }
    4951
    5052    Kind m_kind;
     
    5254    AtomicString m_label;
    5355    AtomicString m_language;
     56    int m_index;
    5457
    5558    AudioTrackPrivateAVF()
    56     : m_kind(None)
     59        : m_kind(None)
     60        , m_index(0)
    5761    {
    5862    }
  • trunk/Source/WebCore/platform/graphics/avfoundation/VideoTrackPrivateAVF.h

    r162139 r174402  
    3737public:
    3838
     39    virtual int trackIndex() const { return m_index; }
    3940    virtual Kind kind() const override { return m_kind; }
    4041    virtual AtomicString id() const override { return m_id; }
     
    4748    void setLabel(AtomicString label) { m_label = label; }
    4849    void setLanguage(AtomicString language) { m_language = language; }
     50    void setTrackIndex(int index) { m_index = index; }
    4951
    5052    Kind m_kind;
     
    5254    AtomicString m_label;
    5355    AtomicString m_language;
     56    int m_index;
    5457
    5558    VideoTrackPrivateAVF()
    5659        : m_kind(None)
     60        , m_index(0)
    5761    {
    5862    }
  • trunk/Source/WebCore/platform/graphics/avfoundation/objc/AudioTrackPrivateAVFObjC.mm

    r168755 r174402  
    4444    AudioTrackPrivateAVF::setEnabled(m_impl->enabled());
    4545
     46    setTrackIndex(m_impl->trackID());
    4647    setKind(m_impl->audioKind());
    4748    setId(m_impl->id());
  • trunk/Source/WebCore/platform/graphics/avfoundation/objc/VideoTrackPrivateAVFObjC.cpp

    r168755 r174402  
    5050    VideoTrackPrivateAVF::setSelected(m_impl->enabled());
    5151
     52    setTrackIndex(m_impl->trackID());
    5253    setKind(m_impl->videoKind());
    5354    setId(m_impl->id());
  • trunk/Source/WebCore/platform/gtk/LocalizedStringsGtk.cpp

    r165676 r174402  
    811811    return String::fromUTF8(C_("Menu item label for a closed captions track that has no other name", "No label"));
    812812}
     813
     814String audioTrackNoLabelText()
     815{
     816    return String::fromUTF8(C_("Menu item label for an audio track that has no other name", "No label"));
     817}
    813818#endif
    814819
Note: See TracChangeset for help on using the changeset viewer.