Skip to content

Commit 1a35c26

Browse files
committed
Fix: Handling with indexes
1 parent e5d6cdd commit 1a35c26

File tree

2 files changed

+159
-111
lines changed

2 files changed

+159
-111
lines changed

composeApp/src/desktopMain/kotlin/edneyosf/edconv/features/converter/ConverterViewModel.kt

Lines changed: 41 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -69,6 +69,7 @@ class ConverterViewModel(private val config: EdConfig, private val process: EdPr
6969
onProgress = ::onProgress
7070
)
7171
observeEncoders()
72+
observeIndexes()
7273
observeInput()
7374
observeQueue()
7475
}
@@ -101,7 +102,11 @@ class ConverterViewModel(private val config: EdConfig, private val process: EdPr
101102
presetVideo = video?.defaultPreset,
102103
compressionTypeVideo = video?.compressions?.firstOrNull()
103104
)
104-
val encoder = if(type == MediaType.AUDIO) audio else video
105+
val encoder = type?.currentEncoder(
106+
indexVideo = indexVideo,
107+
encoderVideo = video,
108+
encoderAudio = audio
109+
)
105110

106111
if(input != null) newState.copy(output = encoder?.toOutput(inputMedia = input))
107112
else newState
@@ -110,6 +115,24 @@ class ConverterViewModel(private val config: EdConfig, private val process: EdPr
110115
}
111116
}
112117

