// Fill out your copyright notice in the Description page of Project Settings. #include "BPFileIO.h" #include "ModuleManager.h" #include "FileHelper.h" #include "ImageUtils.h" #include "IImageWrapper.h" #include "IImageWrapperModule.h" bool UBPFileIO::VerifyOrCreateDirectory(const FString & TestDir) { IPlatformFile& PlatformFile = FPlatformFileManager::Get().GetPlatformFile(); // Directory Exists? if (!PlatformFile.DirectoryExists(*TestDir)) { PlatformFile.CreateDirectory(*TestDir); if (!PlatformFile.DirectoryExists(*TestDir)) { return false; } } return true; } bool UBPFileIO::VerifyDirectory(const FString & TestDir) { IPlatformFile& PlatformFile = FPlatformFileManager::Get().GetPlatformFile(); // Directory Exists? if (!PlatformFile.DirectoryExists(*TestDir)) { return false; } return true; } uint8 getMpegVersion(uint8 num) { /* 00 - MPEG Version 2.5 (unofficial) 01 - reserved 10 - MPEG Version 2 (ISO/IEC 13818-3) 11 - MPEG Version 1 (ISO/IEC 11172-3) */ if ((num & 0x03) == 0x03) { return 1; } if ((num & 0x02) == 0x02) { return 2; } return 0; } uint8 getMpegLayer(uint8 num) { /** 00 - reserved 01 - Layer III 10 - Layer II 11 - Layer I */ if ((num & 0x03) == 0x03) { return 1; } if ((num & 0x02) == 0x02) { return 2; } if ((num & 0x01) == 0x01) { return 3; } return 0; } int BITRATES[3][5][16] = { {}, { {}, {0, 32, 64, 96, 128, 160, 192, 224, 256, 288, 320, 352, 384, 416, 448, 0}, {0, 32, 48, 56, 64, 80, 96, 112, 128, 160, 192, 224, 256, 320, 384, 0}, {0, 32, 40, 48, 56, 64, 80, 96, 112, 128, 160, 192, 224, 256, 320, 0}, {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0} }, { {}, {0, 32, 48, 56, 64, 80, 96, 112, 128, 144, 160, 176, 192, 224, 256, 0}, {0, 8, 16, 24, 32, 40, 48, 56, 64, 80, 96, 112, 128, 144, 160, 0}, {0, 8, 16, 24, 32, 40, 48, 56, 64, 80, 96, 112, 128, 144, 160, 0}, {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0} } }; int SAMPLE_RATES[3][4] = { {0, 0, 0, 0}, {44100, 48000, 32000, 0}, {22050, 24000, 16000, 0} }; int SAMPLES_PER_FRAME[3][4] = { {0, 0, 0, 0}, {0, 384, 1152, 1152}, {0, 384, 1152, 576} }; int getMpegFrameLength(bool has_padding, int sample_rate, uint8 layer, int bitrate, int num_samples) { uint8 padding = has_padding ? 1 : 0; if (sample_rate == 0) { return 0; } if (layer == 1) { return ((int) (12.0 * bitrate / sample_rate + padding)) * 4; } return ((int) (num_samples * (bitrate / 8) / sample_rate)) + padding; } uint8 getMpegChannels(uint8 num) { /* 00 - Stereo 01 - Joint stereo (Stereo) 10 - Dual channel (2 mono channels) 11 - Single channel (Mono) */ if ((num & 0x03) == 0x03) { return 1; } return 2; } int CheckFrameInfo(TArray FileData, int i, int depth) { bool isMP3 = (FileData[i] << 8 | (FileData[i + 1] & 0xF0)) == 0xFFF0; if (!isMP3) return -1; bool padding = (FileData[i + 2] & 0x02) >> 1 == 0x01; uint8 mpegVersion = getMpegVersion(FileData[i + 1] >> 3); uint8 mpegLayer = getMpegLayer(FileData[i + 1] >> 1); int bitRate = BITRATES[mpegVersion][mpegLayer][(FileData[i + 2] >> 4) & 0x0F] * 1000; int sampleRate = SAMPLE_RATES[mpegVersion][(FileData[i + 2] >> 2) & 0x03]; int sampleCount = SAMPLES_PER_FRAME[mpegVersion][mpegLayer]; uint8 channels = getMpegChannels(FileData[i + 3] >> 6); int frameLength = getMpegFrameLength(padding, sampleRate, mpegLayer, bitRate, sampleCount); if (frameLength == 0) return -1; UE_LOG(LogTemp, Error, TEXT("Possible mp3 V: %d, L: %d, P: %d, Bitrate: %d, Channels: %d, Sample rate: %d, Sample count: %d, Frame len: %d"), mpegVersion, mpegLayer, padding, bitRate, channels, sampleRate, sampleCount, frameLength); if (depth < 2) { int otherBitrate = CheckFrameInfo(FileData, i + frameLength, depth + 1); if (otherBitrate != bitRate) { return -1; } } return bitRate; } FString UBPFileIO::CheckAudioFormatMatches(const FString & TestPath) { FString unknownProblem = "Error loading song file"; TArray FileData; if (!FFileHelper::LoadFileToArray(FileData, *TestPath)) { UE_LOG(LogTemp, Error, TEXT("Failed to load file")); return unknownProblem; } if (FileData.Num() < 1024) { return unknownProblem; } for (int i = 0; i < 1024; i++) { if ((FileData[i] << 8 | (FileData[i+1] & 0xF0)) == 0xFFF0) { if (CheckFrameInfo(FileData, i, 0) != -1) { if (TestPath.EndsWith(".ogg")) { return "That looks like an MP3, you can't just rename files to change their type.\nGo get audacity and convert it properly."; } return "That looks like an MP3, but it needs to be an ogg.\nPlease use audacity to convert it."; } return unknownProblem; } } return unknownProblem; } FString UBPFileIO::CheckImageFormatMatches(const FString & TestPath) { FString unknownProblem = "Something's weird with your cover image, and i don't know what it is."; IImageWrapperModule& ImageWrapperModule = FModuleManager::LoadModuleChecked(FName("ImageWrapper")); TArray FileData; if (!FFileHelper::LoadFileToArray(FileData, *TestPath)) { UE_LOG(LogTemp, Error, TEXT("Failed to load file")); return unknownProblem; } EImageFormat fileFormat = ImageWrapperModule.DetectImageFormat(FileData.GetData(), FileData.Num()); if ((TestPath.EndsWith(".png") && fileFormat == EImageFormat::PNG) || ((TestPath.EndsWith(".jpg") || TestPath.EndsWith(".jpeg")) && (fileFormat == EImageFormat::JPEG || fileFormat == EImageFormat::GrayscaleJPEG))) { return unknownProblem; } else if (!TestPath.EndsWith(".png") && !TestPath.EndsWith(".jpg") && !TestPath.EndsWith(".jpeg")) { return "Your cover image needs to be a jpg or png and end with .jpg, .jpeg or .png"; } FString fileFormatStr; switch (fileFormat) { case EImageFormat::BMP: fileFormatStr = "BMP"; break; case EImageFormat::PNG: fileFormatStr = "PNG"; break; case EImageFormat::JPEG: case EImageFormat::GrayscaleJPEG: fileFormatStr = "JPG"; break; case EImageFormat::ICO: fileFormatStr = "ICO"; break; case EImageFormat::EXR: fileFormatStr = "EXR"; break; case EImageFormat::ICNS: fileFormatStr = "ICNS"; break; case EImageFormat::Invalid: default: fileFormatStr = "Unknown"; } return "Your cover image appears to be a " + fileFormatStr + " file, but the extension does not match"; } TArray UBPFileIO::FindAllDirectories(const FString & TestDir) { TArray result; IFileManager& FileManager = IFileManager::Get(); FString FinalPath = TestDir + "/*"; FileManager.FindFiles(result, *FinalPath, false, true); return result; } TArray UBPFileIO::FindAllFiles(const FString & TestDir) { TArray result; IFileManager& FileManager = IFileManager::Get(); FString FinalPath = TestDir + "/*"; FileManager.FindFiles(result, *FinalPath, true, false); return result; } bool UBPFileIO::VerifyFile(const FString & TestFile) { if (FPlatformFileManager::Get().GetPlatformFile().FileExists(*TestFile)) { return true; } return false; } bool UBPFileIO::RenameOrMoveFile(const FString & InputFile, const FString & OutputFile) { if (!FPlatformFileManager::Get().GetPlatformFile().FileExists(*InputFile)) { return false; } if (!FPlatformFileManager::Get().GetPlatformFile().MoveFile(*OutputFile, *InputFile)) { return false; } return true; } bool UBPFileIO::CopyFile(const FString & File, const FString& OutputDirectory, const FString& newName) { IPlatformFile& PlatformFile = FPlatformFileManager::Get().GetPlatformFile(); if (PlatformFile.FileExists(*File)) { if (PlatformFile.DirectoryExists(*OutputDirectory)) { PlatformFile.CopyFile(*FString(OutputDirectory + "/" + newName), *File); return true; } } return false; } bool UBPFileIO::DeleteFile(const FString & File) { if (!FPlatformFileManager::Get().GetPlatformFile().DeleteFile(*File)) { return false; } return true; } bool UBPFileIO::DeleteDirectory(const FString & Directory) { if (!FPlatformFileManager::Get().GetPlatformFile().DeleteDirectoryRecursively(*Directory)) { return false; } return true; } int UBPFileIO::getFileSize(const FString & File) { return FPlatformFileManager::Get().GetPlatformFile().FileSize(*File); } int UBPFileIO::getTimestamp(const FString & File) { return FPlatformFileManager::Get().GetPlatformFile().GetTimeStamp(*File).ToUnixTimestamp(); } bool UBPFileIO::SaveStringTextToFile( FString SaveDirectory, FString JoyfulFileName, FString SaveText, bool AllowOverWriting ) { if (!FPlatformFileManager::Get().GetPlatformFile().CreateDirectoryTree(*SaveDirectory)) { //Could not make the specified directory return false; //~~~~~~~~~~~~~~~~~~~~~~ } //get complete file path SaveDirectory += "\\"; SaveDirectory += JoyfulFileName; //No over-writing? if (!AllowOverWriting) { //Check if file exists already if (FPlatformFileManager::Get().GetPlatformFile().FileExists(*SaveDirectory)) { //no overwriting return false; } } return FFileHelper::SaveStringToFile(SaveText, *SaveDirectory, FFileHelper::EEncodingOptions::ForceUTF8WithoutBOM); }