Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Modify Offline module API #3275

Merged
Merged
Show file tree
Hide file tree
Changes from 6 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
81 changes: 77 additions & 4 deletions index.d.ts
Expand Up @@ -44,7 +44,29 @@ declare namespace dashjs {
reset(): void;
}

export interface OfflineRecord {
id: string;
progress: number;
url: string;
originalUrl: string;
status: string;
}

interface OfflineController {
loadRecordsFromStorage(): Promise<void>;
getAllRecords(): OfflineRecord[];
createRecord(manifestURL: string): Promise<string>;
startRecord(id: string, mediaInfos: MediaInfo[]);
stopRecord(id: string): void;
resumeRecord(id: string): void;
deleteRecord(id: string): void;
getRecordProgression(id: string): number;
resetRecords(): void;
reset(): void;
}

export interface Bitrate {
id?: string;
width?: number;
height?: number;
bandwidth?: number;
Expand Down Expand Up @@ -195,7 +217,8 @@ declare namespace dashjs {
on(type: ManifestLoadedEvent['type'], listener: (e: ManifestLoadedEvent) => void, scope?: object): void;
on(type: MetricEvent['type'], listener: (e: MetricEvent) => void, scope?: object): void;
on(type: MetricChangedEvent['type'], listener: (e: MetricChangedEvent) => void, scope?: object): void;
on(type: OfflineStreamEvent['type'], listener: (e: OfflineStreamEvent) => void, scope?: object): void;
on(type: OfflineRecordEvent['type'], listener: (e: OfflineRecordEvent) => void, scope?: object): void;
on(type: OfflineRecordLoademetadataEvent['type'], listener: (e: OfflineRecordLoademetadataEvent) => void, scope?: object): void;
on(type: PeriodSwitchEvent['type'], listener: (e: PeriodSwitchEvent) => void, scope?: object): void;
on(type: PlaybackErrorEvent['type'], listener: (e: PlaybackErrorEvent) => void, scope?: object): void;
on(type: PlaybackPausedEvent['type'], listener: (e: PlaybackPausedEvent) => void, scope?: object): void;
Expand Down Expand Up @@ -283,6 +306,7 @@ declare namespace dashjs {
getProtectionController(): ProtectionController;
attachProtectionController(value: ProtectionController): void;
setProtectionData(value: ProtectionData): void;
getOfflineController(): OfflineController;
enableManifestDateHeaderTimeSource(value: boolean): void;
displayCaptionsOnTop(value: boolean): void;
attachTTMLRenderingDiv(div: HTMLDivElement): void;
Expand Down Expand Up @@ -352,7 +376,24 @@ declare namespace dashjs {
KEY_SYSTEM_ACCESS_DENIED_ERROR_CODE: 112;
KEY_SESSION_CREATED_ERROR_CODE: 113;
MEDIA_KEY_MESSAGE_LICENSER_ERROR_CODE: 114;
// MSS errors
MSS_NO_TFRF_CODE: 200;
MSS_UNSUPPORTED_CODEC_CODE: 201;
// Offline errors
OFFLINE_ERROR: 11000;
INDEXEDDB_QUOTA_EXCEED_ERROR: 11001;
INDEXEDDB_INVALID_STATE_ERROR: 11002;
INDEXEDDB_NOT_READABLE_ERROR: 11003;
INDEXEDDB_NOT_FOUND_ERROR: 11004;
INDEXEDDB_NETWORK_ERROR: 11005;
INDEXEDDB_DATA_ERROR: 11006;
INDEXEDDB_TRANSACTION_INACTIVE_ERROR: 11007;
INDEXEDDB_NOT_ALLOWED_ERROR: 11008;
INDEXEDDB_NOT_SUPPORTED_ERROR: 11009;
INDEXEDDB_VERSION_ERROR: 11010;
INDEXEDDB_TIMEOUT_ERROR: 11011;
INDEXEDDB_ABORT_ERROR: 11012;
INDEXEDDB_UNKNOWN_ERROR: 11013;
}

interface MediaPlayerEvents {
Expand Down Expand Up @@ -382,6 +423,10 @@ declare namespace dashjs {
METRIC_ADDED: 'metricAdded';
METRIC_CHANGED: 'metricChanged';
METRIC_UPDATED: 'metricUpdated';
OFFLINE_RECORD_FINISHED: 'public_offlineRecordFinished';
OFFLINE_RECORD_LOADEDMETADATA: 'public_offlineRecordLoadedmetadata';
OFFLINE_RECORD_STARTED: 'public_offlineRecordStarted';
OFFLINE_RECORD_STOPPED: 'public_offlineRecordStopped';
PERIOD_SWITCH_COMPLETED: 'periodSwitchCompleted';
PERIOD_SWITCH_STARTED: 'periodSwitchStarted';
PLAYBACK_ENDED: 'playbackEnded';
Expand Down Expand Up @@ -496,6 +541,7 @@ declare namespace dashjs {
MediaPlayerErrors['TIMED_TEXT_ERROR_ID_PARSE_CODE'] |
MediaPlayerErrors['MANIFEST_ERROR_ID_MULTIPLEXED_CODE'] |
MediaPlayerErrors['MEDIASOURCE_TYPE_UNSUPPORTED_CODE'] |
// Protection errors
MediaPlayerErrors['MEDIA_KEYERR_CODE'] |
MediaPlayerErrors['MEDIA_KEYERR_UNKNOWN_CODE'] |
MediaPlayerErrors['MEDIA_KEYERR_CLIENT_CODE'] |
Expand All @@ -511,9 +557,26 @@ declare namespace dashjs {
MediaPlayerErrors['KEY_SYSTEM_ACCESS_DENIED_ERROR_CODE'] |
MediaPlayerErrors['KEY_SESSION_CREATED_ERROR_CODE'] |
MediaPlayerErrors['MEDIA_KEY_MESSAGE_LICENSER_ERROR_CODE'] |
MediaPlayerErrors['MSS_NO_TFRF_CODE'],
message:string,
data:object,
// Offline errors
MediaPlayerErrors['OFFLINE_ERROR'] |
MediaPlayerErrors['INDEXEDDB_QUOTA_EXCEED_ERROR'] |
MediaPlayerErrors['INDEXEDDB_INVALID_STATE_ERROR'] |
MediaPlayerErrors['INDEXEDDB_NOT_READABLE_ERROR'] |
MediaPlayerErrors['INDEXEDDB_NOT_FOUND_ERROR'] |
MediaPlayerErrors['INDEXEDDB_NETWORK_ERROR'] |
MediaPlayerErrors['INDEXEDDB_DATA_ERROR'] |
MediaPlayerErrors['INDEXEDDB_TRANSACTION_INACTIVE_ERROR'] |
MediaPlayerErrors['INDEXEDDB_NOT_ALLOWED_ERROR'] |
MediaPlayerErrors['INDEXEDDB_NOT_SUPPORTED_ERROR'] |
MediaPlayerErrors['INDEXEDDB_VERSION_ERROR'] |
MediaPlayerErrors['INDEXEDDB_TIMEOUT_ERROR'] |
MediaPlayerErrors['INDEXEDDB_ABORT_ERROR'] |
MediaPlayerErrors['INDEXEDDB_UNKNOWN_ERROR'] |
// MSS errors
MediaPlayerErrors['MSS_NO_TFRF_CODE'] |
MediaPlayerErrors['MSS_UNSUPPORTED_CODEC_CODE'],
message: string,
data: object,
}
}

Expand Down Expand Up @@ -621,6 +684,16 @@ declare namespace dashjs {
mediaType: MediaType;
}

export interface OfflineRecordEvent extends Event {
type: MediaPlayerEvents['OFFLINE_RECORD_FINISHED' | 'OFFLINE_RECORD_STARTED' | 'OFFLINE_RECORD_STOPPED' | 'OFFLINE_RECORD_STOPPED'];
id: string;
}

export interface OfflineRecordLoademetadataEvent extends Event {
type: MediaPlayerEvents['OFFLINE_RECORD_LOADEDMETADATA'];
madiaInfos: MediaInfo[];
}

export interface PeriodSwitchEvent extends Event {
type: MediaPlayerEvents['PERIOD_SWITCH_COMPLETED' | 'PERIOD_SWITCH_STARTED'];
toStreamInfo: StreamInfo | null;
Expand Down
71 changes: 44 additions & 27 deletions samples/offline/app/main.js
Expand Up @@ -263,8 +263,8 @@ app.controller('DashController', function ($scope, $timeout, $q, sources, contri
if ($scope.player) {
$scope.player.updateSettings(config);
}
if ($scope.downloader) {
$scope.downloader.updateSettings({ 'debug': { 'logLevel': dashjs.Debug.LOG_LEVEL_DEBUG } });
if ($scope.offlinePlayer) {
$scope.offlinePlayer.updateSettings({ 'debug': { 'logLevel': dashjs.Debug.LOG_LEVEL_DEBUG } });
}
} else {
// Set default initial configuration
Expand All @@ -283,7 +283,7 @@ app.controller('DashController', function ($scope, $timeout, $q, sources, contri
}
};
$scope.player.updateSettings(initialConfig);
$scope.downloader.updateSettings({ 'debug': { 'logLevel': dashjs.Debug.LOG_LEVEL_INFO } });
$scope.offlinePlayer.updateSettings({ 'debug': { 'logLevel': dashjs.Debug.LOG_LEVEL_INFO } });
}
};
reqConfig.open('GET', 'dashjs_config.json', true);
Expand Down Expand Up @@ -340,7 +340,6 @@ app.controller('DashController', function ($scope, $timeout, $q, sources, contri
}
}, $scope);


$scope.player.initialize($scope.video, null, $scope.autoPlaySelected);

// Add HTML-rendered TTML subtitles except for Firefox < v49 (issue #1164)
Expand Down Expand Up @@ -438,16 +437,16 @@ app.controller('DashController', function ($scope, $timeout, $q, sources, contri
// Download setup
//
////////////////////////////////////////
$scope.downloader = dashjs.MediaPlayer().create(); /* jshint ignore:line */
$scope.downloader.initialize($scope.video, null, $scope.autoPlaySelected);
$scope.offlinePlayer = dashjs.MediaPlayer().create(); /* jshint ignore:line */
$scope.offlinePlayer.initialize($scope.video, null, $scope.autoPlaySelected);

$scope.downloads = DownloadService.getDownloads();
DownloadService.init($scope.downloader);
DownloadService.init($scope.offlinePlayer);

$scope.downloader.on(dashjs.MediaPlayer.events.DOWNLOADABLE_REPRESENTATIONS_LOADED, function (e) { /* jshint ignore:line */
console.log(JSON.stringify(e.data));
$scope.downloadableRepresentations = e.data.downloadableRepresentations;
$scope.manifestId = e.data.id;
$scope.offlinePlayer.on(dashjs.MediaPlayer.events.OFFLINE_RECORD_LOADEDMETADATA, function (e) { /* jshint ignore:line */
console.log(JSON.stringify(e));
$scope.mediaInfos = e.mediaInfos;
$scope.manifestId = e.id;
$scope.showRepresentationModal();
}, $scope);

Expand Down Expand Up @@ -670,32 +669,32 @@ app.controller('DashController', function ($scope, $timeout, $q, sources, contri
switch (level) {
case 'none':
$scope.player.updateSettings({ 'debug': { 'logLevel': dashjs.Debug.LOG_LEVEL_NONE } });
$scope.downloader.updateSettings({ 'debug': { 'logLevel': dashjs.Debug.LOG_LEVEL_NONE } });
$scope.offlinePlayer.updateSettings({ 'debug': { 'logLevel': dashjs.Debug.LOG_LEVEL_NONE } });
break;

case 'fatal':
$scope.player.updateSettings({ 'debug': { 'logLevel': dashjs.Debug.LOG_LEVEL_FATAL } });
$scope.downloader.updateSettings({ 'debug': { 'logLevel': dashjs.Debug.LOG_LEVEL_FATAL } });
$scope.offlinePlayer.updateSettings({ 'debug': { 'logLevel': dashjs.Debug.LOG_LEVEL_FATAL } });
break;

case 'error':
$scope.player.updateSettings({ 'debug': { 'logLevel': dashjs.Debug.LOG_LEVEL_ERROR } });
$scope.downloader.updateSettings({ 'debug': { 'logLevel': dashjs.Debug.LOG_LEVEL_ERROR } });
$scope.offlinePlayer.updateSettings({ 'debug': { 'logLevel': dashjs.Debug.LOG_LEVEL_ERROR } });
break;

case 'warning':
$scope.player.updateSettings({ 'debug': { 'logLevel': dashjs.Debug.LOG_LEVEL_WARNING } });
$scope.downloader.updateSettings({ 'debug': { 'logLevel': dashjs.Debug.LOG_LEVEL_WARNING } });
$scope.offlinePlayer.updateSettings({ 'debug': { 'logLevel': dashjs.Debug.LOG_LEVEL_WARNING } });
break;

case 'info':
$scope.player.updateSettings({ 'debug': { 'logLevel': dashjs.Debug.LOG_LEVEL_INFO } });
$scope.downloader.updateSettings({ 'debug': { 'logLevel': dashjs.Debug.LOG_LEVEL_INFO } });
$scope.offlinePlayer.updateSettings({ 'debug': { 'logLevel': dashjs.Debug.LOG_LEVEL_INFO } });
break;

default:
$scope.player.updateSettings({ 'debug': { 'logLevel': dashjs.Debug.LOG_LEVEL_DEBUG } });
$scope.downloader.updateSettings({ 'debug': { 'logLevel': dashjs.Debug.LOG_LEVEL_DEBUG } });
$scope.offlinePlayer.updateSettings({ 'debug': { 'logLevel': dashjs.Debug.LOG_LEVEL_DEBUG } });
}
};

Expand Down Expand Up @@ -1028,23 +1027,23 @@ app.controller('DashController', function ($scope, $timeout, $q, sources, contri
//
////////////////////////////////////////

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Missing ";" on 1107

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

fixed

$scope.player.on(dashjs.MediaPlayer.events.DOWNLOADING_STARTED, function (e) { /* jshint ignore:line */
$scope.player.on(dashjs.MediaPlayer.events.OFFLINE_RECORD_STARTED, function (e) { /* jshint ignore:line */
$scope.successMessage = e.message;
$('.alert.alert-success').show();
$('.alert.alert-success').fadeTo(2500, 500).slideUp(500, function () {
$('.alert.alert-success').slideUp(500);
});
}, $scope);

$scope.player.on(dashjs.MediaPlayer.events.DOWNLOADING_FINISHED, function (e) { /* jshint ignore:line */
$scope.player.on(dashjs.MediaPlayer.events.OFFLINE_RECORD_FINISHED, function (e) { /* jshint ignore:line */
$scope.successMessage = e.message;
$('.alert.alert-success').show();
$('.alert.alert-success').fadeTo(2500, 500).slideUp(500, function () {
$('.alert.alert-success').slideUp(500);
});
}, $scope);

$scope.player.on(dashjs.MediaPlayer.events.DOWNLOADING_STOPPED, function (e) { /* jshint ignore:line */
$scope.player.on(dashjs.MediaPlayer.events.OFFLINE_RECORD_STOPPED, function (e) { /* jshint ignore:line */
$scope.warningMessage = e.message;
$('.alert.alert-warning').show();
$('.alert.alert-warning').fadeTo(2500, 500).slideUp(500, function () {
Expand All @@ -1058,7 +1057,7 @@ app.controller('DashController', function ($scope, $timeout, $q, sources, contri

$scope.hideRepresentationModal = function () {
$scope.manifestId = undefined;
$scope.downloadableRepresentations = null;
$scope.mediaInfos = null;
$('#representationModal').modal('hide');
};

Expand Down Expand Up @@ -1092,13 +1091,31 @@ app.controller('DashController', function ($scope, $timeout, $q, sources, contri
return representations;
};

$scope.onStartDownload = function () {
let selectedRepresentation = $scope.getSelectedRepresentations();
$scope.getSelectedMediaInfos = function () {
let mediaInfos = [];
$scope.mediaInfos.forEach(mediaInfo => {
let selected = false;
mediaInfo.bitrateList = mediaInfo.bitrateList.filter(bitrate => {
selected = selected || bitrate.selected;
return bitrate.selected;
});
if (selected) {
mediaInfos.push(mediaInfo);
}
});
return mediaInfos;
}

if (selectedRepresentation.video.length >= 1 ||
selectedRepresentation.audio.length >= 1 ||
selectedRepresentation.text.length >= 1) {
$scope.downloader.startDownload($scope.manifestId, selectedRepresentation);
$scope.onStartDownload = function () {
// let selectedRepresentation = $scope.getSelectedRepresentations();
let mediaInfos = $scope.getSelectedMediaInfos();

// if (selectedRepresentation.video.length >= 1 ||
// selectedRepresentation.audio.length >= 1 ||
// selectedRepresentation.text.length >= 1) {
if (mediaInfos.length) {
// $scope.offlinePlayer.getOfflineController().startRecord($scope.manifestId, selectedRepresentation);
$scope.offlinePlayer.getOfflineController().startRecord($scope.manifestId, mediaInfos);
$scope.hideRepresentationModal();
} else {
alert('You must select at least 1 quality !');
Expand Down
10 changes: 5 additions & 5 deletions samples/offline/app/offline/directives/download.js
Expand Up @@ -14,7 +14,7 @@ angular.module('DashPlayer').
scope.progressTimer = null;
scope.downloadProgression = DownloadService.getDownloadProgression(scope.download.id);
scope.isEnabled = true;

scope.$watch('download.status', function (newValue) {
if (newValue === 'created') {
scope.onCreated(scope);
Expand All @@ -35,16 +35,16 @@ angular.module('DashPlayer').
};

scope.doStop = function () {
DownloadService.doStopDownload(scope.download.id);
DownloadService.doStopRecord(scope.download.id);
};

scope.doResume = function () {
DownloadService.doResumeDownload(scope.download.id);
DownloadService.doResumeRecord(scope.download.id);
};

scope.doDelete = function () {
scope.isEnabled = false;
DownloadService.doDeleteDownload(scope.download.id);
DownloadService.doDeleteRecord(scope.download.id);
};

scope.updateDownloadProgression = function () {
Expand All @@ -56,7 +56,7 @@ angular.module('DashPlayer').

scope.isDownloadEnabled = function () {
return scope.isEnabled;
};
};

scope.canPlay = function () {
return scope.download.status === 'stopped' ||
Expand Down