package defpackage; import java.util.Iterator; import java.util.List; import java.util.function.Supplier; @rn(name = "Replay", category = rl.MISC, description = "Keeps the last seconds of gameplay ready to save, records clips and trims them in place") public final class ti extends rm { public static final ti INSTANCE = new ti(); private static final String AUDIO_DEVICE_FAILURE = "clip audio device lookup failed"; private static final String RESOLUTION_LOW = "480p"; private static final String RESOLUTION_MEDIUM = "720p"; private static final String RESOLUTION_HIGH = "1080p"; private static final String QUALITY_LOW = "Low"; private static final String QUALITY_MEDIUM = "Medium"; private static final String QUALITY_HIGH = "High"; private static final int HEIGHT_LOW = 480; private static final int HEIGHT_MEDIUM = 720; private static final int HEIGHT_HIGH = 1080; private static final float JPEG_LOW = 0.62F; private static final float JPEG_MEDIUM = 0.78F; private static final float JPEG_HIGH = 0.9F; private static final int QUANTIZER_LOW = 27; private static final int QUANTIZER_MEDIUM = 22; private static final int QUANTIZER_HIGH = 18; private static final long MILLIS_PER_SECOND = 1000L; private static final float PERCENT_SCALE = 100.0F; private static final long BYTES_PER_MEGABYTE = 1048576L; private static final long BYTES_PER_GIGABYTE = 1073741824L; private static final int MIN_EXPORT_THREADS = 1; private static final int MAX_EXPORT_THREADS = 4; private static final int CORES_PER_EXPORT_THREAD = 2; private static final int[] CAPTURE_HEIGHTS; public final sg resolution; public final sm framerate; public final rv autoTune; public final ru instantReplay; public final sm bufferSeconds; public final sm memoryLimit; public final sm storageLimit; public final sm exportFramerate; public final sg quality; public final ru gameAudio; public final sg gameAudioSource; public final ru microphone; public final sg microphoneSource; public final ru autoExport; public final ru openEditor; public final sm previewVolume; public final sc saveKey; public final sc recordKey; public final sc libraryKey; private ti() { String var10003 = "Resolution"; String[] var10004 = new String[3]; var10004[0] = "720p"; var10004[1] = "480p"; var10004[2] = "1080p"; this.resolution = new sg(var10003, var10004) .describe( "480p", "Cheapest to record, fine for sharing in chat" ) .describe( "720p", "Balanced, the default for clips" ) .describe( "1080p", "Sharpest, costs the most cpu while buffering" ) .description( "Height the frames are downscaled to before they are stored" ); this.framerate = new sm("Framerate", 30.0F, 10.0F, 144.0F, 1.0F) .description( "Frames captured per second, higher values cost more cpu and memory" ); this.autoTune = new rv("Auto", () -> aje.getInstance().start()) .description( "Measures for a few seconds what this machine sustains, then applies the highest resolution, framerate and memory limit that fit. Clears the buffered replay" ); this.instantReplay = new ru( "Instant Replay", (boolean)((((51220884 | -51220883) + (51220884 & -51220883)) ) != 0)) .description( "Keep the last seconds buffered so they can be saved after they happened" ); this.bufferSeconds = new sm( "Buffer", 30.0F, 5.0F, 120.0F, 5.0F, this.instantReplay::isEnabled ) .description( "How many seconds the instant replay keeps ready" ); this.memoryLimit = new sm( "Memory Limit", 256.0F, 64.0F, 1024.0F, 32.0F, this.instantReplay::isEnabled ) .description( "Upper bound in megabytes for the buffered frames" ); this.storageLimit = new sm("Storage", 8.0F, 1.0F, 64.0F, 1.0F) .description( "Gigabytes of clips kept on disk before the oldest ones are removed" ); this.exportFramerate = new sm( "Export FPS", 60.0F, 24.0F, 120.0F, 1.0F ) .description( "Framerate of the exported video, extra captured frames are dropped" ); var10003 = "Quality"; var10004 = new String[3]; var10004[0] = "Medium"; var10004[1] = "Low"; var10004[2] = "High"; this.quality = new sg(var10003, var10004) .describe( "Low", "Smallest buffer and file, softest picture" ) .describe( "Medium", "Balanced picture and size" ) .describe( "High", "Cleanest picture, the biggest files" ) .description( "Compression used for buffered frames and exported video" ); this.gameAudio = new ru( "Game Audio", (boolean)((((899333948 ^ -899333948) + ((899333948 & -899333948) << 1)) ) != 0)) .description( "Record what the game plays, needs a loopback input such as Stereo Mix or BlackHole" ); var10003 = "Game Device"; Supplier var5 = this.gameAudio::isEnabled; String[] var10005 = new String[1]; var10005[0] = "Auto"; this.gameAudioSource = new sg(var10003, var5, var10005) .description( "Input the game sound is captured from" ); this.microphone = new ru( "Microphone", (boolean)((((-1677017054 ^ 1677017054) + ((-1677017054 & 1677017054) << 1)) ) != 0)) .description( "Mix your microphone into the clip" ); var10003 = "Mic Device"; Supplier var6 = this.microphone::isEnabled; var10005 = new String[1]; var10005[0] = "Auto"; this.microphoneSource = new sg(var10003, var6, var10005) .description( "Input the microphone is captured from" ); this.autoExport = new ru( "Auto Export", (boolean)((((1433392962 ^ -1433392962) + ((1433392962 & -1433392962) << 1)) ) != 0)) .description( "Write the mp4 straight after a clip is saved instead of waiting for the editor" ); this.openEditor = new ru( "Open Editor", (boolean)((((-1848373380 ^ 1848373380) + ((-1848373380 & 1848373380) << 1)) ) != 0)) .description( "Jump into the trim editor as soon as a clip is saved" ); this.previewVolume = new sm("Preview Volume", 100.0F, 0.0F, 100.0F, 5.0F) .description( "Playback volume of the clip editor" ); this.saveKey = new sc( "Save Replay", (2099435445 | -2099435147) + (2099435445 & -2099435147) ) .description( "Stores the buffered seconds as a clip" ); this.recordKey = new sc( "Record", (-142705756 | 142706055) + (-142705756 & 142706055) ) .description( "Starts and stops a manual recording" ); this.libraryKey = new sc( "Clips", (-1201388595 | 1201388890) + (-1201388595 & 1201388890) ) .description( "Opens the clip library and trim editor" ); this.loadAudioDevices(); this.hideFromModuleCard(); } private void hideFromModuleCard() { Iterator var1 = null; ro var2 = null; int var3 = -980845074; while (true) { switch (var3) { case -2033921481: return; case -1798361704: var2.setVisible(() -> Boolean.valueOf((boolean)((((1989526043 | -1989526043) + (1989526043 & -1989526043))) != 0))); var3 = 2119859184; break; case -980845074: default: var1 = this.getSettings().iterator(); var3 = -745307607; break; case -745307607: if (var1.hasNext()) { var3 = 1829459865; } else { var3 = -2033921481; } break; case 1829459865: var2 = (ro)var1.next(); if (!(var2 instanceof sc)) { var3 = -1798361704; } else { var3 = 2119859184; } break; case 2119859184: var3 = -745307607; } } } private void loadAudioDevices() { try { List var1 = ajq.inputDevices(); this.gameAudioSource.replaceValues(var1); this.microphoneSource.replaceValues(var1); } catch (Throwable var2) { id.error( Cif.MEDIA, "clip audio device lookup failed", var2 ); } } public String gameAudioDevice() { String var1 = null; int var2 = -1858956924; while (true) { switch (var2) { case -1858956924: default: var1 = this.gameAudioSource.get(); if (!"Auto".equals(var1)) { var2 = 738727317; } else { var2 = 2091312160; } break; case 738727317: return ajq.resolveDevice(var1); case 2091312160: return ajq.detectLoopbackDevice(); } } } public String microphoneDevice() { return ajq.resolveDevice(this.microphoneSource.get()); } @Override public void onDisable() { super.onDisable(); ajn.getInstance().shutdown(); } @k public void onKey(er var1) { ajn var2 = null; int var3 = 322515931; while (true) { switch (var3) { case -1973664990: if (var1.is(this.recordKey.getKeyCode())) { var3 = -867346940; } else { var3 = -298343398; } break; case -1224514233: return; case -867346940: var2.toggleRecording(); return; case -298343398: if (var1.is(this.libraryKey.getKeyCode())) { var3 = 279005349; } else { var3 = 599027319; } break; case 7220183: if (mc.gui.screen() != null) { var3 = -1224514233; } else { var3 = 1511403765; } break; case 279005349: aby.open(); var3 = 599027319; break; case 322515931: default: if (var1.getAction() == (-1313499834 | 1313499835) + (-1313499834 & 1313499835)) { var3 = 7220183; } else { var3 = -1224514233; } break; case 599027319: return; case 667926549: var2.saveInstantReplay(); return; case 1511403765: var2 = ajn.getInstance(); if (var1.is(this.saveKey.getKeyCode())) { var3 = 667926549; } else { var3 = -1973664990; } } } } public static int[] captureHeights() { return (int[])CAPTURE_HEIGHTS.clone(); } public void applyCaptureProfile(int var1, int var2, int var3) { this.resolution.set(heightMode(var1)); this.quality.set("High"); this.framerate.setCurrent(var2); this.memoryLimit.setCurrent(var3); } private static String heightMode(int var0) { String var2 = null; int var1 = -1548044500; while (true) { switch (var1) { case -1800839749: return var2; case -1548044500: default: if (var0 >= (304681142 | -304680062) + (304681142 & -304680062)) { var1 = -487921123; } else { var1 = -1137774942; } break; case -1137774942: if (var0 >= (685338989 ^ -685338269) + ((685338989 & -685338269) << 1)) { var1 = -443463283; } else { var1 = 1235319257; } break; case -487921123: return "1080p"; case -443463283: var2 = "720p"; var1 = -1800839749; break; case 1235319257: var2 = "480p"; var1 = -1800839749; } } } public int captureHeight() { int var2 = 0; int var1 = -1660900468; while (true) { switch (var1) { case -1822408903: return 480; case -1660900468: default: if (this.resolution.is("480p")) { var1 = -1822408903; } else { var1 = -243178634; } break; case -1284817233: return var2; case -243178634: if (this.resolution.is("1080p")) { var1 = 99113982; } else { var1 = 544955321; } break; case 99113982: var2 = 1080; var1 = -1284817233; break; case 544955321: var2 = 720; var1 = -1284817233; } } } public int captureFps() { return Math.round(this.framerate.getCurrent()); } public float jpegQuality() { float var2 = 0.0F; int var1 = -275292694; while (true) { switch (var1) { case -792210472: var2 = 0.9F; var1 = 1944777135; break; case -275292694: default: if (this.quality.is("Low")) { var1 = 1586581496; } else { var1 = 1632902305; } break; case 1577126482: var2 = 0.78F; var1 = 1944777135; break; case 1586581496: return 0.62F; case 1632902305: if (this.quality.is("High")) { var1 = -792210472; } else { var1 = 1577126482; } break; case 1944777135: return var2; } } } public int exportQuantizer() { int var2 = 0; int var1 = -1572292549; while (true) { switch (var1) { case -2081132624: return var2; case -1572292549: default: if (this.quality.is("Low")) { var1 = 292978868; } else { var1 = -1248895528; } break; case -1518442369: var2 = 18; var1 = -2081132624; break; case -1248895528: if (this.quality.is("High")) { var1 = -1518442369; } else { var1 = -886075674; } break; case -886075674: var2 = 22; var1 = -2081132624; break; case 292978868: return 27; } } } public float previewGain() { return this.previewVolume.getCurrent() / 100.0F; } public int exportFps() { return Math.round(this.exportFramerate.getCurrent()); } public int exportThreads() { return Math.clamp( Runtime.getRuntime().availableProcessors() / (2), 1, (1881771119 | -1881771115) + (1881771119 & -1881771115) ); } public long bufferMillis() { return (long)this.bufferSeconds.getCurrent() * ((8473840490956687632L ^ -8473840490956686632L) + ((8473840490956687632L & -8473840490956686632L) << 1)); } public long storageBytes() { return (long)this.storageLimit.getCurrent() * ((8882843681655584144L | -8882843680581842320L) + (8882843681655584144L & -8882843680581842320L)); } public long bufferBytes() { return (long)this.memoryLimit.getCurrent() * ((2166254671518597803L | -2166254671517549227L) + (2166254671518597803L & -2166254671517549227L)); } static { int[] var10000 = new int[3]; var10000[0] = 1080; var10000[1] = 720; var10000[2] = 480; CAPTURE_HEIGHTS = var10000; } }