diff --git a/CHANGELOG.md b/CHANGELOG.md index d100c196..c1bf0c93 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -3,6 +3,7 @@ ### Features - Added optional configuration option `handleTrackDropEvent` which lets you decide how drop events get converted into tracks. +- New Webamp instance methods: `.stop()`, `.getMediaStatus()`, and `.seekToTime(seconds)`. See [usage.md](./docs/usage.md) for more details. ### Bug Fixes: diff --git a/docs/usage.md b/docs/usage.md index a0cf0e4c..f8844447 100644 --- a/docs/usage.md +++ b/docs/usage.md @@ -219,6 +219,22 @@ Seek backward n seconds in the current track. webamp.seekBackward(10); ``` +### `seekToTime(seconds)` + +Seek to a given time within the current track. + +```JavaScript +webamp.seekToTime(15.5); +``` + +### `getMediaStatus()` + +Get the current "playing" status. The return value is one of: `"PLAYING"`, `"STOPPED"`, or `"PAUSED"`. + +```JavaScript +const isPlaying = webamp.getMediaStatus() === "PLAYING"; +``` + ### `pause(): void` Pause the current track. @@ -235,6 +251,14 @@ Play the current track. webamp.play(); ``` +### `stop(): void` + +Stop the currently playing audio. Equivilant to pressing the "stop" button. + +```JavaScript +webamp.stop(); +``` + ### `renderWhenReady(domNode: HTMLElement): Promise` Webamp will wait until it has fetched the skin and fully parsed it, and then render itself into a new DOM node at the end of the `` tag. diff --git a/index.d.ts b/index.d.ts index 139edb27..98cf83b1 100644 --- a/index.d.ts +++ b/index.d.ts @@ -169,6 +169,11 @@ export default class Webamp { */ public seekBackward(seconds: number): void; + /** + * Seek to a given time within the current track + */ + public seekToTime(seconds: number): void; + /** * Pause the current tack */ @@ -179,6 +184,11 @@ export default class Webamp { */ public play(): void; + /** + * Stop the currently playing audio. Equivilant to pressing the "stop" button + */ + public stop(): void; + /** * Webamp will wait until it has fetched the skin and fully parsed it and then render itself. * @@ -203,6 +213,11 @@ export default class Webamp { cb: (trackInfo: LoadedURLTrack | null) => void ): () => void; + /** + * Get the current "playing" status. + */ + public getMediaStatus(): "PLAYING" | "STOPPED" | "PAUSED"; + /** * A callback which will be called when Webamp is _about to_ close. Returns an * "unsubscribe" function. The callback will be passed a `cancel` function diff --git a/js/actionCreators/index.ts b/js/actionCreators/index.ts index a0b2b96d..83f3473c 100644 --- a/js/actionCreators/index.ts +++ b/js/actionCreators/index.ts @@ -45,6 +45,7 @@ export { nextN, next, previous, + seekToTime, seekForward, seekBackward, setVolume, diff --git a/js/actionCreators/media.ts b/js/actionCreators/media.ts index 203eb529..bfa13a27 100644 --- a/js/actionCreators/media.ts +++ b/js/actionCreators/media.ts @@ -88,21 +88,25 @@ export function previous(): Dispatchable { return nextN(-1); } -export function seekForward(seconds: number): Dispatchable { +export function seekToTime(seconds: number): Dispatchable { return function(dispatch, getState) { const state = getState(); - const timeElapsed = Selectors.getTimeElapsed(state); const duration = Selectors.getDuration(state); if (duration == null) { return; } - const newTimeElapsed = timeElapsed + seconds; dispatch({ type: SEEK_TO_PERCENT_COMPLETE, - percent: (newTimeElapsed / duration) * 100, + percent: (seconds / duration) * 100, }); }; } +export function seekForward(seconds: number): Dispatchable { + return function(dispatch, getState) { + const timeElapsed = Selectors.getTimeElapsed(getState()); + dispatch(seekToTime(timeElapsed + seconds)); + }; +} export function seekBackward(seconds: number): Dispatchable { return seekForward(-seconds); diff --git a/js/reducers/media.ts b/js/reducers/media.ts index 8abf0cb6..890ac7dd 100644 --- a/js/reducers/media.ts +++ b/js/reducers/media.ts @@ -25,7 +25,7 @@ export interface MediaState { balance: number; shuffle: boolean; repeat: boolean; - status: MediaStatus | null; // TODO: Convert this to an enum + status: MediaStatus; } const defaultState = { diff --git a/js/selectors.ts b/js/selectors.ts index 06e14038..d51bc8e1 100644 --- a/js/selectors.ts +++ b/js/selectors.ts @@ -8,6 +8,7 @@ import { WindowPositions, PlaylistStyle, TransitionType, + MediaStatus, } from "./types"; import { createSelector } from "reselect"; import * as Utils from "./utils"; @@ -269,6 +270,10 @@ export const getCurrentTrackDisplayName = createSelector( } ); +export const getMediaStatus = (state: AppState): MediaStatus | null => { + return state.media.status; +}; + export const getMediaIsPlaying = (state: AppState) => state.media.status === MEDIA_STATUS.PLAYING; diff --git a/js/webampLazy.tsx b/js/webampLazy.tsx index 9e15b643..24b914ae 100644 --- a/js/webampLazy.tsx +++ b/js/webampLazy.tsx @@ -302,6 +302,10 @@ class Winamp { this.store.dispatch(Actions.pause()); } + stop() { + this.store.dispatch(Actions.stop()); + } + seekBackward(seconds: number) { this.store.dispatch(Actions.seekBackward(seconds)); } @@ -310,6 +314,10 @@ class Winamp { this.store.dispatch(Actions.seekForward(seconds)); } + seekToTime(seconds: number) { + this.store.dispatch(Actions.seekToTime(seconds)); + } + nextTrack() { this.store.dispatch(Actions.next()); } @@ -338,6 +346,10 @@ class Winamp { this.store.dispatch(Actions.loadMediaFiles(tracks, LOAD_STYLE.PLAY)); } + getMediaStatus() { + return Selectors.getMediaStatus(this.store.getState()); + } + onWillClose(cb: (cancel: () => void) => void): () => void { return this._actionEmitter.on(CLOSE_REQUESTED, action => { cb(action.cancel);