Skip to content
This repository has been archived by the owner on Apr 19, 2024. It is now read-only.

Commit

Permalink
implement sound cloud progress
Browse files Browse the repository at this point in the history
  • Loading branch information
fikryfahrezy committed Jul 4, 2023
1 parent 450686d commit dd54bb9
Show file tree
Hide file tree
Showing 10 changed files with 125 additions and 65 deletions.
2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "svelte-player",
"version": "0.0.7",
"version": "0.0.8",
"license": "MIT",
"repository": {
"type": "git",
Expand Down
1 change: 1 addition & 0 deletions src/lib/PlayerMedia.svelte
Original file line number Diff line number Diff line change
Expand Up @@ -342,6 +342,7 @@
{width}
{height}
{muted}
{volume}
bind:this={player}
on:mount={handlePlayerMount}
on:ready={handleReady}
Expand Down
1 change: 1 addition & 0 deletions src/lib/players/FilePlayer.svelte
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@
export let playing: boolean;
export let loop: boolean;
export let controls: boolean;
export const volume: number | null = null; // not used yet, but for suppress the warn from svelte check
export let muted: boolean;
export let width: string;
export let height: string;
Expand Down
1 change: 1 addition & 0 deletions src/lib/players/NotImplemented.svelte
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@
export const playing: boolean | undefined = undefined;
export const loop: boolean | undefined = undefined;
export const controls: boolean | undefined = undefined;
export const volume: number | null = null;
export const muted: boolean | undefined = undefined;
export const width: string | undefined = undefined;
export const height: string | undefined = undefined;
Expand Down
100 changes: 56 additions & 44 deletions src/lib/players/SoundCloud.svelte
Original file line number Diff line number Diff line change
Expand Up @@ -10,11 +10,12 @@
export const playing: boolean | undefined = undefined;
export const loop: boolean | undefined = undefined;
export const controls: boolean | undefined = undefined;
export let volume: number | null;
export const muted: boolean | undefined = undefined;
export const width: string | undefined = undefined;
export const height: string | undefined = undefined;
export const playsinline: boolean | undefined = undefined;
export const config: SoundCloudConfig | undefined = undefined;
export let config: SoundCloudConfig;
function handlePropsUrlChange(propsUrl: typeof url) {
if (propsUrl instanceof Array) {
Expand All @@ -33,11 +34,15 @@
let iframeContainer: HTMLIFrameElement | undefined;
let player: SoundCloudPlayer | undefined;
let duration = 0;
let currentTime = 0;
let fractionLoaded = 0;
onMount(() => {
dispatch('mount');
});
export function load(url: FilePlayerUrl, isReady?: boolean): void {
export function load(url: string, isReady?: boolean): void {
getSDK({
url: SDK_URL,
sdkGlobal: SDK_GLOBAL
Expand All @@ -48,94 +53,101 @@
const { PLAY, PLAY_PROGRESS, PAUSE, FINISH, ERROR } = SC.Widget.Events;
if (!isReady) {
player = SC.Widget(iframeContainer);
player.bind(PLAY, () => {
dispatch('play');
});
player.bind(PAUSE, () => {
const remaining = duration - currentTime;
if (remaining < 0.05) {
// Prevent onPause firing right before onEnded
return;
}
dispatch('pause');
});
player.bind(PLAY_PROGRESS, (e) => {
currentTime = e.currentPosition / 1000;
fractionLoaded = e.loadedProgress;
});
player.bind(FINISH, () => {
dispatch('ended');
});
player.bind(ERROR, (e) => {
dispatch('error', { error: e });
});
}
if (player !== undefined) {
player.load(url, {
...config.options,
callback: () => {
if (player !== undefined) {
player.getDuration((duration) => {
duration = duration / 1000;
dispatch('ready');
});
}
}
});
}
});
}
export function play(): void {
if (player !== undefined) {
// do something
player.play();
}
console.log('play');
}
export function pause() {
if (player !== undefined) {
// do something
player.pause();
}
console.log('pause');
}
export function stop() {
if (player !== undefined) {
// do something
}
console.log('stop');
// do nothing, no implementation
}
export function seekTo(amount: number, keepPlaying?: boolean): void {
export function seekTo(seconds: number, _?: boolean): void {
if (player !== undefined) {
// do something
player.seekTo(seconds * 1000);
}
console.log('seekTo');
}
export function setVolume(fraction: number): void {
if (player !== undefined) {
// do something
player.seekTo(fraction * 100);
}
console.log('setVolume');
}
export function mute(): void {
if (player !== undefined) {
// do something
}
console.log('mute');
setVolume(0);
}
export function unmute(): void {
if (player !== undefined) {
// do something
if (volume !== null) {
setVolume(volume);
}
console.log('unmute');
}
export function setPlaybackRate(rate: number): void {
if (player !== undefined) {
// do something
}
console.log('setPlaybackRate');
// do nothing, no implementation
}
export function setLoop(loop: boolean): void {
if (player !== undefined) {
// do something
}
console.log('setLoop');
// do nothing, no implementation
}
export function getDuration(): number {
if (player !== undefined) {
return 0;
}
return 0;
return duration;
}
export function getCurrentTime(): number {
if (player !== undefined) {
return 0;
}
return 0;
return currentTime;
}
export function getSecondsLoaded(): number {
if (player !== undefined) {
return 0;
}
return 0;
return fractionLoaded * duration;
}
export function getPlayer(): GetPlayerReturn | null {
Expand Down
1 change: 1 addition & 0 deletions src/lib/players/Twitch.svelte
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@
export let playing: boolean;
export const loop: boolean | undefined = undefined;
export let controls: boolean;
export const volume: number | null = null; // not used yet, but for suppress the warn from svelte check
export let muted: boolean;
export const width: string | undefined = undefined;
export const height: string | undefined = undefined;
Expand Down
1 change: 1 addition & 0 deletions src/lib/players/YouTube.svelte
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@
export let playing: boolean;
export let loop: boolean;
export let controls: boolean;
export const volume: number | null = null; // not used yet, but for suppress the warn from svelte check
export const muted: boolean | undefined = undefined; // not used yet, but for suppress the warn from svelte check
export const width: string | undefined = undefined; // not used yet, but for suppress the warn from svelte check
export const height: string | undefined = undefined; // not used yet, but for suppress the warn from svelte check
Expand Down
67 changes: 49 additions & 18 deletions src/lib/players/global-types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -347,6 +347,7 @@ export type Twitch = {
Player: TwitchPlayerConstructor;
};

// https://developers.soundcloud.com/docs/api/html5-widget
export type SoundCloudWidgetLOAD_PROGRESSEvent = 'loadProgress';
export type SoundCloudWidgetPLAY_PROGRESSEvent = 'playProgress';
export type SoundCloudWidgetPLAYEvent = 'play';
Expand All @@ -355,9 +356,9 @@ export type SoundCloudWidgetFINISHEvent = 'finish';
export type SoundCloudWidgetSEEKEvent = 'seek';

export type SoundCloudUIREADYEvent = 'ready';
export type SoundCloudUICLICK_DOWNLOADEvent = 'clickDownload ';
export type SoundCloudUICLICK_BUYEvent = 'clickBuy';
export type SoundCloudUIOPEN_SHARE_PANELEvent = 'openSharePanel';
export type SoundCloudUICLICK_DOWNLOADEvent = 'downloadClicked';
export type SoundCloudUICLICK_BUYEvent = 'buyClicked';
export type SoundCloudUIOPEN_SHARE_PANELEvent = 'sharePanelOpened';
export type SoundCloudUIERROREvent = 'error';

export type SoundCloudPlayerEVENT =
Expand Down Expand Up @@ -387,34 +388,64 @@ export type SoundCloudWidgetEvents = {
ERROR: SoundCloudUIERROREvent;
};

// TODO: Implement this
export type SoundCloudPlayerLoadOptions = {
auto_play: boolean;
color: string /* hex code, example #0066CC */;
buying: boolean;
sharing: boolean;
download: boolean;
show_artwork: boolean;
show_playcount: boolean;
show_user: boolean;
start_track: number /* from 0 */;
single_active: boolean;
callback(): void;
visual: boolean; // Undocumented, but makes player fill container and look better
};

export type SoundCloudPlayerBindCallbackParams = {
soundId: number;
loadedProgress: number;
currentPosition: number;
relativePosition: number;
};

export type SoundCloudPlayerBindCallbackFn = (params: SoundCloudPlayerBindCallbackParams) => void;

// TODO: Fix the any / unknown types
export type SoundCloudPlayer = {
bind(): void;
unbind(): void;
load(): void;
bind(
event: Exclude<SoundCloudPlayerEVENT, SoundCloudUIERROREvent>,
listener: SoundCloudPlayerBindCallbackFn
): void;
bind(
event: Extract<SoundCloudPlayerEVENT, SoundCloudUIERROREvent>,
listener: (e: unknown) => void
): void;
unbind(event: SoundCloudPlayerEVENT): void;
load(url: string, options?: Partial<SoundCloudPlayerLoadOptions>): void;
play(): void;
pause(): void;
toggle(): void;
seekTo(): void;
setVolume(): void;
seekTo(milliseconds: number): void;
setVolume(volume: number /* range 0-100 */): void;
next(): void;
prev(): void;
skip(): void;
getVolume(): void;
getDuration(): void;
getPosition(): void;
getSounds(): void;
getCurrentSound(): void;
getCurrentSoundIndex(): void;
isPaused(): void;
skip(soundIndex: number /* starting from 0 */): void;
getVolume(callback: AnyFunction): number /* range 0-100 */;
getDuration(callback: AnyFunction): number /* in millisecond */;
getPosition(callback: AnyFunction): number /* in millisecond */;
getSounds(callback: AnyFunction): Record<string, never>[];
getCurrentSound(callback: AnyFunction): Record<string, never>;
getCurrentSoundIndex(callback: AnyFunction): number /* index of current sound */;
isPaused(callback: AnyFunction): boolean;
};

export interface SoundCloudWidget {
(container: string | HTMLIFrameElement): SoundCloudPlayer;
Events: SoundCloudWidgetEvents;
}

// https://developers.soundcloud.com/docs/api/html5-widget
export type SoundCloud = {
Widget: SoundCloudWidget;
};
Expand Down
6 changes: 5 additions & 1 deletion src/lib/players/sound-cloud-types.ts
Original file line number Diff line number Diff line change
@@ -1 +1,5 @@
export type SoundCloudConfig = Partial<Record<string, never>>;
import type { SoundCloudPlayerLoadOptions } from './global-types';

export type SoundCloudConfig = {
options: Partial<SoundCloudPlayerLoadOptions>;
};
10 changes: 9 additions & 1 deletion src/lib/props.ts
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,15 @@ export const defaultConfig: Config = {
embedOptions: {},
onUnstarted: noop
},
soundcloud: {},
soundcloud: {
options: {
visual: true,
buying: false,
download: false,
sharing: false,
show_playcount: false
}
},
twitch: {
options: {},
playerId: null
Expand Down

0 comments on commit dd54bb9

Please sign in to comment.