Factorized some container/codec handling code + removed the no longer needed transcode output formats mka and webm
This commit is contained in:
@@ -1,109 +0,0 @@
|
||||
/*
|
||||
* Copyright (C) 2025 Emeric Poupon
|
||||
*
|
||||
* This file is part of LMS.
|
||||
*
|
||||
* LMS is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* LMS is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with LMS. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include "audio/AudioTypes.hpp"
|
||||
|
||||
namespace lms::audio
|
||||
{
|
||||
core::LiteralString containerTypeToString(ContainerType type)
|
||||
{
|
||||
switch (type)
|
||||
{
|
||||
case ContainerType::AIFF:
|
||||
return "AIFF";
|
||||
case ContainerType::APE:
|
||||
return "APE";
|
||||
case ContainerType::ASF:
|
||||
return "ASF";
|
||||
case ContainerType::DSF:
|
||||
return "DSF";
|
||||
case ContainerType::FLAC:
|
||||
return "FLAC";
|
||||
case ContainerType::MP4:
|
||||
return "MP4";
|
||||
case ContainerType::MPC:
|
||||
return "MPC";
|
||||
case ContainerType::MPEG:
|
||||
return "MPEG";
|
||||
case ContainerType::Ogg:
|
||||
return "Ogg";
|
||||
case ContainerType::Shorten:
|
||||
return "Shorten";
|
||||
case ContainerType::TrueAudio:
|
||||
return "TrueAudio";
|
||||
case ContainerType::WAV:
|
||||
return "WAV";
|
||||
case ContainerType::WavPack:
|
||||
return "WavPack";
|
||||
}
|
||||
|
||||
return "";
|
||||
}
|
||||
|
||||
core::LiteralString codecTypeToString(CodecType type)
|
||||
{
|
||||
switch (type)
|
||||
{
|
||||
case CodecType::AAC:
|
||||
return "AAC";
|
||||
case CodecType::AC3:
|
||||
return "AC3";
|
||||
case CodecType::ALAC:
|
||||
return "ALAC";
|
||||
case CodecType::APE:
|
||||
return "APE";
|
||||
case CodecType::DSD:
|
||||
return "DSD";
|
||||
case CodecType::EAC3:
|
||||
return "E-AC3";
|
||||
case CodecType::FLAC:
|
||||
return "FLAC";
|
||||
case CodecType::MP3:
|
||||
return "MP3";
|
||||
case CodecType::MP4ALS:
|
||||
return "MP4ALS";
|
||||
case CodecType::MPC7:
|
||||
return "MPC7";
|
||||
case CodecType::MPC8:
|
||||
return "MPC8";
|
||||
case CodecType::Opus:
|
||||
return "Opus";
|
||||
case CodecType::PCM:
|
||||
return "PCM";
|
||||
case CodecType::Shorten:
|
||||
return "Shorten";
|
||||
case CodecType::TrueAudio:
|
||||
return "TrueAudio";
|
||||
case CodecType::Vorbis:
|
||||
return "Vorbis";
|
||||
case CodecType::WavPack:
|
||||
return "WavPack";
|
||||
case CodecType::WMA1:
|
||||
return "WMA1";
|
||||
case CodecType::WMA2:
|
||||
return "WMA2";
|
||||
case CodecType::WMA9Pro:
|
||||
return "WMA9Pro";
|
||||
case CodecType::WMA9Lossless:
|
||||
return "WMA9Lossless";
|
||||
}
|
||||
|
||||
return "";
|
||||
}
|
||||
} // namespace lms::audio
|
||||
@@ -1,77 +0,0 @@
|
||||
/*
|
||||
* Copyright (C) 2015 Emeric Poupon
|
||||
*
|
||||
* This file is part of LMS.
|
||||
*
|
||||
* LMS is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* LMS is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with LMS. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include "audio/IImageReader.hpp"
|
||||
|
||||
namespace lms::audio
|
||||
{
|
||||
core::LiteralString imageTypeToString(Image::Type type)
|
||||
{
|
||||
switch (type)
|
||||
{
|
||||
case Image::Type::Other:
|
||||
return "Other";
|
||||
case Image::Type::FileIcon:
|
||||
return "FileIcon";
|
||||
case Image::Type::OtherFileIcon:
|
||||
return "OtherFileIcon";
|
||||
case Image::Type::FrontCover:
|
||||
return "FrontCover";
|
||||
case Image::Type::BackCover:
|
||||
return "BackCover";
|
||||
case Image::Type::LeafletPage:
|
||||
return "LeafletPage";
|
||||
case Image::Type::Media:
|
||||
return "Media";
|
||||
case Image::Type::LeadArtist:
|
||||
return "LeadArtist";
|
||||
case Image::Type::Artist:
|
||||
return "Artist";
|
||||
case Image::Type::Conductor:
|
||||
return "Conductor";
|
||||
case Image::Type::Band:
|
||||
return "Band";
|
||||
case Image::Type::Composer:
|
||||
return "Composer";
|
||||
case Image::Type::Lyricist:
|
||||
return "Lyricist";
|
||||
case Image::Type::RecordingLocation:
|
||||
return "RecordingLocation";
|
||||
case Image::Type::DuringRecording:
|
||||
return "DuringRecording";
|
||||
case Image::Type::DuringPerformance:
|
||||
return "DuringPerformance";
|
||||
case Image::Type::MovieScreenCapture:
|
||||
return "MovieScreenCapture";
|
||||
case Image::Type::ColouredFish:
|
||||
return "ColouredFish";
|
||||
case Image::Type::Illustration:
|
||||
return "Illustration";
|
||||
case Image::Type::BandLogo:
|
||||
return "BandLogo";
|
||||
case Image::Type::PublisherLogo:
|
||||
return "PublisherLogo";
|
||||
case Image::Type::Unknown:
|
||||
break;
|
||||
}
|
||||
|
||||
return "Unknown";
|
||||
}
|
||||
|
||||
} // namespace lms::audio
|
||||
@@ -35,7 +35,6 @@ extern "C"
|
||||
#include "core/ITraceLogger.hpp"
|
||||
#include "core/String.hpp"
|
||||
|
||||
#include "audio/AudioTypes.hpp"
|
||||
#include "audio/Exception.hpp"
|
||||
|
||||
namespace lms::audio::ffmpeg
|
||||
@@ -71,83 +70,83 @@ namespace lms::audio::ffmpeg
|
||||
res[core::stringUtils::stringToUpper(tag->key)] = tag->value;
|
||||
}
|
||||
|
||||
std::optional<ContainerType> avdemuxerToContainerType(std::string_view name)
|
||||
std::optional<core::media::ContainerType> avdemuxerToContainerType(std::string_view name)
|
||||
{
|
||||
if (name == "aiff")
|
||||
return ContainerType::AIFF;
|
||||
return core::media::ContainerType::AIFF;
|
||||
if (name == "ape")
|
||||
return ContainerType::APE;
|
||||
return core::media::ContainerType::APE;
|
||||
if (name.starts_with("asf"))
|
||||
return ContainerType::ASF;
|
||||
return core::media::ContainerType::ASF;
|
||||
if (name == "dsf")
|
||||
return ContainerType::DSF;
|
||||
return core::media::ContainerType::DSF;
|
||||
if (name == "flac")
|
||||
return ContainerType::FLAC;
|
||||
return core::media::ContainerType::FLAC;
|
||||
if (name.find("mp4") != std::string_view::npos)
|
||||
return ContainerType::MP4;
|
||||
return core::media::ContainerType::MP4;
|
||||
if (name.starts_with("mpc"))
|
||||
return ContainerType::MPC;
|
||||
return core::media::ContainerType::MPC;
|
||||
if (name == "mp3")
|
||||
return ContainerType::MPEG;
|
||||
return core::media::ContainerType::MPEG;
|
||||
if (name == "ogg")
|
||||
return ContainerType::Ogg;
|
||||
return core::media::ContainerType::Ogg;
|
||||
if (name == "shn")
|
||||
return ContainerType::Shorten;
|
||||
return core::media::ContainerType::Shorten;
|
||||
if (name == "tta")
|
||||
return ContainerType::TrueAudio;
|
||||
return core::media::ContainerType::TrueAudio;
|
||||
if (name == "wav")
|
||||
return ContainerType::WAV;
|
||||
return core::media::ContainerType::WAV;
|
||||
if (name == "wv")
|
||||
return ContainerType::WavPack;
|
||||
return core::media::ContainerType::WavPack;
|
||||
|
||||
return std::nullopt;
|
||||
}
|
||||
|
||||
std::optional<CodecType> avcodecToCodecType(AVCodecID codec)
|
||||
std::optional<core::media::CodecType> avcodecToCodecType(AVCodecID codec)
|
||||
{
|
||||
switch (codec)
|
||||
{
|
||||
case AV_CODEC_ID_AAC:
|
||||
return CodecType::AAC;
|
||||
return core::media::CodecType::AAC;
|
||||
case AV_CODEC_ID_AC3:
|
||||
return CodecType::AC3;
|
||||
return core::media::CodecType::AC3;
|
||||
case AV_CODEC_ID_ALAC:
|
||||
return CodecType::ALAC;
|
||||
return core::media::CodecType::ALAC;
|
||||
case AV_CODEC_ID_APE:
|
||||
return CodecType::APE;
|
||||
return core::media::CodecType::APE;
|
||||
case AV_CODEC_ID_DSD_LSBF:
|
||||
case AV_CODEC_ID_DSD_LSBF_PLANAR:
|
||||
case AV_CODEC_ID_DSD_MSBF:
|
||||
case AV_CODEC_ID_DSD_MSBF_PLANAR:
|
||||
return CodecType::DSD;
|
||||
return core::media::CodecType::DSD;
|
||||
case AV_CODEC_ID_EAC3:
|
||||
return CodecType::EAC3;
|
||||
return core::media::CodecType::EAC3;
|
||||
case AV_CODEC_ID_FLAC:
|
||||
return CodecType::FLAC;
|
||||
return core::media::CodecType::FLAC;
|
||||
case AV_CODEC_ID_MP3:
|
||||
return CodecType::MP3;
|
||||
return core::media::CodecType::MP3;
|
||||
case AV_CODEC_ID_MP4ALS:
|
||||
return CodecType::MP4ALS;
|
||||
return core::media::CodecType::MP4ALS;
|
||||
case AV_CODEC_ID_MUSEPACK7:
|
||||
return CodecType::MPC7;
|
||||
return core::media::CodecType::MPC7;
|
||||
case AV_CODEC_ID_MUSEPACK8:
|
||||
return CodecType::MPC8;
|
||||
return core::media::CodecType::MPC8;
|
||||
case AV_CODEC_ID_OPUS:
|
||||
return CodecType::Opus;
|
||||
return core::media::CodecType::Opus;
|
||||
case AV_CODEC_ID_SHORTEN:
|
||||
return CodecType::Shorten;
|
||||
return core::media::CodecType::Shorten;
|
||||
case AV_CODEC_ID_VORBIS:
|
||||
return CodecType::Vorbis;
|
||||
return core::media::CodecType::Vorbis;
|
||||
case AV_CODEC_ID_WAVPACK:
|
||||
return CodecType::WavPack;
|
||||
return core::media::CodecType::WavPack;
|
||||
case AV_CODEC_ID_WMALOSSLESS:
|
||||
return CodecType::WMA9Lossless;
|
||||
return core::media::CodecType::WMA9Lossless;
|
||||
case AV_CODEC_ID_WMAPRO:
|
||||
return CodecType::WMA9Pro;
|
||||
return core::media::CodecType::WMA9Pro;
|
||||
case AV_CODEC_ID_WMAV1:
|
||||
return CodecType::WMA1;
|
||||
return core::media::CodecType::WMA1;
|
||||
case AV_CODEC_ID_WMAV2:
|
||||
return CodecType::WMA2;
|
||||
return core::media::CodecType::WMA2;
|
||||
|
||||
default:
|
||||
return std::nullopt;
|
||||
|
||||
@@ -27,7 +27,8 @@
|
||||
#include <string>
|
||||
#include <vector>
|
||||
|
||||
#include "audio/AudioTypes.hpp"
|
||||
#include "core/media/CodecType.hpp"
|
||||
#include "core/media/ContainerType.hpp"
|
||||
|
||||
extern "C"
|
||||
{
|
||||
@@ -44,7 +45,7 @@ namespace lms::audio::ffmpeg
|
||||
|
||||
struct ContainerInfo
|
||||
{
|
||||
std::optional<ContainerType> container;
|
||||
std::optional<core::media::ContainerType> container;
|
||||
std::string containerName;
|
||||
|
||||
std::optional<std::size_t> bitrate;
|
||||
@@ -54,7 +55,7 @@ namespace lms::audio::ffmpeg
|
||||
struct StreamInfo
|
||||
{
|
||||
size_t index{};
|
||||
std::optional<CodecType> codec;
|
||||
std::optional<core::media::CodecType> codec;
|
||||
std::string codecName;
|
||||
|
||||
std::optional<size_t> bitrate;
|
||||
|
||||
@@ -24,7 +24,7 @@
|
||||
|
||||
#include "core/ILogger.hpp"
|
||||
|
||||
#include "audio/AudioTypes.hpp"
|
||||
#include "audio/AudioProperties.hpp"
|
||||
#include "audio/IAudioFileInfo.hpp"
|
||||
|
||||
#include "AudioFile.hpp"
|
||||
|
||||
@@ -22,7 +22,7 @@
|
||||
#include <filesystem>
|
||||
#include <optional>
|
||||
|
||||
#include "audio/AudioTypes.hpp"
|
||||
#include "audio/AudioProperties.hpp"
|
||||
#include "audio/IAudioFileInfo.hpp"
|
||||
#include "audio/IAudioFileInfoParser.hpp"
|
||||
|
||||
|
||||
@@ -45,9 +45,9 @@ namespace lms::audio::ffmpeg
|
||||
image.data = picture.data;
|
||||
image.mimeType = picture.mimeType;
|
||||
if (metaDataHasKeyword(metaData, "front"))
|
||||
image.type = Image::Type::FrontCover;
|
||||
image.type = core::media::ImageType::FrontCover;
|
||||
else if (metaDataHasKeyword(metaData, "back"))
|
||||
image.type = Image::Type::BackCover;
|
||||
image.type = core::media::ImageType::BackCover;
|
||||
|
||||
visitor(image);
|
||||
});
|
||||
|
||||
@@ -19,13 +19,14 @@
|
||||
|
||||
#include "Transcoder.hpp"
|
||||
|
||||
#include <atomic>
|
||||
#include <filesystem>
|
||||
#include <iomanip>
|
||||
|
||||
#include "core/IChildProcessManager.hpp"
|
||||
#include "core/IConfig.hpp"
|
||||
#include "core/ILogger.hpp"
|
||||
#include "core/Service.hpp"
|
||||
#include "core/media/MimeType.hpp"
|
||||
|
||||
#include "audio/Exception.hpp"
|
||||
#include "audio/TranscodeTypes.hpp"
|
||||
@@ -42,18 +43,29 @@ namespace lms::audio::ffmpeg
|
||||
{
|
||||
#define LOG(severity, message) LMS_LOG(TRANSCODING, severity, "[" << _debugId << "] - " << message)
|
||||
|
||||
static std::atomic<size_t> globalId{};
|
||||
static std::filesystem::path ffmpegPath;
|
||||
|
||||
void Transcoder::init()
|
||||
namespace
|
||||
{
|
||||
ffmpegPath = core::Service<core::IConfig>::get()->getPath("ffmpeg-file", "/usr/bin/ffmpeg");
|
||||
if (!std::filesystem::exists(ffmpegPath))
|
||||
throw Exception{ "File '" + ffmpegPath.string() + "' does not exist!" };
|
||||
}
|
||||
class FFmpegPath
|
||||
{
|
||||
public:
|
||||
FFmpegPath()
|
||||
{
|
||||
path = core::Service<core::IConfig>::get()->getPath("ffmpeg-file", "/usr/bin/ffmpeg");
|
||||
if (!std::filesystem::exists(path))
|
||||
throw Exception{ "File '" + path.string() + "' does not exist!" };
|
||||
}
|
||||
|
||||
const std::filesystem::path& get() const { return path; }
|
||||
|
||||
private:
|
||||
std::filesystem::path path;
|
||||
};
|
||||
} // namespace
|
||||
|
||||
std::atomic<std::size_t> Transcoder::_nextDebugId;
|
||||
|
||||
Transcoder::Transcoder(const TranscodeParameters& parameters)
|
||||
: _debugId{ globalId++ }
|
||||
: _debugId{ _nextDebugId++ }
|
||||
, _inputParams{ parameters.inputParameters }
|
||||
, _outputParams{ parameters.outputParameters }
|
||||
{
|
||||
@@ -64,8 +76,7 @@ namespace lms::audio::ffmpeg
|
||||
|
||||
void Transcoder::start()
|
||||
{
|
||||
if (ffmpegPath.empty())
|
||||
init();
|
||||
static FFmpegPath ffmpegPath;
|
||||
|
||||
try
|
||||
{
|
||||
@@ -76,15 +87,16 @@ namespace lms::audio::ffmpeg
|
||||
}
|
||||
catch (const std::filesystem::filesystem_error& e)
|
||||
{
|
||||
// TODO store/raise e.code()
|
||||
throw Exception{ "File error '" + _inputParams.filePath.string() + "': " + e.what() };
|
||||
throw IOFileException{ _inputParams.filePath, "Failed to test file existence", e.code() };
|
||||
}
|
||||
|
||||
LOG(INFO, "Transcoding file " << _inputParams.filePath);
|
||||
|
||||
std::vector<std::string> args;
|
||||
|
||||
args.emplace_back(ffmpegPath.string());
|
||||
args.emplace_back(ffmpegPath.get().string());
|
||||
|
||||
// TODO some codecs have restrictions, take them into account (channel count, sample rate, etc.)
|
||||
|
||||
// Make sure:
|
||||
// - we do not produce anything in the stderr output
|
||||
@@ -114,7 +126,7 @@ namespace lms::audio::ffmpeg
|
||||
args.emplace_back("-1");
|
||||
}
|
||||
|
||||
// Skip video flows (including covers)
|
||||
// Skip video flows (including covers!)
|
||||
args.emplace_back("-vn");
|
||||
|
||||
// Output bitrates
|
||||
@@ -124,63 +136,68 @@ namespace lms::audio::ffmpeg
|
||||
args.emplace_back(std::to_string(*_outputParams.bitrate));
|
||||
}
|
||||
|
||||
// Codecs and formats
|
||||
if (_outputParams.format)
|
||||
{
|
||||
switch (*_outputParams.format)
|
||||
args.emplace_back("-f");
|
||||
|
||||
switch (_outputParams.format->container)
|
||||
{
|
||||
case OutputFormat::MP3:
|
||||
args.emplace_back("-f");
|
||||
case core::media::ContainerType::FLAC:
|
||||
args.emplace_back("flac");
|
||||
break;
|
||||
case core::media::ContainerType::Ogg:
|
||||
args.emplace_back("ogg");
|
||||
break;
|
||||
case core::media::ContainerType::MPEG:
|
||||
args.emplace_back("mp3");
|
||||
break;
|
||||
|
||||
case OutputFormat::OGG_OPUS:
|
||||
args.emplace_back("-acodec");
|
||||
default:
|
||||
throw Exception{ "Unsupported container type " + std::string{ core::media::containerTypeToString(_outputParams.format->container).str() } };
|
||||
}
|
||||
|
||||
args.emplace_back("-acodec");
|
||||
|
||||
switch (_outputParams.format->codec)
|
||||
{
|
||||
case core::media::CodecType::MP3:
|
||||
args.emplace_back("libmp3lame");
|
||||
break;
|
||||
|
||||
case core::media::CodecType::Opus:
|
||||
args.emplace_back("libopus");
|
||||
args.emplace_back("-f");
|
||||
args.emplace_back("ogg");
|
||||
break;
|
||||
|
||||
case OutputFormat::MATROSKA_OPUS:
|
||||
args.emplace_back("-acodec");
|
||||
args.emplace_back("libopus");
|
||||
args.emplace_back("-f");
|
||||
args.emplace_back("matroska");
|
||||
break;
|
||||
|
||||
case OutputFormat::OGG_VORBIS:
|
||||
args.emplace_back("-acodec");
|
||||
case core::media::CodecType::Vorbis:
|
||||
args.emplace_back("libvorbis");
|
||||
args.emplace_back("-f");
|
||||
args.emplace_back("ogg");
|
||||
break;
|
||||
|
||||
case OutputFormat::WEBM_VORBIS:
|
||||
args.emplace_back("-acodec");
|
||||
args.emplace_back("libvorbis");
|
||||
args.emplace_back("-f");
|
||||
args.emplace_back("webm");
|
||||
case core::media::CodecType::FLAC:
|
||||
args.emplace_back("flac");
|
||||
break;
|
||||
|
||||
default:
|
||||
throw Exception{ "Unhandled format (" + std::to_string(static_cast<int>(*_outputParams.format)) + ")" };
|
||||
throw Exception{ "Unhandled codec type " + std::string{ codecTypeToString(_outputParams.format->codec).str() } };
|
||||
}
|
||||
}
|
||||
|
||||
args.emplace_back("pipe:1");
|
||||
|
||||
LOG(DEBUG, "Dumping args (" << args.size() << ")");
|
||||
for (const std::string& arg : args)
|
||||
LOG(DEBUG, "Arg = '" << arg << "'");
|
||||
if (core::Service<core::logging::ILogger>::get()->isSeverityActive(core::logging::Severity::DEBUG))
|
||||
{
|
||||
LOG(DEBUG, "Dumping args (" << args.size() << ")");
|
||||
for (const std::string& arg : args)
|
||||
LOG(DEBUG, "Arg = '" << arg << "'");
|
||||
}
|
||||
|
||||
// Caution: stdin must have been closed before
|
||||
try
|
||||
{
|
||||
_childProcess = core::Service<core::IChildProcessManager>::get()->spawnChildProcess(ffmpegPath, args);
|
||||
_childProcess = core::Service<core::IChildProcessManager>::get()->spawnChildProcess(ffmpegPath.get(), args);
|
||||
}
|
||||
catch (core::ChildProcessException& exception)
|
||||
{
|
||||
throw Exception{ "Cannot execute '" + ffmpegPath.string() + "': " + exception.what() };
|
||||
throw Exception{ "Cannot execute '" + ffmpegPath.get().string() + "': " + exception.what() };
|
||||
}
|
||||
}
|
||||
|
||||
@@ -202,25 +219,10 @@ namespace lms::audio::ffmpeg
|
||||
|
||||
std::string_view Transcoder::getOutputMimeType() const
|
||||
{
|
||||
// TODO: use input mime type
|
||||
if (_outputParams.format)
|
||||
{
|
||||
switch (*_outputParams.format)
|
||||
{
|
||||
case OutputFormat::MP3:
|
||||
return "audio/mpeg";
|
||||
case OutputFormat::OGG_OPUS:
|
||||
return "audio/opus";
|
||||
case OutputFormat::MATROSKA_OPUS:
|
||||
return "audio/x-matroska";
|
||||
case OutputFormat::OGG_VORBIS:
|
||||
return "audio/ogg";
|
||||
case OutputFormat::WEBM_VORBIS:
|
||||
return "audio/webm";
|
||||
}
|
||||
}
|
||||
return core::media::getMimeType(_outputParams.format->container, _outputParams.format->codec).str();
|
||||
|
||||
return "application/octet-stream"; // default, should not happen
|
||||
return core::media::getMimeType(_inputParams.audioProperties.container, _inputParams.audioProperties.codec).str();
|
||||
}
|
||||
|
||||
bool Transcoder::finished() const
|
||||
|
||||
@@ -19,6 +19,8 @@
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <atomic>
|
||||
|
||||
#include "audio/ITranscoder.hpp"
|
||||
|
||||
namespace lms::core
|
||||
@@ -47,7 +49,8 @@ namespace lms::audio::ffmpeg
|
||||
static void init();
|
||||
void start();
|
||||
|
||||
const std::size_t _debugId{};
|
||||
static std::atomic<std::size_t> _nextDebugId;
|
||||
const std::size_t _debugId;
|
||||
const TranscodeInputParameters _inputParams;
|
||||
const TranscodeOutputParameters _outputParams;
|
||||
std::unique_ptr<core::IChildProcess> _childProcess;
|
||||
|
||||
@@ -45,7 +45,7 @@
|
||||
|
||||
#include "core/ILogger.hpp"
|
||||
|
||||
#include "audio/AudioTypes.hpp"
|
||||
#include "audio/AudioProperties.hpp"
|
||||
#include "audio/IAudioFileInfo.hpp"
|
||||
#include "audio/IAudioFileInfoParser.hpp"
|
||||
|
||||
@@ -104,27 +104,27 @@ namespace lms::audio::taglib
|
||||
// Guess container from the file type
|
||||
if (const auto* apeFile{ dynamic_cast<const ::TagLib::APE::File*>(&file) })
|
||||
{
|
||||
audioProperties.container = ContainerType::APE;
|
||||
audioProperties.codec = CodecType::APE; // TODO version?
|
||||
audioProperties.container = core::media::ContainerType::APE;
|
||||
audioProperties.codec = core::media::CodecType::APE; // TODO version?
|
||||
audioProperties.bitsPerSample = apeFile->audioProperties()->bitsPerSample();
|
||||
}
|
||||
else if (const auto* asfFile{ dynamic_cast<const ::TagLib::ASF::File*>(&file) })
|
||||
{
|
||||
audioProperties.container = ContainerType::ASF;
|
||||
audioProperties.container = core::media::ContainerType::ASF;
|
||||
|
||||
switch (asfFile->audioProperties()->codec())
|
||||
{
|
||||
case ::TagLib::ASF::Properties::Codec::WMA1:
|
||||
audioProperties.codec = CodecType::WMA1;
|
||||
audioProperties.codec = core::media::CodecType::WMA1;
|
||||
break;
|
||||
case ::TagLib::ASF::Properties::Codec::WMA2:
|
||||
audioProperties.codec = CodecType::WMA2;
|
||||
audioProperties.codec = core::media::CodecType::WMA2;
|
||||
break;
|
||||
case ::TagLib::ASF::Properties::Codec::WMA9Lossless:
|
||||
audioProperties.codec = CodecType::WMA9Lossless;
|
||||
audioProperties.codec = core::media::CodecType::WMA9Lossless;
|
||||
break;
|
||||
case ::TagLib::ASF::Properties::Codec::WMA9Pro:
|
||||
audioProperties.codec = CodecType::WMA9Pro;
|
||||
audioProperties.codec = core::media::CodecType::WMA9Pro;
|
||||
break;
|
||||
case ::TagLib::ASF::Properties::Codec::Unknown:
|
||||
LMS_LOG(AUDIO, DEBUG, "Unhandled ASF codec in " << filePath);
|
||||
@@ -136,27 +136,27 @@ namespace lms::audio::taglib
|
||||
#if LMS_TAGLIB_HAS_DSF
|
||||
else if (const auto* dsfFile{ dynamic_cast<const ::TagLib::DSF::File*>(&file) })
|
||||
{
|
||||
audioProperties.container = ContainerType::DSF;
|
||||
audioProperties.codec = CodecType::DSD;
|
||||
audioProperties.container = core::media::ContainerType::DSF;
|
||||
audioProperties.codec = core::media::CodecType::DSD;
|
||||
audioProperties.bitsPerSample = dsfFile->audioProperties()->bitsPerSample();
|
||||
}
|
||||
#endif // LMS_TAGLIB_HAS_DSF
|
||||
else if (const auto* flacFile{ dynamic_cast<const ::TagLib::FLAC::File*>(&file) })
|
||||
{
|
||||
audioProperties.container = ContainerType::FLAC;
|
||||
audioProperties.codec = CodecType::FLAC;
|
||||
audioProperties.container = core::media::ContainerType::FLAC;
|
||||
audioProperties.codec = core::media::CodecType::FLAC;
|
||||
audioProperties.bitsPerSample = flacFile->audioProperties()->bitsPerSample();
|
||||
}
|
||||
else if (const auto* mp4File{ dynamic_cast<const ::TagLib::MP4::File*>(&file) })
|
||||
{
|
||||
audioProperties.container = ContainerType::MP4;
|
||||
audioProperties.container = core::media::ContainerType::MP4;
|
||||
switch (mp4File->audioProperties()->codec())
|
||||
{
|
||||
case ::TagLib::MP4::Properties::Codec::AAC:
|
||||
audioProperties.codec = CodecType::AAC;
|
||||
audioProperties.codec = core::media::CodecType::AAC;
|
||||
break;
|
||||
case ::TagLib::MP4::Properties::Codec::ALAC:
|
||||
audioProperties.codec = CodecType::ALAC;
|
||||
audioProperties.codec = core::media::CodecType::ALAC;
|
||||
break;
|
||||
case ::TagLib::MP4::Properties::Codec::Unknown:
|
||||
LMS_LOG(AUDIO, DEBUG, "Unhandled MP4 codec in " << filePath);
|
||||
@@ -167,15 +167,15 @@ namespace lms::audio::taglib
|
||||
}
|
||||
else if (const auto* mpcFile{ dynamic_cast<const ::TagLib::MPC::File*>(&file) })
|
||||
{
|
||||
audioProperties.container = ContainerType::MPC;
|
||||
audioProperties.container = core::media::ContainerType::MPC;
|
||||
|
||||
switch (mpcFile->audioProperties()->mpcVersion())
|
||||
{
|
||||
case 7:
|
||||
audioProperties.codec = CodecType::MPC7;
|
||||
audioProperties.codec = core::media::CodecType::MPC7;
|
||||
break;
|
||||
case 8:
|
||||
audioProperties.codec = CodecType::MPC8;
|
||||
audioProperties.codec = core::media::CodecType::MPC8;
|
||||
break;
|
||||
default:
|
||||
LMS_LOG(AUDIO, DEBUG, "Unhandled MPC codec version " << mpcFile->audioProperties()->mpcVersion() << " in " << filePath);
|
||||
@@ -186,13 +186,13 @@ namespace lms::audio::taglib
|
||||
{
|
||||
const auto& properties{ *mpegFile->audioProperties() };
|
||||
|
||||
audioProperties.container = ContainerType::MPEG;
|
||||
audioProperties.container = core::media::ContainerType::MPEG;
|
||||
if ((properties.version() == TagLib::MPEG::Header::Version::Version1 || properties.version() == TagLib::MPEG::Header::Version::Version2 || properties.version() == TagLib::MPEG::Header::Version::Version2_5)
|
||||
&& mpegFile->audioProperties()->layer() == 3)
|
||||
audioProperties.codec = CodecType::MP3; // could be MPEG-1 layer 3 or MPEG-2(.5) layer 3
|
||||
audioProperties.codec = core::media::CodecType::MP3; // could be MPEG-1 layer 3 or MPEG-2(.5) layer 3
|
||||
#if LMS_TAGLIB_HAS_ADTS
|
||||
else if (mpegFile->audioProperties()->isADTS()) // likely AAC
|
||||
audioProperties.codec = CodecType::AAC;
|
||||
audioProperties.codec = core::media::CodecType::AAC;
|
||||
#endif
|
||||
else
|
||||
{
|
||||
@@ -202,44 +202,44 @@ namespace lms::audio::taglib
|
||||
}
|
||||
else if (dynamic_cast<const ::TagLib::Ogg::Opus::File*>(&file))
|
||||
{
|
||||
audioProperties.container = ContainerType::Ogg;
|
||||
audioProperties.codec = CodecType::Opus;
|
||||
audioProperties.container = core::media::ContainerType::Ogg;
|
||||
audioProperties.codec = core::media::CodecType::Opus;
|
||||
}
|
||||
else if (dynamic_cast<const ::TagLib::Ogg::Vorbis::File*>(&file))
|
||||
{
|
||||
audioProperties.container = ContainerType::Ogg;
|
||||
audioProperties.codec = CodecType::Vorbis;
|
||||
audioProperties.container = core::media::ContainerType::Ogg;
|
||||
audioProperties.codec = core::media::CodecType::Vorbis;
|
||||
}
|
||||
else if (const auto* aiffFile{ dynamic_cast<const ::TagLib::RIFF::AIFF::File*>(&file) })
|
||||
{
|
||||
audioProperties.container = ContainerType::AIFF;
|
||||
audioProperties.codec = CodecType::PCM;
|
||||
audioProperties.container = core::media::ContainerType::AIFF;
|
||||
audioProperties.codec = core::media::CodecType::PCM;
|
||||
audioProperties.bitsPerSample = aiffFile->audioProperties()->bitsPerSample();
|
||||
}
|
||||
else if (const auto* wavFile{ dynamic_cast<const ::TagLib::RIFF::WAV::File*>(&file) })
|
||||
{
|
||||
audioProperties.container = ContainerType::WAV;
|
||||
audioProperties.codec = CodecType::PCM;
|
||||
audioProperties.container = core::media::ContainerType::WAV;
|
||||
audioProperties.codec = core::media::CodecType::PCM;
|
||||
audioProperties.bitsPerSample = wavFile->audioProperties()->bitsPerSample();
|
||||
}
|
||||
#if LMS_TAGLIB_HAS_SHORTEN
|
||||
else if (const auto* shortenFile{ dynamic_cast<const ::TagLib::Shorten::File*>(&file) })
|
||||
{
|
||||
audioProperties.container = ContainerType::Shorten;
|
||||
audioProperties.codec = CodecType::Shorten;
|
||||
audioProperties.container = core::media::ContainerType::Shorten;
|
||||
audioProperties.codec = core::media::CodecType::Shorten;
|
||||
audioProperties.bitsPerSample = shortenFile->audioProperties()->bitsPerSample();
|
||||
}
|
||||
#endif // LMS_TAGLIB_HAS_SHORTEN
|
||||
else if (const auto* trueAudioFile{ dynamic_cast<const ::TagLib::TrueAudio::File*>(&file) })
|
||||
{
|
||||
audioProperties.container = ContainerType::TrueAudio;
|
||||
audioProperties.codec = CodecType::TrueAudio;
|
||||
audioProperties.container = core::media::ContainerType::TrueAudio;
|
||||
audioProperties.codec = core::media::CodecType::TrueAudio;
|
||||
audioProperties.bitsPerSample = trueAudioFile->audioProperties()->bitsPerSample();
|
||||
}
|
||||
else if (const auto* wavPackFile{ dynamic_cast<const ::TagLib::WavPack::File*>(&file) })
|
||||
{
|
||||
audioProperties.container = ContainerType::WavPack;
|
||||
audioProperties.codec = CodecType::WavPack;
|
||||
audioProperties.container = core::media::ContainerType::WavPack;
|
||||
audioProperties.codec = core::media::CodecType::WavPack;
|
||||
audioProperties.bitsPerSample = wavPackFile->audioProperties()->bitsPerSample();
|
||||
}
|
||||
else
|
||||
|
||||
@@ -22,7 +22,7 @@
|
||||
#include <filesystem>
|
||||
#include <optional>
|
||||
|
||||
#include "audio/AudioTypes.hpp"
|
||||
#include "audio/AudioProperties.hpp"
|
||||
#include "audio/IAudioFileInfo.hpp"
|
||||
#include "audio/IAudioFileInfoParser.hpp"
|
||||
#include "audio/IImageReader.hpp"
|
||||
|
||||
@@ -44,157 +44,157 @@ namespace lms::audio::taglib
|
||||
{
|
||||
namespace
|
||||
{
|
||||
Image::Type imageTypeFromfromID3v2(TagLib::ID3v2::AttachedPictureFrame::Type type)
|
||||
core::media::ImageType imageTypeFromfromID3v2(TagLib::ID3v2::AttachedPictureFrame::Type type)
|
||||
{
|
||||
switch (type)
|
||||
{
|
||||
case ::TagLib::ID3v2::AttachedPictureFrame::Type::Other:
|
||||
return Image::Type::Other;
|
||||
return core::media::ImageType::Other;
|
||||
case ::TagLib::ID3v2::AttachedPictureFrame::Type::FileIcon:
|
||||
return Image::Type::FileIcon;
|
||||
return core::media::ImageType::FileIcon;
|
||||
case ::TagLib::ID3v2::AttachedPictureFrame::Type::OtherFileIcon:
|
||||
return Image::Type::OtherFileIcon;
|
||||
return core::media::ImageType::OtherFileIcon;
|
||||
case ::TagLib::ID3v2::AttachedPictureFrame::Type::FrontCover:
|
||||
return Image::Type::FrontCover;
|
||||
return core::media::ImageType::FrontCover;
|
||||
case ::TagLib::ID3v2::AttachedPictureFrame::Type::BackCover:
|
||||
return Image::Type::BackCover;
|
||||
return core::media::ImageType::BackCover;
|
||||
case ::TagLib::ID3v2::AttachedPictureFrame::Type::LeafletPage:
|
||||
return Image::Type::LeafletPage;
|
||||
return core::media::ImageType::LeafletPage;
|
||||
case ::TagLib::ID3v2::AttachedPictureFrame::Type::Media:
|
||||
return Image::Type::Media;
|
||||
return core::media::ImageType::Media;
|
||||
case ::TagLib::ID3v2::AttachedPictureFrame::Type::LeadArtist:
|
||||
return Image::Type::LeadArtist;
|
||||
return core::media::ImageType::LeadArtist;
|
||||
case ::TagLib::ID3v2::AttachedPictureFrame::Type::Artist:
|
||||
return Image::Type::Artist;
|
||||
return core::media::ImageType::Artist;
|
||||
case ::TagLib::ID3v2::AttachedPictureFrame::Type::Conductor:
|
||||
return Image::Type::Conductor;
|
||||
return core::media::ImageType::Conductor;
|
||||
case ::TagLib::ID3v2::AttachedPictureFrame::Type::Band:
|
||||
return Image::Type::Band;
|
||||
return core::media::ImageType::Band;
|
||||
case ::TagLib::ID3v2::AttachedPictureFrame::Type::Composer:
|
||||
return Image::Type::Composer;
|
||||
return core::media::ImageType::Composer;
|
||||
case ::TagLib::ID3v2::AttachedPictureFrame::Type::Lyricist:
|
||||
return Image::Type::Lyricist;
|
||||
return core::media::ImageType::Lyricist;
|
||||
case ::TagLib::ID3v2::AttachedPictureFrame::Type::RecordingLocation:
|
||||
return Image::Type::RecordingLocation;
|
||||
return core::media::ImageType::RecordingLocation;
|
||||
case ::TagLib::ID3v2::AttachedPictureFrame::Type::DuringRecording:
|
||||
return Image::Type::DuringRecording;
|
||||
return core::media::ImageType::DuringRecording;
|
||||
case ::TagLib::ID3v2::AttachedPictureFrame::Type::DuringPerformance:
|
||||
return Image::Type::DuringPerformance;
|
||||
return core::media::ImageType::DuringPerformance;
|
||||
case ::TagLib::ID3v2::AttachedPictureFrame::Type::MovieScreenCapture:
|
||||
return Image::Type::MovieScreenCapture;
|
||||
return core::media::ImageType::MovieScreenCapture;
|
||||
case ::TagLib::ID3v2::AttachedPictureFrame::Type::ColouredFish:
|
||||
return Image::Type::ColouredFish;
|
||||
return core::media::ImageType::ColouredFish;
|
||||
case ::TagLib::ID3v2::AttachedPictureFrame::Type::Illustration:
|
||||
return Image::Type::Illustration;
|
||||
return core::media::ImageType::Illustration;
|
||||
case ::TagLib::ID3v2::AttachedPictureFrame::Type::BandLogo:
|
||||
return Image::Type::BandLogo;
|
||||
return core::media::ImageType::BandLogo;
|
||||
case ::TagLib::ID3v2::AttachedPictureFrame::Type::PublisherLogo:
|
||||
return Image::Type::PublisherLogo;
|
||||
return core::media::ImageType::PublisherLogo;
|
||||
}
|
||||
|
||||
return Image::Type::Unknown;
|
||||
return core::media::ImageType::Unknown;
|
||||
}
|
||||
|
||||
Image::Type imageTypeFromfromASF(TagLib::ASF::Picture::Type type)
|
||||
core::media::ImageType imageTypeFromfromASF(TagLib::ASF::Picture::Type type)
|
||||
{
|
||||
switch (type)
|
||||
{
|
||||
case ::TagLib::ASF::Picture::Type::Other:
|
||||
return Image::Type::Other;
|
||||
return core::media::ImageType::Other;
|
||||
case ::TagLib::ASF::Picture::Type::FileIcon:
|
||||
return Image::Type::FileIcon;
|
||||
return core::media::ImageType::FileIcon;
|
||||
case ::TagLib::ASF::Picture::Type::OtherFileIcon:
|
||||
return Image::Type::OtherFileIcon;
|
||||
return core::media::ImageType::OtherFileIcon;
|
||||
case ::TagLib::ASF::Picture::Type::FrontCover:
|
||||
return Image::Type::FrontCover;
|
||||
return core::media::ImageType::FrontCover;
|
||||
case ::TagLib::ASF::Picture::Type::BackCover:
|
||||
return Image::Type::BackCover;
|
||||
return core::media::ImageType::BackCover;
|
||||
case ::TagLib::ASF::Picture::Type::LeafletPage:
|
||||
return Image::Type::LeafletPage;
|
||||
return core::media::ImageType::LeafletPage;
|
||||
case ::TagLib::ASF::Picture::Type::Media:
|
||||
return Image::Type::Media;
|
||||
return core::media::ImageType::Media;
|
||||
case ::TagLib::ASF::Picture::Type::LeadArtist:
|
||||
return Image::Type::LeadArtist;
|
||||
return core::media::ImageType::LeadArtist;
|
||||
case ::TagLib::ASF::Picture::Type::Artist:
|
||||
return Image::Type::Artist;
|
||||
return core::media::ImageType::Artist;
|
||||
case ::TagLib::ASF::Picture::Type::Conductor:
|
||||
return Image::Type::Conductor;
|
||||
return core::media::ImageType::Conductor;
|
||||
case ::TagLib::ASF::Picture::Type::Band:
|
||||
return Image::Type::Band;
|
||||
return core::media::ImageType::Band;
|
||||
case ::TagLib::ASF::Picture::Type::Composer:
|
||||
return Image::Type::Composer;
|
||||
return core::media::ImageType::Composer;
|
||||
case ::TagLib::ASF::Picture::Type::Lyricist:
|
||||
return Image::Type::Lyricist;
|
||||
return core::media::ImageType::Lyricist;
|
||||
case ::TagLib::ASF::Picture::Type::RecordingLocation:
|
||||
return Image::Type::RecordingLocation;
|
||||
return core::media::ImageType::RecordingLocation;
|
||||
case ::TagLib::ASF::Picture::Type::DuringRecording:
|
||||
return Image::Type::DuringRecording;
|
||||
return core::media::ImageType::DuringRecording;
|
||||
case ::TagLib::ASF::Picture::Type::DuringPerformance:
|
||||
return Image::Type::DuringPerformance;
|
||||
return core::media::ImageType::DuringPerformance;
|
||||
case ::TagLib::ASF::Picture::Type::MovieScreenCapture:
|
||||
return Image::Type::MovieScreenCapture;
|
||||
return core::media::ImageType::MovieScreenCapture;
|
||||
case ::TagLib::ASF::Picture::Type::ColouredFish:
|
||||
return Image::Type::ColouredFish;
|
||||
return core::media::ImageType::ColouredFish;
|
||||
case ::TagLib::ASF::Picture::Type::Illustration:
|
||||
return Image::Type::Illustration;
|
||||
return core::media::ImageType::Illustration;
|
||||
case ::TagLib::ASF::Picture::Type::BandLogo:
|
||||
return Image::Type::BandLogo;
|
||||
return core::media::ImageType::BandLogo;
|
||||
case ::TagLib::ASF::Picture::Type::PublisherLogo:
|
||||
return Image::Type::PublisherLogo;
|
||||
return core::media::ImageType::PublisherLogo;
|
||||
}
|
||||
|
||||
return Image::Type::Unknown;
|
||||
return core::media::ImageType::Unknown;
|
||||
}
|
||||
|
||||
Image::Type imageTypeFromfromFLAC(TagLib::FLAC::Picture::Type type)
|
||||
core::media::ImageType imageTypeFromfromFLAC(TagLib::FLAC::Picture::Type type)
|
||||
{
|
||||
switch (type)
|
||||
{
|
||||
case ::TagLib::FLAC::Picture::Type::Other:
|
||||
return Image::Type::Other;
|
||||
return core::media::ImageType::Other;
|
||||
case ::TagLib::FLAC::Picture::Type::FileIcon:
|
||||
return Image::Type::FileIcon;
|
||||
return core::media::ImageType::FileIcon;
|
||||
case ::TagLib::FLAC::Picture::Type::OtherFileIcon:
|
||||
return Image::Type::OtherFileIcon;
|
||||
return core::media::ImageType::OtherFileIcon;
|
||||
case ::TagLib::FLAC::Picture::Type::FrontCover:
|
||||
return Image::Type::FrontCover;
|
||||
return core::media::ImageType::FrontCover;
|
||||
case ::TagLib::FLAC::Picture::Type::BackCover:
|
||||
return Image::Type::BackCover;
|
||||
return core::media::ImageType::BackCover;
|
||||
case ::TagLib::FLAC::Picture::Type::LeafletPage:
|
||||
return Image::Type::LeafletPage;
|
||||
return core::media::ImageType::LeafletPage;
|
||||
case ::TagLib::FLAC::Picture::Type::Media:
|
||||
return Image::Type::Media;
|
||||
return core::media::ImageType::Media;
|
||||
case ::TagLib::FLAC::Picture::Type::LeadArtist:
|
||||
return Image::Type::LeadArtist;
|
||||
return core::media::ImageType::LeadArtist;
|
||||
case ::TagLib::FLAC::Picture::Type::Artist:
|
||||
return Image::Type::Artist;
|
||||
return core::media::ImageType::Artist;
|
||||
case ::TagLib::FLAC::Picture::Type::Conductor:
|
||||
return Image::Type::Conductor;
|
||||
return core::media::ImageType::Conductor;
|
||||
case ::TagLib::FLAC::Picture::Type::Band:
|
||||
return Image::Type::Band;
|
||||
return core::media::ImageType::Band;
|
||||
case ::TagLib::FLAC::Picture::Type::Composer:
|
||||
return Image::Type::Composer;
|
||||
return core::media::ImageType::Composer;
|
||||
case ::TagLib::FLAC::Picture::Type::Lyricist:
|
||||
return Image::Type::Lyricist;
|
||||
return core::media::ImageType::Lyricist;
|
||||
case ::TagLib::FLAC::Picture::Type::RecordingLocation:
|
||||
return Image::Type::RecordingLocation;
|
||||
return core::media::ImageType::RecordingLocation;
|
||||
case ::TagLib::FLAC::Picture::Type::DuringRecording:
|
||||
return Image::Type::DuringRecording;
|
||||
return core::media::ImageType::DuringRecording;
|
||||
case ::TagLib::FLAC::Picture::Type::DuringPerformance:
|
||||
return Image::Type::DuringPerformance;
|
||||
return core::media::ImageType::DuringPerformance;
|
||||
case ::TagLib::FLAC::Picture::Type::MovieScreenCapture:
|
||||
return Image::Type::MovieScreenCapture;
|
||||
return core::media::ImageType::MovieScreenCapture;
|
||||
case ::TagLib::FLAC::Picture::Type::ColouredFish:
|
||||
return Image::Type::ColouredFish;
|
||||
return core::media::ImageType::ColouredFish;
|
||||
case ::TagLib::FLAC::Picture::Type::Illustration:
|
||||
return Image::Type::Illustration;
|
||||
return core::media::ImageType::Illustration;
|
||||
case ::TagLib::FLAC::Picture::Type::BandLogo:
|
||||
return Image::Type::BandLogo;
|
||||
return core::media::ImageType::BandLogo;
|
||||
case ::TagLib::FLAC::Picture::Type::PublisherLogo:
|
||||
return Image::Type::PublisherLogo;
|
||||
return core::media::ImageType::PublisherLogo;
|
||||
}
|
||||
|
||||
return Image::Type::Unknown;
|
||||
return core::media::ImageType::Unknown;
|
||||
}
|
||||
|
||||
const char* mp4ImageFormatToMimeType(TagLib::MP4::CoverArt::Format format)
|
||||
@@ -217,14 +217,14 @@ namespace lms::audio::taglib
|
||||
}
|
||||
|
||||
#if LMS_TAGLIB_HAS_APE_COMPLEX_PROPERTIES
|
||||
Image::Type imageTypeFromAPEPictureType(std::string_view pictureType)
|
||||
core::media::ImageType imageTypeFromAPEPictureType(std::string_view pictureType)
|
||||
{
|
||||
if (core::stringUtils::stringCaseInsensitiveContains(pictureType, "front"))
|
||||
return Image::Type::FrontCover;
|
||||
return core::media::ImageType::FrontCover;
|
||||
if (core::stringUtils::stringCaseInsensitiveContains(pictureType, "back"))
|
||||
return Image::Type::BackCover;
|
||||
return core::media::ImageType::BackCover;
|
||||
|
||||
return Image::Type::Unknown;
|
||||
return core::media::ImageType::Unknown;
|
||||
}
|
||||
#endif // LMS_TAGLIB_HAS_APE_COMPLEX_PROPERTIES
|
||||
|
||||
@@ -294,7 +294,7 @@ namespace lms::audio::taglib
|
||||
image.data = pictureData;
|
||||
|
||||
// By convention, consider the first cover art as the front cover
|
||||
image.type = firstCover ? Image::Type::FrontCover : Image::Type::Unknown;
|
||||
image.type = firstCover ? core::media::ImageType::FrontCover : core::media::ImageType::Unknown;
|
||||
firstCover = false;
|
||||
|
||||
visitor(image);
|
||||
|
||||
@@ -111,7 +111,7 @@ namespace lms::audio::taglib::utils
|
||||
{
|
||||
const std::error_code ec{ errno, std::generic_category() };
|
||||
LMS_LOG(METADATA, DEBUG, "fopen failed for " << p << ": " << ec.message());
|
||||
throw IOFileException{ "fopen failed", ec };
|
||||
throw IOFileException{ p, "fopen failed", ec };
|
||||
}
|
||||
|
||||
int fd{ ::fileno(file) };
|
||||
@@ -119,7 +119,7 @@ namespace lms::audio::taglib::utils
|
||||
{
|
||||
const std::error_code ec{ errno, std::generic_category() };
|
||||
LMS_LOG(METADATA, DEBUG, "fileno failed for " << p << ": " << ec.message());
|
||||
throw IOFileException{ "fileno failed", ec };
|
||||
throw IOFileException{ p, "fileno failed", ec };
|
||||
}
|
||||
|
||||
return TagLib::FileStream{ fd, true };
|
||||
|
||||
Reference in New Issue
Block a user