Skip to content

Commit

Permalink
fixed bug when no path is provided
Browse files Browse the repository at this point in the history
  • Loading branch information
cyanide0081 committed Feb 3, 2023
1 parent 2e11ce5 commit 40a2e2d
Show file tree
Hide file tree
Showing 10 changed files with 139 additions and 141 deletions.
72 changes: 44 additions & 28 deletions README.md
Original file line number Diff line number Diff line change
@@ -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

<br>

## **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
<br>

### **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`
<br>

## 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
<br>

## **Usage**

This tool's argument syntax is not that different from FFmpeg itself, with the basic structure being:
>
> `rffmpeg -path <in-path> -fmt <in-fmt(s)> -opts <parameters> -ext <out-ext>`
> \> `rffmpeg -path <in-path> -fmt <in-fmt(s)> -opts <parameters> -ext <out-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:
>
<br>

## **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,
Expand All @@ -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

<br>

## **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,
Expand All @@ -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
<br>

***

- **p.s.:** you will get a Windows SmartScreen warning the first time you run it (assuming you have it enabled)
<br>

p.s.: you will get a Windows SmartScreen warning the first time you run it(assuming you have it enabled)
2 changes: 1 addition & 1 deletion include/constants.h
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down
5 changes: 2 additions & 3 deletions include/input.h
Original file line number Diff line number Diff line change
Expand Up @@ -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
4 changes: 3 additions & 1 deletion include/typefunctions.h
Original file line number Diff line number Diff line change
Expand Up @@ -5,4 +5,6 @@

formattedTime_t formatTime(double seconds);

#endif
void removeTrailingNewLine(char16_t *string);

#endif
45 changes: 28 additions & 17 deletions makefile
Original file line number Diff line number Diff line change
@@ -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
clean:
del /Q .\\src\\obj\\*
# del /Q .\\src\\dep\\*
del .\\rffmpeg.exe
del .\\debug.exe
2 changes: 1 addition & 1 deletion src/handlers.c
Original file line number Diff line number Diff line change
Expand Up @@ -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') {
Expand Down
121 changes: 46 additions & 75 deletions src/input.c
Original file line number Diff line number Diff line change
@@ -1,133 +1,104 @@
#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 <path> -f <container> -p <params> -o <container> */
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;
char16_t *token = wcstok_s(argumentBuffer, u"=", &parserState);

/* 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;
}
Loading

0 comments on commit 40a2e2d

Please sign in to comment.