118+
private fun observeIndexes() {
119+
viewModelScope.launch {
120+
_state.map { it.indexAudio to it.indexVideo }
121+
.distinctUntilChanged()
122+
.collectLatest { (audio, video) ->
123+
val state = _state.value
124+
val input = state.input
125+
val encoder = state.type?.currentEncoder(
126+
indexVideo = video,
127+
encoderVideo = state.encoderVideo,
128+
encoderAudio = state.encoderAudio
129+
)
130+
131+
if(input != null) _state.update { copy(output = encoder?.toOutput(inputMedia = input)) }
132+
}
133+
}
134+
}
135+
113136
fun setInput(newInput: InputMedia?, newType: MediaType?) {
114137
if(newInput != null && newType != null) {
115138
_state.updateAndSync {
@@ -131,21 +154,24 @@ class ConverterViewModel(private val config: EdConfig, private val process: EdPr
131154

132155
val newEncoderAudio = encoderAudio ?: Encoder.OPUS
133156
val newEncoderVideo = encoderVideo ?: Encoder.AV1
134-
val newOutput = if(newType == MediaType.AUDIO)
135-
newEncoderAudio.toOutput(inputMedia = newInput)
136-
else
137-
newEncoderVideo.toOutput(inputMedia = newInput)
157+
val newEncoder = type?.currentEncoder(
158+
indexVideo = indexVideo,
159+
encoderVideo = newEncoderVideo,
160+
encoderAudio = newEncoderAudio
161+
)
138162

139163
copy(
140164
input = newInput,
141165
type = newType,
166+
indexVideo = if(newInput.videos.isEmpty()) -1 else 0,
167+
indexAudio = if(newInput.audios.isEmpty()) -1 else 0,
142168
encoderAudio = newEncoderAudio,
143169
encoderVideo = newEncoderVideo,
144170
resolution = newResolution,
145171
pixelFormat = newPixelFormat,
146172
channels = newChannels,
147173
sampleRate = newSampleRate,
148-
output = newOutput
174+
output = newEncoder.toOutput(inputMedia = newInput)
149175
)
150176
}
151177
}
@@ -204,7 +230,7 @@ class ConverterViewModel(private val config: EdConfig, private val process: EdPr
204230

205231
val streamVideo = input?.videos?.firstOrNull()
206232
val streamAudio = input?.audios?.firstOrNull()
207-
var inputChannels: Int? = null
233+
var inputChannels: Int?
208234
var customChannelsArgs: List<String>? = null
209235

210236
if(streamAudio != null && encoderAudio != null) {
@@ -481,6 +507,14 @@ class ConverterViewModel(private val config: EdConfig, private val process: EdPr
481507

482508
override fun setHdr10ToSdr(enabled: Boolean) { _state.updateAndSync { copy(hdr10ToSdr = enabled) } }
483509

510+
private fun MediaType.currentEncoder(indexVideo: Int?, encoderVideo: Encoder?, encoderAudio: Encoder?) =
511+
when {
512+
this == MediaType.VIDEO && indexVideo == -1 -> encoderAudio
513+
this == MediaType.AUDIO -> encoderAudio
514+
this == MediaType.VIDEO -> encoderVideo
515+
else -> encoderVideo
516+
}
517+
484518
private fun Encoder?.toOutput(inputMedia: InputMedia): Pair<String, String>? {
485519
var output: Pair<String, String>? = null
486520

composeApp/src/desktopMain/kotlin/edneyosf/edconv/features/converter/ui/ConverterScreen.kt

Lines changed: 118 additions & 104 deletions
Original file line numberDiff line numberDiff line change
@@ -68,6 +68,8 @@ private fun ConverterState.Content(command: String, event: ConverterEvent) {
6868
val invalidOutputFile = outputFile?.extension?.isBlank() == true
6969
val hasVideo = input?.videos?.isNotEmpty() == true
7070
val hasAudio = input?.audios?.isNotEmpty() == true
71+
val videoEnabled = indexVideo != -1
72+
val audioEnabled = indexAudio != -1
7173

7274
Column(
7375
modifier = Modifier.padding(all = dimens.md),
@@ -106,73 +108,79 @@ private fun ConverterState.Content(command: String, event: ConverterEvent) {
106108
onValueChange = event::setIndexVideo,
107109
onClick = { event.setIndexVideo(0) }
108110
)
109-
AllIndexesInput(
110-
enabled = indexVideo == null,
111-
onClick = { event.setIndexVideo(null) }
112-
)
113-
DisableIndexInput(
114-
enabled = indexVideo == -1,
115-
onClick = { event.setIndexVideo(-1) }
116-
)
117-
}
118-
Row(
119-
horizontalArrangement = Arrangement.spacedBy(space = dimens.xl),
120-
verticalAlignment = Alignment.CenterVertically
121-
) {
122-
EncoderInput(
123-
value = encoderVideo,
124-
compression = compressionTypeVideo,
125-
mediaType = MediaType.VIDEO,
126-
onValueChange = event::setEncoderVideo,
127-
onClick = { event.setCompressionTypeVideo(null) }
128-
)
129-
CopyInput(compressionType = compressionTypeVideo) {
130-
event.setCompressionTypeVideo(CompressionType.COPY)
111+
if(input.videos.size > 1) {
112+
AllIndexesInput(
113+
enabled = indexVideo == null,
114+
onClick = { event.setIndexVideo(null) }
115+
)
116+
}
117+
if(indexAudio != -1){
118+
DisableIndexInput(
119+
enabled = !videoEnabled,
120+
onClick = { event.setIndexVideo(-1) }
121+
)
131122
}
132-
CBRInput(
133-
encoder = encoderVideo,
134-
bitrate = bitrateVideo,
135-
compressionType = compressionTypeVideo,
136-
mediaType = encoderVideo?.mediaType,
137-
onClick = { event.setCompressionTypeVideo(CompressionType.CBR) },
138-
onValueChange = event::setBitrateVideo
139-
)
140-
CRFInput(
141-
onClick = { event.setCompressionTypeVideo(CompressionType.CRF) },
142-
onValueChange = event::setBitrateControlVideo
143-
)
144123
}
145-
if(compressionTypeVideo != CompressionType.COPY) {
124+
if(videoEnabled) {
125+
Row(
126+
horizontalArrangement = Arrangement.spacedBy(space = dimens.xl),
127+
verticalAlignment = Alignment.CenterVertically
128+
) {
129+
EncoderInput(
130+
value = encoderVideo,
131+
compression = compressionTypeVideo,
132+
mediaType = MediaType.VIDEO,
133+
onValueChange = event::setEncoderVideo,
134+
onClick = { event.setCompressionTypeVideo(null) }
135+
)
136+
CopyInput(compressionType = compressionTypeVideo) {
137+
event.setCompressionTypeVideo(CompressionType.COPY)
138+
}
139+
CBRInput(
140+
encoder = encoderVideo,
141+
bitrate = bitrateVideo,
142+
compressionType = compressionTypeVideo,
143+
mediaType = encoderVideo?.mediaType,
144+
onClick = { event.setCompressionTypeVideo(CompressionType.CBR) },
145+
onValueChange = event::setBitrateVideo
146+
)
147+
CRFInput(
148+
onClick = { event.setCompressionTypeVideo(CompressionType.CRF) },
149+
onValueChange = event::setBitrateControlVideo
150+
)
151+
}
152+
if(compressionTypeVideo != CompressionType.COPY) {
153+
Row(
154+
verticalAlignment = Alignment.CenterVertically,
155+
horizontalArrangement = Arrangement.spacedBy(space = dimens.xl)
156+
) {
157+
ResolutionInput(
158+
value = resolution,
159+
onValueChange = event::setResolution
160+
)
161+
PixelFormatInput(
162+
value = pixelFormat,
163+
onValueChange = event::setPixelFormat
164+
)
165+
PresetInput(onValueChange = event::setPresetVideo)
166+
}
167+
}
146168
Row(
147169
verticalAlignment = Alignment.CenterVertically,
148170
horizontalArrangement = Arrangement.spacedBy(space = dimens.xl)
149-
) {
150-
ResolutionInput(
151-
value = resolution,
152-
onValueChange = event::setResolution
171+
){
172+
CheckboxInput(
173+
checked = noSubtitle,
174+
label = strings[NO_SUBTITLE_INPUT],
175+
onCheckedChange = event::setNoSubtitle
153176
)
154-
PixelFormatInput(
155-
value = pixelFormat,
156-
onValueChange = event::setPixelFormat
177+
CheckboxInput(
178+
checked = hdr10ToSdr,
179+
label = strings[HDR10_TO_SDR],
180+
onCheckedChange = event::setHdr10ToSdr
157181
)
158-
PresetInput(onValueChange = event::setPresetVideo)
159182
}
160183
}
161-
Row(
162-
verticalAlignment = Alignment.CenterVertically,
163-
horizontalArrangement = Arrangement.spacedBy(space = dimens.xl)
164-
){
165-
CheckboxInput(
166-
checked = noSubtitle,
167-
label = strings[NO_SUBTITLE_INPUT],
168-
onCheckedChange = event::setNoSubtitle
169-
)
170-
CheckboxInput(
171-
checked = hdr10ToSdr,
172-
label = strings[HDR10_TO_SDR],
173-
onCheckedChange = event::setHdr10ToSdr
174-
)
175-
}
176184
}
177185
}
178186
if(hasAudio) {
@@ -191,55 +199,61 @@ private fun ConverterState.Content(command: String, event: ConverterEvent) {
191199
onValueChange = event::setIndexAudio,
192200
onClick = { event.setIndexAudio(0) }
193201
)
194-
AllIndexesInput(
195-
enabled = indexAudio == null,
196-
onClick = { event.setIndexAudio(null) }
197-
)
198-
DisableIndexInput(
199-
enabled = indexAudio == -1,
200-
onClick = { event.setIndexAudio(-1) }
201-
)
202-
}
203-
Row(
204-
horizontalArrangement = Arrangement.spacedBy(space = dimens.xl),
205-
verticalAlignment = Alignment.CenterVertically
206-
){
207-
EncoderInput(
208-
value = encoderAudio,
209-
compression = compressionTypeAudio,
210-
mediaType = MediaType.AUDIO,
211-
onValueChange = event::setEncoderAudio,
212-
onClick = { event.setCompressionTypeAudio(null) }
213-
)
214-
CopyInput(compressionType = compressionTypeAudio) {
215-
event.setCompressionTypeAudio(CompressionType.COPY)
202+
if(input.audios.size > 1) {
203+
AllIndexesInput(
204+
enabled = indexAudio == null,
205+
onClick = { event.setIndexAudio(null) }
206+
)
207+
}
208+
if(indexVideo != -1){
209+
DisableIndexInput(
210+
enabled = !audioEnabled,
211+
onClick = { event.setIndexAudio(-1) }
212+
)
216213
}
217-
CBRInput(
218-
encoder = encoderAudio,
219-
bitrate = bitrateAudio,
220-
compressionType = compressionTypeAudio,
221-
mediaType = encoderAudio?.mediaType,
222-
onClick = { event.setCompressionTypeAudio(CompressionType.CBR) },
223-
onValueChange = event::setBitrateAudio
224-
)
225-
VBRInput(
226-
onClick = { event.setCompressionTypeAudio(CompressionType.VBR) },
227-
onValueChange = event::setBitrateControlAudio
228-
)
229214
}
230-
if(compressionTypeAudio != CompressionType.COPY) {
215+
if(audioEnabled) {
231216
Row(
232-
verticalAlignment = Alignment.CenterVertically,
233-
horizontalArrangement = Arrangement.spacedBy(space = dimens.xl)
234-
) {
235-
ChannelsInput(
236-
value = channels,
237-
onValueChange = event::setChannels
217+
horizontalArrangement = Arrangement.spacedBy(space = dimens.xl),
218+
verticalAlignment = Alignment.CenterVertically
219+
){
220+
EncoderInput(
221+
value = encoderAudio,
222+
compression = compressionTypeAudio,
223+
mediaType = MediaType.AUDIO,
224+
onValueChange = event::setEncoderAudio,
225+
onClick = { event.setCompressionTypeAudio(null) }
238226
)
239-
SampleRateInput(
240-
value = sampleRate,
241-
onValueChange = event::setSampleRate
227+
CopyInput(compressionType = compressionTypeAudio) {
228+
event.setCompressionTypeAudio(CompressionType.COPY)
229+
}
230+
CBRInput(
231+
encoder = encoderAudio,
232+
bitrate = bitrateAudio,
233+
compressionType = compressionTypeAudio,
234+
mediaType = encoderAudio?.mediaType,
235+
onClick = { event.setCompressionTypeAudio(CompressionType.CBR) },
236+
onValueChange = event::setBitrateAudio
242237
)
238+
VBRInput(
239+
onClick = { event.setCompressionTypeAudio(CompressionType.VBR) },
240+
onValueChange = event::setBitrateControlAudio
241+
)
242+
}
243+
if(compressionTypeAudio != CompressionType.COPY) {
244+
Row(
245+
verticalAlignment = Alignment.CenterVertically,
246+
horizontalArrangement = Arrangement.spacedBy(space = dimens.xl)
247+
) {
248+
ChannelsInput(
249+
value = channels,
250+
onValueChange = event::setChannels
251+
)
252+
SampleRateInput(
253+
value = sampleRate,
254+
onValueChange = event::setSampleRate
255+
)
256+
}
243257
}
244258
}
245259
}
@@ -471,8 +485,8 @@ private fun IndexInput(value: Int?, max: Int, enabled: Boolean, onValueChange: (
471485

472486
@Composable
473487
private fun EncoderInput(
474-
value: Encoder?, compression: CompressionType?, mediaType: MediaType?, onValueChange: (Encoder) -> Unit,
475-
onClick: () -> Unit
488+
value: Encoder?, compression: CompressionType?, mediaType: MediaType?,
489+
onValueChange: (Encoder) -> Unit, onClick: () -> Unit
476490
) {
477491
var expanded by remember { mutableStateOf(value = false) }
478492
val encoders = Encoder.getAll().filter { it.mediaType == mediaType }

0 commit comments

Comments
 (0)