Skip to content

Commit

Permalink
Creating the first version of a feature to restore current song's pla…
Browse files Browse the repository at this point in the history
…yback position when closing/opening the player
  • Loading branch information
carlosrafaelgn committed Jul 22, 2022
1 parent 13a711e commit a8a0780
Show file tree
Hide file tree
Showing 14 changed files with 334 additions and 208 deletions.
Binary file modified Android/app/release/app-release.apk
Binary file not shown.
159 changes: 82 additions & 77 deletions Android/app/src/main/assets/assets/js/scripts.min.js

Large diffs are not rendered by default.

6 changes: 3 additions & 3 deletions Android/app/src/main/assets/index.html
Original file line number Diff line number Diff line change
Expand Up @@ -53,8 +53,8 @@
--playlist-item-size: 56px;
}
</style>
<link rel="stylesheet" type="text/css" href="assets/css/graphicalFilterEditor.css?20220712" />
<link rel="stylesheet" type="text/css" href="assets/css/style.css?20220712" />
<link rel="stylesheet" type="text/css" href="assets/css/graphicalFilterEditor.css?20220722" />
<link rel="stylesheet" type="text/css" href="assets/css/style.css?20220722" />
</head>
<body>
<div id="ruler" style="position: absolute; z-index: -1; left: 0; top: 0; height: 8rem; visibility: hidden; pointer-events: none;"></div>
Expand Down Expand Up @@ -161,7 +161,7 @@
//<![CDATA[
"use strict";

var CACHE_VERSION = "20220712";
var CACHE_VERSION = "20220722";

