Minor cleanup on audio codecs

This commit is contained in:
emeric
2025-12-07 22:40:45 +01:00
parent 66e4f9ef92
commit 6d27f18f19
38 changed files with 521 additions and 553 deletions
+34 -34
View File
@@ -70,83 +70,83 @@ namespace lms::audio::ffmpeg
res[core::stringUtils::stringToUpper(tag->key)] = tag->value; res[core::stringUtils::stringToUpper(tag->key)] = tag->value;
} }
std::optional<core::media::ContainerType> avdemuxerToContainerType(std::string_view name) std::optional<core::media::Container> avdemuxerToContainerType(std::string_view name)
{ {
if (name == "aiff") if (name == "aiff")
return core::media::ContainerType::AIFF; return core::media::Container::AIFF;
if (name == "ape") if (name == "ape")
return core::media::ContainerType::APE; return core::media::Container::APE;
if (name.starts_with("asf")) if (name.starts_with("asf"))
return core::media::ContainerType::ASF; return core::media::Container::ASF;
if (name == "dsf") if (name == "dsf")
return core::media::ContainerType::DSF; return core::media::Container::DSF;
if (name == "flac") if (name == "flac")
return core::media::ContainerType::FLAC; return core::media::Container::FLAC;
if (name.find("mp4") != std::string_view::npos) if (name.find("mp4") != std::string_view::npos)
return core::media::ContainerType::MP4; return core::media::Container::MP4;
if (name.starts_with("mpc")) if (name.starts_with("mpc"))
return core::media::ContainerType::MPC; return core::media::Container::MPC;
if (name == "mp3") if (name == "mp3")
return core::media::ContainerType::MPEG; return core::media::Container::MPEG;
if (name == "ogg") if (name == "ogg")
return core::media::ContainerType::Ogg; return core::media::Container::Ogg;
if (name == "shn") if (name == "shn")
return core::media::ContainerType::Shorten; return core::media::Container::Shorten;
if (name == "tta") if (name == "tta")
return core::media::ContainerType::TrueAudio; return core::media::Container::TrueAudio;
if (name == "wav") if (name == "wav")
return core::media::ContainerType::WAV; return core::media::Container::WAV;
if (name == "wv") if (name == "wv")
return core::media::ContainerType::WavPack; return core::media::Container::WavPack;
return std::nullopt; return std::nullopt;
} }
std::optional<core::media::CodecType> avcodecToCodecType(AVCodecID codec) std::optional<core::media::Codec> avcodecToCodecType(AVCodecID codec)
{ {
switch (codec) switch (codec)
{ {
case AV_CODEC_ID_AAC: case AV_CODEC_ID_AAC:
return core::media::CodecType::AAC; return core::media::Codec::AAC;
case AV_CODEC_ID_AC3: case AV_CODEC_ID_AC3:
return core::media::CodecType::AC3; return core::media::Codec::AC3;
case AV_CODEC_ID_ALAC: case AV_CODEC_ID_ALAC:
return core::media::CodecType::ALAC; return core::media::Codec::ALAC;
case AV_CODEC_ID_APE: case AV_CODEC_ID_APE:
return core::media::CodecType::APE; return core::media::Codec::APE;
case AV_CODEC_ID_DSD_LSBF: case AV_CODEC_ID_DSD_LSBF:
case AV_CODEC_ID_DSD_LSBF_PLANAR: case AV_CODEC_ID_DSD_LSBF_PLANAR:
case AV_CODEC_ID_DSD_MSBF: case AV_CODEC_ID_DSD_MSBF:
case AV_CODEC_ID_DSD_MSBF_PLANAR: case AV_CODEC_ID_DSD_MSBF_PLANAR:
return core::media::CodecType::DSD; return core::media::Codec::DSD;
case AV_CODEC_ID_EAC3: case AV_CODEC_ID_EAC3:
return core::media::CodecType::EAC3; return core::media::Codec::EAC3;
case AV_CODEC_ID_FLAC: case AV_CODEC_ID_FLAC:
return core::media::CodecType::FLAC; return core::media::Codec::FLAC;
case AV_CODEC_ID_MP3: case AV_CODEC_ID_MP3:
return core::media::CodecType::MP3; return core::media::Codec::MP3;
case AV_CODEC_ID_MP4ALS: case AV_CODEC_ID_MP4ALS:
return core::media::CodecType::MP4ALS; return core::media::Codec::MP4ALS;
case AV_CODEC_ID_MUSEPACK7: case AV_CODEC_ID_MUSEPACK7:
return core::media::CodecType::MPC7; return core::media::Codec::MPC7;
case AV_CODEC_ID_MUSEPACK8: case AV_CODEC_ID_MUSEPACK8:
return core::media::CodecType::MPC8; return core::media::Codec::MPC8;
case AV_CODEC_ID_OPUS: case AV_CODEC_ID_OPUS:
return core::media::CodecType::Opus; return core::media::Codec::Opus;
case AV_CODEC_ID_SHORTEN: case AV_CODEC_ID_SHORTEN:
return core::media::CodecType::Shorten; return core::media::Codec::Shorten;
case AV_CODEC_ID_VORBIS: case AV_CODEC_ID_VORBIS:
return core::media::CodecType::Vorbis; return core::media::Codec::Vorbis;
case AV_CODEC_ID_WAVPACK: case AV_CODEC_ID_WAVPACK:
return core::media::CodecType::WavPack; return core::media::Codec::WavPack;
case AV_CODEC_ID_WMALOSSLESS: case AV_CODEC_ID_WMALOSSLESS:
return core::media::CodecType::WMA9Lossless; return core::media::Codec::WMA9Lossless;
case AV_CODEC_ID_WMAPRO: case AV_CODEC_ID_WMAPRO:
return core::media::CodecType::WMA9Pro; return core::media::Codec::WMA9Pro;
case AV_CODEC_ID_WMAV1: case AV_CODEC_ID_WMAV1:
return core::media::CodecType::WMA1; return core::media::Codec::WMA1;
case AV_CODEC_ID_WMAV2: case AV_CODEC_ID_WMAV2:
return core::media::CodecType::WMA2; return core::media::Codec::WMA2;
default: default:
return std::nullopt; return std::nullopt;
+4 -4
View File
@@ -27,8 +27,8 @@
#include <string> #include <string>
#include <vector> #include <vector>
#include "core/media/CodecType.hpp" #include "core/media/Codec.hpp"
#include "core/media/ContainerType.hpp" #include "core/media/Container.hpp"
extern "C" extern "C"
{ {
@@ -45,7 +45,7 @@ namespace lms::audio::ffmpeg
struct ContainerInfo struct ContainerInfo
{ {
std::optional<core::media::ContainerType> container; std::optional<core::media::Container> container;
std::string containerName; std::string containerName;
std::optional<std::size_t> bitrate; std::optional<std::size_t> bitrate;
@@ -55,7 +55,7 @@ namespace lms::audio::ffmpeg
struct StreamInfo struct StreamInfo
{ {
size_t index{}; size_t index{};
std::optional<core::media::CodecType> codec; std::optional<core::media::Codec> codec;
std::string codecName; std::string codecName;
std::optional<size_t> bitrate; std::optional<size_t> bitrate;
+9 -9
View File
@@ -161,42 +161,42 @@ namespace lms::audio::ffmpeg
switch (_outputParams.format->container) switch (_outputParams.format->container)
{ {
case core::media::ContainerType::FLAC: case core::media::Container::FLAC:
args.emplace_back("flac"); args.emplace_back("flac");
break; break;
case core::media::ContainerType::Ogg: case core::media::Container::Ogg:
args.emplace_back("ogg"); args.emplace_back("ogg");
break; break;
case core::media::ContainerType::MPEG: case core::media::Container::MPEG:
args.emplace_back("mp3"); args.emplace_back("mp3");
break; break;
default: default:
throw Exception{ "Unsupported container type " + std::string{ core::media::containerTypeToString(_outputParams.format->container).str() } }; throw Exception{ "Unsupported container type " + std::string{ core::media::containerToString(_outputParams.format->container).str() } };
} }
args.emplace_back("-acodec"); args.emplace_back("-acodec");
switch (_outputParams.format->codec) switch (_outputParams.format->codec)
{ {
case core::media::CodecType::MP3: case core::media::Codec::MP3:
args.emplace_back("libmp3lame"); args.emplace_back("libmp3lame");
break; break;
case core::media::CodecType::Opus: case core::media::Codec::Opus:
args.emplace_back("libopus"); args.emplace_back("libopus");
break; break;
case core::media::CodecType::Vorbis: case core::media::Codec::Vorbis:
args.emplace_back("libvorbis"); args.emplace_back("libvorbis");
break; break;
case core::media::CodecType::FLAC: case core::media::Codec::FLAC:
args.emplace_back("flac"); args.emplace_back("flac");
break; break;
default: default:
throw Exception{ "Unhandled codec type " + std::string{ codecTypeToString(_outputParams.format->codec).str() } }; throw Exception{ "Unhandled codec type " + std::string{ core::media::getCodecDesc(_outputParams.format->codec).name.str() } };
} }
} }
+34 -34
View File
@@ -104,27 +104,27 @@ namespace lms::audio::taglib
// Guess container from the file type // Guess container from the file type
if (const auto* apeFile{ dynamic_cast<const ::TagLib::APE::File*>(&file) }) if (const auto* apeFile{ dynamic_cast<const ::TagLib::APE::File*>(&file) })
{ {
audioProperties.container = core::media::ContainerType::APE; audioProperties.container = core::media::Container::APE;
audioProperties.codec = core::media::CodecType::APE; // TODO version? audioProperties.codec = core::media::Codec::APE; // TODO version?
audioProperties.bitsPerSample = apeFile->audioProperties()->bitsPerSample(); audioProperties.bitsPerSample = apeFile->audioProperties()->bitsPerSample();
} }
else if (const auto* asfFile{ dynamic_cast<const ::TagLib::ASF::File*>(&file) }) else if (const auto* asfFile{ dynamic_cast<const ::TagLib::ASF::File*>(&file) })
{ {
audioProperties.container = core::media::ContainerType::ASF; audioProperties.container = core::media::Container::ASF;
switch (asfFile->audioProperties()->codec()) switch (asfFile->audioProperties()->codec())
{ {
case ::TagLib::ASF::Properties::Codec::WMA1: case ::TagLib::ASF::Properties::Codec::WMA1:
audioProperties.codec = core::media::CodecType::WMA1; audioProperties.codec = core::media::Codec::WMA1;
break; break;
case ::TagLib::ASF::Properties::Codec::WMA2: case ::TagLib::ASF::Properties::Codec::WMA2:
audioProperties.codec = core::media::CodecType::WMA2; audioProperties.codec = core::media::Codec::WMA2;
break; break;
case ::TagLib::ASF::Properties::Codec::WMA9Lossless: case ::TagLib::ASF::Properties::Codec::WMA9Lossless:
audioProperties.codec = core::media::CodecType::WMA9Lossless; audioProperties.codec = core::media::Codec::WMA9Lossless;
break; break;
case ::TagLib::ASF::Properties::Codec::WMA9Pro: case ::TagLib::ASF::Properties::Codec::WMA9Pro:
audioProperties.codec = core::media::CodecType::WMA9Pro; audioProperties.codec = core::media::Codec::WMA9Pro;
break; break;
case ::TagLib::ASF::Properties::Codec::Unknown: case ::TagLib::ASF::Properties::Codec::Unknown:
LMS_LOG(AUDIO, DEBUG, "Unhandled ASF codec in " << filePath); LMS_LOG(AUDIO, DEBUG, "Unhandled ASF codec in " << filePath);
@@ -136,27 +136,27 @@ namespace lms::audio::taglib
#if LMS_TAGLIB_HAS_DSF #if LMS_TAGLIB_HAS_DSF
else if (const auto* dsfFile{ dynamic_cast<const ::TagLib::DSF::File*>(&file) }) else if (const auto* dsfFile{ dynamic_cast<const ::TagLib::DSF::File*>(&file) })
{ {
audioProperties.container = core::media::ContainerType::DSF; audioProperties.container = core::media::Container::DSF;
audioProperties.codec = core::media::CodecType::DSD; audioProperties.codec = core::media::Codec::DSD;
audioProperties.bitsPerSample = dsfFile->audioProperties()->bitsPerSample(); audioProperties.bitsPerSample = dsfFile->audioProperties()->bitsPerSample();
} }
#endif // LMS_TAGLIB_HAS_DSF #endif // LMS_TAGLIB_HAS_DSF
else if (const auto* flacFile{ dynamic_cast<const ::TagLib::FLAC::File*>(&file) }) else if (const auto* flacFile{ dynamic_cast<const ::TagLib::FLAC::File*>(&file) })
{ {
audioProperties.container = core::media::ContainerType::FLAC; audioProperties.container = core::media::Container::FLAC;
audioProperties.codec = core::media::CodecType::FLAC; audioProperties.codec = core::media::Codec::FLAC;
audioProperties.bitsPerSample = flacFile->audioProperties()->bitsPerSample(); audioProperties.bitsPerSample = flacFile->audioProperties()->bitsPerSample();
} }
else if (const auto* mp4File{ dynamic_cast<const ::TagLib::MP4::File*>(&file) }) else if (const auto* mp4File{ dynamic_cast<const ::TagLib::MP4::File*>(&file) })
{ {
audioProperties.container = core::media::ContainerType::MP4; audioProperties.container = core::media::Container::MP4;
switch (mp4File->audioProperties()->codec()) switch (mp4File->audioProperties()->codec())
{ {
case ::TagLib::MP4::Properties::Codec::AAC: case ::TagLib::MP4::Properties::Codec::AAC:
audioProperties.codec = core::media::CodecType::AAC; audioProperties.codec = core::media::Codec::AAC;
break; break;
case ::TagLib::MP4::Properties::Codec::ALAC: case ::TagLib::MP4::Properties::Codec::ALAC:
audioProperties.codec = core::media::CodecType::ALAC; audioProperties.codec = core::media::Codec::ALAC;
break; break;
case ::TagLib::MP4::Properties::Codec::Unknown: case ::TagLib::MP4::Properties::Codec::Unknown:
LMS_LOG(AUDIO, DEBUG, "Unhandled MP4 codec in " << filePath); 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) }) else if (const auto* mpcFile{ dynamic_cast<const ::TagLib::MPC::File*>(&file) })
{ {
audioProperties.container = core::media::ContainerType::MPC; audioProperties.container = core::media::Container::MPC;
switch (mpcFile->audioProperties()->mpcVersion()) switch (mpcFile->audioProperties()->mpcVersion())
{ {
case 7: case 7:
audioProperties.codec = core::media::CodecType::MPC7; audioProperties.codec = core::media::Codec::MPC7;
break; break;
case 8: case 8:
audioProperties.codec = core::media::CodecType::MPC8; audioProperties.codec = core::media::Codec::MPC8;
break; break;
default: default:
LMS_LOG(AUDIO, DEBUG, "Unhandled MPC codec version " << mpcFile->audioProperties()->mpcVersion() << " in " << filePath); 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() }; const auto& properties{ *mpegFile->audioProperties() };
audioProperties.container = core::media::ContainerType::MPEG; audioProperties.container = core::media::Container::MPEG;
if ((properties.version() == TagLib::MPEG::Header::Version::Version1 || properties.version() == TagLib::MPEG::Header::Version::Version2 || properties.version() == TagLib::MPEG::Header::Version::Version2_5) 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) && mpegFile->audioProperties()->layer() == 3)
audioProperties.codec = core::media::CodecType::MP3; // could be MPEG-1 layer 3 or MPEG-2(.5) layer 3 audioProperties.codec = core::media::Codec::MP3; // could be MPEG-1 layer 3 or MPEG-2(.5) layer 3
#if LMS_TAGLIB_HAS_ADTS #if LMS_TAGLIB_HAS_ADTS
else if (mpegFile->audioProperties()->isADTS()) // likely AAC else if (mpegFile->audioProperties()->isADTS()) // likely AAC
audioProperties.codec = core::media::CodecType::AAC; audioProperties.codec = core::media::Codec::AAC;
#endif #endif
else else
{ {
@@ -202,44 +202,44 @@ namespace lms::audio::taglib
} }
else if (dynamic_cast<const ::TagLib::Ogg::Opus::File*>(&file)) else if (dynamic_cast<const ::TagLib::Ogg::Opus::File*>(&file))
{ {
audioProperties.container = core::media::ContainerType::Ogg; audioProperties.container = core::media::Container::Ogg;
audioProperties.codec = core::media::CodecType::Opus; audioProperties.codec = core::media::Codec::Opus;
} }
else if (dynamic_cast<const ::TagLib::Ogg::Vorbis::File*>(&file)) else if (dynamic_cast<const ::TagLib::Ogg::Vorbis::File*>(&file))
{ {
audioProperties.container = core::media::ContainerType::Ogg; audioProperties.container = core::media::Container::Ogg;
audioProperties.codec = core::media::CodecType::Vorbis; audioProperties.codec = core::media::Codec::Vorbis;
} }
else if (const auto* aiffFile{ dynamic_cast<const ::TagLib::RIFF::AIFF::File*>(&file) }) else if (const auto* aiffFile{ dynamic_cast<const ::TagLib::RIFF::AIFF::File*>(&file) })
{ {
audioProperties.container = core::media::ContainerType::AIFF; audioProperties.container = core::media::Container::AIFF;
audioProperties.codec = core::media::CodecType::PCM; audioProperties.codec = core::media::Codec::PCM;
audioProperties.bitsPerSample = aiffFile->audioProperties()->bitsPerSample(); audioProperties.bitsPerSample = aiffFile->audioProperties()->bitsPerSample();
} }
else if (const auto* wavFile{ dynamic_cast<const ::TagLib::RIFF::WAV::File*>(&file) }) else if (const auto* wavFile{ dynamic_cast<const ::TagLib::RIFF::WAV::File*>(&file) })
{ {
audioProperties.container = core::media::ContainerType::WAV; audioProperties.container = core::media::Container::WAV;
audioProperties.codec = core::media::CodecType::PCM; audioProperties.codec = core::media::Codec::PCM;
audioProperties.bitsPerSample = wavFile->audioProperties()->bitsPerSample(); audioProperties.bitsPerSample = wavFile->audioProperties()->bitsPerSample();
} }
#if LMS_TAGLIB_HAS_SHORTEN #if LMS_TAGLIB_HAS_SHORTEN
else if (const auto* shortenFile{ dynamic_cast<const ::TagLib::Shorten::File*>(&file) }) else if (const auto* shortenFile{ dynamic_cast<const ::TagLib::Shorten::File*>(&file) })
{ {
audioProperties.container = core::media::ContainerType::Shorten; audioProperties.container = core::media::Container::Shorten;
audioProperties.codec = core::media::CodecType::Shorten; audioProperties.codec = core::media::Codec::Shorten;
audioProperties.bitsPerSample = shortenFile->audioProperties()->bitsPerSample(); audioProperties.bitsPerSample = shortenFile->audioProperties()->bitsPerSample();
} }
#endif // LMS_TAGLIB_HAS_SHORTEN #endif // LMS_TAGLIB_HAS_SHORTEN
else if (const auto* trueAudioFile{ dynamic_cast<const ::TagLib::TrueAudio::File*>(&file) }) else if (const auto* trueAudioFile{ dynamic_cast<const ::TagLib::TrueAudio::File*>(&file) })
{ {
audioProperties.container = core::media::ContainerType::TrueAudio; audioProperties.container = core::media::Container::TrueAudio;
audioProperties.codec = core::media::CodecType::TrueAudio; audioProperties.codec = core::media::Codec::TrueAudio;
audioProperties.bitsPerSample = trueAudioFile->audioProperties()->bitsPerSample(); audioProperties.bitsPerSample = trueAudioFile->audioProperties()->bitsPerSample();
} }
else if (const auto* wavPackFile{ dynamic_cast<const ::TagLib::WavPack::File*>(&file) }) else if (const auto* wavPackFile{ dynamic_cast<const ::TagLib::WavPack::File*>(&file) })
{ {
audioProperties.container = core::media::ContainerType::WavPack; audioProperties.container = core::media::Container::WavPack;
audioProperties.codec = core::media::CodecType::WavPack; audioProperties.codec = core::media::Codec::WavPack;
audioProperties.bitsPerSample = wavPackFile->audioProperties()->bitsPerSample(); audioProperties.bitsPerSample = wavPackFile->audioProperties()->bitsPerSample();
} }
else else
@@ -22,15 +22,15 @@
#include <chrono> #include <chrono>
#include <optional> #include <optional>
#include "core/media/CodecType.hpp" #include "core/media/Codec.hpp"
#include "core/media/ContainerType.hpp" #include "core/media/Container.hpp"
namespace lms::audio namespace lms::audio
{ {
struct AudioProperties struct AudioProperties
{ {
core::media::ContainerType container; core::media::Container container;
core::media::CodecType codec; core::media::Codec codec;
std::chrono::milliseconds duration; std::chrono::milliseconds duration;
unsigned bitrate; unsigned bitrate;
unsigned channelCount; unsigned channelCount;
@@ -23,8 +23,8 @@
#include <filesystem> #include <filesystem>
#include <optional> #include <optional>
#include "core/media/CodecType.hpp" #include "core/media/Codec.hpp"
#include "core/media/ContainerType.hpp" #include "core/media/Container.hpp"
#include "audio/AudioProperties.hpp" #include "audio/AudioProperties.hpp"
@@ -39,8 +39,8 @@ namespace lms::audio
struct TranscodeOutputFormat struct TranscodeOutputFormat
{ {
core::media::ContainerType container; core::media::Container container;
core::media::CodecType codec; core::media::Codec codec;
}; };
struct TranscodeOutputParameters struct TranscodeOutputParameters
+2 -2
View File
@@ -13,8 +13,8 @@ configure_file(
add_library(lmscore STATIC add_library(lmscore STATIC
impl/http/Client.cpp impl/http/Client.cpp
impl/http/SendQueue.cpp impl/http/SendQueue.cpp
impl/media/CodecType.cpp impl/media/Codec.cpp
impl/media/ContainerType.cpp impl/media/Container.cpp
impl/media/ImageType.cpp impl/media/ImageType.cpp
impl/media/MimeType.cpp impl/media/MimeType.cpp
impl/ArchiveZipper.cpp impl/ArchiveZipper.cpp
+68
View File
@@ -0,0 +1,68 @@
/*
* 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 "core/media/Codec.hpp"
#include "core/Exception.hpp"
#include <algorithm>
#include <array>
namespace lms::core::media
{
namespace
{
constexpr std::array codecDescs{
CodecDesc{ Codec::AAC, "AAC", "Advanced Audio Coding", false },
CodecDesc{ Codec::AC3, "AC3", "Dolby AC-3", false },
CodecDesc{ Codec::ALAC, "ALAC", "Apple Lossless Audio Codec", true },
CodecDesc{ Codec::APE, "APE", "Monkey's Audio", true },
CodecDesc{ Codec::DSD, "DSD", "Direct Stream Digital", true },
CodecDesc{ Codec::EAC3, "E-AC3", "Dolby Digital Plus", false },
CodecDesc{ Codec::FLAC, "FLAC", "Free Lossless Audio Codec", true },
CodecDesc{ Codec::MP3, "MP3", "MPEG-3", false },
CodecDesc{ Codec::MP4ALS, "MP4ALS", "MPEG-4 Audio Lossless Coding", true },
CodecDesc{ Codec::MPC7, "MPC7", "Musepack7", false },
CodecDesc{ Codec::MPC8, "MPC8", "Musepack8", false },
CodecDesc{ Codec::Opus, "Opus", "Opus", false },
CodecDesc{ Codec::PCM, "PCM", "Pulse-code modulation", false },
CodecDesc{ Codec::Shorten, "Shorten", "Shorten", true },
CodecDesc{ Codec::TrueAudio, "TTA", "The True Audio", true },
CodecDesc{ Codec::Vorbis, "Vorbis", "Vorbis", false },
CodecDesc{ Codec::WavPack, "WavPack", "WavPack", true },
CodecDesc{ Codec::WMA1, "WMA1", "Windows Media Audio", false },
CodecDesc{ Codec::WMA2, "WMA2", "Windows Media Audio 2", false },
CodecDesc{ Codec::WMA9Pro, "WMA9Pro", "Windows Media Audio Professional", false },
CodecDesc{ Codec::WMA9Lossless, "WMA9Lossless", "Windows Media Audio Lossless", true },
};
} // namespace
void visitCodecs(const std::function<void(const CodecDesc&)>& visitor)
{
std::for_each(std::cbegin(codecDescs), std::cend(codecDescs), visitor);
}
const CodecDesc& getCodecDesc(Codec type)
{
const auto it{ std::find_if(codecDescs.begin(), codecDescs.end(), [type](const auto& desc) { return desc.type == type; }) };
if (it == codecDescs.end()) [[unlikely]]
throw LmsException{ "Unknown codec type" };
return *it;
}
} // namespace lms::core::media
-108
View File
@@ -1,108 +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 "core/media/CodecType.hpp"
namespace lms::core::media
{
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 "Unknown";
}
bool isCodecLossless(CodecType type)
{
switch (type)
{
case CodecType::ALAC:
case CodecType::APE:
case CodecType::DSD:
case CodecType::FLAC:
case CodecType::MP4ALS:
case CodecType::PCM:
case CodecType::Shorten:
case CodecType::TrueAudio:
case CodecType::WavPack:
case CodecType::WMA9Lossless:
return true;
case CodecType::AAC:
case CodecType::AC3:
case CodecType::EAC3:
case CodecType::MP3:
case CodecType::MPC7:
case CodecType::MPC8:
case CodecType::Opus:
case CodecType::Vorbis:
case CodecType::WMA1:
case CodecType::WMA2:
case CodecType::WMA9Pro:
return false;
}
return false;
}
} // namespace lms::core::media
@@ -17,39 +17,39 @@
* along with LMS. If not, see <http://www.gnu.org/licenses/>. * along with LMS. If not, see <http://www.gnu.org/licenses/>.
*/ */
#include "core/media/ContainerType.hpp" #include "core/media/Container.hpp"
namespace lms::core::media namespace lms::core::media
{ {
core::LiteralString containerTypeToString(ContainerType type) core::LiteralString containerToString(Container type)
{ {
switch (type) switch (type)
{ {
case ContainerType::AIFF: case Container::AIFF:
return "AIFF"; return "AIFF";
case ContainerType::APE: case Container::APE:
return "APE"; return "APE";
case ContainerType::ASF: case Container::ASF:
return "ASF"; return "ASF";
case ContainerType::DSF: case Container::DSF:
return "DSF"; return "DSF";
case ContainerType::FLAC: case Container::FLAC:
return "FLAC"; return "FLAC";
case ContainerType::MP4: case Container::MP4:
return "MP4"; return "MP4";
case ContainerType::MPC: case Container::MPC:
return "MPC"; return "MPC";
case ContainerType::MPEG: case Container::MPEG:
return "MPEG"; return "MPEG";
case ContainerType::Ogg: case Container::Ogg:
return "Ogg"; return "Ogg";
case ContainerType::Shorten: case Container::Shorten:
return "Shorten"; return "Shorten";
case ContainerType::TrueAudio: case Container::TrueAudio:
return "TrueAudio"; return "TrueAudio";
case ContainerType::WAV: case Container::WAV:
return "WAV"; return "WAV";
case ContainerType::WavPack: case Container::WavPack:
return "WavPack"; return "WavPack";
} }
+20 -20
View File
@@ -21,57 +21,57 @@
namespace lms::core::media namespace lms::core::media
{ {
core::LiteralString getMimeType(ContainerType container, CodecType codec) core::LiteralString getMimeType(Container container, Codec codec)
{ {
switch (container) switch (container)
{ {
case ContainerType::AIFF: case Container::AIFF:
return "audio/x-aiff"; return "audio/x-aiff";
case ContainerType::APE: case Container::APE:
return "audio/x-monkeys-audio"; return "audio/x-monkeys-audio";
case ContainerType::ASF: case Container::ASF:
return "audio/x-ms-wma"; return "audio/x-ms-wma";
case ContainerType::DSF: case Container::DSF:
return "audio/x-dsd-dsf"; return "audio/x-dsd-dsf";
case ContainerType::FLAC: case Container::FLAC:
return "audio/flac"; return "audio/flac";
case ContainerType::MP4: case Container::MP4:
switch (codec) switch (codec)
{ {
case CodecType::AAC: case Codec::AAC:
return "audio/mp4; codecs=\"mp4a.40.2\""; return "audio/mp4; codecs=\"mp4a.40.2\"";
case CodecType::ALAC: case Codec::ALAC:
return "audio/mp4; codecs=\"alac\""; return "audio/mp4; codecs=\"alac\"";
case CodecType::MP4ALS: case Codec::MP4ALS:
return "audio/mp4; codecs=\"mp4als\""; return "audio/mp4; codecs=\"mp4als\"";
default: default:
return "audio/mp4"; return "audio/mp4";
} }
case ContainerType::MPC: case Container::MPC:
return "audio/x-musepack"; return "audio/x-musepack";
case ContainerType::MPEG: case Container::MPEG:
return "audio/mpeg"; return "audio/mpeg";
case ContainerType::Ogg: case Container::Ogg:
switch (codec) switch (codec)
{ {
case CodecType::Opus: case Codec::Opus:
return "audio/opus"; return "audio/opus";
case CodecType::Vorbis: case Codec::Vorbis:
return "audio/ogg; codecs=\"vorbis\""; return "audio/ogg; codecs=\"vorbis\"";
case CodecType::FLAC: case Codec::FLAC:
return "audio/ogg; codecs=\"flac\""; return "audio/ogg; codecs=\"flac\"";
default: default:
return "audio/ogg"; return "audio/ogg";
} }
case ContainerType::Shorten: case Container::Shorten:
return "audio/x-shn"; return "audio/x-shn";
case ContainerType::TrueAudio: case Container::TrueAudio:
return "audio/x-tta"; return "audio/x-tta";
case ContainerType::WAV: case Container::WAV:
return "audio/wav"; return "audio/wav";
case ContainerType::WavPack: case Container::WavPack:
return "audio/x-wavpack"; return "audio/x-wavpack";
} }
@@ -19,11 +19,13 @@
#pragma once #pragma once
#include <functional>
#include "core/LiteralString.hpp" #include "core/LiteralString.hpp"
namespace lms::core::media namespace lms::core::media
{ {
enum class CodecType enum class Codec
{ {
AAC, AAC,
AC3, AC3,
@@ -48,7 +50,13 @@ namespace lms::core::media
WMA9Lossless, WMA9Lossless,
}; };
core::LiteralString codecTypeToString(CodecType type); struct CodecDesc
{
bool isCodecLossless(CodecType type); Codec type;
core::LiteralString name;
core::LiteralString longName;
bool isLossless;
};
void visitCodecs(const std::function<void(const CodecDesc&)>& visitor);
const CodecDesc& getCodecDesc(Codec type);
} // namespace lms::core::media } // namespace lms::core::media
@@ -23,7 +23,7 @@
namespace lms::core::media namespace lms::core::media
{ {
enum class ContainerType enum class Container
{ {
AIFF, AIFF,
APE, // Monkey's Audio APE, // Monkey's Audio
@@ -40,5 +40,5 @@ namespace lms::core::media
WavPack, WavPack,
}; };
core::LiteralString containerTypeToString(ContainerType type); core::LiteralString containerToString(Container type);
} // namespace lms::core::media } // namespace lms::core::media
@@ -20,10 +20,10 @@
#pragma once #pragma once
#include "core/LiteralString.hpp" #include "core/LiteralString.hpp"
#include "core/media/CodecType.hpp" #include "core/media/Codec.hpp"
#include "core/media/ContainerType.hpp" #include "core/media/Container.hpp"
namespace lms::core::media namespace lms::core::media
{ {
core::LiteralString getMimeType(ContainerType container, CodecType codec); core::LiteralString getMimeType(Container container, Codec codec);
} }
+1 -1
View File
@@ -83,7 +83,7 @@ namespace lms::db
query.where("t.release_id = ?").bind(params.release); query.where("t.release_id = ?").bind(params.release);
if (params.filters.codec.has_value()) if (params.filters.codec.has_value())
query.where("t.codec = ?").bind(detail::getDbCodecType(*params.filters.codec)); query.where("t.codec = ?").bind(detail::getDbCodec(*params.filters.codec));
if (params.filters.mediaLibrary.isValid()) if (params.filters.mediaLibrary.isValid())
query.where("t.media_library_id = ?").bind(params.filters.mediaLibrary); query.where("t.media_library_id = ?").bind(params.filters.mediaLibrary);
+1 -1
View File
@@ -57,7 +57,7 @@ namespace lms::db
query.join("track t ON t.id = t_a_l.track_id"); query.join("track t ON t.id = t_a_l.track_id");
if (params.filters.codec.has_value()) if (params.filters.codec.has_value())
query.where("t.codec = ?").bind(detail::getDbCodecType(*params.filters.codec)); query.where("t.codec = ?").bind(detail::getDbCodec(*params.filters.codec));
if (params.filters.mediaLibrary.isValid()) if (params.filters.mediaLibrary.isValid())
query.where("t.media_library_id = ?").bind(params.filters.mediaLibrary); query.where("t.media_library_id = ?").bind(params.filters.mediaLibrary);
@@ -99,12 +99,12 @@ namespace lms::db
utils::forEachQueryRangeResult(query, params.range, func); utils::forEachQueryRangeResult(query, params.range, func);
} }
std::optional<core::media::ContainerType> PodcastEpisode::getContainer() const std::optional<core::media::Container> PodcastEpisode::getContainer() const
{ {
return detail::getMediaContainerType(_container); return detail::getMediaContainerType(_container);
} }
std::optional<core::media::CodecType> PodcastEpisode::getCodec() const std::optional<core::media::Codec> PodcastEpisode::getCodec() const
{ {
return detail::getMediaCodecType(_codec); return detail::getMediaCodecType(_codec);
} }
@@ -119,14 +119,14 @@ namespace lms::db
return _artwork.id(); return _artwork.id();
} }
void PodcastEpisode::setContainer(core::media::ContainerType container) void PodcastEpisode::setContainer(core::media::Container container)
{ {
_container = detail::getDbContainerType(container); _container = detail::getDbContainer(container);
} }
void PodcastEpisode::setCodec(core::media::CodecType codec) void PodcastEpisode::setCodec(core::media::Codec codec)
{ {
_codec = detail::getDbCodecType(codec); _codec = detail::getDbCodec(codec);
} }
void PodcastEpisode::setArtwork(ObjectPtr<Artwork> artwork) void PodcastEpisode::setArtwork(ObjectPtr<Artwork> artwork)
+5 -5
View File
@@ -220,7 +220,7 @@ namespace lms::db
} }
if (params.filters.codec.has_value()) if (params.filters.codec.has_value())
query.where("t.codec = ?").bind(detail::getDbCodecType(params.filters.codec.value())); query.where("t.codec = ?").bind(detail::getDbCodec(params.filters.codec.value()));
if (params.releaseGroupMBID) if (params.releaseGroupMBID)
query.where("group_mbid = ?").bind(params.releaseGroupMBID->getAsString()); query.where("group_mbid = ?").bind(params.releaseGroupMBID->getAsString());
@@ -684,15 +684,15 @@ namespace lms::db
return utils::fetchQuerySingleResult(session()->query<int>("SELECT COALESCE(AVG(t.bitrate), 0) FROM track t").where("release_id = ?").bind(getId()).where("bitrate > 0")); return utils::fetchQuerySingleResult(session()->query<int>("SELECT COALESCE(AVG(t.bitrate), 0) FROM track t").where("release_id = ?").bind(getId()).where("bitrate > 0"));
} }
std::vector<core::media::CodecType> Release::getCodecs() const std::vector<core::media::Codec> Release::getCodecs() const
{ {
assert(session()); assert(session());
// Get the codec ordered by frequency // Get the codec ordered by frequency
auto query{ session()->query<detail::CodecType>("SELECT t.codec FROM track t").where("release_id = ?").bind(getId()).groupBy("t.codec").orderBy("COUNT(t.id) DESC") }; auto query{ session()->query<detail::Codec>("SELECT t.codec FROM track t").where("release_id = ?").bind(getId()).groupBy("t.codec").orderBy("COUNT(t.id) DESC") };
std::vector<core::media::CodecType> res; std::vector<core::media::Codec> res;
utils::forEachQueryResult(query, [&](detail::CodecType codec) { utils::forEachQueryResult(query, [&](detail::Codec codec) {
if (const auto mediaCodecType{ detail::getMediaCodecType(codec) }) if (const auto mediaCodecType{ detail::getMediaCodecType(codec) })
res.push_back(*mediaCodecType); res.push_back(*mediaCodecType);
}); });
+7 -7
View File
@@ -198,7 +198,7 @@ namespace lms::db
} }
if (params.filters.codec.has_value()) if (params.filters.codec.has_value())
query.where("t.codec = ?").bind(detail::getDbCodecType(*params.filters.codec)); query.where("t.codec = ?").bind(detail::getDbCodec(*params.filters.codec));
switch (params.sortMethod) switch (params.sortMethod)
{ {
@@ -528,14 +528,14 @@ namespace lms::db
_absoluteFilePath = filePath; _absoluteFilePath = filePath;
} }
void Track::setContainer(core::media::ContainerType container) void Track::setContainer(core::media::Container container)
{ {
_container = detail::getDbContainerType(container); _container = detail::getDbContainer(container);
} }
void Track::setCodec(core::media::CodecType codec) void Track::setCodec(core::media::Codec codec)
{ {
_codec = detail::getDbCodecType(codec); _codec = detail::getDbCodec(codec);
} }
void Track::setName(std::string_view name) void Track::setName(std::string_view name)
@@ -618,12 +618,12 @@ namespace lms::db
_preferredMediaArtwork = getDboPtr(artwork); _preferredMediaArtwork = getDboPtr(artwork);
} }
std::optional<core::media::ContainerType> Track::getContainer() const std::optional<core::media::Container> Track::getContainer() const
{ {
return detail::getMediaContainerType(_container); return detail::getMediaContainerType(_container);
} }
std::optional<core::media::CodecType> Track::getCodec() const std::optional<core::media::Codec> Track::getCodec() const
{ {
return detail::getMediaCodecType(_codec); return detail::getMediaCodecType(_codec);
} }
+1 -1
View File
@@ -70,7 +70,7 @@ namespace lms::db
query.join("track t ON t.id = t_l_e.track_id"); query.join("track t ON t.id = t_l_e.track_id");
if (params.filters.codec.has_value()) if (params.filters.codec.has_value())
query.where("t.codec = ?").bind(detail::getDbCodecType(*params.filters.codec)); query.where("t.codec = ?").bind(detail::getDbCodec(*params.filters.codec));
if (params.filters.mediaLibrary.isValid()) if (params.filters.mediaLibrary.isValid())
query.where("t.media_library_id = ?").bind(params.filters.mediaLibrary); query.where("t.media_library_id = ?").bind(params.filters.mediaLibrary);
+144 -144
View File
@@ -21,182 +21,182 @@
namespace lms::db::detail namespace lms::db::detail
{ {
std::optional<core::media::ContainerType> getMediaContainerType(db::detail::ContainerType container) std::optional<core::media::Container> getMediaContainerType(db::detail::Container container)
{ {
switch (container) switch (container)
{ {
case ContainerType::AIFF: case Container::AIFF:
return core::media::ContainerType::AIFF; return core::media::Container::AIFF;
case ContainerType::APE: case Container::APE:
return core::media::ContainerType::APE; return core::media::Container::APE;
case ContainerType::ASF: case Container::ASF:
return core::media::ContainerType::ASF; return core::media::Container::ASF;
case ContainerType::DSF: case Container::DSF:
return core::media::ContainerType::DSF; return core::media::Container::DSF;
case ContainerType::FLAC: case Container::FLAC:
return core::media::ContainerType::FLAC; return core::media::Container::FLAC;
case ContainerType::MP4: case Container::MP4:
return core::media::ContainerType::MP4; return core::media::Container::MP4;
case ContainerType::MPC: case Container::MPC:
return core::media::ContainerType::MPC; return core::media::Container::MPC;
case ContainerType::MPEG: case Container::MPEG:
return core::media::ContainerType::MPEG; return core::media::Container::MPEG;
case ContainerType::Ogg: case Container::Ogg:
return core::media::ContainerType::Ogg; return core::media::Container::Ogg;
case ContainerType::Shorten: case Container::Shorten:
return core::media::ContainerType::Shorten; return core::media::Container::Shorten;
case ContainerType::TrueAudio: case Container::TrueAudio:
return core::media::ContainerType::TrueAudio; return core::media::Container::TrueAudio;
case ContainerType::WAV: case Container::WAV:
return core::media::ContainerType::WAV; return core::media::Container::WAV;
case ContainerType::WavPack: case Container::WavPack:
return core::media::ContainerType::WavPack; return core::media::Container::WavPack;
case ContainerType::Unknown: case Container::Unknown:
break; break;
} }
return std::nullopt; return std::nullopt;
} }
db::detail::ContainerType getDbContainerType(core::media::ContainerType container) db::detail::Container getDbContainer(core::media::Container container)
{ {
switch (container) switch (container)
{ {
case core::media::ContainerType::AIFF: case core::media::Container::AIFF:
return ContainerType::AIFF; return Container::AIFF;
case core::media::ContainerType::APE: case core::media::Container::APE:
return ContainerType::APE; return Container::APE;
case core::media::ContainerType::ASF: case core::media::Container::ASF:
return ContainerType::ASF; return Container::ASF;
case core::media::ContainerType::DSF: case core::media::Container::DSF:
return ContainerType::DSF; return Container::DSF;
case core::media::ContainerType::FLAC: case core::media::Container::FLAC:
return ContainerType::FLAC; return Container::FLAC;
case core::media::ContainerType::MP4: case core::media::Container::MP4:
return ContainerType::MP4; return Container::MP4;
case core::media::ContainerType::MPC: case core::media::Container::MPC:
return ContainerType::MPC; return Container::MPC;
case core::media::ContainerType::MPEG: case core::media::Container::MPEG:
return ContainerType::MPEG; return Container::MPEG;
case core::media::ContainerType::Ogg: case core::media::Container::Ogg:
return ContainerType::Ogg; return Container::Ogg;
case core::media::ContainerType::Shorten: case core::media::Container::Shorten:
return ContainerType::Shorten; return Container::Shorten;
case core::media::ContainerType::TrueAudio: case core::media::Container::TrueAudio:
return ContainerType::TrueAudio; return Container::TrueAudio;
case core::media::ContainerType::WAV: case core::media::Container::WAV:
return ContainerType::WAV; return Container::WAV;
case core::media::ContainerType::WavPack: case core::media::Container::WavPack:
return ContainerType::WavPack; return Container::WavPack;
} }
return ContainerType::Unknown; return Container::Unknown;
} }
std::optional<core::media::CodecType> getMediaCodecType(db::detail::CodecType codec) std::optional<core::media::Codec> getMediaCodecType(db::detail::Codec codec)
{ {
switch (codec) switch (codec)
{ {
case CodecType::AAC: case Codec::AAC:
return core::media::CodecType::AAC; return core::media::Codec::AAC;
case CodecType::AC3: case Codec::AC3:
return core::media::CodecType::AC3; return core::media::Codec::AC3;
case CodecType::ALAC: case Codec::ALAC:
return core::media::CodecType::ALAC; return core::media::Codec::ALAC;
case CodecType::APE: case Codec::APE:
return core::media::CodecType::APE; return core::media::Codec::APE;
case CodecType::DSD: case Codec::DSD:
return core::media::CodecType::DSD; return core::media::Codec::DSD;
case CodecType::EAC3: case Codec::EAC3:
return core::media::CodecType::EAC3; return core::media::Codec::EAC3;
case CodecType::FLAC: case Codec::FLAC:
return core::media::CodecType::FLAC; return core::media::Codec::FLAC;
case CodecType::MP3: case Codec::MP3:
return core::media::CodecType::MP3; return core::media::Codec::MP3;
case CodecType::MP4ALS: case Codec::MP4ALS:
return core::media::CodecType::MP4ALS; return core::media::Codec::MP4ALS;
case CodecType::MPC7: case Codec::MPC7:
return core::media::CodecType::MPC7; return core::media::Codec::MPC7;
case CodecType::MPC8: case Codec::MPC8:
return core::media::CodecType::MPC8; return core::media::Codec::MPC8;
case CodecType::Opus: case Codec::Opus:
return core::media::CodecType::Opus; return core::media::Codec::Opus;
case CodecType::PCM: case Codec::PCM:
return core::media::CodecType::PCM; return core::media::Codec::PCM;
case CodecType::Shorten: case Codec::Shorten:
return core::media::CodecType::Shorten; return core::media::Codec::Shorten;
case CodecType::TrueAudio: case Codec::TrueAudio:
return core::media::CodecType::TrueAudio; return core::media::Codec::TrueAudio;
case CodecType::Vorbis: case Codec::Vorbis:
return core::media::CodecType::Vorbis; return core::media::Codec::Vorbis;
case CodecType::WavPack: case Codec::WavPack:
return core::media::CodecType::WavPack; return core::media::Codec::WavPack;
case CodecType::WMA1: case Codec::WMA1:
return core::media::CodecType::WMA1; return core::media::Codec::WMA1;
case CodecType::WMA2: case Codec::WMA2:
return core::media::CodecType::WMA2; return core::media::Codec::WMA2;
case CodecType::WMA9Pro: case Codec::WMA9Pro:
return core::media::CodecType::WMA9Pro; return core::media::Codec::WMA9Pro;
case CodecType::WMA9Lossless: case Codec::WMA9Lossless:
return core::media::CodecType::WMA9Lossless; return core::media::Codec::WMA9Lossless;
case CodecType::Unknown: case Codec::Unknown:
break; break;
} }
return std::nullopt; return std::nullopt;
} }
db::detail::CodecType getDbCodecType(core::media::CodecType codec) db::detail::Codec getDbCodec(core::media::Codec codec)
{ {
switch (codec) switch (codec)
{ {
case core::media::CodecType::AAC: case core::media::Codec::AAC:
return CodecType::AAC; return Codec::AAC;
case core::media::CodecType::AC3: case core::media::Codec::AC3:
return CodecType::AC3; return Codec::AC3;
case core::media::CodecType::ALAC: case core::media::Codec::ALAC:
return CodecType::ALAC; return Codec::ALAC;
case core::media::CodecType::APE: case core::media::Codec::APE:
return CodecType::APE; return Codec::APE;
case core::media::CodecType::DSD: case core::media::Codec::DSD:
return CodecType::DSD; return Codec::DSD;
case core::media::CodecType::EAC3: case core::media::Codec::EAC3:
return CodecType::EAC3; return Codec::EAC3;
case core::media::CodecType::FLAC: case core::media::Codec::FLAC:
return CodecType::FLAC; return Codec::FLAC;
case core::media::CodecType::MP3: case core::media::Codec::MP3:
return CodecType::MP3; return Codec::MP3;
case core::media::CodecType::MP4ALS: case core::media::Codec::MP4ALS:
return CodecType::MP4ALS; return Codec::MP4ALS;
case core::media::CodecType::MPC7: case core::media::Codec::MPC7:
return CodecType::MPC7; return Codec::MPC7;
case core::media::CodecType::MPC8: case core::media::Codec::MPC8:
return CodecType::MPC8; return Codec::MPC8;
case core::media::CodecType::Opus: case core::media::Codec::Opus:
return CodecType::Opus; return Codec::Opus;
case core::media::CodecType::PCM: case core::media::Codec::PCM:
return CodecType::PCM; return Codec::PCM;
case core::media::CodecType::Shorten: case core::media::Codec::Shorten:
return CodecType::Shorten; return Codec::Shorten;
case core::media::CodecType::TrueAudio: case core::media::Codec::TrueAudio:
return CodecType::TrueAudio; return Codec::TrueAudio;
case core::media::CodecType::Vorbis: case core::media::Codec::Vorbis:
return CodecType::Vorbis; return Codec::Vorbis;
case core::media::CodecType::WavPack: case core::media::Codec::WavPack:
return CodecType::WavPack; return Codec::WavPack;
case core::media::CodecType::WMA1: case core::media::Codec::WMA1:
return CodecType::WMA1; return Codec::WMA1;
case core::media::CodecType::WMA2: case core::media::Codec::WMA2:
return CodecType::WMA2; return Codec::WMA2;
case core::media::CodecType::WMA9Pro: case core::media::Codec::WMA9Pro:
return CodecType::WMA9Pro; return Codec::WMA9Pro;
case core::media::CodecType::WMA9Lossless: case core::media::Codec::WMA9Lossless:
return CodecType::WMA9Lossless; return Codec::WMA9Lossless;
} }
return CodecType::Unknown; return Codec::Unknown;
} }
core::media::ImageType getMediaImageType(db::detail::ImageType type) core::media::ImageType getMediaImageType(db::detail::ImageType type)
@@ -21,19 +21,19 @@
#include <optional> #include <optional>
#include "core/media/CodecType.hpp" #include "core/media/Codec.hpp"
#include "core/media/ContainerType.hpp" #include "core/media/Container.hpp"
#include "core/media/ImageType.hpp" #include "core/media/ImageType.hpp"
#include "database/objects/detail/Types.hpp" #include "database/objects/detail/Types.hpp"
namespace lms::db::detail namespace lms::db::detail
{ {
std::optional<core::media::ContainerType> getMediaContainerType(db::detail::ContainerType container); std::optional<core::media::Container> getMediaContainerType(db::detail::Container container);
db::detail::ContainerType getDbContainerType(core::media::ContainerType container); db::detail::Container getDbContainer(core::media::Container container);
std::optional<core::media::CodecType> getMediaCodecType(db::detail::CodecType codec); std::optional<core::media::Codec> getMediaCodecType(db::detail::Codec codec);
db::detail::CodecType getDbCodecType(core::media::CodecType codec); db::detail::Codec getDbCodec(core::media::Codec codec);
core::media::ImageType getMediaImageType(db::detail::ImageType type); core::media::ImageType getMediaImageType(db::detail::ImageType type);
db::detail::ImageType getDbImageType(core::media::ImageType type); db::detail::ImageType getDbImageType(core::media::ImageType type);
@@ -23,7 +23,7 @@
#include <span> #include <span>
#include <vector> #include <vector>
#include "core/media/CodecType.hpp" #include "core/media/Codec.hpp"
#include "database/objects/ClusterId.hpp" #include "database/objects/ClusterId.hpp"
#include "database/objects/LabelId.hpp" #include "database/objects/LabelId.hpp"
@@ -34,11 +34,11 @@ namespace lms::db
{ {
struct Filters struct Filters
{ {
MediaLibraryId mediaLibrary; // tracks that belongs to this library MediaLibraryId mediaLibrary; // tracks that belongs to this library
std::vector<ClusterId> clusters; // tracks that belong to *all* these clusters std::vector<ClusterId> clusters; // tracks that belong to *all* these clusters
LabelId label; // tracks which release has this label LabelId label; // tracks which release has this label
ReleaseTypeId releaseType; // tracks which release has this type ReleaseTypeId releaseType; // tracks which release has this type
std::optional<core::media::CodecType> codec; // tracks that match this codec std::optional<core::media::Codec> codec; // tracks that match this codec
Filters& setClusters(std::span<const ClusterId> _clusters) Filters& setClusters(std::span<const ClusterId> _clusters)
{ {
@@ -60,7 +60,7 @@ namespace lms::db
releaseType = _releaseType; releaseType = _releaseType;
return *this; return *this;
} }
Filters& setCodec(std::optional<core::media::CodecType> _codec) Filters& setCodec(std::optional<core::media::Codec> _codec)
{ {
codec = _codec; codec = _codec;
return *this; return *this;
@@ -29,8 +29,8 @@
#include <Wt/Dbo/collection.h> #include <Wt/Dbo/collection.h>
#include <Wt/WDateTime.h> #include <Wt/WDateTime.h>
#include "core/media/CodecType.hpp" #include "core/media/Codec.hpp"
#include "core/media/ContainerType.hpp" #include "core/media/Container.hpp"
#include "database/Object.hpp" #include "database/Object.hpp"
#include "database/Types.hpp" #include "database/Types.hpp"
@@ -97,8 +97,8 @@ namespace lms::db
// Audio properties // Audio properties
std::chrono::milliseconds getDuration() const { return _duration; } std::chrono::milliseconds getDuration() const { return _duration; }
std::optional<core::media::ContainerType> getContainer() const; std::optional<core::media::Container> getContainer() const;
std::optional<core::media::CodecType> getCodec() const; std::optional<core::media::Codec> getCodec() const;
std::size_t getBitrate() const { return _bitrate; } std::size_t getBitrate() const { return _bitrate; }
std::size_t getChannelCount() const { return _channelCount; } std::size_t getChannelCount() const { return _channelCount; }
std::size_t getSampleRate() const { return _sampleRate; } std::size_t getSampleRate() const { return _sampleRate; }
@@ -128,8 +128,8 @@ namespace lms::db
// Audio properties // Audio properties
void setDuration(std::chrono::milliseconds duration) { _duration = duration; } void setDuration(std::chrono::milliseconds duration) { _duration = duration; }
void setContainer(core::media::ContainerType container); void setContainer(core::media::Container container);
void setCodec(core::media::CodecType codec); void setCodec(core::media::Codec codec);
void setBitrate(std::size_t bitrate) { _bitrate = bitrate; } void setBitrate(std::size_t bitrate) { _bitrate = bitrate; }
void setChannelCount(std::size_t channelCount) { _channelCount = channelCount; } void setChannelCount(std::size_t channelCount) { _channelCount = channelCount; }
void setSampleRate(std::size_t sampleRate) { _sampleRate = sampleRate; } void setSampleRate(std::size_t sampleRate) { _sampleRate = sampleRate; }
@@ -193,8 +193,8 @@ namespace lms::db
// Audio properties // Audio properties
std::chrono::duration<int, std::milli> _duration{ 0 }; std::chrono::duration<int, std::milli> _duration{ 0 };
detail::ContainerType _container{ detail::ContainerType::Unknown }; detail::Container _container{ detail::Container::Unknown };
detail::CodecType _codec{ detail::CodecType::Unknown }; detail::Codec _codec{ detail::Codec::Unknown };
int _bitrate{}; // in bps int _bitrate{}; // in bps
int _channelCount{}; int _channelCount{};
int _sampleRate{}; int _sampleRate{};
@@ -31,7 +31,7 @@
#include "core/EnumSet.hpp" #include "core/EnumSet.hpp"
#include "core/PartialDateTime.hpp" #include "core/PartialDateTime.hpp"
#include "core/UUID.hpp" #include "core/UUID.hpp"
#include "core/media/CodecType.hpp" #include "core/media/Codec.hpp"
#include "database/IdRange.hpp" #include "database/IdRange.hpp"
#include "database/Object.hpp" #include "database/Object.hpp"
@@ -280,7 +280,7 @@ namespace lms::db
std::optional<std::string> getCopyright() const; std::optional<std::string> getCopyright() const;
std::optional<std::string> getCopyrightURL() const; std::optional<std::string> getCopyrightURL() const;
std::size_t getMeanBitrate() const; std::size_t getMeanBitrate() const;
std::vector<core::media::CodecType> getCodecs() const; std::vector<core::media::Codec> getCodecs() const;
// Accessors // Accessors
std::string_view getName() const { return _name; } std::string_view getName() const { return _name; }
@@ -34,8 +34,8 @@
#include "core/EnumSet.hpp" #include "core/EnumSet.hpp"
#include "core/PartialDateTime.hpp" #include "core/PartialDateTime.hpp"
#include "core/UUID.hpp" #include "core/UUID.hpp"
#include "core/media/CodecType.hpp" #include "core/media/Codec.hpp"
#include "core/media/ContainerType.hpp" #include "core/media/Container.hpp"
#include "database/IdRange.hpp" #include "database/IdRange.hpp"
#include "database/Object.hpp" #include "database/Object.hpp"
@@ -232,8 +232,8 @@ namespace lms::db
// Audio properties // Audio properties
void setDuration(std::chrono::milliseconds duration) { _duration = duration; } void setDuration(std::chrono::milliseconds duration) { _duration = duration; }
void setContainer(core::media::ContainerType container); void setContainer(core::media::Container container);
void setCodec(core::media::CodecType codec); void setCodec(core::media::Codec codec);
void setBitrate(std::size_t bitrate) { _bitrate = bitrate; } void setBitrate(std::size_t bitrate) { _bitrate = bitrate; }
void setChannelCount(std::size_t channelCount) { _channelCount = channelCount; } void setChannelCount(std::size_t channelCount) { _channelCount = channelCount; }
void setSampleRate(std::size_t sampleRate) { _sampleRate = sampleRate; } void setSampleRate(std::size_t sampleRate) { _sampleRate = sampleRate; }
@@ -278,8 +278,8 @@ namespace lms::db
// Audio properties // Audio properties
std::chrono::milliseconds getDuration() const { return _duration; } std::chrono::milliseconds getDuration() const { return _duration; }
std::optional<core::media::ContainerType> getContainer() const; std::optional<core::media::Container> getContainer() const;
std::optional<core::media::CodecType> getCodec() const; std::optional<core::media::Codec> getCodec() const;
std::size_t getBitrate() const { return _bitrate; } std::size_t getBitrate() const { return _bitrate; }
std::size_t getChannelCount() const { return _channelCount; } std::size_t getChannelCount() const { return _channelCount; }
std::size_t getSampleRate() const { return _sampleRate; } std::size_t getSampleRate() const { return _sampleRate; }
@@ -383,8 +383,8 @@ namespace lms::db
// Audio properties // Audio properties
std::chrono::duration<int, std::milli> _duration{}; std::chrono::duration<int, std::milli> _duration{};
detail::ContainerType _container{ detail::ContainerType::Unknown }; detail::Container _container{ detail::Container::Unknown };
detail::CodecType _codec{ detail::CodecType::Unknown }; detail::Codec _codec{ detail::Codec::Unknown };
int _bitrate{}; // in bps int _bitrate{}; // in bps
int _channelCount{}; int _channelCount{};
int _sampleRate{}; int _sampleRate{};
@@ -49,7 +49,7 @@ namespace lms::db::detail
PublisherLogo = 21 PublisherLogo = 21
}; };
enum class ContainerType enum class Container
{ {
Unknown = 0, Unknown = 0,
@@ -68,7 +68,7 @@ namespace lms::db::detail
WavPack = 13, WavPack = 13,
}; };
enum class CodecType enum class Codec
{ {
Unknown = 0, Unknown = 0,
+3 -3
View File
@@ -530,15 +530,15 @@ namespace lms::db::tests
TrackArtistLink::create(session, track1.get(), artist1.get(), TrackArtistLinkType::Artist); TrackArtistLink::create(session, track1.get(), artist1.get(), TrackArtistLinkType::Artist);
TrackArtistLink::create(session, track2.get(), artist2.get(), TrackArtistLinkType::Artist); TrackArtistLink::create(session, track2.get(), artist2.get(), TrackArtistLinkType::Artist);
track1.get().modify()->setCodec(core::media::CodecType::MP3); track1.get().modify()->setCodec(core::media::Codec::MP3);
track2.get().modify()->setCodec(core::media::CodecType::FLAC); track2.get().modify()->setCodec(core::media::Codec::FLAC);
} }
{ {
auto transaction{ session.createReadTransaction() }; auto transaction{ session.createReadTransaction() };
Artist::FindParameters params; Artist::FindParameters params;
params.setFilters(Filters{}.setCodec(core::media::CodecType::FLAC)); params.setFilters(Filters{}.setCodec(core::media::Codec::FLAC));
const auto artists{ Artist::find(session, params) }; const auto artists{ Artist::find(session, params) };
ASSERT_EQ(artists.results.size(), 1); ASSERT_EQ(artists.results.size(), 1);
+8 -8
View File
@@ -1229,22 +1229,22 @@ namespace lms::db::tests
{ {
auto transaction{ session.createWriteTransaction() }; auto transaction{ session.createWriteTransaction() };
track1.get().modify()->setCodec(core::media::CodecType::FLAC); track1.get().modify()->setCodec(core::media::Codec::FLAC);
track1.get().modify()->setRelease(release1.get()); track1.get().modify()->setRelease(release1.get());
track2.get().modify()->setCodec(core::media::CodecType::MP3); track2.get().modify()->setCodec(core::media::Codec::MP3);
track2.get().modify()->setRelease(release1.get()); track2.get().modify()->setRelease(release1.get());
track3.get().modify()->setCodec(core::media::CodecType::MP3); track3.get().modify()->setCodec(core::media::Codec::MP3);
track3.get().modify()->setRelease(release1.get()); track3.get().modify()->setRelease(release1.get());
track4.get().modify()->setCodec(core::media::CodecType::AAC); track4.get().modify()->setCodec(core::media::Codec::AAC);
track4.get().modify()->setRelease(release1.get()); track4.get().modify()->setRelease(release1.get());
} }
{ {
auto transaction{ session.createReadTransaction() }; auto transaction{ session.createReadTransaction() };
EXPECT_EQ(release1->getCodecs(), (std::vector<core::media::CodecType>{ core::media::CodecType::MP3, core::media::CodecType::FLAC, core::media::CodecType::AAC })); EXPECT_EQ(release1->getCodecs(), (std::vector<core::media::Codec>{ core::media::Codec::MP3, core::media::Codec::FLAC, core::media::Codec::AAC }));
} }
} }
@@ -1263,10 +1263,10 @@ namespace lms::db::tests
{ {
auto transaction{ session.createWriteTransaction() }; auto transaction{ session.createWriteTransaction() };
track1.get().modify()->setCodec(core::media::CodecType::FLAC); track1.get().modify()->setCodec(core::media::Codec::FLAC);
track1.get().modify()->setRelease(release1.get()); track1.get().modify()->setRelease(release1.get());
track2.get().modify()->setCodec(core::media::CodecType::MP3); track2.get().modify()->setCodec(core::media::Codec::MP3);
track2.get().modify()->setRelease(release2.get()); track2.get().modify()->setRelease(release2.get());
} }
@@ -1274,7 +1274,7 @@ namespace lms::db::tests
auto transaction{ session.createReadTransaction() }; auto transaction{ session.createReadTransaction() };
Release::FindParameters params; Release::FindParameters params;
params.setFilters(Filters{}.setCodec(core::media::CodecType::MP3)); params.setFilters(Filters{}.setCodec(core::media::Codec::MP3));
auto releases{ Release::findIds(session, params) }; auto releases{ Release::findIds(session, params) };
ASSERT_EQ(releases.results.size(), 1); ASSERT_EQ(releases.results.size(), 1);
+3 -3
View File
@@ -245,15 +245,15 @@ namespace lms::db::tests
{ {
auto transaction{ session.createWriteTransaction() }; auto transaction{ session.createWriteTransaction() };
track1.get().modify()->setCodec(core::media::CodecType::MP3); track1.get().modify()->setCodec(core::media::Codec::MP3);
track2.get().modify()->setCodec(core::media::CodecType::FLAC); track2.get().modify()->setCodec(core::media::Codec::FLAC);
} }
{ {
auto transaction{ session.createReadTransaction() }; auto transaction{ session.createReadTransaction() };
Track::FindParameters params; Track::FindParameters params;
params.setFilters(Filters{}.setCodec(core::media::CodecType::FLAC)); params.setFilters(Filters{}.setCodec(core::media::Codec::FLAC));
const auto tracks{ Track::find(session, params) }; const auto tracks{ Track::find(session, params) };
ASSERT_EQ(tracks.results.size(), 1); ASSERT_EQ(tracks.results.size(), 1);
@@ -53,13 +53,13 @@ namespace lms::api::subsonic
struct OutputFormat struct OutputFormat
{ {
std::string name; std::string name;
core::media::ContainerType container; core::media::Container container;
core::media::CodecType codec; core::media::Codec codec;
}; };
constexpr std::array outputFormats{ constexpr std::array outputFormats{
OutputFormat{ "mp3", core::media::ContainerType::MPEG, core::media::CodecType::MP3 }, OutputFormat{ "mp3", core::media::Container::MPEG, core::media::Codec::MP3 },
OutputFormat{ "opus", core::media::ContainerType::Ogg, core::media::CodecType::Opus }, OutputFormat{ "opus", core::media::Container::Ogg, core::media::Codec::Opus },
OutputFormat{ "vorbis", core::media::ContainerType::Ogg, core::media::CodecType::Vorbis }, OutputFormat{ "vorbis", core::media::Container::Ogg, core::media::Codec::Vorbis },
}; };
std::optional<OutputFormat> getOutputFormatByName(std::string_view format) std::optional<OutputFormat> getOutputFormatByName(std::string_view format)
@@ -48,8 +48,8 @@ namespace lms::api::subsonic
{ {
StreamDetails res; StreamDetails res;
res.protocol = "http"; res.protocol = "http";
res.container = core::media::containerTypeToString(audioProperties.container).str(); res.container = core::media::containerToString(audioProperties.container).str();
res.codec = core::media::codecTypeToString(audioProperties.codec).str(); res.codec = core::media::getCodecDesc(audioProperties.codec).name.str();
res.audioChannels = audioProperties.channelCount; res.audioChannels = audioProperties.channelCount;
res.audioBitrate = audioProperties.bitrate; res.audioBitrate = audioProperties.bitrate;
res.audioProfile = ""; // TODO res.audioProfile = ""; // TODO
@@ -34,13 +34,13 @@ namespace lms::api::subsonic::detail
namespace namespace
{ {
constexpr std::array supportedTranscodeOutputFormats{ constexpr std::array supportedTranscodeOutputFormats{
audio::TranscodeOutputFormat{ .container = core::media::ContainerType::MPEG, .codec = core::media::CodecType::MP3 }, audio::TranscodeOutputFormat{ .container = core::media::Container::MPEG, .codec = core::media::Codec::MP3 },
audio::TranscodeOutputFormat{ .container = core::media::ContainerType::Ogg, .codec = core::media::CodecType::Vorbis }, audio::TranscodeOutputFormat{ .container = core::media::Container::Ogg, .codec = core::media::Codec::Vorbis },
audio::TranscodeOutputFormat{ .container = core::media::ContainerType::Ogg, .codec = core::media::CodecType::Opus }, audio::TranscodeOutputFormat{ .container = core::media::Container::Ogg, .codec = core::media::Codec::Opus },
audio::TranscodeOutputFormat{ .container = core::media::ContainerType::FLAC, .codec = core::media::CodecType::FLAC }, audio::TranscodeOutputFormat{ .container = core::media::Container::FLAC, .codec = core::media::Codec::FLAC },
}; };
bool isMatchingContainerName(core::media::ContainerType container, std::string_view containerStr) bool isMatchingContainerName(core::media::Container container, std::string_view containerStr)
{ {
using namespace std::literals; // for "..."sv using namespace std::literals; // for "..."sv
@@ -62,43 +62,43 @@ namespace lms::api::subsonic::detail
switch (container) switch (container)
{ {
case core::media::ContainerType::AIFF: case core::media::Container::AIFF:
containerNames = aiffNames; containerNames = aiffNames;
break; break;
case core::media::ContainerType::APE: case core::media::Container::APE:
containerNames = apeNames; containerNames = apeNames;
break; break;
case core::media::ContainerType::ASF: case core::media::Container::ASF:
containerNames = asfNames; containerNames = asfNames;
break; break;
case core::media::ContainerType::DSF: case core::media::Container::DSF:
containerNames = dsfNames; containerNames = dsfNames;
break; break;
case core::media::ContainerType::MPC: case core::media::Container::MPC:
containerNames = mpcNames; containerNames = mpcNames;
break; break;
case core::media::ContainerType::MPEG: case core::media::Container::MPEG:
containerNames = mpegNames; containerNames = mpegNames;
break; break;
case core::media::ContainerType::Ogg: case core::media::Container::Ogg:
containerNames = oggNames; containerNames = oggNames;
break; break;
case core::media::ContainerType::FLAC: case core::media::Container::FLAC:
containerNames = flacNames; containerNames = flacNames;
break; break;
case core::media::ContainerType::MP4: case core::media::Container::MP4:
containerNames = mp4Names; containerNames = mp4Names;
break; break;
case core::media::ContainerType::Shorten: case core::media::Container::Shorten:
containerNames = shortenNames; containerNames = shortenNames;
break; break;
case core::media::ContainerType::TrueAudio: case core::media::Container::TrueAudio:
containerNames = trueAudioNames; containerNames = trueAudioNames;
break; break;
case core::media::ContainerType::WAV: case core::media::Container::WAV:
containerNames = wavNames; containerNames = wavNames;
break; break;
case core::media::ContainerType::WavPack: case core::media::Container::WavPack:
containerNames = wavPackNames; containerNames = wavPackNames;
break; break;
} }
@@ -106,7 +106,7 @@ namespace lms::api::subsonic::detail
return std::any_of(std::cbegin(containerNames), std::cend(containerNames), [&](std::string_view containerName) { return core::stringUtils::stringCaseInsensitiveEqual(containerName, containerStr); }); return std::any_of(std::cbegin(containerNames), std::cend(containerNames), [&](std::string_view containerName) { return core::stringUtils::stringCaseInsensitiveEqual(containerName, containerStr); });
} }
bool isMatchingCodecName(core::media::CodecType codec, std::string_view codecStr) bool isMatchingCodecName(core::media::Codec codec, std::string_view codecStr)
{ {
using namespace std::literals; // for "..."sv using namespace std::literals; // for "..."sv
@@ -135,67 +135,67 @@ namespace lms::api::subsonic::detail
std::span<const std::string_view> codecNames; std::span<const std::string_view> codecNames;
switch (codec) switch (codec)
{ {
case core::media::CodecType::AAC: case core::media::Codec::AAC:
codecNames = aacCodecNames; codecNames = aacCodecNames;
break; break;
case core::media::CodecType::AC3: case core::media::Codec::AC3:
codecNames = ac3CodecNames; codecNames = ac3CodecNames;
break; break;
case core::media::CodecType::ALAC: case core::media::Codec::ALAC:
codecNames = alacCodecNames; codecNames = alacCodecNames;
break; break;
case core::media::CodecType::APE: case core::media::Codec::APE:
codecNames = apeCodecNames; codecNames = apeCodecNames;
break; break;
case core::media::CodecType::DSD: case core::media::Codec::DSD:
codecNames = dsdCodecNames; codecNames = dsdCodecNames;
break; break;
case core::media::CodecType::EAC3: case core::media::Codec::EAC3:
codecNames = eac3CodecNames; codecNames = eac3CodecNames;
break; break;
case core::media::CodecType::FLAC: case core::media::Codec::FLAC:
codecNames = flacCodecNames; codecNames = flacCodecNames;
break; break;
case core::media::CodecType::MP3: case core::media::Codec::MP3:
codecNames = mp3CodecNames; codecNames = mp3CodecNames;
break; break;
case core::media::CodecType::MP4ALS: case core::media::Codec::MP4ALS:
codecNames = mp4alsCodecNames; codecNames = mp4alsCodecNames;
break; break;
case core::media::CodecType::MPC7: case core::media::Codec::MPC7:
codecNames = mpc7CodecNames; codecNames = mpc7CodecNames;
break; break;
case core::media::CodecType::MPC8: case core::media::Codec::MPC8:
codecNames = mpc8CodecNames; codecNames = mpc8CodecNames;
break; break;
case core::media::CodecType::Opus: case core::media::Codec::Opus:
codecNames = opusCodecNames; codecNames = opusCodecNames;
break; break;
case core::media::CodecType::PCM: case core::media::Codec::PCM:
codecNames = pcmCodecNames; codecNames = pcmCodecNames;
break; break;
case core::media::CodecType::Shorten: case core::media::Codec::Shorten:
codecNames = shortenCodecNames; codecNames = shortenCodecNames;
break; break;
case core::media::CodecType::TrueAudio: case core::media::Codec::TrueAudio:
codecNames = trueAudioCodecNames; codecNames = trueAudioCodecNames;
break; break;
case core::media::CodecType::Vorbis: case core::media::Codec::Vorbis:
codecNames = vorbisCodecNames; codecNames = vorbisCodecNames;
break; break;
case core::media::CodecType::WavPack: case core::media::Codec::WavPack:
codecNames = wavPackCodecNames; codecNames = wavPackCodecNames;
break; break;
case core::media::CodecType::WMA1: case core::media::Codec::WMA1:
codecNames = wma1CodecNames; codecNames = wma1CodecNames;
break; break;
case core::media::CodecType::WMA2: case core::media::Codec::WMA2:
codecNames = wma2CodecNames; codecNames = wma2CodecNames;
break; break;
case core::media::CodecType::WMA9Lossless: case core::media::Codec::WMA9Lossless:
codecNames = wma9LosslessCodecNames; codecNames = wma9LosslessCodecNames;
break; break;
case core::media::CodecType::WMA9Pro: case core::media::Codec::WMA9Pro:
codecNames = wma9ProCodecNames; codecNames = wma9ProCodecNames;
break; break;
} }
@@ -343,7 +343,7 @@ namespace lms::api::subsonic::detail
return adjustResult.type == AdjustResult::Type::None; return adjustResult.type == AdjustResult::Type::None;
} }
const CodecProfile* getAudioCodecProfile(std::span<const CodecProfile> codecProfiles, core::media::CodecType codec) const CodecProfile* getAudioCodecProfile(std::span<const CodecProfile> codecProfiles, core::media::Codec codec)
{ {
for (const CodecProfile& profile : codecProfiles) for (const CodecProfile& profile : codecProfiles)
{ {
@@ -463,9 +463,9 @@ namespace lms::api::subsonic::detail
transcodedStream.container = profile.container; // put back what was requested instead of our internal names transcodedStream.container = profile.container; // put back what was requested instead of our internal names
transcodedStream.codec = profile.audioCodec; // put back what was requested instead of our internal names transcodedStream.codec = profile.audioCodec; // put back what was requested instead of our internal names
if (core::media::isCodecLossless(source.codec)) if (core::media::getCodecDesc(source.codec).isLossless)
{ {
if (!core::media::isCodecLossless(transcodeFormat->codec)) if (!core::media::getCodecDesc(transcodeFormat->codec).isLossless)
{ {
// If coming from lossless source, maximize the bitrate if going to a non lossless source // If coming from lossless source, maximize the bitrate if going to a non lossless source
// otherwise, pick a good enough value as we don't want to keep the original bitrate which does not make sense for lossy codecs // otherwise, pick a good enough value as we don't want to keep the original bitrate which does not make sense for lossy codecs
@@ -486,7 +486,7 @@ namespace lms::api::subsonic::detail
{ {
// source is lossy // source is lossy
if (core::media::isCodecLossless(transcodeFormat->codec)) if (core::media::getCodecDesc(transcodeFormat->codec).isLossless)
return std::nullopt; // not compatible with lossless codecs return std::nullopt; // not compatible with lossless codecs
// let's pick the same bitrate as the lossy source // let's pick the same bitrate as the lossy source
@@ -504,7 +504,7 @@ namespace lms::api::subsonic::detail
for (const Limitation& limitation : codecProfile->limitations) for (const Limitation& limitation : codecProfile->limitations)
{ {
const AdjustResult result{ applyLimitation(source, limitation, transcodedStream) }; const AdjustResult result{ applyLimitation(source, limitation, transcodedStream) };
if (limitation.name == Limitation::Type::AudioBitrate && core::media::isCodecLossless(transcodeFormat->codec) && result.type == AdjustResult::Type::Adjusted) if (limitation.name == Limitation::Type::AudioBitrate && core::media::getCodecDesc(transcodeFormat->codec).isLossless && result.type == AdjustResult::Type::Adjusted)
return std::nullopt; // not compatible with lossless codecs return std::nullopt; // not compatible with lossless codecs
if (result.type == AdjustResult::Type::CannotAdjust) if (result.type == AdjustResult::Type::CannotAdjust)
+38 -38
View File
@@ -22,8 +22,8 @@
#include <gtest/gtest.h> #include <gtest/gtest.h>
#include "core/Utils.hpp" #include "core/Utils.hpp"
#include "core/media/CodecType.hpp" #include "core/media/Codec.hpp"
#include "core/media/ContainerType.hpp" #include "core/media/Container.hpp"
#include "endpoints/transcoding/TranscodeDecision.hpp" #include "endpoints/transcoding/TranscodeDecision.hpp"
#include "payloads/ClientInfo.hpp" #include "payloads/ClientInfo.hpp"
@@ -111,8 +111,8 @@ namespace lms::api::subsonic
} } }, } } },
}, },
.source = { .source = {
.container = core::media::ContainerType::MPEG, .container = core::media::Container::MPEG,
.codec = core::media::CodecType::MP3, .codec = core::media::Codec::MP3,
.duration = std::chrono::seconds{ 60 }, .duration = std::chrono::seconds{ 60 },
.bitrate = 128'000, .bitrate = 128'000,
.channelCount = 2, .channelCount = 2,
@@ -141,8 +141,8 @@ namespace lms::api::subsonic
} } }, } } },
}, },
.source = { .source = {
.container = core::media::ContainerType::MPEG, .container = core::media::Container::MPEG,
.codec = core::media::CodecType::MP3, .codec = core::media::Codec::MP3,
.duration = std::chrono::seconds{ 60 }, .duration = std::chrono::seconds{ 60 },
.bitrate = 128'000, .bitrate = 128'000,
.channelCount = 2, .channelCount = 2,
@@ -171,8 +171,8 @@ namespace lms::api::subsonic
} } }, } } },
}, },
.source = { .source = {
.container = core::media::ContainerType::MPEG, .container = core::media::Container::MPEG,
.codec = core::media::CodecType::MP3, .codec = core::media::Codec::MP3,
.duration = std::chrono::seconds{ 60 }, .duration = std::chrono::seconds{ 60 },
.bitrate = 128'000, .bitrate = 128'000,
.channelCount = 2, .channelCount = 2,
@@ -201,8 +201,8 @@ namespace lms::api::subsonic
} } }, } } },
}, },
.source = { .source = {
.container = core::media::ContainerType::MPEG, .container = core::media::Container::MPEG,
.codec = core::media::CodecType::MP3, .codec = core::media::Codec::MP3,
.duration = std::chrono::seconds{ 60 }, .duration = std::chrono::seconds{ 60 },
.bitrate = 192'000, .bitrate = 192'000,
.channelCount = 2, .channelCount = 2,
@@ -231,8 +231,8 @@ namespace lms::api::subsonic
} } }, } } },
}, },
.source = { .source = {
.container = core::media::ContainerType::MPEG, .container = core::media::Container::MPEG,
.codec = core::media::CodecType::MP3, .codec = core::media::Codec::MP3,
.duration = std::chrono::seconds{ 60 }, .duration = std::chrono::seconds{ 60 },
.bitrate = 192'000, .bitrate = 192'000,
.channelCount = 2, .channelCount = 2,
@@ -255,8 +255,8 @@ namespace lms::api::subsonic
.codecProfiles = { { .type = "AudioCodec", .name = "mp3", .limitations = {} } }, .codecProfiles = { { .type = "AudioCodec", .name = "mp3", .limitations = {} } },
}, },
.source = { .source = {
.container = core::media::ContainerType::MPEG, .container = core::media::Container::MPEG,
.codec = core::media::CodecType::MP3, .codec = core::media::Codec::MP3,
.duration = std::chrono::seconds{ 60 }, .duration = std::chrono::seconds{ 60 },
.bitrate = 192'000, .bitrate = 192'000,
.channelCount = 5, .channelCount = 5,
@@ -283,8 +283,8 @@ namespace lms::api::subsonic
.codecProfiles = { { .type = "AudioCodec", .name = "mp3", .limitations = { { .name = Limitation::Type::AudioChannels, .comparison = Limitation::ComparisonOperator::LessThanEqual, .values = { "2" }, .required = true } } } }, .codecProfiles = { { .type = "AudioCodec", .name = "mp3", .limitations = { { .name = Limitation::Type::AudioChannels, .comparison = Limitation::ComparisonOperator::LessThanEqual, .values = { "2" }, .required = true } } } },
}, },
.source = { .source = {
.container = core::media::ContainerType::MPEG, .container = core::media::Container::MPEG,
.codec = core::media::CodecType::MP3, .codec = core::media::Codec::MP3,
.duration = std::chrono::seconds{ 60 }, .duration = std::chrono::seconds{ 60 },
.bitrate = 192'000, .bitrate = 192'000,
.channelCount = 5, .channelCount = 5,
@@ -311,8 +311,8 @@ namespace lms::api::subsonic
.codecProfiles = { { .type = "AudioCodec", .name = "mp3", .limitations = { { .name = Limitation::Type::AudioChannels, .comparison = Limitation::ComparisonOperator::LessThanEqual, .values = { "2" }, .required = true } } } }, .codecProfiles = { { .type = "AudioCodec", .name = "mp3", .limitations = { { .name = Limitation::Type::AudioChannels, .comparison = Limitation::ComparisonOperator::LessThanEqual, .values = { "2" }, .required = true } } } },
}, },
.source = { .source = {
.container = core::media::ContainerType::Ogg, .container = core::media::Container::Ogg,
.codec = core::media::CodecType::Opus, .codec = core::media::Codec::Opus,
.duration = std::chrono::seconds{ 60 }, .duration = std::chrono::seconds{ 60 },
.bitrate = 128'000, .bitrate = 128'000,
.channelCount = 2, .channelCount = 2,
@@ -339,8 +339,8 @@ namespace lms::api::subsonic
.codecProfiles = { { .type = "AudioCodec", .name = "mp3", .limitations = {} } }, .codecProfiles = { { .type = "AudioCodec", .name = "mp3", .limitations = {} } },
}, },
.source = { .source = {
.container = core::media::ContainerType::FLAC, .container = core::media::Container::FLAC,
.codec = core::media::CodecType::FLAC, .codec = core::media::Codec::FLAC,
.duration = std::chrono::seconds{ 60 }, .duration = std::chrono::seconds{ 60 },
.bitrate = 750'000, .bitrate = 750'000,
.channelCount = 2, .channelCount = 2,
@@ -362,8 +362,8 @@ namespace lms::api::subsonic
}, },
.codecProfiles = {} }, .codecProfiles = {} },
.source = { .source = {
.container = core::media::ContainerType::FLAC, .container = core::media::Container::FLAC,
.codec = core::media::CodecType::FLAC, .codec = core::media::Codec::FLAC,
.duration = std::chrono::seconds{ 60 }, .duration = std::chrono::seconds{ 60 },
.bitrate = 750'000, .bitrate = 750'000,
.channelCount = 2, .channelCount = 2,
@@ -388,8 +388,8 @@ namespace lms::api::subsonic
.codecProfiles = {}, .codecProfiles = {},
}, },
.source = { .source = {
.container = core::media::ContainerType::MPEG, .container = core::media::Container::MPEG,
.codec = core::media::CodecType::MP3, .codec = core::media::Codec::MP3,
.duration = std::chrono::seconds{ 60 }, .duration = std::chrono::seconds{ 60 },
.bitrate = 128'000, .bitrate = 128'000,
.channelCount = 2, .channelCount = 2,
@@ -414,8 +414,8 @@ namespace lms::api::subsonic
.codecProfiles = {}, .codecProfiles = {},
}, },
.source = { .source = {
.container = core::media::ContainerType::MPEG, .container = core::media::Container::MPEG,
.codec = core::media::CodecType::MP3, .codec = core::media::Codec::MP3,
.duration = std::chrono::seconds{ 60 }, .duration = std::chrono::seconds{ 60 },
.bitrate = 128'000, .bitrate = 128'000,
.channelCount = 2, .channelCount = 2,
@@ -440,8 +440,8 @@ namespace lms::api::subsonic
.codecProfiles = {}, .codecProfiles = {},
}, },
.source = { .source = {
.container = core::media::ContainerType::FLAC, .container = core::media::Container::FLAC,
.codec = core::media::CodecType::FLAC, .codec = core::media::Codec::FLAC,
.duration = std::chrono::seconds{ 60 }, .duration = std::chrono::seconds{ 60 },
.bitrate = 1'000'000, .bitrate = 1'000'000,
.channelCount = 2, .channelCount = 2,
@@ -478,8 +478,8 @@ namespace lms::api::subsonic
}, },
}, },
.source = { .source = {
.container = core::media::ContainerType::FLAC, .container = core::media::Container::FLAC,
.codec = core::media::CodecType::FLAC, .codec = core::media::Codec::FLAC,
.duration = std::chrono::seconds{ 60 }, .duration = std::chrono::seconds{ 60 },
.bitrate = 950'000, .bitrate = 950'000,
.channelCount = 2, .channelCount = 2,
@@ -517,8 +517,8 @@ namespace lms::api::subsonic
}, },
}, },
.source = { .source = {
.container = core::media::ContainerType::FLAC, .container = core::media::Container::FLAC,
.codec = core::media::CodecType::FLAC, .codec = core::media::Codec::FLAC,
.duration = std::chrono::seconds{ 60 }, .duration = std::chrono::seconds{ 60 },
.bitrate = 950'000, .bitrate = 950'000,
.channelCount = 2, .channelCount = 2,
@@ -555,8 +555,8 @@ namespace lms::api::subsonic
}, },
}, },
.source = { .source = {
.container = core::media::ContainerType::Ogg, .container = core::media::Container::Ogg,
.codec = core::media::CodecType::Vorbis, .codec = core::media::Codec::Vorbis,
.duration = std::chrono::seconds{ 60 }, .duration = std::chrono::seconds{ 60 },
.bitrate = 128'000, .bitrate = 128'000,
.channelCount = 2, .channelCount = 2,
@@ -593,8 +593,8 @@ namespace lms::api::subsonic
}, },
}, },
.source = { .source = {
.container = core::media::ContainerType::DSF, .container = core::media::Container::DSF,
.codec = core::media::CodecType::DSD, .codec = core::media::Codec::DSD,
.duration = std::chrono::seconds{ 60 }, .duration = std::chrono::seconds{ 60 },
.bitrate = 950'000, .bitrate = 950'000,
.channelCount = 2, .channelCount = 2,
@@ -623,8 +623,8 @@ namespace lms::api::subsonic
} } }, } } },
}, },
.source = { .source = {
.container = core::media::ContainerType::MPEG, .container = core::media::Container::MPEG,
.codec = core::media::CodecType::MP3, .codec = core::media::Codec::MP3,
.duration = std::chrono::seconds{ 60 }, .duration = std::chrono::seconds{ 60 },
.bitrate = 128'000, .bitrate = 128'000,
.channelCount = 2, .channelCount = 2,
+2 -2
View File
@@ -142,11 +142,11 @@ namespace lms::ui
// Codecs // Codecs
{ {
std::string codecStr; std::string codecStr;
for (core::media::CodecType codec : release->getCodecs()) for (core::media::Codec codec : release->getCodecs())
{ {
if (!codecStr.empty()) if (!codecStr.empty())
codecStr += " · "; codecStr += " · ";
codecStr += core::media::codecTypeToString(codec).str(); codecStr += core::media::getCodecDesc(codec).name.str();
} }
if (!codecStr.empty()) if (!codecStr.empty())
+1 -1
View File
@@ -130,7 +130,7 @@ namespace lms::ui::TrackListHelpers
if (const auto codec{ track->getCodec() }) if (const auto codec{ track->getCodec() })
{ {
trackInfo->setCondition("if-has-codec", true); trackInfo->setCondition("if-has-codec", true);
trackInfo->bindString("codec", core::media::codecTypeToString(*codec).c_str(), Wt::TextFormat::Plain); trackInfo->bindString("codec", core::media::getCodecDesc(*codec).name.c_str(), Wt::TextFormat::Plain);
} }
trackInfo->bindString("duration", utils::durationToString(track->getDuration())); trackInfo->bindString("duration", utils::durationToString(track->getDuration()));
@@ -124,11 +124,11 @@ namespace lms::ui
switch (format) switch (format)
{ {
case db::TranscodingOutputFormat::MP3: case db::TranscodingOutputFormat::MP3:
return audio::TranscodeOutputFormat{ core::media::ContainerType::MPEG, core::media::CodecType::MP3 }; return audio::TranscodeOutputFormat{ core::media::Container::MPEG, core::media::Codec::MP3 };
case db::TranscodingOutputFormat::OGG_OPUS: case db::TranscodingOutputFormat::OGG_OPUS:
return audio::TranscodeOutputFormat{ core::media::ContainerType::Ogg, core::media::CodecType::Opus }; return audio::TranscodeOutputFormat{ core::media::Container::Ogg, core::media::Codec::Opus };
case db::TranscodingOutputFormat::OGG_VORBIS: case db::TranscodingOutputFormat::OGG_VORBIS:
return audio::TranscodeOutputFormat{ core::media::ContainerType::Ogg, core::media::CodecType::Vorbis }; return audio::TranscodeOutputFormat{ core::media::Container::Ogg, core::media::Codec::Vorbis };
} }
TRANSCODE_LOG(ERROR, "Cannot convert from db audio format to transcoding format"); TRANSCODE_LOG(ERROR, "Cannot convert from db audio format to transcoding format");
+2 -2
View File
@@ -41,8 +41,8 @@ namespace lms::audio
std::ostream& operator<<(std::ostream& os, const AudioProperties& audioProperties) std::ostream& operator<<(std::ostream& os, const AudioProperties& audioProperties)
{ {
os << "\tDuration: " << std::fixed << std::setprecision(2) << std::chrono::duration_cast<std::chrono::duration<float>>(audioProperties.duration) << '\n'; os << "\tDuration: " << std::fixed << std::setprecision(2) << std::chrono::duration_cast<std::chrono::duration<float>>(audioProperties.duration) << '\n';
os << "\tContainer: " << core::media::containerTypeToString(audioProperties.container) << '\n'; os << "\tContainer: " << core::media::containerToString(audioProperties.container) << '\n';
os << "\tCodec: " << core::media::codecTypeToString(audioProperties.codec) << '\n'; os << "\tCodec: " << core::media::getCodecDesc(audioProperties.codec).name << '\n';
os << "\tMimeType: " << core::media::getMimeType(audioProperties.container, audioProperties.codec) << '\n'; os << "\tMimeType: " << core::media::getMimeType(audioProperties.container, audioProperties.codec) << '\n';
os << "\tBitrate: " << audioProperties.bitrate << " bps" << '\n'; os << "\tBitrate: " << audioProperties.bitrate << " bps" << '\n';
if (audioProperties.bitsPerSample) if (audioProperties.bitsPerSample)