From 40a2e2dd7027675558660ccf9b97164250d24f0f Mon Sep 17 00:00:00 2001 From: cyanide0081 Date: Fri, 3 Feb 2023 00:13:56 -0300 Subject: [PATCH] fixed bug when no path is provided --- README.md | 72 ++++++++++++++---------- include/constants.h | 2 +- include/input.h | 5 +- include/typefunctions.h | 4 +- makefile | 45 +++++++++------ src/handlers.c | 2 +- src/input.c | 121 +++++++++++++++------------------------- src/main.c | 22 +++----- src/terminal.c | 3 +- src/typefunctions.c | 4 ++ 10 files changed, 139 insertions(+), 141 deletions(-) diff --git a/README.md b/README.md index db83b93..93c721f 100644 --- a/README.md +++ b/README.md @@ -1,39 +1,52 @@ -# RFFmpeg +# **RFFmpeg** -Windows command-line/console window tool for automating *FFmpeg* file conversions inside a specific directory + Windows command-line/console window tool for automating FFmpeg file conversions inside a specific directory * Run with `--help` to read the help page +
+## **Installation** -## Installation + In order to use this tool you will first need to install FFmpeg, so here are two ways to do it: -> In order to use this tool you will have to: -> -> 1. download a build of [**FFmpeg**](https://ffmpeg.org/download.html) -> -> 2. add **_*/ffmpeg/bin_** to your `PATH` environment variable -> -> 3. download the latest build of this tool [**here**](https://github.com/cyanide0081/rffmpeg/releases) -> -> 4. (**optional**) put **_rffmpeg.exe_** in your **_*/ffmpeg/bin_** folder so you can call it from any directory +
+ +### **Method 1:** Using _winget_ (recommended) + + If you're using Windows 10.1709 or newer, you can install it by simply opening PowerShell and running: +> \> `winget install ffmpeg` +
-## Usage +### **Method 2:** Downloading it directly -> - This tool's argument syntax is not that different from FFmpeg itself, with the basic structure being: +> +>1. download the latest Windows build of [**FFmpeg**](https://www.gyan.dev/ffmpeg/builds/ffmpeg-release-essentials.zip) +> +> 2. Extract the archive and add the _C:\ffmpeg\bin_ folder - the one containing the executables - to your `PATH` by running PS as admin and pasting the following command: +> +> \> `[Environment]::SetEnvironmentVariable("Path", $env:Path + ";C:\ffmpeg\bin", [EnvironmentVariableTarget]::Machine)` +> +> 3. (**optional**) move _rffmpeg.exe_ to your _C:\ffmpeg\bin_ folder so you can call it from any directory + +
+ +## **Usage** + + This tool's argument syntax is not that different from FFmpeg itself, with the basic structure being: > -> `rffmpeg -path -fmt -opts -ext ` +> \> `rffmpeg -path -fmt -opts -ext ` > -> - Here's a basic RFFmpeg command that looks for **.wav** files and converts them to **mp3**: + Here's a basic RFFmpeg command that looks for wav files and converts them to mp3: > -> `rffmpeg -path C:\Users\Music -fmt wav -ext mp3` -> -> +> \> `rffmpeg -path C:\Users\Music -fmt wav -ext mp3` > -> ### Arguments: -> + +
+ + ## **Arguments** > - **path** : must hold a valid directory or else the application will close __*__ > > - **fmt** : must hold one or more formats you wish to transcode separated by commas, @@ -44,12 +57,11 @@ Windows command-line/console window tool for automating *FFmpeg* file conversion > > - **ext** : must hold the extension your output files will use __*__ > -> __*__ All arguments marked with an asterisk are required for the tool to work -> -> -> -> ### Additional Flags -> + * All arguments marked with an asterisk are required for the tool to work + +
+ + ## **Additional Flags** > You can also pass any of the flags below to help you organize your batch conversions a little > > - **--newfolder** : puts your converted files inside a new folder to which you can assign a custom name, @@ -63,6 +75,10 @@ Windows command-line/console window tool for automating *FFmpeg* file conversion > - **--norecursion** : disables file searches inside subfolders, in case your directory contains many folders you > don't want to mess with +
+ *** - - **p.s.:** you will get a Windows SmartScreen warning the first time you run it (assuming you have it enabled) \ No newline at end of file +
+ + p.s.: you will get a Windows SmartScreen warning the first time you run it(assuming you have it enabled) \ No newline at end of file diff --git a/include/constants.h b/include/constants.h index 2a14acc..5024dad 100644 --- a/include/constants.h +++ b/include/constants.h @@ -3,7 +3,7 @@ #define PROGRAM_NAME u"RFF" #define PROGRAM_NAME_FULL u"RFFMPEG" -#define PROGRAM_VERSION u"v0.6.4-beta" +#define PROGRAM_VERSION u"v0.6.5-beta" static const char16_t *fullTitle = PROGRAM_NAME_FULL u" " PROGRAM_VERSION u" (ユニコード)"; static const char16_t *consoleWindowTitle = PROGRAM_NAME u" " PROGRAM_VERSION; diff --git a/include/input.h b/include/input.h index ff020ae..8456bb9 100644 --- a/include/input.h +++ b/include/input.h @@ -2,10 +2,9 @@ #define H_INPUTFUNCTIONS #include "libs.h" -#include "types.h" -char16_t **parseArgumentsFromTerminal(size_t *outputArgumentsCount, char16_t *outputArguments[]); +errno_t parseArgumentsFromTerminal(arguments_t *arguments); -arguments_t parseCommandLineArguments(const int count, const char16_t *rawArguments[]); +errno_t parseCommandLineArguments(const int count, const char16_t *rawArguments[], arguments_t *parsedArguments); #endif \ No newline at end of file diff --git a/include/typefunctions.h b/include/typefunctions.h index 85c07a7..6bf0864 100644 --- a/include/typefunctions.h +++ b/include/typefunctions.h @@ -5,4 +5,6 @@ formattedTime_t formatTime(double seconds); -#endif +void removeTrailingNewLine(char16_t *string); + +#endif \ No newline at end of file diff --git a/makefile b/makefile index 5d312cc..7c7921f 100644 --- a/makefile +++ b/makefile @@ -1,27 +1,38 @@ CC=gcc -CFLAGS=-fdiagnostics-color=always $(OPTIMIZATIONFLAGS) -Wall -Wno-unused-variable -Wno-unused-function -std=c17 -municode +BIN=rffmpeg -IDIR=include -ODIR=src/obj -SDIR=src -LDIR=lib -OPTIMIZATIONFLAGS=-s -Os -fdata-sections -ffunction-sections -Wl,--gc-sections -flto +CDIRS=./src +ODIRS=./src/obj +DDIRS=./src/dep +INCDIRS=./include ./include/man -LIBS=-lm +# This build system builds a file ready to be debugged by default. If you want to use its size optimizations +# for a final build, uncomment OPTFLAGS, comment DBGFLAGS, use `make clean` and just run `make` -_DEPS=libs.h constants.h mainloop.h handlers.h terminal.h input.h man/help.h types.h -DEPS=$(patsubst %,$(IDIR)/%,$(_DEPS)) +DBGFLAGS=#-g +OPTFLAGS=-s -Os -fdata-sections -ffunction-sections -Wl,--gc-sections -flto +DEPFLAGS=-MP -MD +CCFLAGS=-Wall -Wno-unused-variable -Wno-unused-function -std=c17 -municode -fdiagnostics-color=always -municode $(foreach D,$(INCDIRS),-I$(D)) $(DEPFLAGS) -_OBJ=main.o typefunctions.o mainloop.o handlers.o input.o terminal.o -OBJ=$(patsubst %,$(ODIR)/%,$(_OBJ)) +CFILES=$(foreach D,$(CDIRS),$(wildcard $(D)/*.c)) +HFILES=$(foreach D,$(INCDIRS),$(wildcard $(D)/*.h)) +OFILES=$(patsubst $(CDIRS)/%.c, $(ODIRS)/%.o, $(CFILES)) +DFILES=$(patsubst $(ODIRS)/%.o, $(DDIRS)/%.d, $(OFILES)) -$(ODIR)/%.o: $(SDIR)/%.c $(DEPS) - $(CC) -c -o $@ $< $(CFLAGS) +all: $(BIN) -rffmpeg: $(OBJ) - $(CC) -o $@ $^ $(CFLAGS) $(LIBS) +$(BIN): $(OFILES) + $(CC) $(CCFLAGS) $(OPTFLAGS) $(DBGFLAGS) -o $@ $^ + +-include $(DFILES) + +%.o: ../%.c makefile $(HFILES) + $(CC) $(CCFLAGS) $(OPTFLAGS) $(DBGFLAGS) -c -o $@ $< .PHONY: clean -clean: $(OBJ) - rm -f $(OBJ)/*.o \ No newline at end of file +clean: + del /Q .\\src\\obj\\* +# del /Q .\\src\\dep\\* + del .\\rffmpeg.exe + del .\\debug.exe \ No newline at end of file diff --git a/src/handlers.c b/src/handlers.c index 734e34f..9b9ed8e 100644 --- a/src/handlers.c +++ b/src/handlers.c @@ -26,7 +26,7 @@ int preventFilenameOverwrites(char16_t *pureFilename, const char16_t *outputForm errorCode_t handleErrors(arguments_t *arguments) { /* Set current working directory as input path if none is provided */ if (*arguments->inputPath == 0) { - GetCurrentDirectoryW(SHORTBUF, arguments->inputFormatString); + GetCurrentDirectoryW(SHORTBUF, arguments->inputPath); } if (*arguments->inputFormatString == u'\0') { diff --git a/src/input.c b/src/input.c index 03cab86..67c2390 100644 --- a/src/input.c +++ b/src/input.c @@ -1,119 +1,90 @@ #include "../include/input.h" -/* Gets the argument strings from a console menu and formats them to be parsed by parseCommandLineArguments() */ -char16_t **parseArgumentsFromTerminal(size_t *outputArgumentsCount, char16_t *outputArguments[]) { +/* Gets and parses the argument strings from console input dialogs */ +errno_t parseArgumentsFromTerminal(arguments_t *arguments) { size_t currentIndex = 0; DWORD charactersRead = 0; HANDLE consoleInput = GetStdHandle(STD_INPUT_HANDLE); wprintf_s(u"%ls > %lsInput path: %ls", CHARCOLOR_RED, CHARCOLOR_WHITE, CHARCOLOR_WHITE_BOLD); - - outputArguments[currentIndex] = calloc(sizeof(u"-path"), sizeof(char16_t)); - wcscpy_s(outputArguments[currentIndex], PATHBUF, u"-path"); - ++currentIndex; - - outputArguments[currentIndex] = calloc(PATHBUF, sizeof(char16_t)); - - ReadConsoleW(consoleInput, outputArguments[currentIndex], PATHBUF, &charactersRead, NULL); - - outputArguments[currentIndex][wcscspn(outputArguments[currentIndex], u"\r\n")] = u'\0'; // Remove trailing fgets() newline - - ++currentIndex; + ReadConsoleW(consoleInput, arguments->inputPath, PATHBUF, &charactersRead, NULL); + removeTrailingNewLine(arguments->inputPath); wprintf_s(u"%ls > %lsTarget format(s): %ls", CHARCOLOR_RED, CHARCOLOR_WHITE, CHARCOLOR_WHITE_BOLD); - - outputArguments[currentIndex] = calloc(sizeof(u"-fmt"), sizeof(char16_t)); - wcscpy_s(outputArguments[currentIndex], PATHBUF, u"-fmt"); - ++currentIndex; - - outputArguments[currentIndex] = calloc(BUFFER, sizeof(char16_t)); - - ReadConsoleW(consoleInput, outputArguments[currentIndex], BUFFER, &charactersRead, NULL); - - outputArguments[currentIndex][wcscspn(outputArguments[currentIndex], u"\r\n")] = u'\0'; - - ++currentIndex; + ReadConsoleW(consoleInput, arguments->inputFormatString, SHORTBUF, &charactersRead, NULL); + removeTrailingNewLine(arguments->inputFormatString); wprintf_s(u"%ls > %lsFFmpeg options: %ls", CHARCOLOR_RED, CHARCOLOR_WHITE, CHARCOLOR_WHITE_BOLD); - - outputArguments[currentIndex] = calloc(sizeof(u"-opts"), sizeof(char16_t)); - wcscpy_s(outputArguments[currentIndex], PATHBUF, u"-opts"); - ++currentIndex; - - outputArguments[currentIndex] = calloc(BUFFER, sizeof(char16_t)); - - ReadConsoleW(consoleInput, outputArguments[currentIndex], BUFFER, &charactersRead, NULL); - - outputArguments[currentIndex][wcscspn(outputArguments[currentIndex], u"\r\n")] = u'\0'; - - ++currentIndex; + ReadConsoleW(consoleInput, arguments->inputParameters, BUFFER, &charactersRead, NULL); + removeTrailingNewLine(arguments->inputParameters); wprintf_s(u"%ls > %lsOutput extension: %ls", CHARCOLOR_RED, CHARCOLOR_WHITE, CHARCOLOR_WHITE_BOLD); - - outputArguments[currentIndex] = calloc(sizeof(u"-ext"), sizeof(char16_t)); - wcscpy_s(outputArguments[currentIndex], PATHBUF, u"-ext"); - ++currentIndex; - - outputArguments[currentIndex] = calloc(SHORTBUF, sizeof(char16_t)); - - ReadConsoleW(consoleInput, outputArguments[currentIndex], SHORTBUF, &charactersRead, NULL); - - outputArguments[currentIndex][wcscspn(outputArguments[currentIndex], u"\r\n")] = u'\0'; - - ++currentIndex; - - wprintf_s(u"%ls > %lsAdditional flags: %ls", CHARCOLOR_RED, CHARCOLOR_WHITE, CHARCOLOR_WHITE_BOLD); + ReadConsoleW(consoleInput, arguments->outputFormat, SHORTBUF, &charactersRead, NULL); + removeTrailingNewLine(arguments->outputFormat); char16_t optionsString[BUFFER]; + wprintf_s(u"%ls > %lsAdditional flags: %ls", CHARCOLOR_RED, CHARCOLOR_WHITE, CHARCOLOR_WHITE_BOLD); ReadConsoleW(consoleInput, optionsString, BUFFER, &charactersRead, NULL); - optionsString[wcscspn(optionsString, u"\r\n")] = u'\0'; + removeTrailingNewLine(optionsString); + wchar_t *parserState = NULL; wchar_t *token = wcstok_s(optionsString, u", ", &parserState); + + char16_t *optionsList[SHORTBUF] = { NULL }; + size_t optionsCount = 0; - while (token) { - outputArguments[currentIndex] = calloc(SHORTBUF, sizeof(char16_t)); - wcscpy_s(outputArguments[currentIndex], SHORTBUF, token); + for (int i = 0; token != NULL; optionsCount = ++i) { + if ((optionsList[i] = calloc(SHORTBUF, sizeof(char16_t))) == NULL) { + printError(u"not enough memory"); + + return ERROR_NOT_ENOUGH_MEMORY; + } + + wcscpy_s(optionsList[i], SHORTBUF, token); token = wcstok_s(NULL, u", ", &parserState); - ++currentIndex; } - *outputArgumentsCount = currentIndex; + parseCommandLineArguments(optionsCount, (const char16_t**)optionsList, arguments); + + for (int i = 0; i < optionsCount; ++i) { + free(optionsList[i]); + optionsList[i] = NULL; + } wprintf_s(u"\n"); wprintf_s(COLOR_DEFAULT); - return outputArguments; + return NO_ERROR; } -/* Parses the arguments after they've been properly formatted into a sequenced array of strings */ -arguments_t parseCommandLineArguments(const int count, const char16_t *rawArguments[]) { - arguments_t parsedArguments; +/* Parses an array of strings to format parsedArguments accordingly */ +errno_t parseCommandLineArguments(const int count, const char16_t *rawArguments[], arguments_t *parsedArguments) { - for (size_t i = 0; i < count; ++i) { + for (int i = 0; i < count; ++i) { /* fmt: -i -f -p -o */ if (wcscmp(rawArguments[i], u"-path") == 0) { - wcsncpy_s(parsedArguments.inputPath, PATHBUF, rawArguments[++i], PATHBUF); + wcsncpy_s(parsedArguments->inputPath, PATHBUF, rawArguments[++i], PATHBUF); } else if (wcscmp(rawArguments[i], u"-fmt") == 0) { - wcsncpy_s(parsedArguments.inputFormatString, SHORTBUF, rawArguments[++i], BUFFER); + wcsncpy_s(parsedArguments->inputFormatString, SHORTBUF, rawArguments[++i], BUFFER); } else if (wcscmp(rawArguments[i], u"-opts") == 0) { - wcsncpy_s(parsedArguments.inputParameters, BUFFER, rawArguments[++i], BUFFER); + wcsncpy_s(parsedArguments->inputParameters, BUFFER, rawArguments[++i], BUFFER); } else if (wcscmp(rawArguments[i], u"-ext") == 0) { - wcsncpy_s(parsedArguments.outputFormat, SHORTBUF, rawArguments[++i], SHORTBUF); + wcsncpy_s(parsedArguments->outputFormat, SHORTBUF, rawArguments[++i], SHORTBUF); } /* fmt: --help, --newfolder=foldername, --delete, --norecursion, --overwrite, */ if (wcscmp(rawArguments[i], OPT_DISPLAYHELP_STRING) == 0) { - parsedArguments.optionDisplayHelp = true; + parsedArguments->optionDisplayHelp = true; } else if (wcscmp(rawArguments[i], OPT_DELETEOLDFILES_STRING) == 0) { - parsedArguments.optionDeleteOriginalFiles = true; + parsedArguments->optionDeleteOriginalFiles = true; } else if (wcscmp(rawArguments[i], OPT_DISABLERECURSION_STRING) == 0) { - parsedArguments.optionDisableRecursiveSearch = true; + parsedArguments->optionDisableRecursiveSearch = true; } else if (wcscmp(rawArguments[i], OPT_FORCEOVERWRITE_STRING) == 0) { - parsedArguments.optionForceFileOverwrites = true; + parsedArguments->optionForceFileOverwrites = true; } else if (wcsstr(rawArguments[i], OPT_MAKENEWFOLDER_STRING)) { - parsedArguments.optionMakeNewFolder = true; + parsedArguments->optionMakeNewFolder = true; char16_t *argumentBuffer = wcsdup(rawArguments[i]); // duplicate argument string for analysis char16_t *parserState; @@ -121,13 +92,13 @@ arguments_t parseCommandLineArguments(const int count, const char16_t *rawArgume /* If there's an '=' sign, pass the string after it to the foldername argument */ if ((token = wcstok_s(NULL, u"=", &parserState)) != NULL) { - parsedArguments.optionCustomFolderName = true; - wcscpy_s(parsedArguments.customFolderName, PATHBUF, token); + parsedArguments->optionCustomFolderName = true; + wcscpy_s(parsedArguments->customFolderName, PATHBUF, token); } free(argumentBuffer); } } - return parsedArguments; + return NO_ERROR; } \ No newline at end of file diff --git a/src/main.c b/src/main.c index 537c620..e4534e7 100644 --- a/src/main.c +++ b/src/main.c @@ -19,22 +19,18 @@ int wmain(int argc, const char16_t *argv[]) { wprintf_s(u"%ls%ls%ls\n\n", CHARCOLOR_RED, fullTitle, COLOR_DEFAULT); - arguments_t *parsedArguments = malloc(sizeof(arguments_t)); + arguments_t *parsedArguments = calloc(1, sizeof(arguments_t)); - if (inputMode == ARGUMENTS) { - *parsedArguments = parseCommandLineArguments(argc, argv); - } else { - size_t consoleArgumentsCount = 0; - char16_t *consoleArguments[SHORTBUF]; + if (parsedArguments == NULL) { + printError(u"not enough memory"); - parseArgumentsFromTerminal(&consoleArgumentsCount, consoleArguments); - - *parsedArguments = parseCommandLineArguments(consoleArgumentsCount, (const char16_t**)consoleArguments); + return ERROR_NOT_ENOUGH_MEMORY; + } - for (size_t i = 0; i < consoleArgumentsCount; ++i) { - free(consoleArguments[i]); - consoleArguments[i] = NULL; - } + if (inputMode == ARGUMENTS) { + parseCommandLineArguments(argc, argv, parsedArguments); + } else { + parseArgumentsFromTerminal(parsedArguments); } if (parsedArguments->optionDisplayHelp == true && inputMode == ARGUMENTS) { diff --git a/src/terminal.c b/src/terminal.c index abd407b..a88e5ba 100644 --- a/src/terminal.c +++ b/src/terminal.c @@ -36,8 +36,7 @@ errno_t enableVirtualTerminalProcessing(PDWORD originalConsoleMode) { void displayEndDialog(processInfo_t *processInformation) { if (processInformation->convertedFiles == 0) { - printError(u"No input files were found\n"); - wprintf_s(u"\n"); + printError(u"No input files were found"); } else { formattedTime_t executionTime = formatTime(processInformation->executionTime); diff --git a/src/typefunctions.c b/src/typefunctions.c index af08bbd..0c5f1d2 100644 --- a/src/typefunctions.c +++ b/src/typefunctions.c @@ -8,4 +8,8 @@ formattedTime_t formatTime(double seconds) { time.seconds = (double)(seconds - (time.hours * 3600) - (time.minutes * 60)); return time; +} + +void removeTrailingNewLine(char16_t *string) { + string[wcscspn(string, u"\r\n")] = u'\0'; } \ No newline at end of file