Subsonic API: added contentType and transcodedContentType fields, fixes #363
This commit is contained in:
@@ -258,35 +258,39 @@ namespace Av
|
||||
return res;
|
||||
}
|
||||
|
||||
std::optional<AudioFileFormat> guessAudioFileFormat(const std::filesystem::path& file)
|
||||
std::string_view getMimeType(const std::filesystem::path& fileExtension)
|
||||
{
|
||||
const AVOutputFormat* format{ ::av_guess_format(NULL, file.string().c_str(), NULL) };
|
||||
if (!format || !format->name)
|
||||
static const std::unordered_map<std::filesystem::path, std::string_view> entries
|
||||
{
|
||||
LMS_LOG(AV, INFO) << "File '" << file.string() << "': cannot guess file format!";
|
||||
return std::nullopt;
|
||||
}
|
||||
{".mp3", "audio/mpeg"},
|
||||
{".ogg", "audio/ogg"},
|
||||
{".oga", "audio/ogg"},
|
||||
{".opus", "audio/opus"},
|
||||
{".aac", "audio/aac"},
|
||||
{".alac", "audio/mp4"},
|
||||
{".m4a", "audio/mp4"},
|
||||
{".m4b", "audio/mp4"},
|
||||
{".flac", "audio/flac"},
|
||||
{".webm", "audio/webm"},
|
||||
{".wav", "audio/x-wav"},
|
||||
{".wma", "audio/x-ms-wma"},
|
||||
{".ape", "audio/x-monkeys-audio"},
|
||||
{".mpc", "audio/x-musepack"},
|
||||
{".shn", "audio/x-shn"},
|
||||
{".aif", "audio/x-aiff"},
|
||||
{".aiff", "audio/x-aiff"},
|
||||
{".m3u", "audio/x-mpegurl"},
|
||||
{".pls", "audio/x-scpls"},
|
||||
{".dsf", "audio/dsd"},
|
||||
{".wv", "audio/x-wavpack"},
|
||||
{".wvp", "audio/x-wavpack"},
|
||||
{".mka", "audio/x-matroska"},
|
||||
};
|
||||
|
||||
LMS_LOG(AV, DEBUG) << "File '" << file.string() << "', formats = '" << format->name << "'";
|
||||
auto it{ entries.find(fileExtension) };
|
||||
if (it == std::cend(entries))
|
||||
return "";
|
||||
|
||||
const auto formats{ StringUtils::splitString(format->name, ",") };
|
||||
if (formats.size() > 1)
|
||||
LMS_LOG(AV, INFO) << "File '" << file.string() << "' reported several formats: '" << format->name << "'";
|
||||
|
||||
std::vector<std::string_view> mimeTypes;
|
||||
if (format->mime_type)
|
||||
mimeTypes = StringUtils::splitString(format->mime_type, ",");
|
||||
|
||||
if (mimeTypes.empty())
|
||||
LMS_LOG(AV, INFO) << "File '" << file.string() << "', no mime type found!";
|
||||
else if (mimeTypes.size() > 1)
|
||||
LMS_LOG(AV, INFO) << "File '" << file.string() << "' reported several mime types: '" << format->mime_type << "'";
|
||||
|
||||
AudioFileFormat res;
|
||||
res.format = formats.front();
|
||||
res.mimeType = mimeTypes.empty() ? "application/octet-stream" : mimeTypes.front();
|
||||
|
||||
return res;
|
||||
return it->second;
|
||||
}
|
||||
|
||||
} // namespace Av
|
||||
|
||||
@@ -26,13 +26,7 @@ namespace Av
|
||||
{
|
||||
std::unique_ptr<IResourceHandler> createRawResourceHandler(const std::filesystem::path& path)
|
||||
{
|
||||
std::string mimeType;
|
||||
const auto guessedAudioFormat{ Av::guessAudioFileFormat(path) };
|
||||
if (guessedAudioFormat)
|
||||
mimeType = guessedAudioFormat->mimeType;
|
||||
else
|
||||
mimeType = "application/octet-stream";
|
||||
|
||||
return createFileResourceHandler(path, mimeType);
|
||||
std::string_view mimeType{ Av::getMimeType(path.extension()) };
|
||||
return createFileResourceHandler(path, mimeType.empty() ? "application/octet-stream" : mimeType);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -27,6 +27,7 @@
|
||||
#include <unordered_map>
|
||||
#include <optional>
|
||||
#include <string>
|
||||
#include <string_view>
|
||||
#include <vector>
|
||||
|
||||
#include "Types.hpp"
|
||||
@@ -72,7 +73,7 @@ namespace Av
|
||||
std::string format;
|
||||
};
|
||||
|
||||
std::optional<AudioFileFormat> guessAudioFileFormat(const std::filesystem::path& file);
|
||||
std::string_view getMimeType(const std::filesystem::path& fileExtension);
|
||||
|
||||
} // namespace Av
|
||||
|
||||
|
||||
@@ -21,6 +21,7 @@
|
||||
|
||||
#include <string_view>
|
||||
|
||||
#include "av/IAudioFile.hpp"
|
||||
#include "services/database/Artist.hpp"
|
||||
#include "services/database/Cluster.hpp"
|
||||
#include "services/database/Listen.hpp"
|
||||
@@ -123,7 +124,11 @@ namespace API::Subsonic
|
||||
trackResponse.setAttribute("suffix", extension.string().substr(1));
|
||||
}
|
||||
|
||||
trackResponse.setAttribute("transcodedSuffix", formatToSuffix(user->getSubsonicDefaultTranscodeFormat()));
|
||||
{
|
||||
const std::string fileSuffix{ formatToSuffix(user->getSubsonicDefaultTranscodeFormat()) };
|
||||
trackResponse.setAttribute("transcodedSuffix", fileSuffix);
|
||||
trackResponse.setAttribute("transcodedContentType", Av::getMimeType(std::filesystem::path{ "." + fileSuffix }));
|
||||
}
|
||||
|
||||
trackResponse.setAttribute("coverArt", idToString(track->getId()));
|
||||
|
||||
@@ -151,6 +156,7 @@ namespace API::Subsonic
|
||||
trackResponse.setAttribute("bitRate", (track->getBitrate() / 1000));
|
||||
trackResponse.setAttribute("type", "music");
|
||||
trackResponse.setAttribute("created", StringUtils::toISO8601String(track->getLastWritten()));
|
||||
trackResponse.setAttribute("contentType", Av::getMimeType(track->getPath().extension()));
|
||||
|
||||
if (const Wt::WDateTime dateTime{ Service<Feedback::IFeedbackService>::get()->getStarredDateTime(user->getId(), track->getId()) }; dateTime.isValid())
|
||||
trackResponse.setAttribute("starred", StringUtils::toISO8601String(dateTime));
|
||||
|
||||
@@ -152,10 +152,10 @@ namespace UserInterface
|
||||
}
|
||||
}
|
||||
|
||||
if (std::size_t meanBitrate{ release->getMeanBitrate() })
|
||||
if (const std::size_t meanBitrate{ release->getMeanBitrate() })
|
||||
{
|
||||
releaseInfo->setCondition("if-has-bitrate", true);
|
||||
releaseInfo->bindString("bitrate", std::to_string(release->getMeanBitrate() / 1000) + " kbps");
|
||||
releaseInfo->bindString("bitrate", std::to_string(meanBitrate / 1000) + " kbps");
|
||||
}
|
||||
|
||||
Wt::WPushButton* okBtn{ releaseInfo->bindNew<Wt::WPushButton>("ok-btn", Wt::WString::tr("Lms.ok")) };
|
||||
|
||||
Reference in New Issue
Block a user