├── .editorconfig ├── .gitattributes ├── .github └── workflows │ └── build.yml ├── .gitignore ├── .gitmodules ├── .nuke ├── build.schema.json └── parameters.json ├── GitVersion.yml ├── LICENSE ├── README.md ├── build.cmd ├── build.ps1 ├── build.sh ├── build ├── .editorconfig ├── Build.cs ├── Configuration.cs ├── Directory.Build.props ├── Directory.Build.targets ├── DownloadTools.cs ├── PackInstaller.cs ├── PlistWriter.cs ├── rmbox-build.csproj └── rmbox-build.csproj.DotSettings ├── common ├── Assets │ ├── rmbox-transparent.png │ ├── rmbox.icns │ ├── rmbox.ico │ └── rmbox.png ├── installer │ └── nsis │ │ ├── .editorconfig │ │ ├── .gitignore │ │ ├── assistedInstaller.nsh │ │ ├── common.nsh │ │ ├── include │ │ ├── StdUtils.nsh │ │ ├── StrContains.nsh │ │ ├── extractAppPackage.nsh │ │ ├── installUtil.nsh │ │ └── installer.nsh │ │ ├── installSection.nsh │ │ ├── installer.nsi │ │ ├── messages.nsh │ │ ├── multiUser.nsh │ │ └── uninstaller.nsh └── meta │ └── rmbenv.exe.manifest ├── examples ├── lua │ └── rmbox-plugin-lua-example │ │ ├── .editorconfig │ │ ├── .gitignore │ │ └── rmbox-plugin-lua-example.lua ├── node │ └── rmbox-plugin-node-example │ │ ├── .editorconfig │ │ ├── .eslintrc.js │ │ ├── .gitignore │ │ ├── .prettierrc.js │ │ ├── jsconfig.json │ │ ├── package.json │ │ ├── src │ │ ├── index.ts │ │ └── rmbox.d.ts │ │ └── tsconfig.json └── python │ └── rmbox-plugin-python-example │ ├── .editorconfig │ ├── .gitignore │ └── rmbox-plugin-python-example.py ├── lgtm.yml ├── plugins ├── rmbox-plugin-audio │ ├── AudioMeta.cs │ ├── ConfigSections │ │ ├── ViewModels │ │ │ ├── AudioConfigSectionViewModel.cs │ │ │ └── AudioQualityConfigSectionViewModel.cs │ │ └── Views │ │ │ ├── AudioConfigSection.axaml │ │ │ ├── AudioConfigSection.axaml.cs │ │ │ ├── AudioQualityConfigSection.axaml │ │ │ └── AudioQualityConfigSection.axaml.cs │ ├── Operations │ │ └── AudioEncodeOperation.cs │ └── rmbox-plugin-audio.csproj ├── rmbox-plugin-common │ ├── CommonMeta.cs │ ├── ConfigSections │ │ ├── ViewModels │ │ │ ├── AdvancedTrackConfigSectionViewModel.cs │ │ │ ├── CustomArgsConfigSectionViewModel.cs │ │ │ ├── IOConfigSectionViewModel.cs │ │ │ ├── IntroConfigSectionViewModel.cs │ │ │ ├── MuxConfigSectionViewModel.cs │ │ │ ├── MuxOptionsConfigSectionViewModel.cs │ │ │ ├── OutputConfigSectionViewModel.cs │ │ │ └── PictureFlowConfigSectionViewModel.cs │ │ └── Views │ │ │ ├── AdvancedTrackConfigSection.axaml │ │ │ ├── AdvancedTrackConfigSection.axaml.cs │ │ │ ├── CustomArgsConfigSection.axaml │ │ │ ├── CustomArgsConfigSection.axaml.cs │ │ │ ├── IOConfigSection.axaml │ │ │ ├── IOConfigSection.axaml.cs │ │ │ ├── IntroConfigSection.axaml │ │ │ ├── IntroConfigSection.axaml.cs │ │ │ ├── MuxConfigSection.axaml │ │ │ ├── MuxConfigSection.axaml.cs │ │ │ ├── MuxOptionsConfigSection.axaml │ │ │ ├── MuxOptionsConfigSection.axaml.cs │ │ │ ├── OutputConfigSection.axaml │ │ │ ├── OutputConfigSection.axaml.cs │ │ │ ├── PictureFlowConfigSection.axaml │ │ │ └── PictureFlowConfigSection.axaml.cs │ ├── Formatters │ │ └── NullFormatter.cs │ └── rmbox-plugin-common.csproj ├── rmbox-plugin-ffmpeg │ ├── FFmpegMeta.cs │ ├── Formatters │ │ └── FFmpegFormatter.cs │ ├── Operations │ │ ├── BilibiliLoudnormOperation.cs │ │ ├── FFmpegAddAudioTrackOperation.cs │ │ ├── FFmpegAddBlankVideoTrackOperation.cs │ │ ├── FFmpegAddMuteAudioTrackOperation.cs │ │ ├── FFmpegAudioSilenceRemoveOperation.cs │ │ ├── FFmpegBlankVideoOperation.cs │ │ ├── FFmpegClearSubtitleOperation.cs │ │ ├── FFmpegCopyOperation.cs │ │ ├── FFmpegEncodeOperation.cs │ │ ├── FFmpegExtractAudioOperation.cs │ │ ├── FFmpegExtractVideoOperation.cs │ │ ├── FFmpegFillBlackOperation.cs │ │ ├── FFmpegLoudnormOperation.cs │ │ ├── FFmpegMetaRotateOperation.cs │ │ ├── FFmpegMuxAudioOperation.cs │ │ ├── FFmpegMuxOperation.cs │ │ ├── FFmpegMuxSubtitleOperation.cs │ │ ├── FFmpegPictureFlowOperation.cs │ │ ├── FFmpegRemoveAudioTrackOperation.cs │ │ ├── FFmpegReplaceAudioTrackOperation.cs │ │ ├── FFmpegStillImageOperation.cs │ │ └── FFmpegVfrFixOperation.cs │ ├── Resources │ │ └── Markdowns │ │ │ ├── FFmpegCopyOperation.md │ │ │ └── FFmpegMetaRotateOperation.md │ └── rmbox-plugin-ffmpeg.csproj ├── rmbox-plugin-hwenc │ ├── ConfigSections │ │ ├── ViewModels │ │ │ ├── HwEncCodecConfigSectionViewModel.cs │ │ │ ├── HwEncCoreConfigSectionViewModel.cs │ │ │ └── HwEncQualityConfigSectionViewModel.cs │ │ └── Views │ │ │ ├── HwEncCodecConfigSection.axaml │ │ │ ├── HwEncCodecConfigSection.axaml.cs │ │ │ ├── HwEncCoreConfigSection.axaml │ │ │ ├── HwEncCoreConfigSection.axaml.cs │ │ │ ├── HwEncQualityConfigSection.axaml │ │ │ └── HwEncQualityConfigSection.axaml.cs │ ├── Formatters │ │ └── HwEncFormatter.cs │ ├── HwEncMeta.cs │ ├── Operations │ │ └── HwEncOperation.cs │ └── rmbox-plugin-hwenc.csproj └── rmbox-plugin-x264 │ ├── ConfigSections │ ├── ViewModels │ │ ├── X264CoreConfigSectionViewModel.cs │ │ ├── X264DemuxerConfigSectionViewModel.cs │ │ └── X264EncodeQualityConfigSectionViewModel.cs │ └── Views │ │ ├── X264CoreConfigSection.axaml │ │ ├── X264CoreConfigSection.axaml.cs │ │ ├── X264DemuxerConfigSection.axaml │ │ ├── X264DemuxerConfigSection.axaml.cs │ │ ├── X264EncodeQualityConfigSection.axaml │ │ └── X264EncodeQualityConfigSection.axaml.cs │ ├── Formatters │ └── X26xFormatter.cs │ ├── Operations │ └── X264EncodeOperation.cs │ ├── Resources │ └── Markdowns │ │ └── X264EncodeOperation.md │ ├── X264Meta.cs │ └── rmbox-plugin-x264.csproj ├── rmbox.sln ├── src ├── rmbenv │ ├── .gitignore │ ├── go.mod │ ├── go.sum │ ├── main.go │ └── versioninfo.json ├── rmbox-plugbase │ ├── Core │ │ ├── Interfaces │ │ │ ├── ConfigSectionBase.cs │ │ │ ├── IMeta.cs │ │ │ └── IOperation.cs │ │ ├── OperationException.cs │ │ ├── ProcessRunnerException.cs │ │ ├── ProjectParseException.cs │ │ └── TaskCommand.cs │ ├── Formatting │ │ ├── FormattedEvent.cs │ │ └── IFormatter.cs │ ├── Utils │ │ ├── Converters │ │ │ ├── ConverterExtension.cs │ │ │ └── StringBoolConverter.cs │ │ ├── Extensions │ │ │ ├── CommandExtension.cs │ │ │ ├── FormatPath.cs │ │ │ ├── GetAllFiles.cs │ │ │ ├── PathExtension.cs │ │ │ ├── ProcessExtension.cs │ │ │ └── StringExtension.cs │ │ └── StorageHelper.cs │ └── rmbox-plugbase.csproj ├── rmbox-shell │ ├── App.axaml │ ├── App.axaml.cs │ ├── Core │ │ └── Exporter.cs │ ├── Helpers │ │ └── CommandHelper.cs │ ├── Models │ │ └── OperationModel.cs │ ├── Program.cs │ ├── Properties │ │ └── launchSettings.json │ ├── Resources │ │ └── Markdowns │ │ │ └── ReleaseNote.md │ ├── Services │ │ ├── OperationService.cs │ │ ├── QueueService.cs │ │ └── RunnerService.cs │ ├── Styles │ │ └── Accent.xaml │ ├── Utils │ │ └── ConfigSections │ │ │ ├── BatchIOConfigSection.axaml │ │ │ ├── BatchIOConfigSection.axaml.cs │ │ │ └── BatchIOConfigSectionViewModel.cs │ ├── ViewModels │ │ ├── Operations │ │ │ ├── BatchOperationViewModel.cs │ │ │ ├── OperationViewModelBase.cs │ │ │ └── SingleOperationViewModel.cs │ │ └── Project │ │ │ ├── BatchProjectViewModel.cs │ │ │ ├── ProjectViewModel.cs │ │ │ └── SingleProjectViewModel.cs │ ├── Views │ │ ├── AboutView.axaml │ │ ├── AboutView.axaml.cs │ │ ├── Operations │ │ │ ├── BatchOperationView.axaml │ │ │ ├── BatchOperationView.axaml.cs │ │ │ ├── SingleOperationView.axaml │ │ │ └── SingleOperationView.axaml.cs │ │ ├── PluginManagerView.axaml │ │ ├── PluginManagerView.axaml.cs │ │ ├── PluginView.axaml │ │ ├── PluginView.axaml.cs │ │ ├── QueueStatus.cs │ │ ├── QueueView.axaml │ │ ├── QueueView.axaml.cs │ │ ├── StartView.axaml │ │ └── StartView.axaml.cs │ ├── Windows │ │ ├── MainWindow.axaml │ │ ├── MainWindow.axaml.cs │ │ ├── SplashWindow.axaml │ │ └── SplashWindow.axaml.cs │ └── rmbox-shell.csproj ├── rmbox-vpygen │ ├── .editorconfig │ ├── .eslintrc.js │ ├── .gitignore │ ├── .prettierrc.js │ ├── jsconfig.json │ ├── package.json │ ├── src │ │ └── index.ts │ └── tsconfig.json └── rmbox │ ├── Composition │ ├── IPluginGenerator.cs │ ├── Roslim │ │ ├── IRoslimGenerator.cs │ │ ├── RoslimException.cs │ │ ├── RoslimGenerator.cs │ │ ├── RoslimMeta.cs │ │ └── RoslimOperation.cs │ └── Services │ │ ├── IPluginService.cs │ │ ├── PluginCompositionException.cs │ │ ├── PluginLoadContext.cs │ │ ├── PluginService.cs │ │ └── PluginServiceInitialize.cs │ ├── Core │ ├── Parser │ │ ├── BatchProjectParser.cs │ │ ├── IParser.cs │ │ ├── ProjectParser.cs │ │ ├── QueueProjectParser.cs │ │ └── SingleProjectParser.cs │ ├── ProcessRunner.cs │ └── Processor.cs │ ├── Formatting │ └── FormattingService.cs │ ├── Program.cs │ ├── Properties │ └── launchSettings.json │ ├── Services │ └── CommandLine │ │ ├── CommandLineService.cs │ │ └── ProcessOptions.cs │ ├── Utils │ └── RmboxConsoleFormatter.cs │ └── rmbox.csproj └── test └── rmbox-test └── rmbox-test.csproj /.editorconfig: -------------------------------------------------------------------------------- 1 | # editorconfig.org 2 | 3 | # top-most EditorConfig file 4 | root = true 5 | 6 | # Default settings: 7 | # A newline ending every file 8 | # Use 4 spaces as indentation 9 | [*] 10 | insert_final_newline = true 11 | indent_style = space 12 | indent_size = 4 13 | trim_trailing_whitespace = true 14 | 15 | [project.json] 16 | indent_size = 2 17 | 18 | # Generated code 19 | [*{_AssemblyInfo.cs,.notsupported.cs}] 20 | generated_code = true 21 | -------------------------------------------------------------------------------- /.gitmodules: -------------------------------------------------------------------------------- 1 | [submodule "lib/rmnd-metro"] 2 | path = lib/rmnd-metro 3 | url = https://github.com/Ruminoid/rmnd-metro.git 4 | [submodule "lib/rmnd-common2"] 5 | path = lib/rmnd-common2 6 | url = https://github.com/Ruminoid/Common2.git 7 | -------------------------------------------------------------------------------- /.nuke/parameters.json: -------------------------------------------------------------------------------- 1 | { 2 | "$schema": "./build.schema.json", 3 | "Solution": "rmbox.sln" 4 | } -------------------------------------------------------------------------------- /GitVersion.yml: -------------------------------------------------------------------------------- 1 | assembly-versioning-scheme: MajorMinorPatchTag 2 | mode: ContinuousDelivery 3 | tag-prefix: 'v' 4 | increment: Patch 5 | branches: {} 6 | ignore: 7 | sha: [] 8 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 |
2 | 3 | 4 | 5 |

Ruminoid Toolbox

6 | 7 |

Visual Processing Toolbox.

8 | 9 |

For more information, please visit https://update.ruminoid.world.

10 | 11 |
12 | 13 | ## 许可 14 | 15 | Ruminoid Toolbox 使用 AGPL 协议授权。使用本产品或其源代码时,你不能将其闭源,改变许可协议或进行商业销售。 16 | 17 | 如果你发现了任何违规行为,请告知开发者。 18 | -------------------------------------------------------------------------------- /build.cmd: -------------------------------------------------------------------------------- 1 | :; set -eo pipefail 2 | :; SCRIPT_DIR=$(cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd) 3 | :; ${SCRIPT_DIR}/build.sh "$@" 4 | :; exit $? 5 | 6 | @ECHO OFF 7 | powershell -ExecutionPolicy ByPass -NoProfile "%~dp0build.ps1" %* 8 | -------------------------------------------------------------------------------- /build.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | 3 | bash --version 2>&1 | head -n 1 4 | 5 | set -eo pipefail 6 | SCRIPT_DIR=$(cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd) 7 | 8 | ########################################################################### 9 | # CONFIGURATION 10 | ########################################################################### 11 | 12 | BUILD_PROJECT_FILE="$SCRIPT_DIR/build/rmbox-build.csproj" 13 | TEMP_DIRECTORY="$SCRIPT_DIR//.nuke/temp" 14 | 15 | DOTNET_GLOBAL_FILE="$SCRIPT_DIR//global.json" 16 | DOTNET_INSTALL_URL="https://dot.net/v1/dotnet-install.sh" 17 | DOTNET_CHANNEL="Current" 18 | 19 | export DOTNET_CLI_TELEMETRY_OPTOUT=1 20 | export DOTNET_SKIP_FIRST_TIME_EXPERIENCE=1 21 | export DOTNET_MULTILEVEL_LOOKUP=0 22 | 23 | ########################################################################### 24 | # EXECUTION 25 | ########################################################################### 26 | 27 | function FirstJsonValue { 28 | perl -nle 'print $1 if m{"'"$1"'": "([^"]+)",?}' <<< "${@:2}" 29 | } 30 | 31 | # If dotnet CLI is installed globally and it matches requested version, use for execution 32 | if [ -x "$(command -v dotnet)" ] && dotnet --version &>/dev/null; then 33 | export DOTNET_EXE="$(command -v dotnet)" 34 | else 35 | # Download install script 36 | DOTNET_INSTALL_FILE="$TEMP_DIRECTORY/dotnet-install.sh" 37 | mkdir -p "$TEMP_DIRECTORY" 38 | curl -Lsfo "$DOTNET_INSTALL_FILE" "$DOTNET_INSTALL_URL" 39 | chmod +x "$DOTNET_INSTALL_FILE" 40 | 41 | # If global.json exists, load expected version 42 | if [[ -f "$DOTNET_GLOBAL_FILE" ]]; then 43 | DOTNET_VERSION=$(FirstJsonValue "version" "$(cat "$DOTNET_GLOBAL_FILE")") 44 | if [[ "$DOTNET_VERSION" == "" ]]; then 45 | unset DOTNET_VERSION 46 | fi 47 | fi 48 | 49 | # Install by channel or version 50 | DOTNET_DIRECTORY="$TEMP_DIRECTORY/dotnet-unix" 51 | if [[ -z ${DOTNET_VERSION+x} ]]; then 52 | "$DOTNET_INSTALL_FILE" --install-dir "$DOTNET_DIRECTORY" --channel "$DOTNET_CHANNEL" --no-path 53 | else 54 | "$DOTNET_INSTALL_FILE" --install-dir "$DOTNET_DIRECTORY" --version "$DOTNET_VERSION" --no-path 55 | fi 56 | export DOTNET_EXE="$DOTNET_DIRECTORY/dotnet" 57 | fi 58 | 59 | echo "Microsoft (R) .NET Core SDK version $("$DOTNET_EXE" --version)" 60 | 61 | "$DOTNET_EXE" build "$BUILD_PROJECT_FILE" /nodeReuse:false /p:UseSharedCompilation=false -nologo -clp:NoSummary --verbosity quiet 62 | "$DOTNET_EXE" run --project "$BUILD_PROJECT_FILE" --no-build -- "$@" 63 | -------------------------------------------------------------------------------- /build/.editorconfig: -------------------------------------------------------------------------------- 1 | [*.cs] 2 | dotnet_style_qualification_for_field = false:warning 3 | dotnet_style_qualification_for_property = false:warning 4 | dotnet_style_qualification_for_method = false:warning 5 | dotnet_style_qualification_for_event = false:warning 6 | dotnet_style_require_accessibility_modifiers = never:warning 7 | 8 | csharp_style_expression_bodied_methods = true:silent 9 | csharp_style_expression_bodied_properties = true:warning 10 | csharp_style_expression_bodied_indexers = true:warning 11 | csharp_style_expression_bodied_accessors = true:warning 12 | -------------------------------------------------------------------------------- /build/Configuration.cs: -------------------------------------------------------------------------------- 1 | using System.ComponentModel; 2 | using Nuke.Common.Tooling; 3 | 4 | [TypeConverter(typeof(TypeConverter))] 5 | public class Configuration : Enumeration 6 | { 7 | public static Configuration Debug = new Configuration { Value = nameof(Debug) }; 8 | public static Configuration Release = new Configuration { Value = nameof(Release) }; 9 | 10 | public static implicit operator string(Configuration configuration) 11 | { 12 | return configuration.Value; 13 | } 14 | } 15 | -------------------------------------------------------------------------------- /build/Directory.Build.props: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | -------------------------------------------------------------------------------- /build/Directory.Build.targets: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | -------------------------------------------------------------------------------- /build/PackInstaller.cs: -------------------------------------------------------------------------------- 1 | using Nuke.Common; 2 | using Nuke.Common.IO; 3 | using Nuke.Common.Tooling; 4 | using Nuke.Common.Utilities.Collections; 5 | using static Nuke.Common.IO.FileSystemTasks; 6 | 7 | partial class Build 8 | { 9 | Target PackMac => _ => _ 10 | .Executes(() => 11 | { 12 | AbsolutePath MacDirectory = DistDirectory / "RuminoidToolbox.app"; 13 | AbsolutePath MacContentsDirectory = MacDirectory / "Contents"; 14 | AbsolutePath MacMacOSDirectory = MacContentsDirectory / "MacOS"; 15 | AbsolutePath MacResourcesDirectory = MacContentsDirectory / "Resources"; 16 | 17 | new[] 18 | { 19 | MacDirectory, 20 | MacContentsDirectory, 21 | MacMacOSDirectory, 22 | MacResourcesDirectory 23 | }.ForEach(EnsureCleanDirectory); 24 | 25 | Logger.Info("Copying contents."); 26 | ForceCopyDirectoryRecursively( 27 | PackDirectory, 28 | MacMacOSDirectory); 29 | 30 | Logger.Info("Copying icon."); 31 | CopyFileToDirectory( 32 | RootDirectory / "common" / "Assets" / "rmbox.icns", 33 | MacResourcesDirectory, 34 | FileExistsPolicy.Overwrite); 35 | 36 | new Plist 37 | { 38 | CFBundleName = "Toolbox", 39 | CFBundleDisplayName = "Ruminoid Toolbox", 40 | CFBundleSpokenName = "Ruminoid Toolbox", 41 | CFBundleIdentifier = "world.ruminoid.toolbox", 42 | LSApplicationCategoryType = "public.app-category.developer-tools", 43 | CFBundleVersion = GitVersion.MajorMinorPatch, 44 | CFBundleExecutable = "rmbenv", 45 | CFBundleIconFile = "rmbox.icns", 46 | CFBundleShortVersionString = GitVersion.MajorMinorPatch 47 | }.Write(MacContentsDirectory); 48 | 49 | Logger.Info("Configuring privileges."); 50 | ProcessTasks.StartShell( 51 | "chmod -R 775 RuminoidToolbox.app", 52 | DistDirectory) 53 | .AssertZeroExitCode(); 54 | }); 55 | 56 | Target PackWindows => _ => _ 57 | .Executes(() => 58 | { 59 | ProcessTasks.StartShell( 60 | $"makensis -DVersion={GitVersion.MajorMinorPatch} common/installer/nsis/installer.nsi") 61 | .AssertZeroExitCode(); 62 | }); 63 | } 64 | -------------------------------------------------------------------------------- /build/rmbox-build.csproj: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | Exe 5 | net5.0 6 | 7 | CS0649;CS0169 8 | .. 9 | .. 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | -------------------------------------------------------------------------------- /common/Assets/rmbox-transparent.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Ruminoid/Toolbox/3cb3b1747c95b29d2a326863e8192d6bbb69821e/common/Assets/rmbox-transparent.png -------------------------------------------------------------------------------- /common/Assets/rmbox.icns: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Ruminoid/Toolbox/3cb3b1747c95b29d2a326863e8192d6bbb69821e/common/Assets/rmbox.icns -------------------------------------------------------------------------------- /common/Assets/rmbox.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Ruminoid/Toolbox/3cb3b1747c95b29d2a326863e8192d6bbb69821e/common/Assets/rmbox.ico -------------------------------------------------------------------------------- /common/Assets/rmbox.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Ruminoid/Toolbox/3cb3b1747c95b29d2a326863e8192d6bbb69821e/common/Assets/rmbox.png -------------------------------------------------------------------------------- /common/installer/nsis/.editorconfig: -------------------------------------------------------------------------------- 1 | [*.{nsh,nsi}] 2 | indent_size = 2 3 | -------------------------------------------------------------------------------- /common/installer/nsis/.gitignore: -------------------------------------------------------------------------------- 1 | *.exe 2 | -------------------------------------------------------------------------------- /common/installer/nsis/assistedInstaller.nsh: -------------------------------------------------------------------------------- 1 | !include StrContains.nsh 2 | !insertmacro MUI_PAGE_DIRECTORY 3 | # pageDirectory leave doesn't work (it seems because $INSTDIR is set after custom leave function) 4 | # so, we use instfiles pre 5 | !define MUI_PAGE_CUSTOMFUNCTION_PRE instFilesPre 6 | # sanitize the MUI_PAGE_DIRECTORY result to make sure it has a application name sub-folder 7 | Function instFilesPre 8 | ${If} ${FileExists} "$INSTDIR\*" 9 | ${StrContains} $0 "${APP_FILENAME}" $INSTDIR 10 | ${If} $0 == "" 11 | StrCpy $INSTDIR "$INSTDIR\${APP_FILENAME}" 12 | ${endIf} 13 | ${endIf} 14 | FunctionEnd 15 | !insertmacro MUI_PAGE_INSTFILES 16 | !insertmacro MUI_PAGE_FINISH 17 | -------------------------------------------------------------------------------- /common/installer/nsis/common.nsh: -------------------------------------------------------------------------------- 1 | !include x64.nsh 2 | !include WinVer.nsh 3 | 4 | BrandingText "${PRODUCT_NAME} ${VERSION}" 5 | ; ShowInstDetails nevershow 6 | SpaceTexts none 7 | FileBufSize 64 8 | Name "${PRODUCT_NAME}" 9 | 10 | !macro check64BitAndSetRegView 11 | ${If} ${IsWin2000} 12 | ${OrIf} ${IsWinME} 13 | ${OrIf} ${IsWinXP} 14 | ${OrIf} ${IsWinVista} 15 | MessageBox MB_OK "$(win7Required)" 16 | Quit 17 | ${EndIf} 18 | 19 | ${If} ${RunningX64} 20 | SetRegView 64 21 | ${Else} 22 | MessageBox MB_OK|MB_ICONEXCLAMATION "$(x64WinRequired)" 23 | Quit 24 | ${EndIf} 25 | !macroend 26 | 27 | !macro setLinkVars 28 | # old desktop shortcut (could exist or not since the user might has selected to delete it) 29 | ReadRegStr $oldShortcutName SHELL_CONTEXT "${INSTALL_REGISTRY_KEY}" ShortcutName 30 | ${if} $oldShortcutName == "" 31 | StrCpy $oldShortcutName "${SHORTCUT_NAME}" 32 | ${endIf} 33 | StrCpy $oldDesktopLink "$DESKTOP\$oldShortcutName.lnk" 34 | 35 | # new desktop shortcut (will be created/renamed in case of a fresh installation or if the user haven't deleted the initial one) 36 | StrCpy $newDesktopLink "$DESKTOP\${SHORTCUT_NAME}.lnk" 37 | 38 | ReadRegStr $oldMenuDirectory SHELL_CONTEXT "${INSTALL_REGISTRY_KEY}" MenuDirectory 39 | ${if} $oldMenuDirectory == "" 40 | StrCpy $oldStartMenuLink "$SMPROGRAMS\$oldShortcutName.lnk" 41 | ${else} 42 | StrCpy $oldStartMenuLink "$SMPROGRAMS\$oldMenuDirectory\$oldShortcutName.lnk" 43 | ${endIf} 44 | 45 | # new menu shortcut (will be created/renamed in case of a fresh installation or if the user haven't deleted the initial one) 46 | !ifdef MENU_FILENAME 47 | StrCpy $newStartMenuLink "$SMPROGRAMS\${MENU_FILENAME}\${SHORTCUT_NAME}.lnk" 48 | !else 49 | StrCpy $newStartMenuLink "$SMPROGRAMS\${SHORTCUT_NAME}.lnk" 50 | !endif 51 | !macroend 52 | -------------------------------------------------------------------------------- /common/installer/nsis/include/StrContains.nsh: -------------------------------------------------------------------------------- 1 | ; StrContains 2 | ; This function does a case sensitive searches for an occurrence of a substring in a string. 3 | ; It returns the substring if it is found. 4 | ; Otherwise it returns null(""). 5 | ; Written by kenglish_hi 6 | ; Adapted from StrReplace written by dandaman32 7 | 8 | 9 | Var STR_HAYSTACK 10 | Var STR_NEEDLE 11 | Var STR_CONTAINS_VAR_1 12 | Var STR_CONTAINS_VAR_2 13 | Var STR_CONTAINS_VAR_3 14 | Var STR_CONTAINS_VAR_4 15 | Var STR_RETURN_VAR 16 | 17 | Function StrContains 18 | Exch $STR_NEEDLE 19 | Exch 1 20 | Exch $STR_HAYSTACK 21 | ; Uncomment to debug 22 | ;MessageBox MB_OK 'STR_NEEDLE = $STR_NEEDLE STR_HAYSTACK = $STR_HAYSTACK ' 23 | StrCpy $STR_RETURN_VAR "" 24 | StrCpy $STR_CONTAINS_VAR_1 -1 25 | StrLen $STR_CONTAINS_VAR_2 $STR_NEEDLE 26 | StrLen $STR_CONTAINS_VAR_4 $STR_HAYSTACK 27 | loop: 28 | IntOp $STR_CONTAINS_VAR_1 $STR_CONTAINS_VAR_1 + 1 29 | StrCpy $STR_CONTAINS_VAR_3 $STR_HAYSTACK $STR_CONTAINS_VAR_2 $STR_CONTAINS_VAR_1 30 | StrCmp $STR_CONTAINS_VAR_3 $STR_NEEDLE found 31 | StrCmp $STR_CONTAINS_VAR_1 $STR_CONTAINS_VAR_4 done 32 | Goto loop 33 | found: 34 | StrCpy $STR_RETURN_VAR $STR_NEEDLE 35 | Goto done 36 | done: 37 | Pop $STR_NEEDLE ;Prevent "invalid opcode" errors and keep the 38 | Exch $STR_RETURN_VAR 39 | FunctionEnd 40 | 41 | !macro _StrContainsConstructor OUT NEEDLE HAYSTACK 42 | Push `${HAYSTACK}` 43 | Push `${NEEDLE}` 44 | Call StrContains 45 | Pop `${OUT}` 46 | !macroend 47 | 48 | !define StrContains '!insertmacro "_StrContainsConstructor"' -------------------------------------------------------------------------------- /common/installer/nsis/include/extractAppPackage.nsh: -------------------------------------------------------------------------------- 1 | !macro extractEmbeddedAppPackage 2 | !ifdef COMPRESS 3 | SetCompress off 4 | !endif 5 | 6 | File /oname=$PLUGINSDIR\app-bundle.7z "${APP_BUNDLE}" 7 | 8 | !ifdef COMPRESS 9 | SetCompress "${COMPRESS}" 10 | !endif 11 | 12 | Nsis7z::ExtractWithDetails "$PLUGINSDIR\app-bundle.7z" "Unpacking bundle %s..." 13 | 14 | DetailPrint "Copying files..." 15 | nsExec::ExecToStack '"$SYSDIR\cmd.exe" /c xcopy.exe "$INSTDIR\RuminoidToolbox\*" "$INSTDIR" /Y /E /I' 16 | Pop $0 17 | Pop $1 18 | RMDir /r "$INSTDIR\RuminoidToolbox" 19 | 20 | WriteUninstaller "$INSTDIR\${UNINSTALLER_OUT_FILE}" 21 | !macroend 22 | -------------------------------------------------------------------------------- /common/installer/nsis/installSection.nsh: -------------------------------------------------------------------------------- 1 | !include installer.nsh 2 | 3 | InitPluginsDir 4 | 5 | StrCpy $appExe "$INSTDIR\${APP_EXECUTABLE_FILENAME}" 6 | 7 | # must be called before uninstallOldVersion 8 | !insertmacro setLinkVars 9 | 10 | Var /GLOBAL keepShortcuts 11 | StrCpy $keepShortcuts "false" 12 | !insertMacro setIsTryToKeepShortcuts 13 | ${if} $isTryToKeepShortcuts == "true" 14 | ReadRegStr $R1 SHELL_CONTEXT "${INSTALL_REGISTRY_KEY}" KeepShortcuts 15 | 16 | ${if} $R1 == "true" 17 | ${andIf} ${FileExists} "$appExe" 18 | StrCpy $keepShortcuts "true" 19 | ${endIf} 20 | ${endif} 21 | 22 | !insertmacro uninstallOldVersion SHELL_CONTEXT 23 | 24 | SetOutPath $INSTDIR 25 | 26 | !insertmacro installApplicationFiles 27 | !insertmacro registryAddInstallInfo 28 | !insertmacro addStartMenuLink $keepShortcuts 29 | !insertmacro addDesktopLink $keepShortcuts 30 | -------------------------------------------------------------------------------- /common/installer/nsis/multiUser.nsh: -------------------------------------------------------------------------------- 1 | !include FileFunc.nsh 2 | 3 | !define FOLDERID_UserProgramFiles {5CD7AEE2-2219-4A67-B85D-6C9CE15660CB} 4 | !define KF_FLAG_CREATE 0x00008000 5 | 6 | # allow user to define own custom 7 | !define /ifndef INSTALL_REGISTRY_KEY "Software\${APP_GUID}" 8 | !define /ifndef UNINSTALL_REGISTRY_KEY "Software\Microsoft\Windows\CurrentVersion\Uninstall\${APP_GUID}" 9 | 10 | Var PerUserInstallationFolder 11 | 12 | !macro setInstallModePerUser 13 | SetShellVarContext current 14 | # сhecks registry for previous installation path 15 | ReadRegStr $perUserInstallationFolder HKCU "${INSTALL_REGISTRY_KEY}" InstallLocation 16 | ${if} $perUserInstallationFolder != "" 17 | StrCpy $INSTDIR $perUserInstallationFolder 18 | ${else} 19 | StrCpy $0 "$LocalAppData\Programs" 20 | System::Store S 21 | # Win7 has a per-user programfiles known folder and this can be a non-default location 22 | System::Call 'SHELL32::SHGetKnownFolderPath(g "${FOLDERID_UserProgramFiles}", i ${KF_FLAG_CREATE}, p 0, *p .r2)i.r1' 23 | ${If} $1 == 0 24 | System::Call '*$2(&w${NSIS_MAX_STRLEN} .s)' 25 | StrCpy $0 $1 26 | System::Call 'OLE32::CoTaskMemFree(p r2)' 27 | ${endif} 28 | System::Store L 29 | StrCpy $INSTDIR "$0\${APP_FILENAME}" 30 | ${endif} 31 | !macroend 32 | -------------------------------------------------------------------------------- /common/installer/nsis/uninstaller.nsh: -------------------------------------------------------------------------------- 1 | Function un.onInit 2 | !insertmacro check64BitAndSetRegView 3 | 4 | MessageBox MB_OKCANCEL "$(areYouSureToUninstall)" IDOK +2 5 | Quit 6 | 7 | !insertmacro setInstallModePerUser 8 | FunctionEnd 9 | 10 | Section "Uninstall" 11 | !insertmacro setLinkVars 12 | 13 | WinShell::UninstAppUserModelId "${APP_ID}" 14 | 15 | WinShell::UninstShortcut "$oldDesktopLink" 16 | Delete "$oldDesktopLink" 17 | 18 | WinShell::UninstShortcut "$oldStartMenuLink" 19 | 20 | Delete "$oldStartMenuLink" 21 | ReadRegStr $R1 SHELL_CONTEXT "${INSTALL_REGISTRY_KEY}" MenuDirectory 22 | ${ifNot} $R1 == "" 23 | RMDir "$SMPROGRAMS\$R1" 24 | ${endIf} 25 | 26 | # refresh the desktop 27 | System::Call 'shell32::SHChangeNotify(i, i, i, i) v (0x08000000, 0, 0, 0)' 28 | 29 | # delete the installed files 30 | RMDir /r $INSTDIR 31 | 32 | DeleteRegKey SHELL_CONTEXT "${UNINSTALL_REGISTRY_KEY}" 33 | DeleteRegKey SHELL_CONTEXT "${INSTALL_REGISTRY_KEY}" 34 | SectionEnd 35 | -------------------------------------------------------------------------------- /common/meta/rmbenv.exe.manifest: -------------------------------------------------------------------------------- 1 | 2 | 3 | 8 | 9 | 10 | 11 | 14 | 15 | 16 | 17 | 18 | -------------------------------------------------------------------------------- /examples/lua/rmbox-plugin-lua-example/.editorconfig: -------------------------------------------------------------------------------- 1 | # https://editorconfig.org/ 2 | 3 | [*] 4 | indent_style = space 5 | insert_final_newline = true 6 | trim_trailing_whitespace = true 7 | end_of_line = lf 8 | charset = utf-8 9 | indent_size = 2 10 | table_width = 2 11 | 12 | [*.lua] 13 | indent_size = 4 14 | table_width = 4 15 | 16 | [*.json] 17 | indent_size = 2 18 | -------------------------------------------------------------------------------- /examples/lua/rmbox-plugin-lua-example/.gitignore: -------------------------------------------------------------------------------- 1 | # Compiled Lua sources 2 | luac.out 3 | 4 | # luarocks build files 5 | *.src.rock 6 | *.zip 7 | *.tar.gz 8 | 9 | # Object files 10 | *.o 11 | *.os 12 | *.ko 13 | *.obj 14 | *.elf 15 | 16 | # Precompiled Headers 17 | *.gch 18 | *.pch 19 | 20 | # Libraries 21 | *.lib 22 | *.a 23 | *.la 24 | *.lo 25 | *.def 26 | *.exp 27 | 28 | # Shared objects (inc. Windows DLLs) 29 | *.dll 30 | *.so 31 | *.so.* 32 | *.dylib 33 | 34 | # Executables 35 | *.exe 36 | *.out 37 | *.app 38 | *.i*86 39 | *.x86_64 40 | *.hex 41 | 42 | # Visual Studio Code config 43 | .vscode/ 44 | -------------------------------------------------------------------------------- /examples/lua/rmbox-plugin-lua-example/rmbox-plugin-lua-example.lua: -------------------------------------------------------------------------------- 1 | json = require 'json' 2 | 3 | local meta = { 4 | id = 'Ruminoid.Toolbox.Plugins.Examples.RmboxPluginLuaExample', 5 | class_name = 'RmboxPluginLuaExample', 6 | name = 'Lua 插件示例', 7 | type = 'operation', 8 | description = 'Lua 编写的 Ruminoid Toolbox 插件示例。', 9 | rate = 2, 10 | category = '示例插件', 11 | author = 'Il Harper', 12 | config_sections = { 13 | ["Ruminoid.Toolbox.Plugins.Common.ConfigSections.IOConfigSection"] = {} 14 | } 15 | } 16 | 17 | if (type(arg[1]) == "nil") then 18 | print(json.encode(meta)) 19 | os.exit(0) 20 | end 21 | 22 | io.input(arg[1]) 23 | local config_section_data = io.read("a") 24 | 25 | local config_sections = json.decode(config_section_data) 26 | local io_section = 27 | config_sections["Ruminoid.Toolbox.Plugins.Common.ConfigSections.IOConfigSection"] 28 | 29 | local commands = { 30 | target = "ffmpeg", 31 | args = "-i " + io_section["input"] + " " + io_section["output"], 32 | formatter = "ffmpeg" 33 | } 34 | 35 | print(json.encode(commands)) 36 | -------------------------------------------------------------------------------- /examples/node/rmbox-plugin-node-example/.editorconfig: -------------------------------------------------------------------------------- 1 | # editorconfig.org 2 | 3 | [*] 4 | indent_style = space 5 | indent_size = 2 6 | end_of_line = lf 7 | charset = utf-8 8 | trim_trailing_whitespace = true 9 | insert_final_newline = true 10 | -------------------------------------------------------------------------------- /examples/node/rmbox-plugin-node-example/.eslintrc.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | root: true, 3 | env: { 4 | node: true, 5 | es2020: true, 6 | }, 7 | parser: '@typescript-eslint/parser', 8 | plugins: ['prettier', '@typescript-eslint'], 9 | extends: [ 10 | 'eslint:recommended', 11 | 'plugin:@typescript-eslint/recommended', 12 | 'prettier', 13 | 'plugin:prettier/recommended', 14 | 'prettier/@typescript-eslint', 15 | ], 16 | } 17 | -------------------------------------------------------------------------------- /examples/node/rmbox-plugin-node-example/.gitignore: -------------------------------------------------------------------------------- 1 | # Created by .ignore support plugin (hsz.mobi) 2 | ### Node template 3 | # Logs 4 | /logs 5 | *.log 6 | npm-debug.log* 7 | yarn-debug.log* 8 | yarn-error.log* 9 | 10 | # Runtime data 11 | pids 12 | *.pid 13 | *.seed 14 | *.pid.lock 15 | 16 | # Directory for instrumented libs generated by jscoverage/JSCover 17 | lib-cov 18 | 19 | # Coverage directory used by tools like istanbul 20 | coverage 21 | 22 | # nyc test coverage 23 | .nyc_output 24 | 25 | # Grunt intermediate storage (http://gruntjs.com/creating-plugins#storing-task-files) 26 | .grunt 27 | 28 | # Bower dependency directory (https://bower.io/) 29 | bower_components 30 | 31 | # node-waf configuration 32 | .lock-wscript 33 | 34 | # Compiled binary addons (https://nodejs.org/api/addons.html) 35 | build/Release 36 | 37 | # Dependency directories 38 | node_modules/ 39 | jspm_packages/ 40 | 41 | # TypeScript v1 declaration files 42 | typings/ 43 | 44 | # Optional npm cache directory 45 | .npm 46 | 47 | # Optional eslint cache 48 | .eslintcache 49 | 50 | # Optional REPL history 51 | .node_repl_history 52 | 53 | # Output of 'npm pack' 54 | *.tgz 55 | 56 | # Yarn Integrity file 57 | .yarn-integrity 58 | 59 | # dotenv environment variables file 60 | .env 61 | 62 | # parcel-bundler cache (https://parceljs.org/) 63 | .cache 64 | 65 | # next.js build output 66 | .next 67 | 68 | # nuxt.js build output 69 | .nuxt 70 | 71 | # Nuxt generate 72 | dist 73 | 74 | # vuepress build output 75 | .vuepress/dist 76 | 77 | # Serverless directories 78 | .serverless 79 | 80 | # IDE / Editor 81 | .idea 82 | 83 | # Service worker 84 | sw.* 85 | 86 | # macOS 87 | .DS_Store 88 | 89 | # Vim swap files 90 | *.swp 91 | 92 | # Visual Studio Code config 93 | .vscode/ 94 | 95 | # Package lock 96 | package-lock.json 97 | -------------------------------------------------------------------------------- /examples/node/rmbox-plugin-node-example/.prettierrc.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | semi: false, 3 | arrowParens: 'always', 4 | singleQuote: true, 5 | } 6 | -------------------------------------------------------------------------------- /examples/node/rmbox-plugin-node-example/jsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "compilerOptions": { 3 | "module": "esnext", 4 | "target": "esnext", 5 | "moduleResolution": "node" 6 | }, 7 | "exclude": [ 8 | "node_modules", 9 | "dist" 10 | ] 11 | } 12 | -------------------------------------------------------------------------------- /examples/node/rmbox-plugin-node-example/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "rmbox-plugin-node-example", 3 | "version": "0.1.0", 4 | "description": "The node example plugin for Ruminoid Toolbox.", 5 | "main": "dist/index.js", 6 | "scripts": { 7 | "dev": "ts-node src/index.ts", 8 | "build": "tsc -b", 9 | "lint": "eslint src --ext .js,.ts --ignore-path .gitignore --fix" 10 | }, 11 | "author": "Il Harper", 12 | "license": "MIT", 13 | "devDependencies": { 14 | "@types/node": "^14.14.16", 15 | "@typescript-eslint/eslint-plugin": "^4.11.1", 16 | "@typescript-eslint/parser": "^4.11.1", 17 | "cross-env": "^7.0.3", 18 | "eslint": "^7.16.0", 19 | "eslint-config-prettier": "^7.1.0", 20 | "eslint-plugin-prettier": "^3.3.0", 21 | "prettier": "^2.2.1", 22 | "ts-node": "^9.1.1", 23 | "typescript": "^4.1.3" 24 | } 25 | } 26 | -------------------------------------------------------------------------------- /examples/node/rmbox-plugin-node-example/src/index.ts: -------------------------------------------------------------------------------- 1 | import * as fs from 'fs' 2 | import { Command, Meta } from './rmbox' 3 | 4 | const meta: Meta = { 5 | id: 'Ruminoid.Toolbox.Plugins.Examples.RmboxPluginNodeExample', 6 | class_name: 'RmboxPluginNodeExample', 7 | name: 'Node 插件示例', 8 | type: 'operation', 9 | description: 'Node 编写的 Ruminoid Toolbox 插件示例。', 10 | rate: 2, 11 | category: '示例插件', 12 | author: 'Il Harper', 13 | config_sections: { 14 | 'Ruminoid.Toolbox.Plugins.Common.ConfigSections.IOConfigSection': {}, 15 | }, 16 | } 17 | 18 | if (process.argv.length <= 2) { 19 | console.log(JSON.stringify(meta)) 20 | process.exit(0) 21 | } 22 | 23 | const configSectionData: string = fs.readFileSync(process.argv[2], { 24 | encoding: 'utf-8', 25 | }) 26 | const configSections = JSON.parse(configSectionData) 27 | const ioSection = 28 | configSections[ 29 | 'Ruminoid.Toolbox.Plugins.Common.ConfigSections.IOConfigSection' 30 | ] 31 | 32 | const commands: Command[] = [ 33 | { 34 | target: 'ffmpeg', 35 | args: `-i ${ioSection['input']} ${ioSection['output']}`, 36 | formatter: 'ffmpeg', 37 | }, 38 | ] 39 | 40 | console.log(JSON.stringify(commands)) 41 | -------------------------------------------------------------------------------- /examples/node/rmbox-plugin-node-example/src/rmbox.d.ts: -------------------------------------------------------------------------------- 1 | /* eslint-disable @typescript-eslint/no-explicit-any */ 2 | 3 | export interface Meta { 4 | id: string 5 | class_name: string 6 | name: string 7 | type: string 8 | description: string 9 | config_sections: { [K: string]: any } 10 | [K: string]: any 11 | } 12 | 13 | export interface Command { 14 | target: string 15 | args: string 16 | formatter: string 17 | } 18 | -------------------------------------------------------------------------------- /examples/node/rmbox-plugin-node-example/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "compilerOptions": { 3 | "target": "ESNext", 4 | "module": "CommonJS", 5 | "moduleResolution": "Node", 6 | "lib": [ 7 | "ESNext", 8 | "ESNext.AsyncIterable" 9 | ], 10 | "outDir": "dist", 11 | "esModuleInterop": true, 12 | "sourceMap": true, 13 | "strict": true, 14 | "experimentalDecorators": true, 15 | "types": [ 16 | "@types/node" 17 | ] 18 | }, 19 | "include": [ 20 | "src" 21 | ] 22 | } 23 | -------------------------------------------------------------------------------- /examples/python/rmbox-plugin-python-example/.editorconfig: -------------------------------------------------------------------------------- 1 | # https://editorconfig.org/ 2 | 3 | [*] 4 | indent_style = space 5 | indent_size = 4 6 | insert_final_newline = true 7 | trim_trailing_whitespace = true 8 | end_of_line = lf 9 | charset = utf-8 10 | 11 | [*.json] 12 | indent_size = 2 13 | -------------------------------------------------------------------------------- /examples/python/rmbox-plugin-python-example/.gitignore: -------------------------------------------------------------------------------- 1 | # Byte-compiled / optimized / DLL files 2 | __pycache__/ 3 | *.py[cod] 4 | *$py.class 5 | 6 | # C extensions 7 | *.so 8 | 9 | # Distribution / packaging 10 | .Python 11 | build/ 12 | develop-eggs/ 13 | dist/ 14 | downloads/ 15 | eggs/ 16 | .eggs/ 17 | lib/ 18 | lib64/ 19 | parts/ 20 | sdist/ 21 | var/ 22 | wheels/ 23 | pip-wheel-metadata/ 24 | share/python-wheels/ 25 | *.egg-info/ 26 | .installed.cfg 27 | *.egg 28 | MANIFEST 29 | 30 | # PyInstaller 31 | # Usually these files are written by a python script from a template 32 | # before PyInstaller builds the exe, so as to inject date/other infos into it. 33 | *.manifest 34 | *.spec 35 | 36 | # Installer logs 37 | pip-log.txt 38 | pip-delete-this-directory.txt 39 | 40 | # Unit test / coverage reports 41 | htmlcov/ 42 | .tox/ 43 | .nox/ 44 | .coverage 45 | .coverage.* 46 | .cache 47 | nosetests.xml 48 | coverage.xml 49 | *.cover 50 | *.py,cover 51 | .hypothesis/ 52 | .pytest_cache/ 53 | 54 | # Translations 55 | *.mo 56 | *.pot 57 | 58 | # Django stuff: 59 | *.log 60 | local_settings.py 61 | db.sqlite3 62 | db.sqlite3-journal 63 | 64 | # Flask stuff: 65 | instance/ 66 | .webassets-cache 67 | 68 | # Scrapy stuff: 69 | .scrapy 70 | 71 | # Sphinx documentation 72 | docs/_build/ 73 | 74 | # PyBuilder 75 | target/ 76 | 77 | # Jupyter Notebook 78 | .ipynb_checkpoints 79 | 80 | # IPython 81 | profile_default/ 82 | ipython_config.py 83 | 84 | # pyenv 85 | .python-version 86 | 87 | # pipenv 88 | # According to pypa/pipenv#598, it is recommended to include Pipfile.lock in version control. 89 | # However, in case of collaboration, if having platform-specific dependencies or dependencies 90 | # having no cross-platform support, pipenv may install dependencies that don't work, or not 91 | # install all needed dependencies. 92 | #Pipfile.lock 93 | 94 | # PEP 582; used by e.g. github.com/David-OConnor/pyflow 95 | __pypackages__/ 96 | 97 | # Celery stuff 98 | celerybeat-schedule 99 | celerybeat.pid 100 | 101 | # SageMath parsed files 102 | *.sage.py 103 | 104 | # Environments 105 | .env 106 | .venv 107 | env/ 108 | venv/ 109 | ENV/ 110 | env.bak/ 111 | venv.bak/ 112 | 113 | # Spyder project settings 114 | .spyderproject 115 | .spyproject 116 | 117 | # Rope project settings 118 | .ropeproject 119 | 120 | # mkdocs documentation 121 | /site 122 | 123 | # mypy 124 | .mypy_cache/ 125 | .dmypy.json 126 | dmypy.json 127 | 128 | # Pyre type checker 129 | .pyre/ 130 | 131 | # Rasa 132 | models/ 133 | 134 | # Visual Studio Code config 135 | .vscode/ 136 | -------------------------------------------------------------------------------- /examples/python/rmbox-plugin-python-example/rmbox-plugin-python-example.py: -------------------------------------------------------------------------------- 1 | import json 2 | import sys 3 | from typing import Any 4 | 5 | argv: str = sys.argv 6 | 7 | meta = { 8 | 'id': 'Ruminoid.Toolbox.Plugins.Examples.RmboxPluginPythonExample', 9 | 'class_name': 'RmboxPluginPythonExample', 10 | 'name': 'Python 插件示例', 11 | 'type': 'operation', 12 | 'description': 'Python 编写的 Ruminoid Toolbox 插件示例。', 13 | 'rate': 2, 14 | 'category': '示例插件', 15 | 'author': 'Il Harper', 16 | 'config_sections': { 17 | 'Ruminoid.Toolbox.Plugins.Common.ConfigSections.IOConfigSection': {}, 18 | }, 19 | } 20 | 21 | if len(argv) == 1: 22 | print(json.dumps(meta)) 23 | sys.exit(0) 24 | 25 | config_sections: Any 26 | 27 | with open(argv[1], 'r', encoding='utf-8') as config_section_file: 28 | config_sections = json.load(config_section_file) 29 | 30 | io_section: Any = config_sections['Ruminoid.Toolbox.Plugins.Common.ConfigSections.IOConfigSection'] 31 | 32 | commands = [ 33 | { 34 | 'target': 'ffmpeg', 35 | 'args': f'-i {io_section["input"]} {io_section["output"]}', 36 | 'formatter': 'ffmpeg', 37 | }, 38 | ] 39 | 40 | print(json.dumps(commands)) 41 | -------------------------------------------------------------------------------- /lgtm.yml: -------------------------------------------------------------------------------- 1 | extraction: 2 | csharp: 3 | index: 4 | build_command: 5 | - ./build.sh Compile --configuration Release 6 | -------------------------------------------------------------------------------- /plugins/rmbox-plugin-audio/AudioMeta.cs: -------------------------------------------------------------------------------- 1 | using Ruminoid.Toolbox.Core; 2 | 3 | namespace Ruminoid.Toolbox.Plugins.Audio 4 | { 5 | [RmboxPlugin] 6 | public class AudioMeta : IMeta 7 | { 8 | public string Name => "音频压制"; 9 | public string Description => "提供了音频压制相关的功能。"; 10 | public string Author => "Il Harper"; 11 | } 12 | } 13 | -------------------------------------------------------------------------------- /plugins/rmbox-plugin-audio/ConfigSections/ViewModels/AudioConfigSectionViewModel.cs: -------------------------------------------------------------------------------- 1 | using Newtonsoft.Json; 2 | using ReactiveUI; 3 | 4 | namespace Ruminoid.Toolbox.Plugins.Audio.ConfigSections.ViewModels 5 | { 6 | [JsonObject(MemberSerialization.OptIn)] 7 | public class AudioConfigSectionViewModel : ReactiveObject 8 | { 9 | #region Data 10 | 11 | [JsonProperty("mode")] 12 | private string _encodeMode = "copy"; 13 | 14 | public string EncodeMode 15 | { 16 | get => _encodeMode; 17 | set => this.RaiseAndSetIfChanged(ref _encodeMode, value); 18 | } 19 | 20 | [JsonProperty("bitrate")] 21 | private int _bitrate = 320; 22 | 23 | public int Bitrate 24 | { 25 | get => _bitrate; 26 | set => this.RaiseAndSetIfChanged(ref _bitrate, value); 27 | } 28 | 29 | #endregion 30 | } 31 | } 32 | -------------------------------------------------------------------------------- /plugins/rmbox-plugin-audio/ConfigSections/ViewModels/AudioQualityConfigSectionViewModel.cs: -------------------------------------------------------------------------------- 1 | using Newtonsoft.Json; 2 | using ReactiveUI; 3 | 4 | namespace Ruminoid.Toolbox.Plugins.Audio.ConfigSections.ViewModels 5 | { 6 | [JsonObject(MemberSerialization.OptIn)] 7 | public class AudioQualityConfigSectionViewModel : ReactiveObject 8 | { 9 | #region Data 10 | 11 | [JsonProperty("bitrate")] 12 | private int _bitrate = 320; 13 | 14 | public int Bitrate 15 | { 16 | get => _bitrate; 17 | set => this.RaiseAndSetIfChanged(ref _bitrate, value); 18 | } 19 | 20 | #endregion 21 | } 22 | } 23 | -------------------------------------------------------------------------------- /plugins/rmbox-plugin-audio/ConfigSections/Views/AudioConfigSection.axaml.cs: -------------------------------------------------------------------------------- 1 | using Avalonia.Markup.Xaml; 2 | using Newtonsoft.Json.Linq; 3 | using Ruminoid.Toolbox.Core; 4 | using Ruminoid.Toolbox.Plugins.Audio.ConfigSections.ViewModels; 5 | 6 | namespace Ruminoid.Toolbox.Plugins.Audio.ConfigSections.Views 7 | { 8 | [ConfigSection( 9 | "Ruminoid.Toolbox.Plugins.Audio.ConfigSections.AudioConfigSection", 10 | "音频")] 11 | public class AudioConfigSection : ConfigSectionBase 12 | { 13 | public AudioConfigSection() 14 | { 15 | InitializeComponent(); 16 | } 17 | 18 | public AudioConfigSection( 19 | JToken sectionConfig) 20 | { 21 | InitializeComponent(); 22 | } 23 | 24 | private void InitializeComponent() 25 | { 26 | AvaloniaXamlLoader.Load(this); 27 | } 28 | 29 | public override object Config => DataContext as AudioConfigSectionViewModel; 30 | } 31 | } 32 | -------------------------------------------------------------------------------- /plugins/rmbox-plugin-audio/ConfigSections/Views/AudioQualityConfigSection.axaml.cs: -------------------------------------------------------------------------------- 1 | using Avalonia.Markup.Xaml; 2 | using Newtonsoft.Json.Linq; 3 | using Ruminoid.Toolbox.Core; 4 | using Ruminoid.Toolbox.Plugins.Audio.ConfigSections.ViewModels; 5 | 6 | namespace Ruminoid.Toolbox.Plugins.Audio.ConfigSections.Views 7 | { 8 | [ConfigSection( 9 | "Ruminoid.Toolbox.Plugins.Audio.ConfigSections.AudioQualityConfigSection", 10 | "音频质量")] 11 | public class AudioQualityConfigSection : ConfigSectionBase 12 | { 13 | public AudioQualityConfigSection() 14 | { 15 | InitializeComponent(); 16 | } 17 | 18 | public AudioQualityConfigSection( 19 | JToken sectionConfig) 20 | { 21 | InitializeComponent(); 22 | } 23 | 24 | private void InitializeComponent() 25 | { 26 | AvaloniaXamlLoader.Load(this); 27 | } 28 | 29 | public override object Config => DataContext as AudioQualityConfigSectionViewModel; 30 | } 31 | } 32 | -------------------------------------------------------------------------------- /plugins/rmbox-plugin-audio/rmbox-plugin-audio.csproj: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | net5.0 5 | Ruminoid.Toolbox.Plugins.Audio 6 | 7 | 8 | 9 | 10 | false 11 | runtime 12 | 13 | 14 | 15 | 16 | 17 | false 18 | runtime 19 | 20 | 21 | 22 | 23 | -------------------------------------------------------------------------------- /plugins/rmbox-plugin-common/CommonMeta.cs: -------------------------------------------------------------------------------- 1 | using Ruminoid.Toolbox.Core; 2 | 3 | namespace Ruminoid.Toolbox.Plugins.Common 4 | { 5 | [RmboxPlugin] 6 | public class CommonMeta : IMeta 7 | { 8 | public string Name => "Ruminoid Toolbox 基础"; 9 | public string Description => "提供了工具箱的基础功能。"; 10 | public string Author => "Il Harper"; 11 | } 12 | } 13 | -------------------------------------------------------------------------------- /plugins/rmbox-plugin-common/ConfigSections/ViewModels/AdvancedTrackConfigSectionViewModel.cs: -------------------------------------------------------------------------------- 1 | using Newtonsoft.Json; 2 | using ReactiveUI; 3 | 4 | namespace Ruminoid.Toolbox.Plugins.Common.ConfigSections.ViewModels 5 | { 6 | [JsonObject(MemberSerialization.OptIn)] 7 | public class AdvancedTrackConfigSectionViewModel : ReactiveObject 8 | { 9 | #region Data 10 | 11 | [JsonProperty("process_mode")] 12 | private string _processMode = "auto"; 13 | 14 | public string ProcessMode 15 | { 16 | get => _processMode; 17 | set => this.RaiseAndSetIfChanged(ref _processMode, value); 18 | } 19 | 20 | #endregion 21 | } 22 | } 23 | -------------------------------------------------------------------------------- /plugins/rmbox-plugin-common/ConfigSections/ViewModels/CustomArgsConfigSectionViewModel.cs: -------------------------------------------------------------------------------- 1 | using Newtonsoft.Json; 2 | using Newtonsoft.Json.Linq; 3 | using ReactiveUI; 4 | 5 | namespace Ruminoid.Toolbox.Plugins.Common.ConfigSections.ViewModels 6 | { 7 | [JsonObject(MemberSerialization.OptIn)] 8 | public class CustomArgsConfigSectionViewModel : ReactiveObject 9 | { 10 | #region Constructor 11 | 12 | public CustomArgsConfigSectionViewModel( 13 | JToken sectionConfig) 14 | { 15 | _defaultArgs = sectionConfig["default_args"]?.ToObject() ?? string.Empty; 16 | _args = _defaultArgs; 17 | } 18 | 19 | #endregion 20 | 21 | private readonly string _defaultArgs; 22 | 23 | #region Bindings 24 | 25 | [JsonProperty("use_custom_args")] 26 | private bool _useCustom; 27 | 28 | public bool UseCustom 29 | { 30 | get => _useCustom; 31 | set 32 | { 33 | if (_useCustom == value) 34 | return; 35 | 36 | Args = value ? _args : _defaultArgs; 37 | 38 | _useCustom = value; 39 | this.RaisePropertyChanged(nameof(UseCustom)); 40 | } 41 | } 42 | 43 | [JsonProperty("args")] 44 | private string _args; 45 | 46 | public string Args 47 | { 48 | get => _args; 49 | set => this.RaiseAndSetIfChanged(ref _args, value); 50 | } 51 | 52 | #endregion 53 | } 54 | } 55 | -------------------------------------------------------------------------------- /plugins/rmbox-plugin-common/ConfigSections/ViewModels/IntroConfigSectionViewModel.cs: -------------------------------------------------------------------------------- 1 | using Newtonsoft.Json; 2 | using Newtonsoft.Json.Linq; 3 | using ReactiveUI; 4 | 5 | namespace Ruminoid.Toolbox.Plugins.Common.ConfigSections.ViewModels 6 | { 7 | [JsonObject(MemberSerialization.OptIn)] 8 | public class IntroConfigSectionViewModel : ReactiveObject 9 | { 10 | #region Constructor 11 | 12 | public IntroConfigSectionViewModel( 13 | JToken sectionConfig) 14 | { 15 | MdText = sectionConfig["intro_text"]?.ToObject() ?? "# 介绍获取失败\n\n插件似乎出现了问题。\n"; 16 | } 17 | 18 | #endregion 19 | 20 | #region Data 21 | 22 | public string MdText { get; } 23 | 24 | #endregion 25 | } 26 | } 27 | -------------------------------------------------------------------------------- /plugins/rmbox-plugin-common/ConfigSections/ViewModels/MuxOptionsConfigSectionViewModel.cs: -------------------------------------------------------------------------------- 1 | using Newtonsoft.Json; 2 | using ReactiveUI; 3 | 4 | namespace Ruminoid.Toolbox.Plugins.Common.ConfigSections.ViewModels 5 | { 6 | [JsonObject(MemberSerialization.OptIn)] 7 | public class MuxOptionsConfigSectionViewModel : ReactiveObject 8 | { 9 | #region Data 10 | 11 | [JsonProperty("use_shortest")] 12 | private bool _useShortest; 13 | 14 | public bool UseShortest 15 | { 16 | get => _useShortest; 17 | set => this.RaiseAndSetIfChanged(ref _useShortest, value); 18 | } 19 | 20 | #endregion 21 | } 22 | } 23 | -------------------------------------------------------------------------------- /plugins/rmbox-plugin-common/ConfigSections/ViewModels/OutputConfigSectionViewModel.cs: -------------------------------------------------------------------------------- 1 | using System.Threading.Tasks; 2 | using Avalonia.Controls; 3 | using Avalonia.VisualTree; 4 | using Newtonsoft.Json; 5 | using ReactiveUI; 6 | using Ruminoid.Toolbox.Plugins.Common.ConfigSections.Views; 7 | 8 | namespace Ruminoid.Toolbox.Plugins.Common.ConfigSections.ViewModels 9 | { 10 | [JsonObject(MemberSerialization.OptIn)] 11 | class OutputConfigSectionViewModel : ReactiveObject 12 | { 13 | #region Constructor 14 | 15 | public OutputConfigSectionViewModel( 16 | OutputConfigSection view) 17 | { 18 | _view = view; 19 | } 20 | 21 | #endregion 22 | 23 | #region Data 24 | 25 | [JsonProperty("output")] 26 | private string _output = ""; 27 | 28 | public string Output 29 | { 30 | get => _output; 31 | set => this.RaiseAndSetIfChanged(ref _output, value); 32 | } 33 | 34 | #endregion 35 | 36 | #region View 37 | 38 | private readonly OutputConfigSection _view; 39 | 40 | #endregion 41 | 42 | #region Operations 43 | 44 | public async Task SaveFile() 45 | { 46 | SaveFileDialog dialog = new SaveFileDialog 47 | { 48 | Title = "选择输出文件", 49 | DefaultExtension = ".mp4" 50 | }; 51 | 52 | var result = await dialog.ShowAsync((Window)_view.GetVisualRoot()); 53 | 54 | if (string.IsNullOrWhiteSpace(result)) return; 55 | 56 | Output = result; 57 | } 58 | 59 | #endregion 60 | } 61 | } 62 | -------------------------------------------------------------------------------- /plugins/rmbox-plugin-common/ConfigSections/Views/AdvancedTrackConfigSection.axaml.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using Avalonia.Markup.Xaml; 3 | using Newtonsoft.Json.Linq; 4 | using Ruminoid.Toolbox.Core; 5 | using Ruminoid.Toolbox.Plugins.Common.ConfigSections.ViewModels; 6 | 7 | namespace Ruminoid.Toolbox.Plugins.Common.ConfigSections.Views 8 | { 9 | [ConfigSection( 10 | "Ruminoid.Toolbox.Plugins.Common.ConfigSections.AdvancedTrackConfigSection", 11 | "高级 (流)")] 12 | public class AdvancedTrackConfigSection : ConfigSectionBase 13 | { 14 | public AdvancedTrackConfigSection() 15 | { 16 | throw new InvalidOperationException(); 17 | } 18 | 19 | public AdvancedTrackConfigSection( 20 | JToken sectionConfig) 21 | { 22 | DataContext = new AdvancedTrackConfigSectionViewModel(); 23 | 24 | InitializeComponent(); 25 | } 26 | 27 | private void InitializeComponent() 28 | { 29 | AvaloniaXamlLoader.Load(this); 30 | } 31 | 32 | public override object Config => DataContext as AdvancedTrackConfigSectionViewModel; 33 | } 34 | } 35 | -------------------------------------------------------------------------------- /plugins/rmbox-plugin-common/ConfigSections/Views/CustomArgsConfigSection.axaml: -------------------------------------------------------------------------------- 1 | 8 | 9 | 14 | 15 | 18 | 19 | 22 | 23 | 24 | 27 | 28 | 29 | 自定义参数 30 | 31 | 32 | 33 | 34 | 如果启用自定义参数,那么操作内所有的默认参数都将失效。确保你提供了所有必须的参数。 35 | 36 | 37 | 38 | 39 | 43 | 44 | 45 | 46 | 参数 47 | 48 | 49 | 50 | 56 | 57 | 58 | 59 | 60 | -------------------------------------------------------------------------------- /plugins/rmbox-plugin-common/ConfigSections/Views/CustomArgsConfigSection.axaml.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using Avalonia.Markup.Xaml; 3 | using Newtonsoft.Json.Linq; 4 | using Ruminoid.Toolbox.Core; 5 | using Ruminoid.Toolbox.Plugins.Common.ConfigSections.ViewModels; 6 | 7 | namespace Ruminoid.Toolbox.Plugins.Common.ConfigSections.Views 8 | { 9 | [ConfigSection( 10 | "Ruminoid.Toolbox.Plugins.Common.ConfigSections.CustomArgsConfigSection", 11 | "自定义参数")] 12 | public class CustomArgsConfigSection : ConfigSectionBase 13 | { 14 | public CustomArgsConfigSection() 15 | { 16 | throw new InvalidOperationException(); 17 | } 18 | 19 | public CustomArgsConfigSection( 20 | JToken sectionConfig) 21 | { 22 | DataContext = new CustomArgsConfigSectionViewModel(sectionConfig); 23 | 24 | InitializeComponent(); 25 | } 26 | 27 | private void InitializeComponent() 28 | { 29 | AvaloniaXamlLoader.Load(this); 30 | } 31 | 32 | public override object Config => DataContext as CustomArgsConfigSectionViewModel; 33 | } 34 | } 35 | -------------------------------------------------------------------------------- /plugins/rmbox-plugin-common/ConfigSections/Views/IOConfigSection.axaml.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Linq; 3 | using Avalonia.Controls; 4 | using Avalonia.Input; 5 | using Avalonia.Markup.Xaml; 6 | using Newtonsoft.Json.Linq; 7 | using Ruminoid.Toolbox.Core; 8 | using Ruminoid.Toolbox.Plugins.Common.ConfigSections.ViewModels; 9 | 10 | namespace Ruminoid.Toolbox.Plugins.Common.ConfigSections.Views 11 | { 12 | [ConfigSection( 13 | IOConfigSectionId, 14 | "输入/输出")] 15 | public sealed class IOConfigSection : ConfigSectionBase 16 | { 17 | public IOConfigSection() 18 | { 19 | throw new InvalidOperationException(); 20 | } 21 | 22 | public IOConfigSection( 23 | JToken sectionConfig) 24 | { 25 | DataContext = new IOConfigSectionViewModel(this, sectionConfig); 26 | 27 | InitializeComponent(); 28 | 29 | _inputFileGrid = this.FindControl("InputFileGrid"); 30 | _subtitleGrid = this.FindControl("SubtitleFileGrid"); 31 | 32 | _inputFileGrid.AddHandler(DragDrop.DropEvent, InputDropHandler); 33 | _subtitleGrid.AddHandler(DragDrop.DropEvent, SubtitleDropHandler); 34 | } 35 | 36 | private void InputDropHandler(object sender, DragEventArgs e) 37 | { 38 | if (e.Data.Contains(DataFormats.Text)) 39 | (DataContext as IOConfigSectionViewModel).Input = e.Data.GetText(); 40 | else if (e.Data.Contains(DataFormats.FileNames)) 41 | (DataContext as IOConfigSectionViewModel).Input = (e.Data.GetFileNames() ?? Array.Empty()).FirstOrDefault(); 42 | } 43 | 44 | private void SubtitleDropHandler(object sender, DragEventArgs e) 45 | { 46 | if (e.Data.Contains(DataFormats.Text)) 47 | (DataContext as IOConfigSectionViewModel).Subtitle = e.Data.GetText(); 48 | else if (e.Data.Contains(DataFormats.FileNames)) 49 | (DataContext as IOConfigSectionViewModel).Subtitle = (e.Data.GetFileNames() ?? Array.Empty()).FirstOrDefault(); 50 | } 51 | 52 | private readonly Grid _inputFileGrid; 53 | private readonly Grid _subtitleGrid; 54 | 55 | private void InitializeComponent() 56 | { 57 | AvaloniaXamlLoader.Load(this); 58 | } 59 | 60 | #region Data 61 | 62 | public override IOConfigSectionViewModel Config => DataContext as IOConfigSectionViewModel; 63 | 64 | #endregion 65 | } 66 | } 67 | -------------------------------------------------------------------------------- /plugins/rmbox-plugin-common/ConfigSections/Views/IntroConfigSection.axaml: -------------------------------------------------------------------------------- 1 | 9 | 12 | 13 | 14 | 15 | 16 | 17 | -------------------------------------------------------------------------------- /plugins/rmbox-plugin-common/ConfigSections/Views/IntroConfigSection.axaml.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using Avalonia.Markup.Xaml; 3 | using Newtonsoft.Json.Linq; 4 | using Ruminoid.Toolbox.Core; 5 | using Ruminoid.Toolbox.Plugins.Common.ConfigSections.ViewModels; 6 | 7 | namespace Ruminoid.Toolbox.Plugins.Common.ConfigSections.Views 8 | { 9 | [ConfigSection( 10 | IntroConfigSectionId, 11 | "介绍")] 12 | public class IntroConfigSection : ConfigSectionBase 13 | { 14 | public IntroConfigSection() 15 | { 16 | throw new InvalidOperationException(); 17 | } 18 | 19 | public IntroConfigSection( 20 | JToken sectionConfig) 21 | { 22 | DataContext = new IntroConfigSectionViewModel(sectionConfig); 23 | 24 | InitializeComponent(); 25 | } 26 | 27 | private void InitializeComponent() 28 | { 29 | AvaloniaXamlLoader.Load(this); 30 | } 31 | 32 | public override object Config => DataContext as IntroConfigSectionViewModel; 33 | } 34 | } 35 | -------------------------------------------------------------------------------- /plugins/rmbox-plugin-common/ConfigSections/Views/MuxOptionsConfigSection.axaml.cs: -------------------------------------------------------------------------------- 1 | using Avalonia.Markup.Xaml; 2 | using Newtonsoft.Json.Linq; 3 | using Ruminoid.Toolbox.Core; 4 | using Ruminoid.Toolbox.Plugins.Common.ConfigSections.ViewModels; 5 | 6 | namespace Ruminoid.Toolbox.Plugins.Common.ConfigSections.Views 7 | { 8 | [ConfigSection( 9 | "Ruminoid.Toolbox.Plugins.Common.ConfigSections.MuxOptionsConfigSection", 10 | "混流选项")] 11 | public class MuxOptionsConfigSection : ConfigSectionBase 12 | { 13 | public MuxOptionsConfigSection() 14 | { 15 | InitializeComponent(); 16 | } 17 | 18 | public MuxOptionsConfigSection( 19 | JToken sectionConfig) 20 | { 21 | DataContext = new MuxOptionsConfigSectionViewModel(); 22 | 23 | InitializeComponent(); 24 | } 25 | 26 | private void InitializeComponent() 27 | { 28 | AvaloniaXamlLoader.Load(this); 29 | } 30 | 31 | public override object Config => DataContext as MuxOptionsConfigSectionViewModel; 32 | } 33 | } 34 | -------------------------------------------------------------------------------- /plugins/rmbox-plugin-common/ConfigSections/Views/OutputConfigSection.axaml: -------------------------------------------------------------------------------- 1 | 8 | 9 | 14 | 15 | 19 | 20 | 24 | 25 | 28 | 29 | 30 | 31 | 输出 32 | 33 | 指定输出文件。输出文件可以是操作所支持的任何文件格式。 34 | 35 | 37 | 40 |