mirror of
https://github.com/captbaritone/webamp.git
synced 2026-07-22 17:47:16 +00:00
Add jsmediatags
This commit is contained in:
parent
172136544e
commit
777486a288
11 changed files with 120 additions and 19 deletions
|
|
@ -1,3 +1,4 @@
|
|||
import jsmediatags from "jsmediatags/dist/jsmediatags";
|
||||
import { parser, creator } from "winamp-eqf";
|
||||
import MyFile from "./myFile";
|
||||
import skinParser from "./skinParser";
|
||||
|
|
@ -42,7 +43,8 @@ import {
|
|||
TOGGLE_VISUALIZER_STYLE,
|
||||
PLAY_TRACK,
|
||||
SET_PLAYLIST_SCROLL_POSITION,
|
||||
DRAG_SELECTED
|
||||
DRAG_SELECTED,
|
||||
SET_MEDIA_TAGS
|
||||
} from "./actionTypes";
|
||||
|
||||
function playRandomTrack() {
|
||||
|
|
@ -171,15 +173,55 @@ export function loadFileFromReference(fileReference) {
|
|||
} else if (EQF_FILENAME_MATCHER.test(fileReference.name)) {
|
||||
dispatch(setEqFromFile(file));
|
||||
} else {
|
||||
const id = uniqueId();
|
||||
const url = URL.createObjectURL(fileReference);
|
||||
dispatch(loadMediaFromUrl(url, fileReference.name, true));
|
||||
dispatch(_loadMediaFromUrl(url, fileReference.name, true, id));
|
||||
dispatch(fetchMediaTags(fileReference, id));
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
let counter = 0;
|
||||
function uniqueId() {
|
||||
return counter++;
|
||||
}
|
||||
|
||||
export function _loadMediaFromUrl(url, name, autoPlay, id) {
|
||||
return { type: LOAD_AUDIO_URL, url, name, autoPlay, id };
|
||||
}
|
||||
|
||||
export function loadMediaFromUrl(url, name, autoPlay) {
|
||||
return { type: LOAD_AUDIO_URL, url, name, autoPlay, id: counter++ };
|
||||
return dispatch => {
|
||||
const id = uniqueId();
|
||||
dispatch(_loadMediaFromUrl(url, name, autoPlay, id));
|
||||
dispatch(fetchMediaTags(url, id));
|
||||
};
|
||||
}
|
||||
|
||||
export function fetchMediaTags(file, id) {
|
||||
// Workaround https://github.com/aadsm/jsmediatags/issues/83
|
||||
if (typeof file === "string" && !/^[a-z]+:\/\//i.test(file)) {
|
||||
file = `${location.protocol}//${location.host}${location.pathname}${file}`;
|
||||
}
|
||||
return dispatch => {
|
||||
try {
|
||||
jsmediatags.read(file, {
|
||||
onSuccess: data => {
|
||||
const { artist, title } = data.tags;
|
||||
// There's more data here, but we don't have a use for it yet:
|
||||
// https://github.com/aadsm/jsmediatags#shortcuts
|
||||
dispatch({ type: SET_MEDIA_TAGS, artist, title, id });
|
||||
},
|
||||
onError: () => {
|
||||
// Nothing to do. The filename will have to suffice.
|
||||
}
|
||||
});
|
||||
} catch (e) {
|
||||
// Possibly jsmediatags could not find a parser for this file?
|
||||
// Nothing to do.
|
||||
// Consider removing this after https://github.com/aadsm/jsmediatags/issues/83 is resolved.
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
export function setSkinFromFile(skinFile) {
|
||||
|
|
|
|||
|
|
@ -56,3 +56,4 @@ export const RANDOMIZE_LIST = "RANDOMIZE_LIST";
|
|||
export const SET_TRACK_ORDER = "SET_TRACK_ORDER";
|
||||
export const PLAY_TRACK = "PLAY_TRACK";
|
||||
export const DRAG_SELECTED = "DRAG_SELECTED";
|
||||
export const SET_MEDIA_TAGS = "SET_MEDIA_TAGS";
|
||||
|
|
|
|||
|
|
@ -7,7 +7,7 @@ import { getTimeStr } from "../../utils";
|
|||
import { STEP_MARQUEE } from "../../actionTypes";
|
||||
import CharacterString from "../CharacterString";
|
||||
import { noMarquee } from "../../config";
|
||||
import { getCurrentTrackNumber } from "../../selectors";
|
||||
import { getMediaText } from "../../selectors";
|
||||
|
||||
const CHAR_WIDTH = 5;
|
||||
|
||||
|
|
@ -30,9 +30,6 @@ export const getPositionText = (duration, seekToPercent) => {
|
|||
return `Seek to: ${newElapsedStr}/${durationStr} (${seekToPercent}%)`;
|
||||
};
|
||||
|
||||
export const getMediaText = (trackNumber, name, duration) =>
|
||||
`${trackNumber}. ${name} (${getTimeStr(duration)}) *** `;
|
||||
|
||||
export const getDoubleSizeModeText = enabled =>
|
||||
`${enabled ? "Disable" : "Enable"} doublesize mode`;
|
||||
|
||||
|
|
@ -158,9 +155,8 @@ const getMarqueeText = state => {
|
|||
default:
|
||||
break;
|
||||
}
|
||||
if (state.media.name) {
|
||||
const trackNumber = getCurrentTrackNumber(state);
|
||||
return getMediaText(trackNumber, state.media.name, state.media.length);
|
||||
if (state.playlist.currentTrack != null) {
|
||||
return getMediaText(state);
|
||||
}
|
||||
return "Winamp 2.91";
|
||||
};
|
||||
|
|
|
|||
|
|
@ -3,9 +3,10 @@ import { connect } from "react-redux";
|
|||
|
||||
import { getTimeStr } from "../../utils";
|
||||
import { TRACK_HEIGHT } from "../../constants";
|
||||
import { dragSelected} from "../../actionCreators";
|
||||
import { dragSelected } from "../../actionCreators";
|
||||
import { getVisibleTrackIds, getScrollOffset } from "../../selectors";
|
||||
import TrackCell from "./TrackCell";
|
||||
import TrackTitle from "./TrackTitle";
|
||||
|
||||
class TrackList extends React.Component {
|
||||
constructor(props) {
|
||||
|
|
@ -47,7 +48,7 @@ class TrackList extends React.Component {
|
|||
{this._renderTracks((id, i) => `${i + 1 + offset}.`)}
|
||||
</div>
|
||||
<div className="playlist-track-titles">
|
||||
{this._renderTracks(id => tracks[id].title)}
|
||||
{this._renderTracks(id => <TrackTitle id={id} />)}
|
||||
</div>
|
||||
<div className="playlist-track-durations">
|
||||
{this._renderTracks(id => getTimeStr(tracks[id].duration))}
|
||||
|
|
|
|||
11
js/components/PlaylistWindow/TrackTitle.js
Normal file
11
js/components/PlaylistWindow/TrackTitle.js
Normal file
|
|
@ -0,0 +1,11 @@
|
|||
import React from "react";
|
||||
import { connect } from "react-redux";
|
||||
import { getTrackDisplayName } from "../../selectors";
|
||||
|
||||
const TrackTitle = props => <span>{props.title}</span>;
|
||||
|
||||
const mapStateToProps = (state, ownProps) => ({
|
||||
title: getTrackDisplayName(state, ownProps.id)
|
||||
});
|
||||
|
||||
export default connect(mapStateToProps)(TrackTitle);
|
||||
|
|
@ -51,7 +51,6 @@ export default media => store => {
|
|||
kbps: "128",
|
||||
khz: Math.round(media.sampleRate() / 1000).toString(),
|
||||
channels: media.channels(),
|
||||
name: media.name,
|
||||
length: media.duration(),
|
||||
id: getCurrentTrackId(store.getState())
|
||||
});
|
||||
|
|
|
|||
|
|
@ -206,7 +206,6 @@ const media = (state, action) => {
|
|||
khz: null,
|
||||
volume: 50,
|
||||
balance: 0,
|
||||
name: "",
|
||||
channels: null,
|
||||
shuffle: false,
|
||||
repeat: false,
|
||||
|
|
@ -215,6 +214,7 @@ const media = (state, action) => {
|
|||
};
|
||||
}
|
||||
switch (action.type) {
|
||||
// TODO: Make these constants
|
||||
case "PLAY":
|
||||
case "IS_PLAYING":
|
||||
return { ...state, status: "PLAYING" };
|
||||
|
|
@ -236,8 +236,7 @@ const media = (state, action) => {
|
|||
length: null,
|
||||
kbps: null,
|
||||
khz: null,
|
||||
channels: null,
|
||||
name: null
|
||||
channels: null
|
||||
};
|
||||
case SET_MEDIA:
|
||||
return {
|
||||
|
|
@ -245,8 +244,7 @@ const media = (state, action) => {
|
|||
length: action.length,
|
||||
kbps: action.kbps,
|
||||
khz: action.khz,
|
||||
channels: action.channels,
|
||||
name: action.name
|
||||
channels: action.channels
|
||||
};
|
||||
case SET_VOLUME:
|
||||
return { ...state, volume: action.volume };
|
||||
|
|
|
|||
|
|
@ -12,7 +12,8 @@ import {
|
|||
RANDOMIZE_LIST,
|
||||
SET_TRACK_ORDER,
|
||||
PLAY_TRACK,
|
||||
DRAG_SELECTED
|
||||
DRAG_SELECTED,
|
||||
SET_MEDIA_TAGS
|
||||
} from "../actionTypes";
|
||||
|
||||
import { shuffle, moveSelected, mapObject, filterObject } from "../utils";
|
||||
|
|
@ -118,6 +119,18 @@ const playlist = (state = defaultPlaylistState, action) => {
|
|||
}
|
||||
}
|
||||
};
|
||||
case SET_MEDIA_TAGS:
|
||||
return {
|
||||
...state,
|
||||
tracks: {
|
||||
...state.tracks,
|
||||
[action.id]: {
|
||||
...state.tracks[action.id],
|
||||
title: action.title,
|
||||
artist: action.artist
|
||||
}
|
||||
}
|
||||
};
|
||||
case PLAY_TRACK:
|
||||
return {
|
||||
...state,
|
||||
|
|
@ -141,3 +154,13 @@ const playlist = (state = defaultPlaylistState, action) => {
|
|||
};
|
||||
|
||||
export default playlist;
|
||||
|
||||
export const getTrackDisplayName = (state, id) => {
|
||||
const { artist, title } = state.tracks[id];
|
||||
if (artist && title) {
|
||||
return `${artist} - ${title}`;
|
||||
} else if (title) {
|
||||
return title;
|
||||
}
|
||||
return "???";
|
||||
};
|
||||
|
|
|
|||
|
|
@ -5,6 +5,7 @@ import {
|
|||
TRACK_HEIGHT
|
||||
} from "./constants";
|
||||
import { createSelector } from "reselect";
|
||||
import * as fromPlaylist from "./reducers/playlist";
|
||||
|
||||
export const getEqfData = state => {
|
||||
const { sliders } = state.equalizer;
|
||||
|
|
@ -137,3 +138,21 @@ export const getVisibleTrackIds = createSelector(
|
|||
(offset, trackOrder, numberOfVisibleTracks) =>
|
||||
trackOrder.slice(offset, offset + numberOfVisibleTracks)
|
||||
);
|
||||
|
||||
export const getPlaylist = state => state.playlist;
|
||||
export const getDuration = state => state.media.length;
|
||||
export const getTrackDisplayName = (state, trackId) =>
|
||||
fromPlaylist.getTrackDisplayName(getPlaylist(state), trackId);
|
||||
|
||||
export const getCurrentTrackDisplayName = state => {
|
||||
const id = getCurrentTrackId(state);
|
||||
return getTrackDisplayName(state, id);
|
||||
};
|
||||
|
||||
export const getMediaText = createSelector(
|
||||
getCurrentTrackNumber,
|
||||
getCurrentTrackDisplayName,
|
||||
getDuration,
|
||||
(trackNumber, name, duration) =>
|
||||
`${trackNumber}. ${name} (${getTimeStr(duration)}) *** `
|
||||
);
|
||||
|
|
|
|||
|
|
@ -66,6 +66,7 @@
|
|||
"classnames": "^2.2.5",
|
||||
"eslint-plugin-import": "^2.7.0",
|
||||
"jest": "^21.2.1",
|
||||
"jsmediatags": "^3.8.1",
|
||||
"jszip": "^3.1.3",
|
||||
"prettier": "^1.6.0",
|
||||
"prop-types": "^15.5.10",
|
||||
|
|
|
|||
10
yarn.lock
10
yarn.lock
|
|
@ -3635,6 +3635,12 @@ jsesc@~0.5.0:
|
|||
version "0.5.0"
|
||||
resolved "https://registry.yarnpkg.com/jsesc/-/jsesc-0.5.0.tgz#e7dee66e35d6fc16f710fe91d5cf69f70f08911d"
|
||||
|
||||
jsmediatags@^3.8.1:
|
||||
version "3.8.1"
|
||||
resolved "https://registry.yarnpkg.com/jsmediatags/-/jsmediatags-3.8.1.tgz#e27d26e957b0b330c28f9762c82940c4dcc64720"
|
||||
dependencies:
|
||||
xhr2 "^0.1.4"
|
||||
|
||||
json-loader@^0.5.4:
|
||||
version "0.5.4"
|
||||
resolved "https://registry.yarnpkg.com/json-loader/-/json-loader-0.5.4.tgz#8baa1365a632f58a3c46d20175fc6002c96e37de"
|
||||
|
|
@ -6066,6 +6072,10 @@ write@^0.2.1:
|
|||
dependencies:
|
||||
mkdirp "^0.5.1"
|
||||
|
||||
xhr2@^0.1.4:
|
||||
version "0.1.4"
|
||||
resolved "https://registry.yarnpkg.com/xhr2/-/xhr2-0.1.4.tgz#7f87658847716db5026323812f818cadab387a5f"
|
||||
|
||||
xml-name-validator@^2.0.1:
|
||||
version "2.0.1"
|
||||
resolved "https://registry.yarnpkg.com/xml-name-validator/-/xml-name-validator-2.0.1.tgz#4d8b8f1eccd3419aa362061becef515e1e559635"
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue