From 5c4cd2332bd25a84d4349c34fa02316ebf8f5b36 Mon Sep 17 00:00:00 2001 From: plato178 Date: Mon, 19 Jun 2023 21:45:01 +0100 Subject: [PATCH 1/9] Add video_codec and audio_codec filter criteria --- graphql/schema/types/filters.graphql | 24 +++++++++++ pkg/models/audio_codec.go | 55 ++++++++++++++++++++++++ pkg/models/filter.go | 9 ++++ pkg/models/scene.go | 4 ++ pkg/models/video_codec.go | 63 ++++++++++++++++++++++++++++ pkg/sqlite/scene.go | 42 +++++++++++++++++++ 6 files changed, 197 insertions(+) create mode 100644 pkg/models/audio_codec.go create mode 100644 pkg/models/video_codec.go diff --git a/graphql/schema/types/filters.graphql b/graphql/schema/types/filters.graphql index 190432594d4..1d7293b9390 100644 --- a/graphql/schema/types/filters.graphql +++ b/graphql/schema/types/filters.graphql @@ -35,6 +35,26 @@ input ResolutionCriterionInput { modifier: CriterionModifier! } +enum VideoCodecEnum { + "h264", H264 + "hevc", HEVC + "av1", AV1 +} + +input VideoCodecCriterionInput { + value: VideoCodecEnum! + modifier: CriterionModifier! +} + +enum AudioCodecEnum { + "aac", AAC +} + +input AudioCodecCriterionInput { + value: AudioCodecEnum! + modifier: CriterionModifier! +} + input PHashDuplicationCriterionInput { duplicated: Boolean """Currently unimplemented""" @@ -194,6 +214,10 @@ input SceneFilterType { duplicated: PHashDuplicationCriterionInput """Filter by resolution""" resolution: ResolutionCriterionInput + """Filter by video codec""" + video_codec: VideoCodecCriterionInput + """Filter by audio codec""" + audio_codec: AudioCodecCriterionInput """Filter by duration (in seconds)""" duration: IntCriterionInput """Filter to only include scenes which have markers. `true` or `false`""" diff --git a/pkg/models/audio_codec.go b/pkg/models/audio_codec.go new file mode 100644 index 00000000000..cd1179d85d2 --- /dev/null +++ b/pkg/models/audio_codec.go @@ -0,0 +1,55 @@ +package models + +import ( + "fmt" + "io" + "strconv" +) + +var audioCodecOptions = map[AudioCodecEnum]string{ + AudioCodecEnum("AAC"): "aac", +} + +type AudioCodecEnum string + +const ( + // aac + AudioCodecEnumAac AudioCodecEnum = "AAC" +) + +var AllAudioCodecEnum = []AudioCodecEnum{ + AudioCodecEnumAac, +} + +func (e AudioCodecEnum) IsValid() bool { + switch e { + case AudioCodecEnumAac: + return true + } + return false +} + +func (e *AudioCodecEnum) UnmarshalGQL(v interface{}) error { + str, ok := v.(string) + if !ok { + return fmt.Errorf("enums must be strings") + } + + *e = AudioCodecEnum(str) + if !e.IsValid() { + return fmt.Errorf("%s is not a valid AudioCodecEnum", str) + } + return nil +} + +func (e AudioCodecEnum) String() string { + return string(e) +} + +func (e AudioCodecEnum) MarshalGQL(w io.Writer) { + fmt.Fprint(w, strconv.Quote(e.String())) +} + +func (e *AudioCodecEnum) GetCodecValue() string { + return audioCodecOptions[*e] +} diff --git a/pkg/models/filter.go b/pkg/models/filter.go index e9ddf7ab366..b64165e1b51 100644 --- a/pkg/models/filter.go +++ b/pkg/models/filter.go @@ -127,6 +127,15 @@ type ResolutionCriterionInput struct { Value ResolutionEnum `json:"value"` Modifier CriterionModifier `json:"modifier"` } +type VideoCodecCriterionInput struct { + Value VideoCodecEnum `json:"value"` + Modifier CriterionModifier `json:"modifier"` +} + +type AudioCodecCriterionInput struct { + Value AudioCodecEnum `json:"value"` + Modifier CriterionModifier `json:"modifier"` +} type HierarchicalMultiCriterionInput struct { Value []string `json:"value"` diff --git a/pkg/models/scene.go b/pkg/models/scene.go index 73e7b6507a7..49cc6384df6 100644 --- a/pkg/models/scene.go +++ b/pkg/models/scene.go @@ -45,6 +45,10 @@ type SceneFilterType struct { Duplicated *PHashDuplicationCriterionInput `json:"duplicated"` // Filter by resolution Resolution *ResolutionCriterionInput `json:"resolution"` + // Filter by video codec + VideoCodec *VideoCodecCriterionInput `json:"video_codec"` + // Filter by audio codec + AudioCodec *AudioCodecCriterionInput `json:"audio_codec"` // Filter by duration (in seconds) Duration *IntCriterionInput `json:"duration"` // Filter to only include scenes which have markers. `true` or `false` diff --git a/pkg/models/video_codec.go b/pkg/models/video_codec.go new file mode 100644 index 00000000000..0a00b5d14ce --- /dev/null +++ b/pkg/models/video_codec.go @@ -0,0 +1,63 @@ +package models + +import ( + "fmt" + "io" + "strconv" +) + +var videoCodecOptions = map[VideoCodecEnum]string{ + VideoCodecEnum("H264"): "h264", + VideoCodecEnum("HEVC"): "hevc", + VideoCodecEnum("AV1"): "av1", +} + +type VideoCodecEnum string + +const ( + // h264 + VideoCodecEnumH264 VideoCodecEnum = "H264" + // hevc + VideoCodecEnumHevc VideoCodecEnum = "HEVC" + // av1 + VideoCodecEnumAv1 VideoCodecEnum = "AV1" +) + +var AllVideoCodecEnum = []VideoCodecEnum{ + VideoCodecEnumH264, + VideoCodecEnumHevc, + VideoCodecEnumAv1, +} + +func (e VideoCodecEnum) IsValid() bool { + switch e { + case VideoCodecEnumH264, VideoCodecEnumHevc, VideoCodecEnumAv1: + return true + } + return false +} + +func (e *VideoCodecEnum) UnmarshalGQL(v interface{}) error { + str, ok := v.(string) + if !ok { + return fmt.Errorf("enums must be strings") + } + + *e = VideoCodecEnum(str) + if !e.IsValid() { + return fmt.Errorf("%s is not a valid VideoCodecEnum", str) + } + return nil +} + +func (e VideoCodecEnum) String() string { + return string(e) +} + +func (e VideoCodecEnum) MarshalGQL(w io.Writer) { + fmt.Fprint(w, strconv.Quote(e.String())) +} + +func (e *VideoCodecEnum) GetCodecValue() string { + return videoCodecOptions[*e] +} diff --git a/pkg/sqlite/scene.go b/pkg/sqlite/scene.go index f2e7f07c240..f26cd0de10a 100644 --- a/pkg/sqlite/scene.go +++ b/pkg/sqlite/scene.go @@ -926,6 +926,10 @@ func (qb *SceneStore) makeFilter(ctx context.Context, sceneFilter *models.SceneF query.handleCriterion(ctx, floatIntCriterionHandler(sceneFilter.Duration, "video_files.duration", qb.addVideoFilesTable)) query.handleCriterion(ctx, resolutionCriterionHandler(sceneFilter.Resolution, "video_files.height", "video_files.width", qb.addVideoFilesTable)) + // [zzz] MJL + query.handleCriterion(ctx, videoCodecCriterionHandler(sceneFilter.VideoCodec, "video_files.video_codec", qb.addVideoFilesTable)) + query.handleCriterion(ctx, audioCodecCriterionHandler(sceneFilter.AudioCodec, "video_files.audio_codec", qb.addVideoFilesTable)) + query.handleCriterion(ctx, hasMarkersCriterionHandler(sceneFilter.HasMarkers)) query.handleCriterion(ctx, sceneIsMissingCriterionHandler(qb, sceneFilter.IsMissing)) query.handleCriterion(ctx, stringCriterionHandler(sceneFilter.URL, "scenes.url")) @@ -1201,6 +1205,44 @@ func resolutionCriterionHandler(resolution *models.ResolutionCriterionInput, hei } } +func videoCodecCriterionHandler(videoCodec *models.VideoCodecCriterionInput, codecColumn string, addJoinFn func(f *filterBuilder)) criterionHandlerFunc { + return func(ctx context.Context, f *filterBuilder) { + if videoCodec != nil && videoCodec.Value.IsValid() { + if addJoinFn != nil { + addJoinFn(f) + } + + codecValue := videoCodec.Value.GetCodecValue() + + switch videoCodec.Modifier { + case models.CriterionModifierEquals: + f.addWhere(fmt.Sprintf("%s = '%s'", codecColumn, codecValue)) + case models.CriterionModifierNotEquals: + f.addWhere(fmt.Sprintf("%s != '%s'", codecColumn, codecValue)) + } + } + } +} + +func audioCodecCriterionHandler(audioCodec *models.AudioCodecCriterionInput, codecColumn string, addJoinFn func(f *filterBuilder)) criterionHandlerFunc { + return func(ctx context.Context, f *filterBuilder) { + if audioCodec != nil && audioCodec.Value.IsValid() { + if addJoinFn != nil { + addJoinFn(f) + } + + codecValue := audioCodec.Value.GetCodecValue() + + switch audioCodec.Modifier { + case models.CriterionModifierEquals: + f.addWhere(fmt.Sprintf("%s = '%s'", codecColumn, codecValue)) + case models.CriterionModifierNotEquals: + f.addWhere(fmt.Sprintf("%s != '%s'", codecColumn, codecValue)) + } + } + } +} + func hasMarkersCriterionHandler(hasMarkers *string) criterionHandlerFunc { return func(ctx context.Context, f *filterBuilder) { if hasMarkers != nil { From ae50310cb8d8f7500bc5fc34c057b397d5a8bd15 Mon Sep 17 00:00:00 2001 From: plato178 Date: Mon, 19 Jun 2023 22:47:01 +0100 Subject: [PATCH 2/9] Add Audio Codec and Video Codec UI filters --- ui/v2.5/src/locales/en-GB.json | 2 + .../list-filter/criteria/audio-codec.ts | 45 +++++++++++++++++++ .../models/list-filter/criteria/factory.ts | 6 +++ .../list-filter/criteria/video-codec.ts | 45 +++++++++++++++++++ ui/v2.5/src/models/list-filter/scenes.ts | 4 ++ ui/v2.5/src/models/list-filter/types.ts | 4 ++ ui/v2.5/src/utils/audioCodec.ts | 30 +++++++++++++ ui/v2.5/src/utils/videoCodec.ts | 32 +++++++++++++ 8 files changed, 168 insertions(+) create mode 100644 ui/v2.5/src/models/list-filter/criteria/audio-codec.ts create mode 100644 ui/v2.5/src/models/list-filter/criteria/video-codec.ts create mode 100644 ui/v2.5/src/utils/audioCodec.ts create mode 100644 ui/v2.5/src/utils/videoCodec.ts diff --git a/ui/v2.5/src/locales/en-GB.json b/ui/v2.5/src/locales/en-GB.json index e5ca446f1f6..4e0f3f14447 100644 --- a/ui/v2.5/src/locales/en-GB.json +++ b/ui/v2.5/src/locales/en-GB.json @@ -129,6 +129,7 @@ "also_known_as": "Also known as", "appears_with": "Appears With", "ascending": "Ascending", + "audio_codec": "Audio Codec", "average_resolution": "Average Resolution", "between_and": "and", "birth_year": "Birth Year", @@ -1259,6 +1260,7 @@ "required": "${path} is a required field" }, "videos": "Videos", + "video_codec": "Video Codec", "view_all": "View All", "weight": "Weight", "weight_kg": "Weight (kg)", diff --git a/ui/v2.5/src/models/list-filter/criteria/audio-codec.ts b/ui/v2.5/src/models/list-filter/criteria/audio-codec.ts new file mode 100644 index 00000000000..393a5ec88f6 --- /dev/null +++ b/ui/v2.5/src/models/list-filter/criteria/audio-codec.ts @@ -0,0 +1,45 @@ +import { + AudioCodecCriterionInput, + CriterionModifier, +} from "src/core/generated-graphql"; +import { stringToAudioCodec, audioCodecStrings } from "src/utils/audioCodec"; +import { CriterionType } from "../types"; +import { CriterionOption, StringCriterion } from "./criterion"; + +abstract class AbstractAudioCodecCriterion extends StringCriterion { + protected toCriterionInput(): AudioCodecCriterionInput | undefined { + const value = stringToAudioCodec(this.value); + + if (value !== undefined) { + return { + value, + modifier: this.modifier, + }; + } + } +} + +class AudioCodecCriterionOptionType extends CriterionOption { + constructor(value: CriterionType) { + super({ + messageID: value, + type: value, + parameterName: value, + modifierOptions: [ + CriterionModifier.Equals, + CriterionModifier.NotEquals, + ], + options: audioCodecStrings, + }); + } +} + +export const AudioCodecCriterionOption = new AudioCodecCriterionOptionType( + "audio_codec" +); + +export class AudioCodecCriterion extends AbstractAudioCodecCriterion { + constructor() { + super(AudioCodecCriterionOption); + } +} \ No newline at end of file diff --git a/ui/v2.5/src/models/list-filter/criteria/factory.ts b/ui/v2.5/src/models/list-filter/criteria/factory.ts index 5096a14b0f3..0b6ca29341f 100644 --- a/ui/v2.5/src/models/list-filter/criteria/factory.ts +++ b/ui/v2.5/src/models/list-filter/criteria/factory.ts @@ -57,6 +57,8 @@ import { StashIDCriterion } from "./stash-ids"; import * as GQL from "src/core/generated-graphql"; import { IUIConfig } from "src/core/config"; import { defaultRatingSystemOptions } from "src/utils/rating"; +import { VideoCodecCriterion } from "./video-codec"; +import { AudioCodecCriterion } from "./audio-codec"; export function makeCriteria( config: GQL.ConfigDataFragment | undefined, @@ -107,6 +109,10 @@ export function makeCriteria( return new ResolutionCriterion(); case "average_resolution": return new AverageResolutionCriterion(); + case "video_codec": + return new VideoCodecCriterion(); + case "audio_codec": + return new AudioCodecCriterion(); case "resume_time": case "duration": case "play_duration": diff --git a/ui/v2.5/src/models/list-filter/criteria/video-codec.ts b/ui/v2.5/src/models/list-filter/criteria/video-codec.ts new file mode 100644 index 00000000000..7dc207d35dd --- /dev/null +++ b/ui/v2.5/src/models/list-filter/criteria/video-codec.ts @@ -0,0 +1,45 @@ +import { + VideoCodecCriterionInput, + CriterionModifier, +} from "src/core/generated-graphql"; +import { stringToVideoCodec, videoCodecStrings } from "src/utils/videoCodec"; +import { CriterionType } from "../types"; +import { CriterionOption, StringCriterion } from "./criterion"; + +abstract class AbstractVideoCodecCriterion extends StringCriterion { + protected toCriterionInput(): VideoCodecCriterionInput | undefined { + const value = stringToVideoCodec(this.value); + + if (value !== undefined) { + return { + value, + modifier: this.modifier, + }; + } + } +} + +class VideoCodecCriterionOptionType extends CriterionOption { + constructor(value: CriterionType) { + super({ + messageID: value, + type: value, + parameterName: value, + modifierOptions: [ + CriterionModifier.Equals, + CriterionModifier.NotEquals, + ], + options: videoCodecStrings, + }); + } +} + +export const VideoCodecCriterionOption = new VideoCodecCriterionOptionType( + "video_codec" +); + +export class VideoCodecCriterion extends AbstractVideoCodecCriterion { + constructor() { + super(VideoCodecCriterionOption); + } +} \ No newline at end of file diff --git a/ui/v2.5/src/models/list-filter/scenes.ts b/ui/v2.5/src/models/list-filter/scenes.ts index f4be9f78a97..92e505becc6 100644 --- a/ui/v2.5/src/models/list-filter/scenes.ts +++ b/ui/v2.5/src/models/list-filter/scenes.ts @@ -13,6 +13,8 @@ import { MoviesCriterionOption } from "./criteria/movies"; import { OrganizedCriterionOption } from "./criteria/organized"; import { PerformersCriterionOption } from "./criteria/performers"; import { ResolutionCriterionOption } from "./criteria/resolution"; +import { VideoCodecCriterionOption } from "./criteria/video-codec"; +import { AudioCodecCriterionOption } from "./criteria/audio-codec"; import { StudiosCriterionOption } from "./criteria/studios"; import { InteractiveCriterionOption } from "./criteria/interactive"; import { @@ -75,6 +77,8 @@ const criterionOptions = [ new NullNumberCriterionOption("rating", "rating100"), createMandatoryNumberCriterionOption("o_counter"), ResolutionCriterionOption, + VideoCodecCriterionOption, + AudioCodecCriterionOption, createMandatoryNumberCriterionOption("duration"), createMandatoryNumberCriterionOption("resume_time"), createMandatoryNumberCriterionOption("play_duration"), diff --git a/ui/v2.5/src/models/list-filter/types.ts b/ui/v2.5/src/models/list-filter/types.ts index 79731eb3bfe..7a545dce145 100644 --- a/ui/v2.5/src/models/list-filter/types.ts +++ b/ui/v2.5/src/models/list-filter/types.ts @@ -109,6 +109,10 @@ export type CriterionType = | "o_counter" | "resolution" | "average_resolution" + + | "video_codec" + | "audio_codec" + | "duration" | "favorite" | "hasMarkers" diff --git a/ui/v2.5/src/utils/audioCodec.ts b/ui/v2.5/src/utils/audioCodec.ts new file mode 100644 index 00000000000..bfbbc0f05f4 --- /dev/null +++ b/ui/v2.5/src/utils/audioCodec.ts @@ -0,0 +1,30 @@ +import { AudioCodecEnum } from "src/core/generated-graphql"; + +const stringAudioCodecMap = new Map([ + ["aac", AudioCodecEnum.Aac], +]); + +export const stringToAudioCodec = ( + value?: string | null, + caseInsensitive?: boolean +) => { + if (!value) { + return undefined; + } + + const ret = stringAudioCodecMap.get(value); + if (ret || !caseInsensitive) { + return ret; + } + + const asUpper = value.toUpperCase(); + const foundEntry = Array.from(stringAudioCodecMap.entries()).find((e) => { + return e[0].toUpperCase() === asUpper; + }); + + if (foundEntry) { + return foundEntry[1]; + } +}; + +export const audioCodecStrings = Array.from(stringAudioCodecMap.keys()); diff --git a/ui/v2.5/src/utils/videoCodec.ts b/ui/v2.5/src/utils/videoCodec.ts new file mode 100644 index 00000000000..a5dd6cbbb57 --- /dev/null +++ b/ui/v2.5/src/utils/videoCodec.ts @@ -0,0 +1,32 @@ +import { VideoCodecEnum } from "src/core/generated-graphql"; + +const stringVideoCodecMap = new Map([ + ["h264", VideoCodecEnum.H264], + ["hevc", VideoCodecEnum.Hevc], + ["av1", VideoCodecEnum.Av1], +]); + +export const stringToVideoCodec = ( + value?: string | null, + caseInsensitive?: boolean +) => { + if (!value) { + return undefined; + } + + const ret = stringVideoCodecMap.get(value); + if (ret || !caseInsensitive) { + return ret; + } + + const asUpper = value.toUpperCase(); + const foundEntry = Array.from(stringVideoCodecMap.entries()).find((e) => { + return e[0].toUpperCase() === asUpper; + }); + + if (foundEntry) { + return foundEntry[1]; + } +}; + +export const videoCodecStrings = Array.from(stringVideoCodecMap.keys()); From 1b20005b8bd7129281da709a27e388a843bca56e Mon Sep 17 00:00:00 2001 From: plato178 Date: Mon, 19 Jun 2023 23:10:36 +0100 Subject: [PATCH 3/9] Add more options to audio and video codec filters --- graphql/schema/types/filters.graphql | 5 +++++ pkg/models/audio_codec.go | 16 ++++++++++++++-- pkg/models/video_codec.go | 10 +++++++++- pkg/sqlite/scene.go | 1 - ui/v2.5/src/utils/audioCodec.ts | 3 +++ ui/v2.5/src/utils/videoCodec.ts | 2 ++ 6 files changed, 33 insertions(+), 4 deletions(-) diff --git a/graphql/schema/types/filters.graphql b/graphql/schema/types/filters.graphql index 1d7293b9390..aa828048d39 100644 --- a/graphql/schema/types/filters.graphql +++ b/graphql/schema/types/filters.graphql @@ -39,6 +39,8 @@ enum VideoCodecEnum { "h264", H264 "hevc", HEVC "av1", AV1 + "wmv3", WMV3 + "vc1", VC1 } input VideoCodecCriterionInput { @@ -48,6 +50,9 @@ input VideoCodecCriterionInput { enum AudioCodecEnum { "aac", AAC + "ac3", AC3 + "mp3", MP3 + "wmav2", WMAV2 } input AudioCodecCriterionInput { diff --git a/pkg/models/audio_codec.go b/pkg/models/audio_codec.go index cd1179d85d2..9f12c105af2 100644 --- a/pkg/models/audio_codec.go +++ b/pkg/models/audio_codec.go @@ -7,7 +7,10 @@ import ( ) var audioCodecOptions = map[AudioCodecEnum]string{ - AudioCodecEnum("AAC"): "aac", + AudioCodecEnum("AAC"): "aac", + AudioCodecEnum("AC3"): "ac3", + AudioCodecEnum("MP3"): "mp3", + AudioCodecEnum("WMAV2"): "wmav2", } type AudioCodecEnum string @@ -15,15 +18,24 @@ type AudioCodecEnum string const ( // aac AudioCodecEnumAac AudioCodecEnum = "AAC" + // ac3 + AudioCodecEnumAc3 AudioCodecEnum = "AC3" + // mp3 + AudioCodecEnumMp3 AudioCodecEnum = "MP3" + // wmav2 + AudioCodecEnumWmav2 AudioCodecEnum = "WMAV2" ) var AllAudioCodecEnum = []AudioCodecEnum{ AudioCodecEnumAac, + AudioCodecEnumAc3, + AudioCodecEnumMp3, + AudioCodecEnumWmav2, } func (e AudioCodecEnum) IsValid() bool { switch e { - case AudioCodecEnumAac: + case AudioCodecEnumAac, AudioCodecEnumAc3, AudioCodecEnumMp3, AudioCodecEnumWmav2: return true } return false diff --git a/pkg/models/video_codec.go b/pkg/models/video_codec.go index 0a00b5d14ce..0f145970a17 100644 --- a/pkg/models/video_codec.go +++ b/pkg/models/video_codec.go @@ -10,6 +10,8 @@ var videoCodecOptions = map[VideoCodecEnum]string{ VideoCodecEnum("H264"): "h264", VideoCodecEnum("HEVC"): "hevc", VideoCodecEnum("AV1"): "av1", + VideoCodecEnum("WMV3"): "wmv3", + VideoCodecEnum("VC1"): "vc1", } type VideoCodecEnum string @@ -21,17 +23,23 @@ const ( VideoCodecEnumHevc VideoCodecEnum = "HEVC" // av1 VideoCodecEnumAv1 VideoCodecEnum = "AV1" + // wmv3 + VideoCodecEnumWmv3 VideoCodecEnum = "WMV3" + // vc1 + VideoCodecEnumVc1 VideoCodecEnum = "VC1" ) var AllVideoCodecEnum = []VideoCodecEnum{ VideoCodecEnumH264, VideoCodecEnumHevc, VideoCodecEnumAv1, + VideoCodecEnumWmv3, + VideoCodecEnumVc1, } func (e VideoCodecEnum) IsValid() bool { switch e { - case VideoCodecEnumH264, VideoCodecEnumHevc, VideoCodecEnumAv1: + case VideoCodecEnumH264, VideoCodecEnumHevc, VideoCodecEnumAv1, VideoCodecEnumWmv3, VideoCodecEnumVc1: return true } return false diff --git a/pkg/sqlite/scene.go b/pkg/sqlite/scene.go index f26cd0de10a..66b7006ddc0 100644 --- a/pkg/sqlite/scene.go +++ b/pkg/sqlite/scene.go @@ -926,7 +926,6 @@ func (qb *SceneStore) makeFilter(ctx context.Context, sceneFilter *models.SceneF query.handleCriterion(ctx, floatIntCriterionHandler(sceneFilter.Duration, "video_files.duration", qb.addVideoFilesTable)) query.handleCriterion(ctx, resolutionCriterionHandler(sceneFilter.Resolution, "video_files.height", "video_files.width", qb.addVideoFilesTable)) - // [zzz] MJL query.handleCriterion(ctx, videoCodecCriterionHandler(sceneFilter.VideoCodec, "video_files.video_codec", qb.addVideoFilesTable)) query.handleCriterion(ctx, audioCodecCriterionHandler(sceneFilter.AudioCodec, "video_files.audio_codec", qb.addVideoFilesTable)) diff --git a/ui/v2.5/src/utils/audioCodec.ts b/ui/v2.5/src/utils/audioCodec.ts index bfbbc0f05f4..e4d7af06260 100644 --- a/ui/v2.5/src/utils/audioCodec.ts +++ b/ui/v2.5/src/utils/audioCodec.ts @@ -2,6 +2,9 @@ import { AudioCodecEnum } from "src/core/generated-graphql"; const stringAudioCodecMap = new Map([ ["aac", AudioCodecEnum.Aac], + ["ac3", AudioCodecEnum.Ac3], + ["mp3", AudioCodecEnum.Mp3], + ["wmav2", AudioCodecEnum.Wmav2], ]); export const stringToAudioCodec = ( diff --git a/ui/v2.5/src/utils/videoCodec.ts b/ui/v2.5/src/utils/videoCodec.ts index a5dd6cbbb57..e1094984097 100644 --- a/ui/v2.5/src/utils/videoCodec.ts +++ b/ui/v2.5/src/utils/videoCodec.ts @@ -4,6 +4,8 @@ const stringVideoCodecMap = new Map([ ["h264", VideoCodecEnum.H264], ["hevc", VideoCodecEnum.Hevc], ["av1", VideoCodecEnum.Av1], + ["wmv3", VideoCodecEnum.Wmv3], + ["vc1", VideoCodecEnum.Vc1], ]); export const stringToVideoCodec = ( From 59fdafb4cc701da81dd4dde226ff077768f65fb8 Mon Sep 17 00:00:00 2001 From: plato178 Date: Tue, 20 Jun 2023 09:22:55 +0100 Subject: [PATCH 4/9] Changes to .gitignore --- .gitignore | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/.gitignore b/.gitignore index 197fd730287..4d3c685aa4f 100644 --- a/.gitignore +++ b/.gitignore @@ -63,4 +63,7 @@ node_modules /stash dist .DS_Store -/.local \ No newline at end of file +/.local + +tsconfig.json +!ui/v2.5/tsconfig.json \ No newline at end of file From 4abf9abdbe574a7097a0290f6b2016ca5381e0b0 Mon Sep 17 00:00:00 2001 From: plato178 Date: Tue, 20 Jun 2023 10:43:51 +0100 Subject: [PATCH 5/9] Run Prettier to correct formatting --- ui/v2.5/src/models/list-filter/criteria/audio-codec.ts | 7 ++----- ui/v2.5/src/models/list-filter/criteria/video-codec.ts | 7 ++----- ui/v2.5/src/models/list-filter/types.ts | 2 -- 3 files changed, 4 insertions(+), 12 deletions(-) diff --git a/ui/v2.5/src/models/list-filter/criteria/audio-codec.ts b/ui/v2.5/src/models/list-filter/criteria/audio-codec.ts index 393a5ec88f6..51364f9541f 100644 --- a/ui/v2.5/src/models/list-filter/criteria/audio-codec.ts +++ b/ui/v2.5/src/models/list-filter/criteria/audio-codec.ts @@ -25,10 +25,7 @@ class AudioCodecCriterionOptionType extends CriterionOption { messageID: value, type: value, parameterName: value, - modifierOptions: [ - CriterionModifier.Equals, - CriterionModifier.NotEquals, - ], + modifierOptions: [CriterionModifier.Equals, CriterionModifier.NotEquals], options: audioCodecStrings, }); } @@ -42,4 +39,4 @@ export class AudioCodecCriterion extends AbstractAudioCodecCriterion { constructor() { super(AudioCodecCriterionOption); } -} \ No newline at end of file +} diff --git a/ui/v2.5/src/models/list-filter/criteria/video-codec.ts b/ui/v2.5/src/models/list-filter/criteria/video-codec.ts index 7dc207d35dd..39c5be1f831 100644 --- a/ui/v2.5/src/models/list-filter/criteria/video-codec.ts +++ b/ui/v2.5/src/models/list-filter/criteria/video-codec.ts @@ -25,10 +25,7 @@ class VideoCodecCriterionOptionType extends CriterionOption { messageID: value, type: value, parameterName: value, - modifierOptions: [ - CriterionModifier.Equals, - CriterionModifier.NotEquals, - ], + modifierOptions: [CriterionModifier.Equals, CriterionModifier.NotEquals], options: videoCodecStrings, }); } @@ -42,4 +39,4 @@ export class VideoCodecCriterion extends AbstractVideoCodecCriterion { constructor() { super(VideoCodecCriterionOption); } -} \ No newline at end of file +} diff --git a/ui/v2.5/src/models/list-filter/types.ts b/ui/v2.5/src/models/list-filter/types.ts index 7a545dce145..a200024f743 100644 --- a/ui/v2.5/src/models/list-filter/types.ts +++ b/ui/v2.5/src/models/list-filter/types.ts @@ -109,10 +109,8 @@ export type CriterionType = | "o_counter" | "resolution" | "average_resolution" - | "video_codec" | "audio_codec" - | "duration" | "favorite" | "hasMarkers" From be45e393c11ea3491d5fe5777184f74959506959 Mon Sep 17 00:00:00 2001 From: plato178 Date: Tue, 20 Jun 2023 10:46:16 +0100 Subject: [PATCH 6/9] Revert "Changes to .gitignore" This reverts commit 59fdafb4cc701da81dd4dde226ff077768f65fb8. --- .gitignore | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/.gitignore b/.gitignore index 4d3c685aa4f..197fd730287 100644 --- a/.gitignore +++ b/.gitignore @@ -63,7 +63,4 @@ node_modules /stash dist .DS_Store -/.local - -tsconfig.json -!ui/v2.5/tsconfig.json \ No newline at end of file +/.local \ No newline at end of file From bdf02b1700d3830e6a7e48dc646cc131a184e017 Mon Sep 17 00:00:00 2001 From: plato178 Date: Tue, 20 Jun 2023 12:52:39 +0100 Subject: [PATCH 7/9] Added more audio and video codec options --- graphql/schema/types/filters.graphql | 12 +++++-- pkg/models/audio_codec.go | 28 ++++++++++++--- pkg/models/video_codec.go | 53 +++++++++++++++++++++------- ui/v2.5/src/utils/audioCodec.ts | 3 ++ ui/v2.5/src/utils/videoCodec.ts | 9 +++-- 5 files changed, 84 insertions(+), 21 deletions(-) diff --git a/graphql/schema/types/filters.graphql b/graphql/schema/types/filters.graphql index aa828048d39..18f811d8c22 100644 --- a/graphql/schema/types/filters.graphql +++ b/graphql/schema/types/filters.graphql @@ -36,11 +36,16 @@ input ResolutionCriterionInput { } enum VideoCodecEnum { + "av1", AV1 "h264", H264 "hevc", HEVC - "av1", AV1 - "wmv3", WMV3 + "mpeg2video", MPEG2_VIDEO + "mpeg4", MPEG4 "vc1", VC1 + "vp6f", VP6F + "wmv1", WMV1 + "wmv2", WMV2 + "wmv3", WMV3 } input VideoCodecCriterionInput { @@ -51,7 +56,10 @@ input VideoCodecCriterionInput { enum AudioCodecEnum { "aac", AAC "ac3", AC3 + "adpcm_ima_wav", ADPCM_IMA_WAV "mp3", MP3 + "pcm_s16le", PCM_S16LE + "wmapro", WMAPRO "wmav2", WMAV2 } diff --git a/pkg/models/audio_codec.go b/pkg/models/audio_codec.go index 9f12c105af2..1f8fcb05365 100644 --- a/pkg/models/audio_codec.go +++ b/pkg/models/audio_codec.go @@ -7,10 +7,13 @@ import ( ) var audioCodecOptions = map[AudioCodecEnum]string{ - AudioCodecEnum("AAC"): "aac", - AudioCodecEnum("AC3"): "ac3", - AudioCodecEnum("MP3"): "mp3", - AudioCodecEnum("WMAV2"): "wmav2", + AudioCodecEnum("AAC"): "aac", + AudioCodecEnum("AC3"): "ac3", + AudioCodecEnum("ADPCM_IMA_WAV"): "adpcm_ima_wav", + AudioCodecEnum("MP3"): "mp3", + AudioCodecEnum("PCM_S16LE"): "pcm_s16le", + AudioCodecEnum("WMAPRO"): "wmapro", + AudioCodecEnum("WMAV2"): "wmav2", } type AudioCodecEnum string @@ -20,8 +23,14 @@ const ( AudioCodecEnumAac AudioCodecEnum = "AAC" // ac3 AudioCodecEnumAc3 AudioCodecEnum = "AC3" + // adpcm_ima_wav + AudioCodecEnumAdpcmImaWav AudioCodecEnum = "ADPCM_IMA_WAV" // mp3 AudioCodecEnumMp3 AudioCodecEnum = "MP3" + // pcm_s16le + AudioCodecEnumPcmS16le AudioCodecEnum = "PCM_S16LE" + // wmapro + AudioCodecEnumWmaPro AudioCodecEnum = "WMAPRO" // wmav2 AudioCodecEnumWmav2 AudioCodecEnum = "WMAV2" ) @@ -29,13 +38,22 @@ const ( var AllAudioCodecEnum = []AudioCodecEnum{ AudioCodecEnumAac, AudioCodecEnumAc3, + AudioCodecEnumAdpcmImaWav, AudioCodecEnumMp3, + AudioCodecEnumPcmS16le, + AudioCodecEnumWmaPro, AudioCodecEnumWmav2, } func (e AudioCodecEnum) IsValid() bool { switch e { - case AudioCodecEnumAac, AudioCodecEnumAc3, AudioCodecEnumMp3, AudioCodecEnumWmav2: + case AudioCodecEnumAac, + AudioCodecEnumAc3, + AudioCodecEnumAdpcmImaWav, + AudioCodecEnumMp3, + AudioCodecEnumPcmS16le, + AudioCodecEnumWmaPro, + AudioCodecEnumWmav2: return true } return false diff --git a/pkg/models/video_codec.go b/pkg/models/video_codec.go index 0f145970a17..28e74d41086 100644 --- a/pkg/models/video_codec.go +++ b/pkg/models/video_codec.go @@ -7,39 +7,68 @@ import ( ) var videoCodecOptions = map[VideoCodecEnum]string{ - VideoCodecEnum("H264"): "h264", - VideoCodecEnum("HEVC"): "hevc", - VideoCodecEnum("AV1"): "av1", - VideoCodecEnum("WMV3"): "wmv3", - VideoCodecEnum("VC1"): "vc1", + VideoCodecEnum("AV1"): "av1", + VideoCodecEnum("H264"): "h264", + VideoCodecEnum("HEVC"): "hevc", + VideoCodecEnum("MPEG2_VIDEO"): "mpeg2video", + VideoCodecEnum("MPEG4"): "mpeg4", + VideoCodecEnum("VC1"): "vc1", + VideoCodecEnum("VP6F"): "vp6f", + VideoCodecEnum("WMV1"): "wmv1", + VideoCodecEnum("WMV2"): "wmv2", + VideoCodecEnum("WMV3"): "wmv3", } type VideoCodecEnum string const ( + // av1 + VideoCodecEnumAv1 VideoCodecEnum = "AV1" // h264 VideoCodecEnumH264 VideoCodecEnum = "H264" // hevc VideoCodecEnumHevc VideoCodecEnum = "HEVC" - // av1 - VideoCodecEnumAv1 VideoCodecEnum = "AV1" - // wmv3 - VideoCodecEnumWmv3 VideoCodecEnum = "WMV3" + // mpeg2video + VideoCodecEnumMpeg2Video VideoCodecEnum = "MPEG2_VIDEO" + // mpeg4 + VideoCodecEnumMpeg4 VideoCodecEnum = "MPEG4" // vc1 VideoCodecEnumVc1 VideoCodecEnum = "VC1" + // vp6f + VideoCodecEnumVp6f VideoCodecEnum = "VP6F" + // wmv1 + VideoCodecEnumWmv1 VideoCodecEnum = "WMV1" + // wmv2 + VideoCodecEnumWmv2 VideoCodecEnum = "WMV2" + // wmv3 + VideoCodecEnumWmv3 VideoCodecEnum = "WMV3" ) var AllVideoCodecEnum = []VideoCodecEnum{ + VideoCodecEnumAv1, VideoCodecEnumH264, VideoCodecEnumHevc, - VideoCodecEnumAv1, - VideoCodecEnumWmv3, + VideoCodecEnumMpeg2Video, + VideoCodecEnumMpeg4, VideoCodecEnumVc1, + VideoCodecEnumVp6f, + VideoCodecEnumWmv1, + VideoCodecEnumWmv2, + VideoCodecEnumWmv3, } func (e VideoCodecEnum) IsValid() bool { switch e { - case VideoCodecEnumH264, VideoCodecEnumHevc, VideoCodecEnumAv1, VideoCodecEnumWmv3, VideoCodecEnumVc1: + case VideoCodecEnumAv1, + VideoCodecEnumH264, + VideoCodecEnumHevc, + VideoCodecEnumMpeg2Video, + VideoCodecEnumMpeg4, + VideoCodecEnumVc1, + VideoCodecEnumVp6f, + VideoCodecEnumWmv1, + VideoCodecEnumWmv2, + VideoCodecEnumWmv3: return true } return false diff --git a/ui/v2.5/src/utils/audioCodec.ts b/ui/v2.5/src/utils/audioCodec.ts index e4d7af06260..caf087362b7 100644 --- a/ui/v2.5/src/utils/audioCodec.ts +++ b/ui/v2.5/src/utils/audioCodec.ts @@ -3,7 +3,10 @@ import { AudioCodecEnum } from "src/core/generated-graphql"; const stringAudioCodecMap = new Map([ ["aac", AudioCodecEnum.Aac], ["ac3", AudioCodecEnum.Ac3], + ["adpcm_ima_wav", AudioCodecEnum.AdpcmImaWav], ["mp3", AudioCodecEnum.Mp3], + ["pcm_s16le", AudioCodecEnum.PcmS16Le], + ["wmapro", AudioCodecEnum.Wmapro], ["wmav2", AudioCodecEnum.Wmav2], ]); diff --git a/ui/v2.5/src/utils/videoCodec.ts b/ui/v2.5/src/utils/videoCodec.ts index e1094984097..00b6285f548 100644 --- a/ui/v2.5/src/utils/videoCodec.ts +++ b/ui/v2.5/src/utils/videoCodec.ts @@ -1,11 +1,16 @@ import { VideoCodecEnum } from "src/core/generated-graphql"; const stringVideoCodecMap = new Map([ + ["av1", VideoCodecEnum.Av1], ["h264", VideoCodecEnum.H264], ["hevc", VideoCodecEnum.Hevc], - ["av1", VideoCodecEnum.Av1], - ["wmv3", VideoCodecEnum.Wmv3], + ["mpeg2video", VideoCodecEnum.Mpeg2Video], + ["mpeg4", VideoCodecEnum.Mpeg4], ["vc1", VideoCodecEnum.Vc1], + ["vp6f", VideoCodecEnum.Vp6F], + ["wmv1", VideoCodecEnum.Wmv1], + ["wmv2", VideoCodecEnum.Wmv2], + ["wmv3", VideoCodecEnum.Wmv3], ]); export const stringToVideoCodec = ( From ce4cf60a0da5f6501b9be6fee242864cd2548ef1 Mon Sep 17 00:00:00 2001 From: plato178 Date: Sun, 2 Jul 2023 19:50:55 +0100 Subject: [PATCH 8/9] Remove custom option filters for video and audio codec in favour of string filters --- graphql/schema/types/filters.graphql | 37 +------ pkg/models/audio_codec.go | 85 --------------- pkg/models/filter.go | 9 -- pkg/models/scene.go | 4 +- pkg/models/video_codec.go | 100 ------------------ pkg/sqlite/scene.go | 36 +------ .../list-filter/criteria/audio-codec.ts | 42 -------- .../models/list-filter/criteria/factory.ts | 10 +- .../list-filter/criteria/video-codec.ts | 42 -------- ui/v2.5/src/models/list-filter/scenes.ts | 6 +- ui/v2.5/src/utils/audioCodec.ts | 36 ------- ui/v2.5/src/utils/videoCodec.ts | 39 ------- 12 files changed, 17 insertions(+), 429 deletions(-) delete mode 100644 pkg/models/audio_codec.go delete mode 100644 pkg/models/video_codec.go delete mode 100644 ui/v2.5/src/models/list-filter/criteria/audio-codec.ts delete mode 100644 ui/v2.5/src/models/list-filter/criteria/video-codec.ts delete mode 100644 ui/v2.5/src/utils/audioCodec.ts delete mode 100644 ui/v2.5/src/utils/videoCodec.ts diff --git a/graphql/schema/types/filters.graphql b/graphql/schema/types/filters.graphql index 18f811d8c22..b80cf851bf3 100644 --- a/graphql/schema/types/filters.graphql +++ b/graphql/schema/types/filters.graphql @@ -35,39 +35,6 @@ input ResolutionCriterionInput { modifier: CriterionModifier! } -enum VideoCodecEnum { - "av1", AV1 - "h264", H264 - "hevc", HEVC - "mpeg2video", MPEG2_VIDEO - "mpeg4", MPEG4 - "vc1", VC1 - "vp6f", VP6F - "wmv1", WMV1 - "wmv2", WMV2 - "wmv3", WMV3 -} - -input VideoCodecCriterionInput { - value: VideoCodecEnum! - modifier: CriterionModifier! -} - -enum AudioCodecEnum { - "aac", AAC - "ac3", AC3 - "adpcm_ima_wav", ADPCM_IMA_WAV - "mp3", MP3 - "pcm_s16le", PCM_S16LE - "wmapro", WMAPRO - "wmav2", WMAV2 -} - -input AudioCodecCriterionInput { - value: AudioCodecEnum! - modifier: CriterionModifier! -} - input PHashDuplicationCriterionInput { duplicated: Boolean """Currently unimplemented""" @@ -228,9 +195,9 @@ input SceneFilterType { """Filter by resolution""" resolution: ResolutionCriterionInput """Filter by video codec""" - video_codec: VideoCodecCriterionInput + video_codec: StringCriterionInput """Filter by audio codec""" - audio_codec: AudioCodecCriterionInput + audio_codec: StringCriterionInput """Filter by duration (in seconds)""" duration: IntCriterionInput """Filter to only include scenes which have markers. `true` or `false`""" diff --git a/pkg/models/audio_codec.go b/pkg/models/audio_codec.go deleted file mode 100644 index 1f8fcb05365..00000000000 --- a/pkg/models/audio_codec.go +++ /dev/null @@ -1,85 +0,0 @@ -package models - -import ( - "fmt" - "io" - "strconv" -) - -var audioCodecOptions = map[AudioCodecEnum]string{ - AudioCodecEnum("AAC"): "aac", - AudioCodecEnum("AC3"): "ac3", - AudioCodecEnum("ADPCM_IMA_WAV"): "adpcm_ima_wav", - AudioCodecEnum("MP3"): "mp3", - AudioCodecEnum("PCM_S16LE"): "pcm_s16le", - AudioCodecEnum("WMAPRO"): "wmapro", - AudioCodecEnum("WMAV2"): "wmav2", -} - -type AudioCodecEnum string - -const ( - // aac - AudioCodecEnumAac AudioCodecEnum = "AAC" - // ac3 - AudioCodecEnumAc3 AudioCodecEnum = "AC3" - // adpcm_ima_wav - AudioCodecEnumAdpcmImaWav AudioCodecEnum = "ADPCM_IMA_WAV" - // mp3 - AudioCodecEnumMp3 AudioCodecEnum = "MP3" - // pcm_s16le - AudioCodecEnumPcmS16le AudioCodecEnum = "PCM_S16LE" - // wmapro - AudioCodecEnumWmaPro AudioCodecEnum = "WMAPRO" - // wmav2 - AudioCodecEnumWmav2 AudioCodecEnum = "WMAV2" -) - -var AllAudioCodecEnum = []AudioCodecEnum{ - AudioCodecEnumAac, - AudioCodecEnumAc3, - AudioCodecEnumAdpcmImaWav, - AudioCodecEnumMp3, - AudioCodecEnumPcmS16le, - AudioCodecEnumWmaPro, - AudioCodecEnumWmav2, -} - -func (e AudioCodecEnum) IsValid() bool { - switch e { - case AudioCodecEnumAac, - AudioCodecEnumAc3, - AudioCodecEnumAdpcmImaWav, - AudioCodecEnumMp3, - AudioCodecEnumPcmS16le, - AudioCodecEnumWmaPro, - AudioCodecEnumWmav2: - return true - } - return false -} - -func (e *AudioCodecEnum) UnmarshalGQL(v interface{}) error { - str, ok := v.(string) - if !ok { - return fmt.Errorf("enums must be strings") - } - - *e = AudioCodecEnum(str) - if !e.IsValid() { - return fmt.Errorf("%s is not a valid AudioCodecEnum", str) - } - return nil -} - -func (e AudioCodecEnum) String() string { - return string(e) -} - -func (e AudioCodecEnum) MarshalGQL(w io.Writer) { - fmt.Fprint(w, strconv.Quote(e.String())) -} - -func (e *AudioCodecEnum) GetCodecValue() string { - return audioCodecOptions[*e] -} diff --git a/pkg/models/filter.go b/pkg/models/filter.go index b64165e1b51..e9ddf7ab366 100644 --- a/pkg/models/filter.go +++ b/pkg/models/filter.go @@ -127,15 +127,6 @@ type ResolutionCriterionInput struct { Value ResolutionEnum `json:"value"` Modifier CriterionModifier `json:"modifier"` } -type VideoCodecCriterionInput struct { - Value VideoCodecEnum `json:"value"` - Modifier CriterionModifier `json:"modifier"` -} - -type AudioCodecCriterionInput struct { - Value AudioCodecEnum `json:"value"` - Modifier CriterionModifier `json:"modifier"` -} type HierarchicalMultiCriterionInput struct { Value []string `json:"value"` diff --git a/pkg/models/scene.go b/pkg/models/scene.go index 49cc6384df6..15cecb38b75 100644 --- a/pkg/models/scene.go +++ b/pkg/models/scene.go @@ -46,9 +46,9 @@ type SceneFilterType struct { // Filter by resolution Resolution *ResolutionCriterionInput `json:"resolution"` // Filter by video codec - VideoCodec *VideoCodecCriterionInput `json:"video_codec"` + VideoCodec *StringCriterionInput `json:"video_codec"` // Filter by audio codec - AudioCodec *AudioCodecCriterionInput `json:"audio_codec"` + AudioCodec *StringCriterionInput `json:"audio_codec"` // Filter by duration (in seconds) Duration *IntCriterionInput `json:"duration"` // Filter to only include scenes which have markers. `true` or `false` diff --git a/pkg/models/video_codec.go b/pkg/models/video_codec.go deleted file mode 100644 index 28e74d41086..00000000000 --- a/pkg/models/video_codec.go +++ /dev/null @@ -1,100 +0,0 @@ -package models - -import ( - "fmt" - "io" - "strconv" -) - -var videoCodecOptions = map[VideoCodecEnum]string{ - VideoCodecEnum("AV1"): "av1", - VideoCodecEnum("H264"): "h264", - VideoCodecEnum("HEVC"): "hevc", - VideoCodecEnum("MPEG2_VIDEO"): "mpeg2video", - VideoCodecEnum("MPEG4"): "mpeg4", - VideoCodecEnum("VC1"): "vc1", - VideoCodecEnum("VP6F"): "vp6f", - VideoCodecEnum("WMV1"): "wmv1", - VideoCodecEnum("WMV2"): "wmv2", - VideoCodecEnum("WMV3"): "wmv3", -} - -type VideoCodecEnum string - -const ( - // av1 - VideoCodecEnumAv1 VideoCodecEnum = "AV1" - // h264 - VideoCodecEnumH264 VideoCodecEnum = "H264" - // hevc - VideoCodecEnumHevc VideoCodecEnum = "HEVC" - // mpeg2video - VideoCodecEnumMpeg2Video VideoCodecEnum = "MPEG2_VIDEO" - // mpeg4 - VideoCodecEnumMpeg4 VideoCodecEnum = "MPEG4" - // vc1 - VideoCodecEnumVc1 VideoCodecEnum = "VC1" - // vp6f - VideoCodecEnumVp6f VideoCodecEnum = "VP6F" - // wmv1 - VideoCodecEnumWmv1 VideoCodecEnum = "WMV1" - // wmv2 - VideoCodecEnumWmv2 VideoCodecEnum = "WMV2" - // wmv3 - VideoCodecEnumWmv3 VideoCodecEnum = "WMV3" -) - -var AllVideoCodecEnum = []VideoCodecEnum{ - VideoCodecEnumAv1, - VideoCodecEnumH264, - VideoCodecEnumHevc, - VideoCodecEnumMpeg2Video, - VideoCodecEnumMpeg4, - VideoCodecEnumVc1, - VideoCodecEnumVp6f, - VideoCodecEnumWmv1, - VideoCodecEnumWmv2, - VideoCodecEnumWmv3, -} - -func (e VideoCodecEnum) IsValid() bool { - switch e { - case VideoCodecEnumAv1, - VideoCodecEnumH264, - VideoCodecEnumHevc, - VideoCodecEnumMpeg2Video, - VideoCodecEnumMpeg4, - VideoCodecEnumVc1, - VideoCodecEnumVp6f, - VideoCodecEnumWmv1, - VideoCodecEnumWmv2, - VideoCodecEnumWmv3: - return true - } - return false -} - -func (e *VideoCodecEnum) UnmarshalGQL(v interface{}) error { - str, ok := v.(string) - if !ok { - return fmt.Errorf("enums must be strings") - } - - *e = VideoCodecEnum(str) - if !e.IsValid() { - return fmt.Errorf("%s is not a valid VideoCodecEnum", str) - } - return nil -} - -func (e VideoCodecEnum) String() string { - return string(e) -} - -func (e VideoCodecEnum) MarshalGQL(w io.Writer) { - fmt.Fprint(w, strconv.Quote(e.String())) -} - -func (e *VideoCodecEnum) GetCodecValue() string { - return videoCodecOptions[*e] -} diff --git a/pkg/sqlite/scene.go b/pkg/sqlite/scene.go index 66b7006ddc0..3bbcea41cf0 100644 --- a/pkg/sqlite/scene.go +++ b/pkg/sqlite/scene.go @@ -926,8 +926,8 @@ func (qb *SceneStore) makeFilter(ctx context.Context, sceneFilter *models.SceneF query.handleCriterion(ctx, floatIntCriterionHandler(sceneFilter.Duration, "video_files.duration", qb.addVideoFilesTable)) query.handleCriterion(ctx, resolutionCriterionHandler(sceneFilter.Resolution, "video_files.height", "video_files.width", qb.addVideoFilesTable)) - query.handleCriterion(ctx, videoCodecCriterionHandler(sceneFilter.VideoCodec, "video_files.video_codec", qb.addVideoFilesTable)) - query.handleCriterion(ctx, audioCodecCriterionHandler(sceneFilter.AudioCodec, "video_files.audio_codec", qb.addVideoFilesTable)) + query.handleCriterion(ctx, codecCriterionHandler(sceneFilter.VideoCodec, "video_files.video_codec", qb.addVideoFilesTable)) + query.handleCriterion(ctx, codecCriterionHandler(sceneFilter.AudioCodec, "video_files.audio_codec", qb.addVideoFilesTable)) query.handleCriterion(ctx, hasMarkersCriterionHandler(sceneFilter.HasMarkers)) query.handleCriterion(ctx, sceneIsMissingCriterionHandler(qb, sceneFilter.IsMissing)) @@ -1204,40 +1204,14 @@ func resolutionCriterionHandler(resolution *models.ResolutionCriterionInput, hei } } -func videoCodecCriterionHandler(videoCodec *models.VideoCodecCriterionInput, codecColumn string, addJoinFn func(f *filterBuilder)) criterionHandlerFunc { +func codecCriterionHandler(codec *models.StringCriterionInput, codecColumn string, addJoinFn func(f *filterBuilder)) criterionHandlerFunc { return func(ctx context.Context, f *filterBuilder) { - if videoCodec != nil && videoCodec.Value.IsValid() { + if codec != nil { if addJoinFn != nil { addJoinFn(f) } - codecValue := videoCodec.Value.GetCodecValue() - - switch videoCodec.Modifier { - case models.CriterionModifierEquals: - f.addWhere(fmt.Sprintf("%s = '%s'", codecColumn, codecValue)) - case models.CriterionModifierNotEquals: - f.addWhere(fmt.Sprintf("%s != '%s'", codecColumn, codecValue)) - } - } - } -} - -func audioCodecCriterionHandler(audioCodec *models.AudioCodecCriterionInput, codecColumn string, addJoinFn func(f *filterBuilder)) criterionHandlerFunc { - return func(ctx context.Context, f *filterBuilder) { - if audioCodec != nil && audioCodec.Value.IsValid() { - if addJoinFn != nil { - addJoinFn(f) - } - - codecValue := audioCodec.Value.GetCodecValue() - - switch audioCodec.Modifier { - case models.CriterionModifierEquals: - f.addWhere(fmt.Sprintf("%s = '%s'", codecColumn, codecValue)) - case models.CriterionModifierNotEquals: - f.addWhere(fmt.Sprintf("%s != '%s'", codecColumn, codecValue)) - } + stringCriterionHandler(codec, codecColumn)(ctx, f) } } } diff --git a/ui/v2.5/src/models/list-filter/criteria/audio-codec.ts b/ui/v2.5/src/models/list-filter/criteria/audio-codec.ts deleted file mode 100644 index 51364f9541f..00000000000 --- a/ui/v2.5/src/models/list-filter/criteria/audio-codec.ts +++ /dev/null @@ -1,42 +0,0 @@ -import { - AudioCodecCriterionInput, - CriterionModifier, -} from "src/core/generated-graphql"; -import { stringToAudioCodec, audioCodecStrings } from "src/utils/audioCodec"; -import { CriterionType } from "../types"; -import { CriterionOption, StringCriterion } from "./criterion"; - -abstract class AbstractAudioCodecCriterion extends StringCriterion { - protected toCriterionInput(): AudioCodecCriterionInput | undefined { - const value = stringToAudioCodec(this.value); - - if (value !== undefined) { - return { - value, - modifier: this.modifier, - }; - } - } -} - -class AudioCodecCriterionOptionType extends CriterionOption { - constructor(value: CriterionType) { - super({ - messageID: value, - type: value, - parameterName: value, - modifierOptions: [CriterionModifier.Equals, CriterionModifier.NotEquals], - options: audioCodecStrings, - }); - } -} - -export const AudioCodecCriterionOption = new AudioCodecCriterionOptionType( - "audio_codec" -); - -export class AudioCodecCriterion extends AbstractAudioCodecCriterion { - constructor() { - super(AudioCodecCriterionOption); - } -} diff --git a/ui/v2.5/src/models/list-filter/criteria/factory.ts b/ui/v2.5/src/models/list-filter/criteria/factory.ts index 0b6ca29341f..b6e8773e76e 100644 --- a/ui/v2.5/src/models/list-filter/criteria/factory.ts +++ b/ui/v2.5/src/models/list-filter/criteria/factory.ts @@ -57,8 +57,6 @@ import { StashIDCriterion } from "./stash-ids"; import * as GQL from "src/core/generated-graphql"; import { IUIConfig } from "src/core/config"; import { defaultRatingSystemOptions } from "src/utils/rating"; -import { VideoCodecCriterion } from "./video-codec"; -import { AudioCodecCriterion } from "./audio-codec"; export function makeCriteria( config: GQL.ConfigDataFragment | undefined, @@ -110,9 +108,13 @@ export function makeCriteria( case "average_resolution": return new AverageResolutionCriterion(); case "video_codec": - return new VideoCodecCriterion(); + return new StringCriterion( + new StringCriterionOption(type, type) + ); case "audio_codec": - return new AudioCodecCriterion(); + return new StringCriterion( + new StringCriterionOption(type, type) + ); case "resume_time": case "duration": case "play_duration": diff --git a/ui/v2.5/src/models/list-filter/criteria/video-codec.ts b/ui/v2.5/src/models/list-filter/criteria/video-codec.ts deleted file mode 100644 index 39c5be1f831..00000000000 --- a/ui/v2.5/src/models/list-filter/criteria/video-codec.ts +++ /dev/null @@ -1,42 +0,0 @@ -import { - VideoCodecCriterionInput, - CriterionModifier, -} from "src/core/generated-graphql"; -import { stringToVideoCodec, videoCodecStrings } from "src/utils/videoCodec"; -import { CriterionType } from "../types"; -import { CriterionOption, StringCriterion } from "./criterion"; - -abstract class AbstractVideoCodecCriterion extends StringCriterion { - protected toCriterionInput(): VideoCodecCriterionInput | undefined { - const value = stringToVideoCodec(this.value); - - if (value !== undefined) { - return { - value, - modifier: this.modifier, - }; - } - } -} - -class VideoCodecCriterionOptionType extends CriterionOption { - constructor(value: CriterionType) { - super({ - messageID: value, - type: value, - parameterName: value, - modifierOptions: [CriterionModifier.Equals, CriterionModifier.NotEquals], - options: videoCodecStrings, - }); - } -} - -export const VideoCodecCriterionOption = new VideoCodecCriterionOptionType( - "video_codec" -); - -export class VideoCodecCriterion extends AbstractVideoCodecCriterion { - constructor() { - super(VideoCodecCriterionOption); - } -} diff --git a/ui/v2.5/src/models/list-filter/scenes.ts b/ui/v2.5/src/models/list-filter/scenes.ts index 92e505becc6..106875a1251 100644 --- a/ui/v2.5/src/models/list-filter/scenes.ts +++ b/ui/v2.5/src/models/list-filter/scenes.ts @@ -13,8 +13,6 @@ import { MoviesCriterionOption } from "./criteria/movies"; import { OrganizedCriterionOption } from "./criteria/organized"; import { PerformersCriterionOption } from "./criteria/performers"; import { ResolutionCriterionOption } from "./criteria/resolution"; -import { VideoCodecCriterionOption } from "./criteria/video-codec"; -import { AudioCodecCriterionOption } from "./criteria/audio-codec"; import { StudiosCriterionOption } from "./criteria/studios"; import { InteractiveCriterionOption } from "./criteria/interactive"; import { @@ -77,8 +75,8 @@ const criterionOptions = [ new NullNumberCriterionOption("rating", "rating100"), createMandatoryNumberCriterionOption("o_counter"), ResolutionCriterionOption, - VideoCodecCriterionOption, - AudioCodecCriterionOption, + createStringCriterionOption("video_codec"), + createStringCriterionOption("audio_codec"), createMandatoryNumberCriterionOption("duration"), createMandatoryNumberCriterionOption("resume_time"), createMandatoryNumberCriterionOption("play_duration"), diff --git a/ui/v2.5/src/utils/audioCodec.ts b/ui/v2.5/src/utils/audioCodec.ts deleted file mode 100644 index caf087362b7..00000000000 --- a/ui/v2.5/src/utils/audioCodec.ts +++ /dev/null @@ -1,36 +0,0 @@ -import { AudioCodecEnum } from "src/core/generated-graphql"; - -const stringAudioCodecMap = new Map([ - ["aac", AudioCodecEnum.Aac], - ["ac3", AudioCodecEnum.Ac3], - ["adpcm_ima_wav", AudioCodecEnum.AdpcmImaWav], - ["mp3", AudioCodecEnum.Mp3], - ["pcm_s16le", AudioCodecEnum.PcmS16Le], - ["wmapro", AudioCodecEnum.Wmapro], - ["wmav2", AudioCodecEnum.Wmav2], -]); - -export const stringToAudioCodec = ( - value?: string | null, - caseInsensitive?: boolean -) => { - if (!value) { - return undefined; - } - - const ret = stringAudioCodecMap.get(value); - if (ret || !caseInsensitive) { - return ret; - } - - const asUpper = value.toUpperCase(); - const foundEntry = Array.from(stringAudioCodecMap.entries()).find((e) => { - return e[0].toUpperCase() === asUpper; - }); - - if (foundEntry) { - return foundEntry[1]; - } -}; - -export const audioCodecStrings = Array.from(stringAudioCodecMap.keys()); diff --git a/ui/v2.5/src/utils/videoCodec.ts b/ui/v2.5/src/utils/videoCodec.ts deleted file mode 100644 index 00b6285f548..00000000000 --- a/ui/v2.5/src/utils/videoCodec.ts +++ /dev/null @@ -1,39 +0,0 @@ -import { VideoCodecEnum } from "src/core/generated-graphql"; - -const stringVideoCodecMap = new Map([ - ["av1", VideoCodecEnum.Av1], - ["h264", VideoCodecEnum.H264], - ["hevc", VideoCodecEnum.Hevc], - ["mpeg2video", VideoCodecEnum.Mpeg2Video], - ["mpeg4", VideoCodecEnum.Mpeg4], - ["vc1", VideoCodecEnum.Vc1], - ["vp6f", VideoCodecEnum.Vp6F], - ["wmv1", VideoCodecEnum.Wmv1], - ["wmv2", VideoCodecEnum.Wmv2], - ["wmv3", VideoCodecEnum.Wmv3], -]); - -export const stringToVideoCodec = ( - value?: string | null, - caseInsensitive?: boolean -) => { - if (!value) { - return undefined; - } - - const ret = stringVideoCodecMap.get(value); - if (ret || !caseInsensitive) { - return ret; - } - - const asUpper = value.toUpperCase(); - const foundEntry = Array.from(stringVideoCodecMap.entries()).find((e) => { - return e[0].toUpperCase() === asUpper; - }); - - if (foundEntry) { - return foundEntry[1]; - } -}; - -export const videoCodecStrings = Array.from(stringVideoCodecMap.keys()); From 8ec4d178809e3bee615cae9274b7064fac6c156a Mon Sep 17 00:00:00 2001 From: WithoutPants <53250216+WithoutPants@users.noreply.github.com> Date: Tue, 11 Jul 2023 11:51:13 +1000 Subject: [PATCH 9/9] Format --- ui/v2.5/src/models/list-filter/criteria/factory.ts | 8 ++------ 1 file changed, 2 insertions(+), 6 deletions(-) diff --git a/ui/v2.5/src/models/list-filter/criteria/factory.ts b/ui/v2.5/src/models/list-filter/criteria/factory.ts index b6e8773e76e..d45042aa0ee 100644 --- a/ui/v2.5/src/models/list-filter/criteria/factory.ts +++ b/ui/v2.5/src/models/list-filter/criteria/factory.ts @@ -108,13 +108,9 @@ export function makeCriteria( case "average_resolution": return new AverageResolutionCriterion(); case "video_codec": - return new StringCriterion( - new StringCriterionOption(type, type) - ); + return new StringCriterion(new StringCriterionOption(type, type)); case "audio_codec": - return new StringCriterion( - new StringCriterionOption(type, type) - ); + return new StringCriterion(new StringCriterionOption(type, type)); case "resume_time": case "duration": case "play_duration":