Skip to content

Commit

Permalink
make language matching more robust (Dash-Industry-Forum#4015)
Browse files Browse the repository at this point in the history
* make language matching more robust
* adding BCP-47 module
* use BCP-47 extended filter in settings matcher

* remove commented code

* downgrade version of bcp-47 modules to v1 as they are compatibel with CommonJS (not ESmodule only); add differentiation between string and RegExp in settings.lang

* enhancing language selection tests, making them more sensitive, adding case with 3-letter code, using RegExp object instead of string with RegExp

* refine documentation of possible data types with langValue in setInitialMediaSettingsFor API
  • Loading branch information
stschr authored and eastkiki committed Oct 4, 2022
1 parent feefff5 commit 4bc83ef
Show file tree
Hide file tree
Showing 3 changed files with 66 additions and 61 deletions.
2 changes: 1 addition & 1 deletion src/streaming/MediaPlayer.js
Original file line number Diff line number Diff line change
Expand Up @@ -1515,7 +1515,7 @@ function MediaPlayer() {
/**
* This method allows to set media settings that will be used to pick the initial track. Format of the settings
* is following: <br />
* {lang: langValue (can be either a string or a regex to match),
* {lang: langValue (can be either a string primitive, a string object, or a RegExp object to match),
* index: indexValue,
* viewpoint: viewpointValue,
* audioChannelConfiguration: audioChannelConfigurationValue,
Expand Down
6 changes: 5 additions & 1 deletion src/streaming/controllers/MediaController.js
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,8 @@ import Events from '../../core/events/Events';
import EventBus from '../../core/EventBus';
import FactoryMaker from '../../core/FactoryMaker';
import Debug from '../../core/Debug';
var bcp47Normalize = require('bcp-47-normalize')
import {extendedFilter} from 'bcp-47-match';

function MediaController() {

Expand Down Expand Up @@ -309,7 +311,9 @@ function MediaController() {
}

function matchSettings(settings, track, isTrackActive = false) {
const matchLang = !settings.lang || (track.lang.match(settings.lang));
const matchLang = !settings.lang || (
(settings.lang instanceof RegExp)?(track.lang.match(settings.lang)):( extendedFilter(track.lang, bcp47Normalize(settings.lang) ).length>0 )
);
const matchIndex = (settings.index === undefined) || (settings.index === null) || (track.index === settings.index);
const matchViewPoint = !settings.viewpoint || (settings.viewpoint === track.viewpoint);
const matchRole = !settings.role || !!track.roles.filter(function (item) {
Expand Down
119 changes: 60 additions & 59 deletions test/unit/streaming.controllers.MediaController.js
Original file line number Diff line number Diff line change
Expand Up @@ -334,99 +334,100 @@ describe('MediaController', function () {
});

describe('Initial Track Management', function () {
let streamInfo = {
id: 'id'
};
let frTrack = {
type: trackType,
streamInfo: streamInfo,
lang: 'fr',
viewpoint: 'viewpoint',
roles: 1,
accessibility: 1,
audioChannelConfiguration: 1
};
const qtzTrack = {
type: trackType,
streamInfo: streamInfo,
lang: 'qtz',
viewpoint: 'viewpoint',
roles: 1,
accessibility: 1,
audioChannelConfiguration: 1
};

it('should check initial media settings to choose initial track', function () {
let streamInfo = {
id: 'id'
};
let track = {
type: trackType,
streamInfo: streamInfo,
lang: 'fr',
viewpoint: 'viewpoint',
roles: 1,
accessibility: 1,
audioChannelConfiguration: 1
};
mediaController.addTrack(frTrack);
mediaController.addTrack(qtzTrack);

mediaController.addTrack(track);
let trackList = mediaController.getTracksFor(trackType, streamInfo.id);
expect(trackList).to.have.lengthOf(2);
expect(objectUtils.areEqual(trackList[0], frTrack)).to.be.true; // jshint ignore:line
expect(objectUtils.areEqual(trackList[1], qtzTrack)).to.be.true; // jshint ignore:line

let currentTrack = mediaController.getCurrentTrackFor(trackType, streamInfo.id);
expect(objectUtils.areEqual(currentTrack, frTrack)).to.be.false; // jshint ignore:line

// call to setInitialMediaSettingsForType
mediaController.setInitialSettings(trackType, {
lang: 'qtz',
viewpoint: 'viewpoint'
});
mediaController.setInitialMediaSettingsForType(trackType, streamInfo);

currentTrack = mediaController.getCurrentTrackFor(trackType, streamInfo.id);
expect(objectUtils.areEqual(currentTrack, qtzTrack)).to.be.true; // jshint ignore:line

});

it('should check initial media settings to choose initial track with 639-2 3-letter code', function () {
mediaController.addTrack(qtzTrack);
mediaController.addTrack(frTrack);

let trackList = mediaController.getTracksFor(trackType, streamInfo.id);
expect(trackList).to.have.lengthOf(1);
expect(objectUtils.areEqual(trackList[0], track)).to.be.true; // jshint ignore:line
expect(trackList).to.have.lengthOf(2);
expect(objectUtils.areEqual(trackList[0], qtzTrack)).to.be.true; // jshint ignore:line
expect(objectUtils.areEqual(trackList[1], frTrack)).to.be.true; // jshint ignore:line

let currentTrack = mediaController.getCurrentTrackFor(trackType, streamInfo.id);
expect(objectUtils.areEqual(currentTrack, track)).to.be.false; // jshint ignore:line
expect(objectUtils.areEqual(currentTrack, frTrack)).to.be.false; // jshint ignore:line

// call to setInitialMediaSettingsForType
mediaController.setInitialSettings(trackType, {
lang: 'fr',
lang: 'fre',
viewpoint: 'viewpoint'
});
mediaController.setInitialMediaSettingsForType(trackType, streamInfo);

currentTrack = mediaController.getCurrentTrackFor(trackType, streamInfo.id);
expect(objectUtils.areEqual(currentTrack, track)).to.be.true; // jshint ignore:line
expect(objectUtils.areEqual(currentTrack, frTrack)).to.be.true; // jshint ignore:line

});

it('should check initial media settings to choose initial track with a string/regex lang', function () {
const streamInfo = {
id: 'id'
};
const track = {
type: trackType,
streamInfo: streamInfo,
lang: 'fr',
viewpoint: 'viewpoint',
roles: 1,
accessibility: 1,
audioChannelConfiguration: 1
};

mediaController.addTrack(track);
mediaController.addTrack(frTrack);
mediaController.addTrack(qtzTrack);

let trackList = mediaController.getTracksFor(trackType, streamInfo.id);
expect(trackList).to.have.lengthOf(1);
expect(objectUtils.areEqual(trackList[0], track)).to.be.true; // jshint ignore:line
expect(trackList).to.have.lengthOf(2);
expect(objectUtils.areEqual(trackList[0], frTrack)).to.be.true; // jshint ignore:line
expect(objectUtils.areEqual(trackList[1], qtzTrack)).to.be.true; // jshint ignore:line

let currentTrack = mediaController.getCurrentTrackFor(trackType, streamInfo.id);
expect(objectUtils.areEqual(currentTrack, track)).to.be.false; // jshint ignore:line
expect(objectUtils.areEqual(currentTrack, frTrack)).to.be.false; // jshint ignore:line

// call to setInitialMediaSettingsForType
mediaController.setInitialSettings(trackType, {
lang: 'fr|en|qtz',
lang: /fr|en|qtz/,
viewpoint: 'viewpoint'
});
mediaController.setInitialMediaSettingsForType(trackType, streamInfo);

currentTrack = mediaController.getCurrentTrackFor(trackType, streamInfo.id);
expect(objectUtils.areEqual(currentTrack, track)).to.be.true; // jshint ignore:line
expect(objectUtils.areEqual(currentTrack, frTrack)).to.be.true; // jshint ignore:line
});

it('should check initial media settings to choose initial track with a regex lang', function () {
const streamInfo = {
id: 'id'
};
const frTrack = {
type: trackType,
streamInfo: streamInfo,
lang: 'fr',
viewpoint: 'viewpoint',
roles: 1,
accessibility: 1,
audioChannelConfiguration: 1
};
const qtzTrack = {
type: trackType,
streamInfo: streamInfo,
lang: 'qtz',
viewpoint: 'viewpoint',
roles: 1,
accessibility: 1,
audioChannelConfiguration: 1
};

mediaController.addTrack(frTrack);
mediaController.addTrack(qtzTrack);

Expand Down

0 comments on commit 4bc83ef

Please sign in to comment.