diff --git a/src/libs/audio/impl/ffmpeg/AudioFileInfo.cpp b/src/libs/audio/impl/ffmpeg/AudioFileInfo.cpp index f8c9f6c6..fe0793f9 100644 --- a/src/libs/audio/impl/ffmpeg/AudioFileInfo.cpp +++ b/src/libs/audio/impl/ffmpeg/AudioFileInfo.cpp @@ -37,18 +37,30 @@ namespace lms::audio::ffmpeg const auto containerInfo{ audioFile.getContainerInfo() }; const auto bestStreamInfo{ audioFile.getBestStreamInfo() }; if (!bestStreamInfo) - throw AudioFileParsingException{ audioFile.getPath(), "Cannot find best audio stream" }; + throw AudioFileParsingException{ "Cannot find best audio stream" }; if (!containerInfo.container) - throw AudioFileParsingException{ audioFile.getPath(), "Unhandled container type '" + containerInfo.containerName + "'" }; + throw AudioFileParsingException{ "Unhandled container type '" + containerInfo.containerName + "'" }; + + if (!bestStreamInfo->codec) + throw AudioFileParsingException{ "Unhandled codec type '" + bestStreamInfo->codecName + "'" }; + + if (!bestStreamInfo->bitrate || *bestStreamInfo->bitrate == 0) + throw AudioFileParsingException{ "Cannot determine bitrate" }; + + if (!bestStreamInfo->channelCount || *bestStreamInfo->channelCount == 0) + throw AudioFileParsingException{ "Cannot determine channel count" }; + + if (!bestStreamInfo->sampleRate || *bestStreamInfo->sampleRate == 0) + throw AudioFileParsingException{ "Cannot determine sample rate" }; audioProperties.container = *containerInfo.container; audioProperties.duration = containerInfo.duration; - audioProperties.codec = bestStreamInfo->codec; - audioProperties.bitrate = bestStreamInfo->bitrate; + audioProperties.codec = *bestStreamInfo->codec; + audioProperties.bitrate = *bestStreamInfo->bitrate; + audioProperties.channelCount = *bestStreamInfo->channelCount; + audioProperties.sampleRate = *bestStreamInfo->sampleRate; audioProperties.bitsPerSample = bestStreamInfo->bitsPerSample; - audioProperties.channelCount = bestStreamInfo->channelCount; - audioProperties.sampleRate = bestStreamInfo->sampleRate; return audioProperties; } diff --git a/src/libs/audio/impl/taglib/AudioFileInfo.cpp b/src/libs/audio/impl/taglib/AudioFileInfo.cpp index 2b509804..f42ff842 100644 --- a/src/libs/audio/impl/taglib/AudioFileInfo.cpp +++ b/src/libs/audio/impl/taglib/AudioFileInfo.cpp @@ -60,9 +60,20 @@ namespace lms::audio::taglib // Common properties audioProperties.bitrate = static_cast(properties.bitrate() * 1000); + if (audioProperties.bitrate == 0) + throw AudioFileParsingException{ "Cannot determine bitrate" }; + audioProperties.channelCount = static_cast(properties.channels()); + if (audioProperties.channelCount == 0) + throw AudioFileParsingException{ "Cannot determine channel count" }; + audioProperties.duration = std::chrono::milliseconds{ properties.lengthInMilliseconds() }; + if (audioProperties.duration == decltype(audioProperties.duration)::zero()) + throw AudioFileParsingException{ "Cannot determine duration" }; + audioProperties.sampleRate = static_cast(properties.sampleRate()); + if (audioProperties.sampleRate == 0) + throw AudioFileParsingException{ "Cannot determine sample rate" }; // Guess container from the file type if (const auto* apeFile{ dynamic_cast(&file) }) @@ -90,8 +101,7 @@ namespace lms::audio::taglib audioProperties.codec = CodecType::WMA9Pro; break; case ::TagLib::ASF::Properties::Codec::Unknown: - audioProperties.codec = std::nullopt; - break; + throw AudioFileParsingException{ "Unhandled ASF codec type" }; } audioProperties.bitsPerSample = asfFile->audioProperties()->bitsPerSample(); @@ -122,8 +132,7 @@ namespace lms::audio::taglib audioProperties.codec = CodecType::ALAC; break; case ::TagLib::MP4::Properties::Codec::Unknown: - audioProperties.codec = std::nullopt; - break; + throw AudioFileParsingException{ "Unhandled MP4 codec type" }; } audioProperties.bitsPerSample = mp4File->audioProperties()->bitsPerSample(); @@ -195,6 +204,13 @@ namespace lms::audio::taglib audioProperties.codec = CodecType::WavPack; audioProperties.bitsPerSample = wavPackFile->audioProperties()->bitsPerSample(); } + else + { + throw AudioFileParsingException{ "Unhandled file type" }; + } + + if (audioProperties.bitsPerSample && *audioProperties.bitsPerSample == 0) + audioProperties.bitsPerSample.reset(); return audioProperties; } diff --git a/src/libs/audio/impl/taglib/Utils.cpp b/src/libs/audio/impl/taglib/Utils.cpp index 7a7bdd39..c550c0d0 100644 --- a/src/libs/audio/impl/taglib/Utils.cpp +++ b/src/libs/audio/impl/taglib/Utils.cpp @@ -229,16 +229,10 @@ namespace lms::audio::taglib::utils } if (!file) - { - LMS_LOG(METADATA, ERROR, "File " << p << ": parsing failed"); - throw AudioFileParsingException{ p, "Parsing failed" }; - } + throw AudioFileParsingException{ "Parsing failed" }; if (!file->audioProperties()) - { - LMS_LOG(METADATA, ERROR, "File " << p << ": no audio properties"); - throw AudioFileNoAudioPropertiesException{ p }; - } + throw AudioFileParsingException{ "No audio properties" }; return file; } diff --git a/src/libs/audio/include/audio/AudioTypes.hpp b/src/libs/audio/include/audio/AudioTypes.hpp index 802d680d..2185056a 100644 --- a/src/libs/audio/include/audio/AudioTypes.hpp +++ b/src/libs/audio/include/audio/AudioTypes.hpp @@ -74,12 +74,12 @@ namespace lms::audio struct AudioProperties { - std::optional container; - std::optional codec; - std::chrono::milliseconds duration{}; - std::optional bitrate; + ContainerType container; + CodecType codec; + std::chrono::milliseconds duration; + unsigned bitrate; + unsigned channelCount; + unsigned sampleRate; std::optional bitsPerSample; - std::optional channelCount; - std::optional sampleRate; }; } // namespace lms::audio \ No newline at end of file diff --git a/src/libs/audio/include/audio/IAudioFileInfo.hpp b/src/libs/audio/include/audio/IAudioFileInfo.hpp index f528a7bc..b417e78b 100644 --- a/src/libs/audio/include/audio/IAudioFileInfo.hpp +++ b/src/libs/audio/include/audio/IAudioFileInfo.hpp @@ -43,19 +43,7 @@ namespace lms::audio class AudioFileParsingException : public Exception { public: - AudioFileParsingException(const std::filesystem::path& path, std::string_view error = "") - : Exception{ error }, _path{ path } {} - - const std::filesystem::path& getPath() const { return _path; } - - private: - std::filesystem::path _path; - }; - - class AudioFileNoAudioPropertiesException : public AudioFileParsingException - { - public: - using AudioFileParsingException::AudioFileParsingException; + using Exception::Exception; }; class IOException : public Exception diff --git a/src/libs/services/scanner/impl/scanners/audiofile/AudioFileScanOperation.cpp b/src/libs/services/scanner/impl/scanners/audiofile/AudioFileScanOperation.cpp index 1be58f75..814b9242 100644 --- a/src/libs/services/scanner/impl/scanners/audiofile/AudioFileScanOperation.cpp +++ b/src/libs/services/scanner/impl/scanners/audiofile/AudioFileScanOperation.cpp @@ -539,10 +539,6 @@ namespace lms::scanner index++; }); } - catch (const audio::AudioFileNoAudioPropertiesException&) - { - addError(getFilePath()); - } catch (const audio::IOException& e) { addError(getFilePath(), e.getErrorCode()); @@ -672,11 +668,11 @@ namespace lms::scanner track.modify()->setScanVersion(getScannerSettings().audioScanVersion); // Audio properties - track.modify()->setBitrate(_file->audioProperties.bitrate ? *_file->audioProperties.bitrate : 0); + track.modify()->setBitrate(_file->audioProperties.bitrate); track.modify()->setBitsPerSample(_file->audioProperties.bitsPerSample ? *_file->audioProperties.bitsPerSample : 0); - track.modify()->setChannelCount(_file->audioProperties.channelCount ? *_file->audioProperties.channelCount : 0); + track.modify()->setChannelCount(_file->audioProperties.channelCount); track.modify()->setDuration(_file->audioProperties.duration); - track.modify()->setSampleRate(_file->audioProperties.sampleRate ? *_file->audioProperties.sampleRate : 0); + track.modify()->setSampleRate(_file->audioProperties.sampleRate); track.modify()->setFileSize(getFileSize()); track.modify()->setLastWriteTime(getLastWriteTime()); diff --git a/src/libs/subsonic/impl/endpoints/MediaRetrieval.cpp b/src/libs/subsonic/impl/endpoints/MediaRetrieval.cpp index 43bb604f..8254c229 100644 --- a/src/libs/subsonic/impl/endpoints/MediaRetrieval.cpp +++ b/src/libs/subsonic/impl/endpoints/MediaRetrieval.cpp @@ -120,10 +120,7 @@ namespace lms::api::subsonic { const auto audioFile{ audio::parseAudioFile(trackPath) }; - if (!audioFile->getAudioProperties().codec) - throw RequestedDataNotFoundError{}; // TODO 404? - - return isCodecCompatibleWithOutputFormat(*audioFile->getAudioProperties().codec, outputFormat); + return isCodecCompatibleWithOutputFormat(audioFile->getAudioProperties().codec, outputFormat); } catch (const audio::Exception& e) { diff --git a/src/lms/ui/explore/ReleaseView.cpp b/src/lms/ui/explore/ReleaseView.cpp index 413cb7fd..63c451d6 100644 --- a/src/lms/ui/explore/ReleaseView.cpp +++ b/src/lms/ui/explore/ReleaseView.cpp @@ -147,12 +147,9 @@ namespace lms::ui { if (const auto audioFile{ audio::parseAudioFile(track->getAbsoluteFilePath()) }) { - if (audioFile->getAudioProperties().codec) - { - releaseInfo->setCondition("if-has-codec", true); - releaseInfo->bindString("codec", audio::codecTypeToString(*audioFile->getAudioProperties().codec).c_str(), Wt::TextFormat::Plain); - break; - } + releaseInfo->setCondition("if-has-codec", true); + releaseInfo->bindString("codec", audio::codecTypeToString(audioFile->getAudioProperties().codec).c_str(), Wt::TextFormat::Plain); + break; } } catch (const audio::Exception& e) diff --git a/src/lms/ui/explore/TrackListHelpers.cpp b/src/lms/ui/explore/TrackListHelpers.cpp index 25821d7c..8721745b 100644 --- a/src/lms/ui/explore/TrackListHelpers.cpp +++ b/src/lms/ui/explore/TrackListHelpers.cpp @@ -133,11 +133,8 @@ namespace lms::ui::TrackListHelpers { if (const auto audioFile{ audio::parseAudioFile(track->getAbsoluteFilePath()) }) { - if (audioFile->getAudioProperties().codec) - { - trackInfo->setCondition("if-has-codec", true); - trackInfo->bindString("codec", audio::codecTypeToString(*audioFile->getAudioProperties().codec).c_str(), Wt::TextFormat::Plain); - } + trackInfo->setCondition("if-has-codec", true); + trackInfo->bindString("codec", audio::codecTypeToString(audioFile->getAudioProperties().codec).c_str(), Wt::TextFormat::Plain); } } catch (const audio::Exception& e) diff --git a/src/tools/audioinfo/LmsAudioInfo.cpp b/src/tools/audioinfo/LmsAudioInfo.cpp index b87ae73b..2a05ad15 100644 --- a/src/tools/audioinfo/LmsAudioInfo.cpp +++ b/src/tools/audioinfo/LmsAudioInfo.cpp @@ -39,19 +39,13 @@ namespace lms::audio std::ostream& operator<<(std::ostream& os, const AudioProperties& audioProperties) { os << "\tDuration: " << std::fixed << std::setprecision(2) << std::chrono::duration_cast>(audioProperties.duration) << std::endl; - - if (audioProperties.container) - os << "\tContainer: " << containerTypeToString(*audioProperties.container) << std::endl; - if (audioProperties.codec) - os << "\tCodec: " << codecTypeToString(*audioProperties.codec) << std::endl; - if (audioProperties.bitrate) - os << "\tBitrate: " << *audioProperties.bitrate << " bps" << std::endl; + os << "\tContainer: " << containerTypeToString(audioProperties.container) << std::endl; + os << "\tCodec: " << codecTypeToString(audioProperties.codec) << std::endl; + os << "\tBitrate: " << audioProperties.bitrate << " bps" << std::endl; if (audioProperties.bitsPerSample) os << "\tBitsPerSample: " << *audioProperties.bitsPerSample << std::endl; - if (audioProperties.channelCount) - os << "\tChannelCount: " << *audioProperties.channelCount << std::endl; - if (audioProperties.sampleRate) - os << "\tSampleRate: " << *audioProperties.sampleRate << std::endl; + os << "\tChannelCount: " << audioProperties.channelCount << std::endl; + os << "\tSampleRate: " << audioProperties.sampleRate << std::endl; return os; }