Add jsmediatags

This commit is contained in:
Jordan Eldredge 2017-11-29 08:39:55 -08:00
parent 172136544e
commit 777486a288
11 changed files with 120 additions and 19 deletions

View file

@ -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) {

View file

@ -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";

View file

@ -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";
};

View file

@ -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))}

View 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);

View file

@ -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())
});

View file

@ -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 };

View file

@ -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 "???";
};

View file

@ -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)}) *** `
);

View file

@ -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",

View file

@ -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"