(function () {
if (location.href.startsWith("file://")) {
Expand Down
159 changes: 82 additions & 77 deletions docs/assets/js/scripts.min.js

Large diffs are not rendered by default.

6 changes: 3 additions & 3 deletions docs/index.html
Original file line number Diff line number Diff line change
Expand Up @@ -76,8 +76,8 @@
--playlist-item-size: 56px;
}
</style>
<link rel="stylesheet" type="text/css" href="assets/css/graphicalFilterEditor.css?20220712" />
<link rel="stylesheet" type="text/css" href="assets/css/style.css?20220712" />
<link rel="stylesheet" type="text/css" href="assets/css/graphicalFilterEditor.css?20220722" />
<link rel="stylesheet" type="text/css" href="assets/css/style.css?20220722" />
</head>
<body>
<div id="ruler" style="position: absolute; z-index: -1; left: 0; top: 0; height: 8rem; visibility: hidden; pointer-events: none;"></div>
Expand Down Expand Up @@ -184,7 +184,7 @@
//<![CDATA[
"use strict";

var CACHE_VERSION = "20220712";
var CACHE_VERSION = "20220722";

(function () {
if (location.href.startsWith("file://")) {
Expand Down
2 changes: 1 addition & 1 deletion docs/sw.js
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,7 @@
// whenever it detects a change in the source code of the
// service worker).
const CACHE_PREFIX = "fplay-static-cache-";
const CACHE_VERSION = "20220712";
const CACHE_VERSION = "20220722";
const CACHE_NAME = CACHE_PREFIX + CACHE_VERSION;

self.addEventListener("install", (event) => {
Expand Down
10 changes: 3 additions & 7 deletions scripts/app.ts
Original file line number Diff line number Diff line change
Expand Up @@ -57,7 +57,6 @@ interface AppCloseHandler {
interface AppSettings {
devicePixelRatio?: number;
playerVolume?: number;
playerPossibleResumeTimeS?: number;
graphicalFilterControlEnabled?: boolean;
graphicalFilterControlSimpleMode?: boolean;
stereoPannerControlEnabled?: boolean;
Expand Down Expand Up @@ -127,10 +126,11 @@ class App {
promises: Promise<void>[] = [],
playlist = App.player.playlist;

App.player.setPlaylistData();

InternalStorage.saveAppSettings({
devicePixelRatio: devicePixelRatio,
playerVolume: App.player.volume,
playerPossibleResumeTimeS: App.player.possibleResumeTimeS,
graphicalFilterControlEnabled: (App.graphicalFilterControl ? App.graphicalFilterControl.enabled : false),
graphicalFilterControlSimpleMode: (App.graphicalFilterControl ? App.graphicalFilterControl.simpleMode : true),
stereoPannerControlEnabled: (App.stereoPannerControl ? App.stereoPannerControl.enabled : false),
Expand Down Expand Up @@ -319,6 +319,7 @@ class App {

App.player = new Player(
appSettings.playerVolume,
InternalStorage.loadPlaylistWeb(),

function (audioContext) {
App.graphicalFilterControl = new GraphicalFilterControl(document.getElementById("filter-container") as HTMLDivElement, document.getElementById("optional-panel-container") as HTMLDivElement, audioContext, appSettings.graphicalFilterControlSimpleMode);
Expand All @@ -343,11 +344,6 @@ class App {
}
);

const playlist = InternalStorage.loadPlaylistWeb();

if (playlist)
App.player.playlist = playlist;

AppUI.init(appSettings);

App.loading = false;
Expand Down
35 changes: 22 additions & 13 deletions scripts/data/list.ts
Original file line number Diff line number Diff line change
Expand Up @@ -205,20 +205,31 @@ class List<T> {
return total + 128;
}

public serialize(writer?: DataWriter | null): DataWriter {
const items = this.items,
count = items.length;
protected get version(): number {
return 0;
}

protected serializeExtraProperties(writer: DataWriter, count: number): DataWriter {
return writer;
}

protected serializeExtraPropertiesWeb(serializedObject: any): any {
return serializedObject;
}

public serialize(writer?: DataWriter | null): DataWriter {
if (!writer)
writer = new DataWriter(this.estimateSerializedLength());

if (!items || !items[0] || !("serialize" in items[0]))
return writer;
const items = this.items,
count = ((items && items[0] && ("serialize" in items[0])) ? items.length : 0);

writer.writeUint8(0) // version
writer.writeUint8(this.version)
.writeInt32(count)
.writeInt32(this._currentIndex);

this.serializeExtraProperties(writer, count);

for (let i = 0; i < count; i++)
(items[i] as any).serialize(writer);

Expand All @@ -227,18 +238,16 @@ class List<T> {

public serializeWeb(): any {
const items = this.items,
count = items.length,
count = ((items && items[0] && ("serializeWeb" in items[0])) ? items.length : 0),
tmp = new Array(count);

if (items && items[0] && ("serializeWeb" in items[0])) {
for (let i = 0; i < count; i++)
tmp[i] = (items[i] as any).serializeWeb();
}
for (let i = 0; i < count; i++)
tmp[i] = (items[i] as any).serializeWeb();

return {
return this.serializeExtraPropertiesWeb({
currentIndex: this._currentIndex,
items: tmp
};
});
}

public moveCurrentToPrevious(): number {
Expand Down
8 changes: 7 additions & 1 deletion scripts/data/metadataExtractor.ts
Original file line number Diff line number Diff line change
Expand Up @@ -24,8 +24,13 @@
// https://github.com/carlosrafaelgn/FPlayWeb
//

enum MetadataFlags {
Seekable = 1
};

interface Metadata {
url: string;
flags: MetadataFlags;
title?: string | null;
artist?: string | null;
album?: string | null;
Expand Down Expand Up @@ -738,7 +743,8 @@ class MetadataExtractor {

private static async extractID3v2Andv1(file: File, f: BufferedFileHandle, tmpPtr: Uint8Array[]): Promise<Metadata | null> {
const metadata: Metadata = {
url: FileUtils.urlOrPathToURL((file as any)["data-path"]) || ""
url: FileUtils.urlOrPathToURL((file as any)["data-path"]) || "",
flags: MetadataFlags.Seekable
};

if (!metadata.url) {
Expand Down
72 changes: 62 additions & 10 deletions scripts/player/player.ts
Original file line number Diff line number Diff line change
Expand Up @@ -51,6 +51,8 @@ class Player {
private lastObjectURL: string | null;
private lastTimeS: number;
private songStartedAutomatically: boolean;
private songToResumeTime: Song | null;
private resumeTimeS: number;

private readonly mediaSession: any | null;

Expand All @@ -69,7 +71,7 @@ class Player {
public oncurrenttimeschange: ((currentTimeS: number) => void) | null;
public onerror: ((message: string) => void) | null;

public constructor(volume?: number, ...intermediateNodesFactory: IntermediateNodeFactory[]) {
public constructor(volume?: number, playlist?: Playlist | null, ...intermediateNodesFactory: IntermediateNodeFactory[]) {
this.audioContextTimeout = 0;
this.audioContextSuspended = true;
// https://developer.mozilla.org/en-US/docs/Web/API/AudioContext/AudioContext#options
Expand Down Expand Up @@ -122,9 +124,11 @@ class Player {
this.lastObjectURL = null;
this.lastTimeS = -1;
this.songStartedAutomatically = true;
this.songToResumeTime = null;
this.resumeTimeS = 0;
this.haltOnAllErrors = false;

this.volume = (volume === undefined ? 0 : volume);
this.volume = volume || 0;

this.audio = null;
this.sourceNode = null;
Expand All @@ -146,6 +150,9 @@ class Player {
mediaSession.setActionHandler("seekforward", this.seekForward.bind(this));
mediaSession.setActionHandler("nexttrack", () => { this.next(); });
}

if (playlist)
this.playlist = playlist;
}

private recreateAudioPath(): void {
Expand Down Expand Up @@ -275,6 +282,13 @@ class Player {

this.stop();
this._playlist = playlist;

// stop() only resets these when _currentSong is not null
this.songToResumeTime = null;
this.resumeTimeS = 0;

if (playlist && playlist.currentIndexResumeTimeS > 0 && (this.songToResumeTime = playlist.currentItem))
this.resumeTimeS = playlist.currentIndexResumeTimeS;
}

public get currentSong(): Song | null {
Expand All @@ -290,13 +304,16 @@ class Player {
return -1;
}

public get possibleResumeTimeS(): number {
public get currentIndexResumeTimeS(): number {
if (this.songToResumeTime)
return this.resumeTimeS;

let t = 0;

if (this._currentSong && this._playlist && this._playlist.currentItem === this._currentSong) {
if (this._currentSong && this._currentSong.isSeekable && this._playlist && this._playlist.currentItem === this._currentSong) {
try {
if (this.audio)
t = this.audio.currentTime;
t = this.audio.currentTime || 0;
} catch (ex: any) {
// Just ignore...
}
Expand All @@ -307,6 +324,11 @@ class Player {
return t;
}

public set currentIndexResumeTimeS(currentIndexResumeTimeS: number) {
if (this.songToResumeTime)
this.resumeTimeS = currentIndexResumeTimeS;
}

private handleError(message: string): void {
const lastTimeS = this.lastTimeS;

Expand All @@ -327,7 +349,7 @@ class Player {

if (!this._playlist || !this._playlist.length)
notifyError = true;
else if (lastTimeS <= 0)
else if (lastTimeS < 0)
notifyError = !this.songStartedAutomatically;

if (notifyError && this.onerror)
Expand Down Expand Up @@ -361,6 +383,23 @@ class Player {
return;

this._loading = false;

if (this.songToResumeTime) {
if (this.audio && this.songToResumeTime === this._currentSong && this.resumeTimeS > 0) {
this.lastTimeS = this.resumeTimeS;
try {
this.audio.currentTime = this.resumeTimeS;
} catch (ex: any) {
// Just ignore...
}
const playPromise = this.audio.play();
if (playPromise)
playPromise.catch(Player.nop);
}
this.songToResumeTime = null;
this.resumeTimeS = 0;
}

//queueMicrotask(this.boundNotifyLoadingChange);
if (this.onloadingchange)
this.onloadingchange(false);
Expand Down Expand Up @@ -536,6 +575,15 @@ class Player {
this.onpausedchange(this._paused);
}*/

public setPlaylistData(): void {
const playlist = this._playlist;

if (!playlist)
return;

playlist.currentIndexResumeTimeS = this.currentIndexResumeTimeS;
}

public previous(automaticCall?: boolean): void {
if (!this._alive || !this._playlist)
return;
Expand Down Expand Up @@ -641,7 +689,9 @@ class Player {

this.audio.appendChild(source);
this.audio.load();
playPromise = this.audio.play();

if (this.songToResumeTime !== currentSong)
playPromise = this.audio.play();
}

// https://developer.mozilla.org/en-US/docs/Web/API/HTMLMediaElement/load#usage_notes
Expand Down Expand Up @@ -699,6 +749,8 @@ class Player {

this._currentSong = null;
this.lastTimeS = -1;
this.songToResumeTime = null;
this.resumeTimeS = 0;
//queueMicrotask(this.boundNotifySongChange);
this.notifySongChange();
}
Expand All @@ -722,11 +774,11 @@ class Player {
}

public seekTo(timeMS: number, relative?: boolean): void {
if (!this._alive || !this.audio || !this._currentSong || this._currentSong.lengthMS <= 0 || !this.audio.seekable || !this.audio.seekable.length)
if (!this._alive || !this.audio || !this._currentSong || !this._currentSong.isSeekable || this._currentSong.lengthMS <= 0 || !this.audio.seekable || !this.audio.seekable.length)
return;

const timeS = Math.min(this.audio.duration, Math.max(0, (timeMS / 1000) + (relative ? this.audio.currentTime : 0)));
this.lastTimeS = timeS || 0.01; // 0.01 just to indicate somesort of playback has already happened
const timeS = Math.min(this.audio.duration || 0, Math.max(0, (timeMS / 1000) + (relative ? this.audio.currentTime : 0)));
this.lastTimeS = timeS;
this.audio.currentTime = timeS;
}
}
Loading

0 comments on commit a8a0780

Please sign in to comment.