mirror of
https://github.com/shaka-project/shaka-player.git
synced 2026-06-19 16:47:01 +03:00
c7368024ae
I went ahead and implemented the full structured preference system that was discussed in https://github.com/shaka-project/shaka-player/issues/1591. Instead of just expanding languages to arrays, I replaced all 14 individual preference fields with 3 structured arrays: ```tsx preferredAudio (language, role, label, channelCount, codec, spatialAudio) preferredText (language, role, format, forced) preferredVideo (label, role, codec, hdrLevel, layout) ``` Each array entry works as an AND filter - so you can say things like "I want Korean with 5.1 surround, but if not available, English is fine too": ```tsx player.configure('preferredAudio', [ {language: 'ko', channelCount: 6}, {language: 'ko'}, {language: 'en'}, ]); ``` <img width="1728" height="965" alt="image" src="https://github.com/user-attachments/assets/7b088150-139b-475e-bdba-5bc77dd4e524" /> **Config** - Replaced the 14 individual fields with 3 arrays of typed preference objects (AudioPreference, TextPreference, VideoPreference). The old fields still work at runtime with a deprecation warning, so existing apps won't break immediately. **Demo** - The demo config UI now shows inline expandable preference lists instead of flat text inputs. You can add/remove entries and configure each field per entry. URL hash serialization was updated to use JSON format, with legacy param fallbacks preserved.
150 lines
4.0 KiB
JavaScript
150 lines
4.0 KiB
JavaScript
/*! @license
|
|
* Shaka Player
|
|
* Copyright 2016 Google LLC
|
|
* SPDX-License-Identifier: Apache-2.0
|
|
*/
|
|
|
|
|
|
goog.provide('shaka.ui.AudioLanguageSelection');
|
|
|
|
goog.require('shaka.ui.Controls');
|
|
goog.require('shaka.ui.Enums');
|
|
goog.require('shaka.ui.LanguageUtils');
|
|
goog.require('shaka.ui.Locales');
|
|
goog.require('shaka.ui.Localization');
|
|
goog.require('shaka.ui.OverflowMenu');
|
|
goog.require('shaka.ui.SettingsMenu');
|
|
goog.require('shaka.ui.Utils');
|
|
goog.require('shaka.util.FakeEvent');
|
|
goog.requireType('shaka.ui.Controls');
|
|
|
|
/**
|
|
* @extends {shaka.ui.SettingsMenu}
|
|
* @final
|
|
* @export
|
|
*/
|
|
shaka.ui.AudioLanguageSelection = class extends shaka.ui.SettingsMenu {
|
|
/**
|
|
* @param {!HTMLElement} parent
|
|
* @param {!shaka.ui.Controls} controls
|
|
*/
|
|
constructor(parent, controls) {
|
|
super(parent, controls, shaka.ui.Enums.MaterialDesignSVGIcons['LANGUAGE']);
|
|
|
|
this.button.classList.add('shaka-language-button');
|
|
this.button.classList.add('shaka-tooltip-status');
|
|
this.menu.classList.add('shaka-audio-languages');
|
|
|
|
this.eventManager.listenMulti(
|
|
this.localization,
|
|
[
|
|
shaka.ui.Localization.LOCALE_UPDATED,
|
|
shaka.ui.Localization.LOCALE_CHANGED,
|
|
], () => {
|
|
this.updateLocalizedStrings_();
|
|
});
|
|
|
|
this.eventManager.listenMulti(
|
|
this.player,
|
|
[
|
|
'loading',
|
|
'loaded',
|
|
'unloading',
|
|
'audiotrackschanged',
|
|
], () => {
|
|
this.onAudioTracksChanged_();
|
|
});
|
|
|
|
if (this.isSubMenu) {
|
|
this.eventManager.listenMulti(
|
|
this.controls,
|
|
[
|
|
'submenuopen',
|
|
'submenuclose',
|
|
], () => {
|
|
this.onAudioTracksChanged_();
|
|
});
|
|
}
|
|
|
|
// Set up all the strings in the user's preferred language.
|
|
this.updateLocalizedStrings_();
|
|
|
|
this.onAudioTracksChanged_();
|
|
}
|
|
|
|
|
|
/** @private */
|
|
onAudioTracksChanged_() {
|
|
const audioTracks = this.player.getAudioTracks() || [];
|
|
|
|
shaka.ui.LanguageUtils.updateAudioTracks(audioTracks, this.menu,
|
|
(track) => this.onAudioTrackSelected_(track),
|
|
/* updateChosen= */ true, this.currentSelection, this.localization,
|
|
this.controls.getConfig());
|
|
shaka.ui.Utils.focusOnTheChosenItem(this.menu);
|
|
|
|
this.controls.dispatchEvent(
|
|
new shaka.util.FakeEvent('languageselectionupdated'));
|
|
|
|
this.button.setAttribute('shaka-status', this.currentSelection.innerText);
|
|
|
|
const numberOfItems = this.menu.getElementsByTagName('button').length;
|
|
shaka.ui.Utils.setDisplay(
|
|
this.button, numberOfItems > 2 && !this.isSubMenuOpened);
|
|
}
|
|
|
|
/**
|
|
* @param {!shaka.extern.AudioTrack} audioTrack
|
|
* @private
|
|
*/
|
|
onAudioTrackSelected_(audioTrack) {
|
|
this.player.selectAudioTrack(audioTrack);
|
|
|
|
// Set audio preference for when reloading the stream (e.g. casting), keep
|
|
// this selection.
|
|
/** @type {shaka.extern.AudioPreference} */
|
|
const pref = {
|
|
language: audioTrack.language,
|
|
role: '',
|
|
label: audioTrack.label || '',
|
|
channelCount: audioTrack.channelsCount || 0,
|
|
codec: '',
|
|
spatialAudio: audioTrack.spatialAudio,
|
|
};
|
|
this.player.configure({preferredAudio: [pref]});
|
|
}
|
|
|
|
|
|
/**
|
|
* @private
|
|
*/
|
|
updateLocalizedStrings_() {
|
|
const LocIds = shaka.ui.Locales.Ids;
|
|
|
|
this.backButton.ariaLabel = this.localization.resolve(LocIds.BACK);
|
|
this.button.ariaLabel = this.localization.resolve(LocIds.LANGUAGE);
|
|
this.nameSpan.textContent =
|
|
this.localization.resolve(LocIds.LANGUAGE);
|
|
this.backSpan.textContent =
|
|
this.localization.resolve(LocIds.LANGUAGE);
|
|
}
|
|
};
|
|
|
|
|
|
/**
|
|
* @implements {shaka.extern.IUIElement.Factory}
|
|
* @final
|
|
*/
|
|
shaka.ui.AudioLanguageSelection.Factory = class {
|
|
/** @override */
|
|
create(rootElement, controls) {
|
|
return new shaka.ui.AudioLanguageSelection(rootElement, controls);
|
|
}
|
|
};
|
|
|
|
shaka.ui.OverflowMenu.registerElement(
|
|
'language', new shaka.ui.AudioLanguageSelection.Factory());
|
|
|
|
shaka.ui.Controls.registerElement(
|
|
'language', new shaka.ui.AudioLanguageSelection.Factory());
|