mirror of
https://github.com/aNNiMON/ffmpegbot
synced 2024-09-19 22:54:20 +03:00
Dynamically updating parameters list based on a user's input
This commit is contained in:
parent
a046585327
commit
bc4e3af5bc
@ -83,6 +83,7 @@ public class MediaProcessingBundle implements CommandBundle<For> {
|
|||||||
if (param != null && ctx.argumentsLength() == 2) {
|
if (param != null && ctx.argumentsLength() == 2) {
|
||||||
final int index = Integer.parseInt(ctx.argument(1));
|
final int index = Integer.parseInt(ctx.argument(1));
|
||||||
param.select(index);
|
param.select(index);
|
||||||
|
parametersResolver.refine(session.getParams());
|
||||||
session.setSelectedParam(null);
|
session.setSelectedParam(null);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -7,6 +7,10 @@ public abstract class BooleanParameter extends Parameter<Boolean> {
|
|||||||
super(id, name, List.of(false, true), value);
|
super(id, name, List.of(false, true), value);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public boolean getValueAsPrimitive() {
|
||||||
|
return (value != null && value);
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public String describeValue(Boolean value) {
|
public String describeValue(Boolean value) {
|
||||||
if (value != null && value) {
|
if (value != null && value) {
|
||||||
|
@ -2,7 +2,9 @@ package com.annimon.ffmpegbot.parameters;
|
|||||||
|
|
||||||
import com.annimon.ffmpegbot.commands.ffmpeg.Visitor;
|
import com.annimon.ffmpegbot.commands.ffmpeg.Visitor;
|
||||||
|
|
||||||
|
import java.util.ArrayList;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
import java.util.Objects;
|
||||||
|
|
||||||
public class OutputFormat extends StringParameter {
|
public class OutputFormat extends StringParameter {
|
||||||
public static final String ID = "output";
|
public static final String ID = "output";
|
||||||
@ -12,7 +14,29 @@ public class OutputFormat extends StringParameter {
|
|||||||
public static final String VIDEO_NOTE = "VIDEO NOTE";
|
public static final String VIDEO_NOTE = "VIDEO NOTE";
|
||||||
|
|
||||||
public OutputFormat(List<String> values, String initialValue) {
|
public OutputFormat(List<String> values, String initialValue) {
|
||||||
super(ID, "➡\uFE0F Output", values, initialValue);
|
super(ID, "➡️ Output", values, initialValue);
|
||||||
|
}
|
||||||
|
|
||||||
|
public OutputFormat disableFormat(String format) {
|
||||||
|
if (possibleValues.size() <= 1) return this;
|
||||||
|
final var values = possibleValues.stream()
|
||||||
|
.filter(f -> !Objects.equals(f, format))
|
||||||
|
.map(Objects::toString)
|
||||||
|
.toList();
|
||||||
|
if (possibleValues.size() == values.size()) {
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
return new OutputFormat(values, values.get(0));
|
||||||
|
}
|
||||||
|
|
||||||
|
public OutputFormat enableFormat(String format) {
|
||||||
|
boolean contains = possibleValues.stream()
|
||||||
|
.anyMatch(f -> Objects.equals(f, format));
|
||||||
|
if (contains) return this;
|
||||||
|
|
||||||
|
final var values = new ArrayList<String>(possibleValues);
|
||||||
|
values.add(format);
|
||||||
|
return new OutputFormat(values, values.get(0));
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@ -12,12 +12,14 @@ public abstract class Parameter<T> {
|
|||||||
protected final String displayName;
|
protected final String displayName;
|
||||||
protected final List<? extends T> possibleValues;
|
protected final List<? extends T> possibleValues;
|
||||||
protected T value;
|
protected T value;
|
||||||
|
private boolean enabled;
|
||||||
|
|
||||||
protected Parameter(String id, String displayName, List<? extends T> values, T value) {
|
protected Parameter(String id, String displayName, List<? extends T> values, T value) {
|
||||||
this.id = id;
|
this.id = id;
|
||||||
this.displayName = displayName;
|
this.displayName = displayName;
|
||||||
this.possibleValues = values;
|
this.possibleValues = values;
|
||||||
this.value = value;
|
this.value = value;
|
||||||
|
this.enabled = true;
|
||||||
checkArgument(!values.isEmpty(), "possible values cannot be empty");
|
checkArgument(!values.isEmpty(), "possible values cannot be empty");
|
||||||
checkArgument(values.contains(value), "possible values must contain a value");
|
checkArgument(values.contains(value), "possible values must contain a value");
|
||||||
}
|
}
|
||||||
@ -34,6 +36,17 @@ public abstract class Parameter<T> {
|
|||||||
return possibleValues.size();
|
return possibleValues.size();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public boolean isEnabled() {
|
||||||
|
return enabled;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void enable() {
|
||||||
|
enabled = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void disable() {
|
||||||
|
enabled = false;
|
||||||
|
}
|
||||||
|
|
||||||
public abstract <I> void accept(Visitor<I> visitor, I input);
|
public abstract <I> void accept(Visitor<I> visitor, I input);
|
||||||
|
|
||||||
|
@ -2,44 +2,68 @@ package com.annimon.ffmpegbot.parameters;
|
|||||||
|
|
||||||
import org.jetbrains.annotations.NotNull;
|
import org.jetbrains.annotations.NotNull;
|
||||||
import java.util.*;
|
import java.util.*;
|
||||||
|
import java.util.stream.Stream;
|
||||||
|
|
||||||
public class Parameters extends AbstractCollection<Parameter<?>> {
|
public class Parameters extends AbstractCollection<Parameter<?>> {
|
||||||
|
|
||||||
private final Map<String, Parameter<?>> enabledParameters;
|
private final Map<String, Parameter<?>> parameters;
|
||||||
private final Map<String, Parameter<?>> disabledParameters;
|
|
||||||
|
|
||||||
public Parameters() {
|
public Parameters() {
|
||||||
enabledParameters = new LinkedHashMap<>();
|
parameters = new LinkedHashMap<>();
|
||||||
disabledParameters = new LinkedHashMap<>();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean add(Parameter<?> parameter) {
|
public boolean add(Parameter<?> parameter) {
|
||||||
return !Objects.equals(parameter, enabledParameters.put(parameter.id, parameter));
|
parameter.enable();
|
||||||
|
return !Objects.equals(parameter, parameters.put(parameter.id, parameter));
|
||||||
}
|
}
|
||||||
|
|
||||||
public Parameter<?> findById(String id) {
|
public Parameter<?> findById(String id) {
|
||||||
return enabledParameters.get(id);
|
final var parameter = parameters.get(id);
|
||||||
|
if (parameter != null && parameter.isEnabled()) {
|
||||||
|
return parameter;
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
public <P extends Parameter<?>> Optional<P> findById(String id, Class<P> clazz) {
|
||||||
|
return Optional.ofNullable(findById(id))
|
||||||
|
.filter(clazz::isInstance)
|
||||||
|
.map(clazz::cast);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void disable(String id) {
|
public void disable(String id) {
|
||||||
Optional.ofNullable(findById(id))
|
Optional.ofNullable(parameters.get(id))
|
||||||
.ifPresent(p -> disabledParameters.put(p.id, p));
|
.ifPresent(Parameter::disable);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void disableAll(Collection<String> ids) {
|
||||||
|
ids.forEach(this::disable);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void enable(String id) {
|
public void enable(String id) {
|
||||||
Optional.ofNullable(disabledParameters.get(id))
|
Optional.ofNullable(parameters.get(id))
|
||||||
.ifPresent(this::add);
|
.ifPresent(Parameter::enable);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void enableAll(Collection<String> ids) {
|
||||||
|
ids.forEach(this::enable);
|
||||||
}
|
}
|
||||||
|
|
||||||
@NotNull
|
@NotNull
|
||||||
@Override
|
@Override
|
||||||
public Iterator<Parameter<?>> iterator() {
|
public Iterator<Parameter<?>> iterator() {
|
||||||
return enabledParameters.values().iterator();
|
return enabledParameters().iterator();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public int size() {
|
public int size() {
|
||||||
return enabledParameters.size();
|
return (int) enabledParameters().count();
|
||||||
|
}
|
||||||
|
|
||||||
|
private Stream<Parameter<?>> enabledParameters() {
|
||||||
|
return parameters.values()
|
||||||
|
.stream()
|
||||||
|
.filter(Parameter::isEnabled);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -5,6 +5,8 @@ import com.annimon.ffmpegbot.session.FileInfo;
|
|||||||
import com.annimon.ffmpegbot.session.FileType;
|
import com.annimon.ffmpegbot.session.FileType;
|
||||||
import org.jetbrains.annotations.NotNull;
|
import org.jetbrains.annotations.NotNull;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
import java.util.Optional;
|
||||||
|
import java.util.Set;
|
||||||
|
|
||||||
public class AudioResolver implements ParametersResolver {
|
public class AudioResolver implements ParametersResolver {
|
||||||
|
|
||||||
@ -28,6 +30,28 @@ public class AudioResolver implements ParametersResolver {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void refine(@NotNull Parameters parameters) {
|
||||||
|
parameters.findById(DisableAudio.ID, DisableAudio.class)
|
||||||
|
.ifPresent(p -> {
|
||||||
|
final Set<String> parameterIds = Set.of(
|
||||||
|
AudioBitrate.ID,
|
||||||
|
AudioCrystalizer.ID,
|
||||||
|
AudioEffect.ID,
|
||||||
|
AudioPitch.ID,
|
||||||
|
AudioVolume.ID
|
||||||
|
);
|
||||||
|
Optional<OutputFormat> outputFormat = parameters.findById(OutputFormat.ID, OutputFormat.class);
|
||||||
|
if (p.getValueAsPrimitive()) {
|
||||||
|
parameters.disableAll(parameterIds);
|
||||||
|
outputFormat.ifPresent(par -> parameters.add(par.disableFormat(OutputFormat.AUDIO)));
|
||||||
|
} else {
|
||||||
|
parameters.enableAll(parameterIds);
|
||||||
|
outputFormat.ifPresent(par -> parameters.add(par.enableFormat(OutputFormat.AUDIO)));
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
private void disableAudioParam(@NotNull Parameters parameters, @NotNull FileType fileType) {
|
private void disableAudioParam(@NotNull Parameters parameters, @NotNull FileType fileType) {
|
||||||
final boolean canAudioBeDisabled = switch (fileType) {
|
final boolean canAudioBeDisabled = switch (fileType) {
|
||||||
case ANIMATION, AUDIO, VOICE -> false;
|
case ANIMATION, AUDIO, VOICE -> false;
|
||||||
|
@ -24,4 +24,11 @@ public class GlobalParametersResolver implements ParametersResolver {
|
|||||||
resolver.resolve(parameters, fileInfo);
|
resolver.resolve(parameters, fileInfo);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void refine(@NotNull Parameters parameters) {
|
||||||
|
for (ParametersResolver resolver : resolvers) {
|
||||||
|
resolver.refine(parameters);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,7 +1,6 @@
|
|||||||
package com.annimon.ffmpegbot.parameters.resolvers;
|
package com.annimon.ffmpegbot.parameters.resolvers;
|
||||||
|
|
||||||
import com.annimon.ffmpegbot.parameters.AudioStreamByLanguage;
|
import com.annimon.ffmpegbot.parameters.*;
|
||||||
import com.annimon.ffmpegbot.parameters.Parameters;
|
|
||||||
import com.annimon.ffmpegbot.session.FileInfo;
|
import com.annimon.ffmpegbot.session.FileInfo;
|
||||||
import com.annimon.ffmpegbot.session.FileType;
|
import com.annimon.ffmpegbot.session.FileType;
|
||||||
import org.jetbrains.annotations.NotNull;
|
import org.jetbrains.annotations.NotNull;
|
||||||
@ -19,4 +18,16 @@ public class MultiAudioStreamsResolver implements ParametersResolver {
|
|||||||
parameters.add(new AudioStreamByLanguage());
|
parameters.add(new AudioStreamByLanguage());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void refine(@NotNull Parameters parameters) {
|
||||||
|
parameters.findById(DisableAudio.ID, DisableAudio.class)
|
||||||
|
.ifPresent(p -> {
|
||||||
|
if (p.getValueAsPrimitive()) {
|
||||||
|
parameters.disable(AudioStreamByLanguage.ID);
|
||||||
|
} else {
|
||||||
|
parameters.enable(AudioStreamByLanguage.ID);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -7,4 +7,15 @@ import org.jetbrains.annotations.NotNull;
|
|||||||
public interface ParametersResolver {
|
public interface ParametersResolver {
|
||||||
|
|
||||||
void resolve(@NotNull Parameters parameters, @NotNull FileInfo fileInfo);
|
void resolve(@NotNull Parameters parameters, @NotNull FileInfo fileInfo);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Refines all parameters based on user input.
|
||||||
|
* <p>
|
||||||
|
* Example: if Disable audio is ON -> removes all audio parameters.
|
||||||
|
*
|
||||||
|
* @param parameters all parameters
|
||||||
|
*/
|
||||||
|
default void refine(@NotNull Parameters parameters) {
|
||||||
|
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -4,6 +4,8 @@ import com.annimon.ffmpegbot.parameters.*;
|
|||||||
import com.annimon.ffmpegbot.session.FileInfo;
|
import com.annimon.ffmpegbot.session.FileInfo;
|
||||||
import org.jetbrains.annotations.NotNull;
|
import org.jetbrains.annotations.NotNull;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
import java.util.Objects;
|
||||||
|
import java.util.Set;
|
||||||
|
|
||||||
public class VideoResolver implements ParametersResolver {
|
public class VideoResolver implements ParametersResolver {
|
||||||
|
|
||||||
@ -25,4 +27,25 @@ public class VideoResolver implements ParametersResolver {
|
|||||||
));
|
));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void refine(@NotNull Parameters parameters) {
|
||||||
|
parameters.findById(OutputFormat.ID, OutputFormat.class)
|
||||||
|
.map(Parameter::getValue)
|
||||||
|
.ifPresent(format -> {
|
||||||
|
final Set<String> parameterIds = Set.of(
|
||||||
|
Contrast.ID,
|
||||||
|
Gamma.ID,
|
||||||
|
Saturation.ID,
|
||||||
|
VideoBitrate.ID,
|
||||||
|
VideoScale.ID,
|
||||||
|
VideoFrameRate.ID
|
||||||
|
);
|
||||||
|
if (Objects.equals(format, OutputFormat.AUDIO)) {
|
||||||
|
parameters.disableAll(parameterIds);
|
||||||
|
} else {
|
||||||
|
parameters.enableAll(parameterIds);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user