Compare commits
3
Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
c8133da5d1 | ||
|
|
bd6e2d0fac | ||
|
|
8ea13ac24e |
No files matched your search
@@ -8,7 +8,7 @@ import { getGenres, getSong, getSongExternalMetadata } from "@/api/queries";
|
||||
import type { ExternalMetadataSource } from "@/models/external-metadata";
|
||||
import type Genre from "@/models/genre";
|
||||
import type { Lyrics } from "@/models/lyrics";
|
||||
import type Song from "@/models/song";
|
||||
import type { SongWithRelations } from "@/models/song";
|
||||
import { songTypeToTranslationKey } from "@/models/utils";
|
||||
import { playTrackAtom, type TrackState } from "@/state/player";
|
||||
import { LyricsIcon, PlayIcon, SongTypeIcon } from "@/ui/icons";
|
||||
@@ -147,7 +147,11 @@ const LyricsView = ({
|
||||
);
|
||||
};
|
||||
|
||||
const InfoView = ({ song }: { song: Song | undefined }) => {
|
||||
const InfoView = ({
|
||||
song,
|
||||
}: {
|
||||
song: SongWithRelations<"master"> | undefined;
|
||||
}) => {
|
||||
const { t } = useTranslation();
|
||||
const { items: genres } = useInfiniteQuery(
|
||||
(songId) => getGenres({ song: songId }),
|
||||
@@ -179,6 +183,18 @@ const InfoView = ({ song }: { song: Song | undefined }) => {
|
||||
/>
|
||||
</View>
|
||||
</View>
|
||||
|
||||
{song?.master.ripSource ? (
|
||||
<View style={styles.row}>
|
||||
<Text
|
||||
content={`${t("fileInfo.ripSource")}:`}
|
||||
variant="itemLabel"
|
||||
/>
|
||||
<View style={styles.row}>
|
||||
<Text content={song.master.ripSource} />
|
||||
</View>
|
||||
</View>
|
||||
) : null}
|
||||
{(genres === undefined || genres.length > 0) && (
|
||||
<View style={styles.row}>
|
||||
<Text
|
||||
|
||||
@@ -65,6 +65,9 @@ export const TrackInfo = ({ trackId }: { trackId: number }) => {
|
||||
: undefined
|
||||
}
|
||||
/>
|
||||
{track?.ripSource ? (
|
||||
<Row label={t("fileInfo.ripSource")} value={track.ripSource} />
|
||||
) : null}
|
||||
<Row label={t("fileInfo.path")} value={file?.path} />
|
||||
<Row
|
||||
label={t("fileInfo.registrationDate")}
|
||||
|
||||
@@ -83,6 +83,9 @@ const TrackFileInfo = ({ trackId }: { trackId: number }) => {
|
||||
"fileInfo.duration": track.data
|
||||
? formatDuration(track.data.duration)
|
||||
: undefined,
|
||||
"fileInfo.ripSource": track.data
|
||||
? (track.data.ripSource ?? t("fileInfo.unknown"))
|
||||
: undefined,
|
||||
"fileInfo.bitRate": track.data
|
||||
? track.data.bitrate
|
||||
? `${track.data.bitrate} kbps`
|
||||
|
||||
@@ -343,15 +343,18 @@ const SongPage: Page<GetPropsTypesFrom<typeof prepareSSR>> = ({ props }) => {
|
||||
{song.data ? (
|
||||
song.data.bpm ? (
|
||||
<Typography
|
||||
sx={{
|
||||
paddingTop: 1,
|
||||
paddingBottom: 4,
|
||||
}}
|
||||
sx={{ paddingBottom: 2 }}
|
||||
>{`BPM: ${song.data.bpm}`}</Typography>
|
||||
) : null
|
||||
) : (
|
||||
<Skeleton width={"50px"} />
|
||||
)}
|
||||
|
||||
{song.data?.master.ripSource ? (
|
||||
<Typography
|
||||
sx={{ paddingBottom: 2 }}
|
||||
>{`${t("fileInfo.ripSource")}: ${song.data.master.ripSource}`}</Typography>
|
||||
) : null}
|
||||
{(genres.items === undefined ||
|
||||
genres.items.length !== 0) && (
|
||||
<Stack
|
||||
|
||||
@@ -0,0 +1,15 @@
|
||||
import * as yup from "yup";
|
||||
|
||||
export const RipSources = [
|
||||
"CD",
|
||||
"DVD",
|
||||
"BluRay",
|
||||
"Cassette",
|
||||
"Digital",
|
||||
"Vinyl",
|
||||
"Other",
|
||||
] as const;
|
||||
|
||||
export type RipSource = (typeof RipSources)[number];
|
||||
|
||||
export const RipSource = yup.mixed<RipSource>().oneOf(RipSources);
|
||||
@@ -20,6 +20,7 @@ import * as yup from "yup";
|
||||
import Illustration from "./illustration";
|
||||
import Release from "./release";
|
||||
import Resource from "./resource";
|
||||
import { RipSource } from "./rip-source";
|
||||
import Song from "./song";
|
||||
import Video from "./video";
|
||||
|
||||
@@ -84,6 +85,7 @@ const Track = Resource.concat(
|
||||
* If the Track is mixed with the previous/next track
|
||||
*/
|
||||
mixed: yup.boolean().required(),
|
||||
ripSource: RipSource.required().nullable().default(null),
|
||||
}),
|
||||
);
|
||||
|
||||
|
||||
@@ -210,6 +210,7 @@
|
||||
"name": "Name",
|
||||
"path": "Path",
|
||||
"registrationDate": "Registration Date",
|
||||
"ripSource": "Rip Source",
|
||||
"type": "Type",
|
||||
"unknown": "Unknown"
|
||||
},
|
||||
|
||||
@@ -208,6 +208,7 @@
|
||||
"name": "Nom",
|
||||
"path": "Chemin",
|
||||
"registrationDate": "Date d'ajout",
|
||||
"ripSource": "Source du rip",
|
||||
"type": "Type",
|
||||
"unknown": "Inconnu"
|
||||
},
|
||||
|
||||
@@ -170,6 +170,9 @@ func SaveMetadata(config config.Config, m internal.Metadata, saveMethod SaveMeta
|
||||
mp.WriteField("label", m.Label)
|
||||
}
|
||||
mp.WriteField("type", string(m.Type))
|
||||
if len(m.RipSource) > 0 {
|
||||
mp.WriteField("ripSource", string(m.RipSource))
|
||||
}
|
||||
for i, genre := range m.Genres {
|
||||
mp.WriteField(fmt.Sprintf("genres[%d]", i), genre)
|
||||
}
|
||||
|
||||
@@ -69,6 +69,8 @@ type Metadata struct {
|
||||
SeriesIndex float64
|
||||
SeriesMbid string
|
||||
|
||||
RipSource RipSource
|
||||
|
||||
IllustrationLocation IllustrationLocation
|
||||
IllustrationStreamIndex int
|
||||
IllustrationPath string
|
||||
@@ -87,6 +89,18 @@ const (
|
||||
|
||||
type AlbumType string
|
||||
|
||||
type RipSource string
|
||||
|
||||
const (
|
||||
CD RipSource = "CD"
|
||||
DVD RipSource = "DVD"
|
||||
BluRay RipSource = "BluRay"
|
||||
Cassette RipSource = "Cassette"
|
||||
Vinyl RipSource = "Vinyl"
|
||||
Digital RipSource = "Digital"
|
||||
OtherRipSource RipSource = "Other"
|
||||
)
|
||||
|
||||
const (
|
||||
Studio AlbumType = "StudioRecording"
|
||||
Live AlbumType = "LiveRecording"
|
||||
|
||||
@@ -240,6 +240,9 @@ func parseMetadataFromEmbeddedTags(filePath string, c config.UserSettings) (inte
|
||||
metadata.SeriesMbid = value
|
||||
})
|
||||
|
||||
ParseTag(tags, []string{"media", "rip source"}, func(value string) {
|
||||
metadata.RipSource = parseRipSource(value)
|
||||
})
|
||||
if !c.UseEmbeddedThumbnails || metadata.Type != internal.Video {
|
||||
if streamIndex := illustration.GetEmbeddedIllustrationStreamIndex(*probeData); streamIndex >= 0 {
|
||||
metadata.IllustrationLocation = internal.Embedded
|
||||
@@ -249,6 +252,29 @@ func parseMetadataFromEmbeddedTags(filePath string, c config.UserSettings) (inte
|
||||
return metadata, errors
|
||||
}
|
||||
|
||||
func parseRipSource(s string) internal.RipSource {
|
||||
s = strings.ReplaceAll(strings.ToLower(s), "-", " ")
|
||||
if strings.Contains(s, "vinyl") {
|
||||
return internal.Vinyl
|
||||
}
|
||||
switch s {
|
||||
case "cd", "sacd", "hdcd", "cd r", "cdr", "minidisc":
|
||||
return internal.CD
|
||||
case "dvd", "vcd", "cdv", "dvd audio", "dualdisc":
|
||||
return internal.DVD
|
||||
case "bluray", "hd dvd":
|
||||
return internal.BluRay
|
||||
case "cassette", "microcassette", "k7":
|
||||
return internal.Cassette
|
||||
case "vinyl", "record":
|
||||
return internal.Vinyl
|
||||
case "digital media":
|
||||
return internal.Digital
|
||||
default:
|
||||
return internal.OtherRipSource
|
||||
}
|
||||
}
|
||||
|
||||
func parseLyrics(value string, metadata *internal.Metadata) {
|
||||
parsedLyrics := internal.ParseLyrics(value)
|
||||
switch l := parsedLyrics.(type) {
|
||||
|
||||
@@ -318,6 +318,7 @@ export default class MetadataService {
|
||||
mixed: parsedTrackName.mixed || releaseIsMixed,
|
||||
isBonus: parsedTrackName.bonus,
|
||||
isRemastered: parsedTrackName.remastered,
|
||||
ripSource: metadata.ripSource ?? null,
|
||||
discName: metadata.discName ?? null,
|
||||
discIndex: metadata.discIndex ?? null,
|
||||
trackIndex: metadata.index ?? null,
|
||||
@@ -326,7 +327,6 @@ export default class MetadataService {
|
||||
metadata.bitrate !== undefined
|
||||
? Math.floor(metadata.bitrate)
|
||||
: null,
|
||||
ripSource: null,
|
||||
duration:
|
||||
metadata.duration !== undefined
|
||||
? Math.floor(metadata.duration)
|
||||
|
||||
@@ -34,7 +34,7 @@ import {
|
||||
Min,
|
||||
MinLength,
|
||||
} from "class-validator";
|
||||
import { AlbumType, TrackType } from "src/prisma/generated/client";
|
||||
import { AlbumType, RipSource, TrackType } from "src/prisma/generated/client";
|
||||
|
||||
/**
|
||||
* Extracted metadata from a track file
|
||||
@@ -301,4 +301,9 @@ export default class Metadata {
|
||||
@IsOptional()
|
||||
@ApiPropertyOptional()
|
||||
seriesMbid?: string;
|
||||
|
||||
@ApiProperty()
|
||||
@IsEnum(RipSource)
|
||||
@IsOptional()
|
||||
ripSource?: RipSource;
|
||||
}
|
||||
Reference in new issue
Block a user