mirror of
https://github.com/TomHarte/CLK.git
synced 2024-06-17 21:30:14 +00:00
Transcribe GetMediaAndPlatforms
away from macros.
This commit is contained in:
parent
baac0768b8
commit
30bf187119
|
@ -102,46 +102,77 @@ std::string get_extension(const std::string &name) {
|
|||
return extension;
|
||||
}
|
||||
|
||||
/// Adds @c instance to @c list and adds @c platforms to the set of @c potential_platforms.
|
||||
/// If @c instance is an @c TargetPlatform::TypeDistinguisher then it is given an opportunity to restrict the set of @c potential_platforms.
|
||||
template <typename ContainerT, typename InstanceT>
|
||||
void insert_instance(ContainerT &list, InstanceT instance, TargetPlatform::IntType &potential_platforms, TargetPlatform::IntType platforms) {
|
||||
list.emplace_back(instance);
|
||||
potential_platforms |= platforms;
|
||||
class MediaAccumulator {
|
||||
public:
|
||||
MediaAccumulator(const std::string &file_name, TargetPlatform::IntType &potential_platforms) :
|
||||
file_name_(file_name), potential_platforms_(potential_platforms), extension_(get_extension(file_name)) {}
|
||||
|
||||
TargetPlatform::TypeDistinguisher *const distinguisher =
|
||||
dynamic_cast<TargetPlatform::TypeDistinguisher *>(list.back().get());
|
||||
if(distinguisher) potential_platforms &= distinguisher->target_platform_type();
|
||||
}
|
||||
/// Adds @c instance to the media collection and adds @c platforms to the set of potentials.
|
||||
/// If @c instance is an @c TargetPlatform::TypeDistinguisher then it is given an opportunity to restrict the set of potentials.
|
||||
template <typename InstanceT>
|
||||
void insert(TargetPlatform::IntType platforms, InstanceT *instance) {
|
||||
if constexpr (std::is_base_of_v<Storage::Disk::Disk, InstanceT>) {
|
||||
media.disks.emplace_back(instance);
|
||||
} else if constexpr (std::is_base_of_v<Storage::Tape::Tape, InstanceT>) {
|
||||
media.tapes.emplace_back(instance);
|
||||
} else if constexpr (std::is_base_of_v<Storage::Cartridge::Cartridge, InstanceT>) {
|
||||
media.cartridges.emplace_back(instance);
|
||||
} else if constexpr (std::is_base_of_v<Storage::MassStorage::MassStorageDevice, InstanceT>) {
|
||||
media.mass_storage_devices.emplace_back(instance);
|
||||
} else {
|
||||
static_assert(always_false_v<InstanceT>, "Unexpected type encountered.");
|
||||
}
|
||||
|
||||
/// Concstructs a new instance of @c InstanceT supplying @c args and adds it to the back of @c list using @c insert_instance.
|
||||
template <typename InstanceT, typename ContainerT, typename... Args>
|
||||
void insert(ContainerT &list, TargetPlatform::IntType &potential_platforms, TargetPlatform::IntType platforms, Args &&... args) {
|
||||
insert_instance(list, new InstanceT(std::forward<Args>(args)...), potential_platforms, platforms);
|
||||
}
|
||||
potential_platforms_ |= platforms;
|
||||
|
||||
/// Calls @c insert with the specified parameters, ignoring any exceptions thrown.
|
||||
template <typename InstanceT, typename ContainerT, typename... Args>
|
||||
void try_insert(ContainerT &list, TargetPlatform::IntType &potential_platforms, TargetPlatform::IntType platforms, Args &&... args) {
|
||||
try {
|
||||
insert<InstanceT>(list, potential_platforms, platforms, std::forward<Args>(args)...);
|
||||
} catch(...) {}
|
||||
}
|
||||
// Check whether the instance itself has any input on target platforms.
|
||||
TargetPlatform::TypeDistinguisher *const distinguisher =
|
||||
dynamic_cast<TargetPlatform::TypeDistinguisher *>(instance);
|
||||
if(distinguisher) potential_platforms_ &= distinguisher->target_platform_type();
|
||||
}
|
||||
|
||||
/// Concstructs a new instance of @c InstanceT supplying @c args and adds it to the back of @c list using @c insert_instance.
|
||||
template <typename InstanceT, typename... Args>
|
||||
void insert(TargetPlatform::IntType platforms, Args &&... args) {
|
||||
insert(platforms, new InstanceT(std::forward<Args>(args)...));
|
||||
}
|
||||
|
||||
/// Calls @c insert with the specified parameters, ignoring any exceptions thrown.
|
||||
template <typename InstanceT, typename... Args>
|
||||
void try_insert(TargetPlatform::IntType platforms, Args &&... args) {
|
||||
try {
|
||||
insert<InstanceT>(platforms, std::forward<Args>(args)...);
|
||||
} catch(...) {}
|
||||
}
|
||||
|
||||
/// Performs a @c try_insert for an object of @c InstanceT if @c extension matches that of the file name,
|
||||
/// providing the file name as the only construction argument.
|
||||
template <typename InstanceT>
|
||||
void try_standard(TargetPlatform::IntType platforms, const char *extension) {
|
||||
if(name_matches(extension)) {
|
||||
try_insert<InstanceT>(platforms, file_name_);
|
||||
}
|
||||
}
|
||||
|
||||
bool name_matches(const char *extension) {
|
||||
return extension_ == extension;
|
||||
}
|
||||
|
||||
Media media;
|
||||
|
||||
private:
|
||||
const std::string &file_name_;
|
||||
TargetPlatform::IntType &potential_platforms_;
|
||||
const std::string extension_;
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
static Media GetMediaAndPlatforms(const std::string &file_name, TargetPlatform::IntType &potential_platforms) {
|
||||
const std::string extension = get_extension(file_name);
|
||||
|
||||
Media result;
|
||||
|
||||
#define Format(ext, list, class, platforms) \
|
||||
if(extension == ext) { \
|
||||
try_insert<class>(list, potential_platforms, platforms, file_name); \
|
||||
}
|
||||
MediaAccumulator accumulator(file_name, potential_platforms);
|
||||
|
||||
// 2MG
|
||||
if(extension == "2mg") {
|
||||
if(accumulator.name_matches("2mg")) {
|
||||
// 2MG uses a factory method; defer to it.
|
||||
try {
|
||||
const auto media = Disk::Disk2MG::open(file_name);
|
||||
|
@ -151,10 +182,10 @@ static Media GetMediaAndPlatforms(const std::string &file_name, TargetPlatform::
|
|||
if constexpr (std::is_same<Type, nullptr_t>::value) {
|
||||
// It's valid for no media to be returned.
|
||||
} else if constexpr (std::is_same<Type, Disk::DiskImageHolderBase *>::value) {
|
||||
insert_instance(result.disks, arg, potential_platforms, TargetPlatform::DiskII);
|
||||
accumulator.insert(TargetPlatform::DiskII, arg);
|
||||
} else if constexpr (std::is_same<Type, MassStorage::MassStorageDevice *>::value) {
|
||||
// TODO: or is it Apple IIgs?
|
||||
insert_instance(result.mass_storage_devices, arg, potential_platforms, TargetPlatform::AppleII);
|
||||
accumulator.insert(TargetPlatform::AppleII, arg);
|
||||
} else {
|
||||
static_assert(always_false_v<Type>, "Unexpected type encountered.");
|
||||
}
|
||||
|
@ -162,106 +193,108 @@ static Media GetMediaAndPlatforms(const std::string &file_name, TargetPlatform::
|
|||
} catch(...) {}
|
||||
}
|
||||
|
||||
Format("80", result.tapes, Tape::ZX80O81P, TargetPlatform::ZX8081) // 80
|
||||
Format("81", result.tapes, Tape::ZX80O81P, TargetPlatform::ZX8081) // 81
|
||||
Format("a26", result.cartridges, Cartridge::BinaryDump, TargetPlatform::Atari2600) // A26
|
||||
Format("adf", result.disks, Disk::DiskImageHolder<Disk::AcornADF>, TargetPlatform::Acorn) // ADF (Acorn)
|
||||
Format("adf", result.disks, Disk::DiskImageHolder<Disk::AmigaADF>, TargetPlatform::Amiga) // ADF (Amiga)
|
||||
Format("adl", result.disks, Disk::DiskImageHolder<Disk::AcornADF>, TargetPlatform::Acorn) // ADL
|
||||
Format("bin", result.cartridges, Cartridge::BinaryDump, TargetPlatform::AllCartridge) // BIN (cartridge dump)
|
||||
Format("cas", result.tapes, Tape::CAS, TargetPlatform::MSX) // CAS
|
||||
Format("cdt", result.tapes, Tape::TZX, TargetPlatform::AmstradCPC) // CDT
|
||||
Format("col", result.cartridges, Cartridge::BinaryDump, TargetPlatform::Coleco) // COL
|
||||
Format("csw", result.tapes, Tape::CSW, TargetPlatform::AllTape) // CSW
|
||||
Format("d64", result.disks, Disk::DiskImageHolder<Disk::D64>, TargetPlatform::Commodore) // D64
|
||||
Format("dat", result.mass_storage_devices, MassStorage::DAT, TargetPlatform::Acorn) // DAT
|
||||
Format("dmk", result.disks, Disk::DiskImageHolder<Disk::DMK>, TargetPlatform::MSX) // DMK
|
||||
Format("do", result.disks, Disk::DiskImageHolder<Disk::AppleDSK>, TargetPlatform::DiskII) // DO
|
||||
Format("dsd", result.disks, Disk::DiskImageHolder<Disk::SSD>, TargetPlatform::Acorn) // DSD
|
||||
Format( "dsk",
|
||||
result.disks,
|
||||
Disk::DiskImageHolder<Disk::CPCDSK>,
|
||||
TargetPlatform::AmstradCPC | TargetPlatform::Oric | TargetPlatform::ZXSpectrum) // DSK (Amstrad CPC, etc)
|
||||
Format("dsk", result.disks, Disk::DiskImageHolder<Disk::AppleDSK>, TargetPlatform::DiskII) // DSK (Apple II)
|
||||
Format("dsk", result.disks, Disk::DiskImageHolder<Disk::MacintoshIMG>, TargetPlatform::Macintosh) // DSK (Macintosh, floppy disk)
|
||||
Format("dsk", result.mass_storage_devices, MassStorage::HFV, TargetPlatform::Macintosh) // DSK (Macintosh, hard disk, single volume image)
|
||||
Format("dsk", result.mass_storage_devices, MassStorage::DSK, TargetPlatform::Macintosh) // DSK (Macintosh, hard disk, full device image)
|
||||
Format("dsk", result.disks, Disk::DiskImageHolder<Disk::FAT12>, TargetPlatform::MSX) // DSK (MSX)
|
||||
Format("dsk", result.disks, Disk::DiskImageHolder<Disk::OricMFMDSK>, TargetPlatform::Oric) // DSK (Oric)
|
||||
Format("g64", result.disks, Disk::DiskImageHolder<Disk::G64>, TargetPlatform::Commodore) // G64
|
||||
Format("hdv", result.mass_storage_devices, MassStorage::HDV, TargetPlatform::AppleII) // HDV (Apple II, hard disk, single volume image)
|
||||
Format( "hfe",
|
||||
result.disks,
|
||||
Disk::DiskImageHolder<Disk::HFE>,
|
||||
TargetPlatform::Acorn | TargetPlatform::AmstradCPC | TargetPlatform::Commodore | TargetPlatform::Oric | TargetPlatform::ZXSpectrum)
|
||||
// HFE (TODO: switch to AllDisk once the MSX stops being so greedy)
|
||||
Format("ima", result.disks, Disk::DiskImageHolder<Disk::FAT12>, TargetPlatform::PCCompatible) // IMG (MS-DOS style)
|
||||
Format("image", result.disks, Disk::DiskImageHolder<Disk::MacintoshIMG>, TargetPlatform::Macintosh) // IMG (DiskCopy 4.2)
|
||||
Format("imd", result.disks, Disk::DiskImageHolder<Disk::IMD>, TargetPlatform::PCCompatible) // IMD
|
||||
Format("img", result.disks, Disk::DiskImageHolder<Disk::MacintoshIMG>, TargetPlatform::Macintosh) // IMG (DiskCopy 4.2)
|
||||
accumulator.try_standard<Tape::ZX80O81P>(TargetPlatform::ZX8081, "80");
|
||||
accumulator.try_standard<Tape::ZX80O81P>(TargetPlatform::ZX8081, "81");
|
||||
|
||||
accumulator.try_standard<Cartridge::BinaryDump>(TargetPlatform::Atari2600, "a26");
|
||||
accumulator.try_standard<Disk::DiskImageHolder<Disk::AcornADF>>(TargetPlatform::Acorn, "adf");
|
||||
accumulator.try_standard<Disk::DiskImageHolder<Disk::AmigaADF>>(TargetPlatform::Amiga, "adf");
|
||||
accumulator.try_standard<Disk::DiskImageHolder<Disk::AcornADF>>(TargetPlatform::Acorn, "adl");
|
||||
|
||||
accumulator.try_standard<Cartridge::BinaryDump>(TargetPlatform::AllCartridge, "bin");
|
||||
|
||||
accumulator.try_standard<Tape::CAS>(TargetPlatform::MSX, "cas");
|
||||
accumulator.try_standard<Tape::TZX>(TargetPlatform::AmstradCPC, "cdt");
|
||||
accumulator.try_standard<Cartridge::BinaryDump>(TargetPlatform::Coleco, "col");
|
||||
accumulator.try_standard<Tape::CSW>(TargetPlatform::AllTape, "csw");
|
||||
|
||||
accumulator.try_standard<Disk::DiskImageHolder<Disk::D64>>(TargetPlatform::Commodore, "d64");
|
||||
accumulator.try_standard<MassStorage::DAT>(TargetPlatform::Acorn, "dat");
|
||||
accumulator.try_standard<Disk::DiskImageHolder<Disk::DMK>>(TargetPlatform::MSX, "dmk");
|
||||
accumulator.try_standard<Disk::DiskImageHolder<Disk::AppleDSK>>(TargetPlatform::DiskII, "do");
|
||||
accumulator.try_standard<Disk::DiskImageHolder<Disk::SSD>>(TargetPlatform::Acorn, "dsd");
|
||||
accumulator.try_standard<Disk::DiskImageHolder<Disk::CPCDSK>>(
|
||||
TargetPlatform::AmstradCPC | TargetPlatform::Oric | TargetPlatform::ZXSpectrum, "dsk");
|
||||
accumulator.try_standard<Disk::DiskImageHolder<Disk::AppleDSK>>(TargetPlatform::DiskII, "dsk");
|
||||
accumulator.try_standard<Disk::DiskImageHolder<Disk::MacintoshIMG>>(TargetPlatform::Macintosh, "dsk");
|
||||
accumulator.try_standard<MassStorage::HFV>(TargetPlatform::Macintosh, "dsk");
|
||||
accumulator.try_standard<MassStorage::DSK>(TargetPlatform::Macintosh, "dsk");
|
||||
accumulator.try_standard<Disk::DiskImageHolder<Disk::FAT12>>(TargetPlatform::MSX, "dsk");
|
||||
accumulator.try_standard<Disk::DiskImageHolder<Disk::OricMFMDSK>>(TargetPlatform::Oric, "dsk");
|
||||
|
||||
accumulator.try_standard<Disk::DiskImageHolder<Disk::G64>>(TargetPlatform::Commodore, "g64");
|
||||
|
||||
accumulator.try_standard<MassStorage::HDV>(TargetPlatform::AppleII, "hdv");
|
||||
accumulator.try_standard<Disk::DiskImageHolder<Disk::HFE>>(
|
||||
TargetPlatform::Acorn | TargetPlatform::AmstradCPC | TargetPlatform::Commodore | TargetPlatform::Oric | TargetPlatform::ZXSpectrum,
|
||||
"hfe"); // TODO: switch to AllDisk once the MSX stops being so greedy.
|
||||
|
||||
accumulator.try_standard<Disk::DiskImageHolder<Disk::FAT12>>(TargetPlatform::PCCompatible, "ima");
|
||||
accumulator.try_standard<Disk::DiskImageHolder<Disk::MacintoshIMG>>(TargetPlatform::Macintosh, "image");
|
||||
accumulator.try_standard<Disk::DiskImageHolder<Disk::IMD>>(TargetPlatform::PCCompatible, "imd");
|
||||
accumulator.try_standard<Disk::DiskImageHolder<Disk::MacintoshIMG>>(TargetPlatform::Macintosh, "img");
|
||||
|
||||
// Treat PC booter as a potential backup only if this doesn't parse as a FAT12.
|
||||
if(extension == "img") {
|
||||
if(accumulator.name_matches("img")) {
|
||||
try {
|
||||
insert<Disk::DiskImageHolder<Disk::FAT12>>(result.disks, potential_platforms, TargetPlatform::FAT12, file_name); // IMG (Enterprise or MS-DOS style)
|
||||
accumulator.insert<Disk::DiskImageHolder<Disk::FAT12>>(TargetPlatform::FAT12, file_name);
|
||||
} catch(...) {
|
||||
Format("img", result.disks, Disk::DiskImageHolder<Disk::PCBooter>, TargetPlatform::PCCompatible) // IMG (PC raw booter)
|
||||
accumulator.try_standard<Disk::DiskImageHolder<Disk::PCBooter>>(TargetPlatform::PCCompatible, "img");
|
||||
}
|
||||
}
|
||||
|
||||
Format( "ipf",
|
||||
result.disks,
|
||||
Disk::DiskImageHolder<Disk::IPF>,
|
||||
TargetPlatform::Amiga | TargetPlatform::AtariST | TargetPlatform::AmstradCPC | TargetPlatform::ZXSpectrum) // IPF
|
||||
Format("msa", result.disks, Disk::DiskImageHolder<Disk::MSA>, TargetPlatform::AtariST) // MSA
|
||||
Format("mx2", result.cartridges, Cartridge::BinaryDump, TargetPlatform::MSX) // MX2
|
||||
Format("nib", result.disks, Disk::DiskImageHolder<Disk::NIB>, TargetPlatform::DiskII) // NIB
|
||||
Format("o", result.tapes, Tape::ZX80O81P, TargetPlatform::ZX8081) // O
|
||||
Format("p", result.tapes, Tape::ZX80O81P, TargetPlatform::ZX8081) // P
|
||||
Format("po", result.disks, Disk::DiskImageHolder<Disk::AppleDSK>, TargetPlatform::DiskII) // PO (original Apple II kind)
|
||||
accumulator.try_standard<Disk::DiskImageHolder<Disk::IPF>>(
|
||||
TargetPlatform::Amiga | TargetPlatform::AtariST | TargetPlatform::AmstradCPC | TargetPlatform::ZXSpectrum,
|
||||
"ipf");
|
||||
|
||||
// PO (Apple IIgs kind)
|
||||
if(extension == "po") {
|
||||
try_insert<Disk::DiskImageHolder<Disk::MacintoshIMG>>(
|
||||
result.disks,
|
||||
potential_platforms, TargetPlatform::AppleIIgs,
|
||||
accumulator.try_standard<Disk::DiskImageHolder<Disk::MSA>>(TargetPlatform::AtariST, "msa");
|
||||
accumulator.try_standard<Cartridge::BinaryDump>(TargetPlatform::MSX, "mx2");
|
||||
accumulator.try_standard<Disk::DiskImageHolder<Disk::NIB>>(TargetPlatform::DiskII, "nib");
|
||||
|
||||
accumulator.try_standard<Tape::ZX80O81P>(TargetPlatform::ZX8081, "o");
|
||||
accumulator.try_standard<Tape::ZX80O81P>(TargetPlatform::ZX8081, "p");
|
||||
accumulator.try_standard<Disk::DiskImageHolder<Disk::AppleDSK>>(TargetPlatform::DiskII, "po");
|
||||
|
||||
if(accumulator.name_matches("po")) {
|
||||
accumulator.try_insert<Disk::DiskImageHolder<Disk::MacintoshIMG>>(
|
||||
TargetPlatform::AppleIIgs,
|
||||
file_name, Disk::MacintoshIMG::FixedType::GCR);
|
||||
}
|
||||
|
||||
Format("p81", result.tapes, Tape::ZX80O81P, TargetPlatform::ZX8081) // P81
|
||||
accumulator.try_standard<Tape::ZX80O81P>(TargetPlatform::ZX8081, "p81");
|
||||
|
||||
// PRG
|
||||
if(extension == "prg") {
|
||||
// try instantiating as a ROM; failing that accept as a tape
|
||||
if(accumulator.name_matches("prg")) {
|
||||
// Try instantiating as a ROM; failing that accept as a tape.
|
||||
try {
|
||||
insert<Cartridge::PRG>(result.cartridges, potential_platforms, TargetPlatform::Commodore, file_name);
|
||||
accumulator.insert<Cartridge::PRG>(TargetPlatform::Commodore, file_name);
|
||||
} catch(...) {
|
||||
try {
|
||||
insert<Tape::PRG>(result.tapes, potential_platforms, TargetPlatform::Commodore, file_name);
|
||||
accumulator.insert<Tape::PRG>(TargetPlatform::Commodore, file_name);
|
||||
} catch(...) {}
|
||||
}
|
||||
}
|
||||
|
||||
Format( "rom",
|
||||
result.cartridges,
|
||||
Cartridge::BinaryDump,
|
||||
TargetPlatform::AcornElectron | TargetPlatform::Coleco | TargetPlatform::MSX) // ROM
|
||||
Format("sg", result.cartridges, Cartridge::BinaryDump, TargetPlatform::Sega) // SG
|
||||
Format("sms", result.cartridges, Cartridge::BinaryDump, TargetPlatform::Sega) // SMS
|
||||
Format("ssd", result.disks, Disk::DiskImageHolder<Disk::SSD>, TargetPlatform::Acorn) // SSD
|
||||
Format("st", result.disks, Disk::DiskImageHolder<Disk::FAT12>, TargetPlatform::AtariST) // ST
|
||||
Format("stx", result.disks, Disk::DiskImageHolder<Disk::STX>, TargetPlatform::AtariST) // STX
|
||||
Format("tap", result.tapes, Tape::CommodoreTAP, TargetPlatform::Commodore) // TAP (Commodore)
|
||||
Format("tap", result.tapes, Tape::OricTAP, TargetPlatform::Oric) // TAP (Oric)
|
||||
Format("tap", result.tapes, Tape::ZXSpectrumTAP, TargetPlatform::ZXSpectrum) // TAP (ZX Spectrum)
|
||||
Format("tsx", result.tapes, Tape::TZX, TargetPlatform::MSX) // TSX
|
||||
Format("tzx", result.tapes, Tape::TZX, TargetPlatform::ZX8081 | TargetPlatform::ZXSpectrum) // TZX
|
||||
Format("uef", result.tapes, Tape::UEF, TargetPlatform::Acorn) // UEF (tape)
|
||||
Format("woz", result.disks, Disk::DiskImageHolder<Disk::WOZ>, TargetPlatform::DiskII) // WOZ
|
||||
accumulator.try_standard<Cartridge::BinaryDump>(
|
||||
TargetPlatform::AcornElectron | TargetPlatform::Coleco | TargetPlatform::MSX,
|
||||
"rom");
|
||||
|
||||
#undef Format
|
||||
accumulator.try_standard<Cartridge::BinaryDump>(TargetPlatform::Sega, "sg");
|
||||
accumulator.try_standard<Cartridge::BinaryDump>(TargetPlatform::Sega, "sms");
|
||||
accumulator.try_standard<Disk::DiskImageHolder<Disk::SSD>>(TargetPlatform::Acorn, "ssd");
|
||||
accumulator.try_standard<Disk::DiskImageHolder<Disk::FAT12>>(TargetPlatform::AtariST, "st");
|
||||
accumulator.try_standard<Disk::DiskImageHolder<Disk::STX>>(TargetPlatform::AtariST, "stx");
|
||||
|
||||
return result;
|
||||
accumulator.try_standard<Tape::CommodoreTAP>(TargetPlatform::Commodore, "tap");
|
||||
accumulator.try_standard<Tape::OricTAP>(TargetPlatform::Oric, "tap");
|
||||
accumulator.try_standard<Tape::ZXSpectrumTAP>(TargetPlatform::ZXSpectrum, "tap");
|
||||
accumulator.try_standard<Tape::TZX>(TargetPlatform::MSX, "tsx");
|
||||
accumulator.try_standard<Tape::TZX>(TargetPlatform::ZX8081 | TargetPlatform::ZXSpectrum, "tzx");
|
||||
|
||||
accumulator.try_standard<Tape::UEF>(TargetPlatform::Acorn, "uef");
|
||||
|
||||
accumulator.try_standard<Disk::DiskImageHolder<Disk::WOZ>>(TargetPlatform::DiskII, "woz");
|
||||
|
||||
return accumulator.media;
|
||||
}
|
||||
|
||||
Media Analyser::Static::GetMedia(const std::string &file_name) {
|
||||
|
|
Loading…
Reference in New Issue
Block a user