diff --git a/src/libs/av/CMakeLists.txt b/src/libs/av/CMakeLists.txt
index 4205e35c..7c556cb3 100644
--- a/src/libs/av/CMakeLists.txt
+++ b/src/libs/av/CMakeLists.txt
@@ -1,6 +1,7 @@
add_library(lmsav SHARED
impl/AudioFile.cpp
+ impl/RawResourceHandlerCreator.cpp
impl/Transcoder.cpp
impl/TranscodeResourceHandler.cpp
impl/Types.cpp
diff --git a/src/libs/av/impl/RawResourceHandlerCreator.cpp b/src/libs/av/impl/RawResourceHandlerCreator.cpp
new file mode 100644
index 00000000..5272b421
--- /dev/null
+++ b/src/libs/av/impl/RawResourceHandlerCreator.cpp
@@ -0,0 +1,38 @@
+/*
+ * Copyright (C) 2023 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 .
+ */
+
+#include "av/RawResourceHandlerCreator.hpp"
+
+#include "av/IAudioFile.hpp"
+#include "utils/FileResourceHandlerCreator.hpp"
+
+namespace Av
+{
+ std::unique_ptr 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);
+ }
+}
diff --git a/src/libs/av/include/av/RawResourceHandlerCreator.hpp b/src/libs/av/include/av/RawResourceHandlerCreator.hpp
new file mode 100644
index 00000000..ed7b0e14
--- /dev/null
+++ b/src/libs/av/include/av/RawResourceHandlerCreator.hpp
@@ -0,0 +1,30 @@
+/*
+ * Copyright (C) 2023 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 .
+ */
+
+#pragma once
+
+#include
+#include
+
+#include "utils/IResourceHandler.hpp"
+
+namespace Av
+{
+ std::unique_ptr createRawResourceHandler(const std::filesystem::path& path);
+}
\ No newline at end of file
diff --git a/src/libs/subsonic/impl/entrypoints/MediaRetrieval.cpp b/src/libs/subsonic/impl/entrypoints/MediaRetrieval.cpp
index 43729bcb..452070e7 100644
--- a/src/libs/subsonic/impl/entrypoints/MediaRetrieval.cpp
+++ b/src/libs/subsonic/impl/entrypoints/MediaRetrieval.cpp
@@ -20,6 +20,7 @@
#include "MediaRetrieval.hpp"
#include "av/IAudioFile.hpp"
+#include "av/RawResourceHandlerCreator.hpp"
#include "av/TranscodeParameters.hpp"
#include "av/TranscodeResourceHandlerCreator.hpp"
#include "av/Types.hpp"
@@ -160,7 +161,7 @@ namespace API::Subsonic
trackPath = track->getPath();
}
- resourceHandler = createFileResourceHandler(trackPath);
+ resourceHandler = Av::createRawResourceHandler(trackPath);
}
else
{
@@ -185,7 +186,7 @@ namespace API::Subsonic
if (streamParameters.transcodeParameters)
resourceHandler = Av::createTranscodeResourceHandler(streamParameters.inputFileParameters, *streamParameters.transcodeParameters, streamParameters.estimateContentLength);
else
- resourceHandler = createFileResourceHandler(streamParameters.inputFileParameters.trackPath);
+ resourceHandler = Av::createRawResourceHandler(streamParameters.inputFileParameters.trackPath);
}
else
{
diff --git a/src/libs/utils/impl/FileResourceHandler.cpp b/src/libs/utils/impl/FileResourceHandler.cpp
index 8e3a6eb0..b0b4e53f 100644
--- a/src/libs/utils/impl/FileResourceHandler.cpp
+++ b/src/libs/utils/impl/FileResourceHandler.cpp
@@ -24,108 +24,106 @@
#include "utils/Logger.hpp"
std::unique_ptr
-createFileResourceHandler(const std::filesystem::path& path)
+createFileResourceHandler(const std::filesystem::path& path, std::string_view mimeType)
{
- return std::make_unique(path);
+ return std::make_unique(path, mimeType);
}
-
-FileResourceHandler::FileResourceHandler(const std::filesystem::path& path)
-: _path {path}
+FileResourceHandler::FileResourceHandler(const std::filesystem::path& path, std::string_view mimeType)
+ : _path{ path }
+ , _mimeType{ mimeType }
{
}
-
Wt::Http::ResponseContinuation*
FileResourceHandler::processRequest(const Wt::Http::Request& request, Wt::Http::Response& response)
{
- ::uint64_t startByte {_offset};
- std::ifstream ifs {_path.string().c_str(), std::ios::in | std::ios::binary};
+ ::uint64_t startByte{ _offset };
+ std::ifstream ifs{ _path.string().c_str(), std::ios::in | std::ios::binary };
- if (startByte == 0)
- {
- if (!ifs)
- {
- LMS_LOG(UTILS, ERROR) << "Cannot open file stream for '" << _path.string() << "'";
- response.setStatus(404);
- return {};
- }
- else
- {
- response.setStatus(200);
- }
+ if (startByte == 0)
+ {
+ if (!ifs)
+ {
+ LMS_LOG(UTILS, ERROR) << "Cannot open file stream for '" << _path.string() << "'";
+ response.setStatus(404);
+ return {};
+ }
- ifs.seekg(0, std::ios::end);
- const ::uint64_t fileSize {static_cast<::uint64_t>(ifs.tellg())};
- ifs.seekg(0, std::ios::beg);
+ ifs.seekg(0, std::ios::end);
+ const ::uint64_t fileSize{ static_cast<::uint64_t>(ifs.tellg()) };
+ ifs.seekg(0, std::ios::beg);
- LMS_LOG(UTILS, DEBUG) << "File '" << _path.string() << "', fileSize = " << fileSize;
+ LMS_LOG(UTILS, DEBUG) << "File '" << _path.string() << "', fileSize = " << fileSize;
- const Wt::Http::Request::ByteRangeSpecifier ranges {request.getRanges(fileSize)};
- if (!ranges.isSatisfiable())
- {
- std::ostringstream contentRange;
- contentRange << "bytes */" << fileSize;
- response.setStatus(416); // Requested range not satisfiable
- response.addHeader("Content-Range", contentRange.str());
+ const Wt::Http::Request::ByteRangeSpecifier ranges{ request.getRanges(fileSize) };
+ if (!ranges.isSatisfiable())
+ {
+ std::ostringstream contentRange;
+ contentRange << "bytes */" << fileSize;
+ response.setStatus(416); // Requested range not satisfiable
+ response.addHeader("Content-Range", contentRange.str());
- LMS_LOG(UTILS, DEBUG) << "Range not satisfiable";
- return {};
- }
+ LMS_LOG(UTILS, DEBUG) << "Range not satisfiable";
+ return {};
+ }
- if (ranges.size() == 1)
- {
- LMS_LOG(UTILS, DEBUG) << "Range requested = " << ranges[0].firstByte() << "/" << ranges[0].lastByte();
+ if (ranges.size() == 1)
+ {
+ LMS_LOG(UTILS, DEBUG) << "Range requested = " << ranges[0].firstByte() << "/" << ranges[0].lastByte();
- response.setStatus(206);
- startByte = ranges[0].firstByte();
- _beyondLastByte = ranges[0].lastByte() + 1;
+ response.setStatus(206);
+ startByte = ranges[0].firstByte();
+ _beyondLastByte = ranges[0].lastByte() + 1;
- std::ostringstream contentRange;
- contentRange << "bytes " << startByte << "-"
- << _beyondLastByte - 1 << "/" << fileSize;
+ std::ostringstream contentRange;
+ contentRange << "bytes " << startByte << "-"
+ << _beyondLastByte - 1 << "/" << fileSize;
- response.addHeader("Content-Range", contentRange.str());
- response.setContentLength(_beyondLastByte - startByte);
- }
- else
- {
- LMS_LOG(UTILS, DEBUG) << "No range requested";
+ response.addHeader("Content-Range", contentRange.str());
+ response.setContentLength(_beyondLastByte - startByte);
+ }
+ else
+ {
+ LMS_LOG(UTILS, DEBUG) << "No range requested";
- _beyondLastByte = fileSize;
- response.setContentLength(_beyondLastByte);
- }
- }
- else if (!ifs)
- {
- LMS_LOG(UTILS, ERROR) << "Cannot reopen file stream for '" << _path.string() << "'";
- return {};
- }
+ response.setStatus(200);
+ _beyondLastByte = fileSize;
+ response.setContentLength(_beyondLastByte);
+ }
- ifs.seekg(static_cast(startByte));
+ LMS_LOG(UTILS, DEBUG) << "Mimetype set to '" << _mimeType << "'";
+ response.setMimeType(_mimeType);
+ }
+ else if (!ifs)
+ {
+ LMS_LOG(UTILS, ERROR) << "Cannot reopen file stream for '" << _path.string() << "'";
+ return {};
+ }
- std::vector buf;
- buf.resize(_chunkSize);
+ ifs.seekg(static_cast(startByte));
- ::uint64_t restSize = _beyondLastByte - startByte;
- ::uint64_t pieceSize = buf.size() > restSize ? restSize : buf.size();
+ std::vector buf;
+ buf.resize(_chunkSize);
- ifs.read(&buf[0], pieceSize);
- const ::uint64_t actualPieceSize {static_cast<::uint64_t>(ifs.gcount())};
- response.out().write(&buf[0], actualPieceSize);
+ ::uint64_t restSize = _beyondLastByte - startByte;
+ ::uint64_t pieceSize = buf.size() > restSize ? restSize : buf.size();
- LMS_LOG(UTILS, DEBUG) << "Written " << actualPieceSize << " bytes";
+ ifs.read(&buf[0], pieceSize);
+ const ::uint64_t actualPieceSize{ static_cast<::uint64_t>(ifs.gcount()) };
+ response.out().write(&buf[0], actualPieceSize);
- LMS_LOG(UTILS, DEBUG) << "Progress: " << actualPieceSize << "/" << restSize;
- if (ifs.good() && actualPieceSize < restSize)
- {
- _offset = startByte + actualPieceSize;
- LMS_LOG(UTILS, DEBUG) << "Job not complete! Next chunk offset = " << _offset;
+ LMS_LOG(UTILS, DEBUG) << "Written " << actualPieceSize << " bytes";
- return response.createContinuation();
- }
+ LMS_LOG(UTILS, DEBUG) << "Progress: " << actualPieceSize << "/" << restSize;
+ if (ifs.good() && actualPieceSize < restSize)
+ {
+ _offset = startByte + actualPieceSize;
+ LMS_LOG(UTILS, DEBUG) << "Job not complete! Next chunk offset = " << _offset;
- LMS_LOG(UTILS, DEBUG) << "Job complete!";
- return nullptr;
+ return response.createContinuation();
+ }
+
+ LMS_LOG(UTILS, DEBUG) << "Job complete!";
+ return nullptr;
}
-
diff --git a/src/libs/utils/impl/FileResourceHandler.hpp b/src/libs/utils/impl/FileResourceHandler.hpp
index 8293f587..c6e8e58a 100644
--- a/src/libs/utils/impl/FileResourceHandler.hpp
+++ b/src/libs/utils/impl/FileResourceHandler.hpp
@@ -20,21 +20,24 @@
#pragma once
#include
+#include
+#include
#include "utils/IResourceHandler.hpp"
class FileResourceHandler final : public IResourceHandler
{
- public:
- FileResourceHandler(const std::filesystem::path& filePath);
+public:
+ FileResourceHandler(const std::filesystem::path& filePath, std::string_view mimeType);
- private:
- Wt::Http::ResponseContinuation* processRequest(const Wt::Http::Request& request, Wt::Http::Response& response) override;
- void abort() override {};
+private:
+ Wt::Http::ResponseContinuation* processRequest(const Wt::Http::Request& request, Wt::Http::Response& response) override;
+ void abort() override {};
- static constexpr std::size_t _chunkSize {65536};
+ static constexpr std::size_t _chunkSize{ 65536 };
- std::filesystem::path _path;
- ::uint64_t _beyondLastByte {};
- ::uint64_t _offset {};
+ std::filesystem::path _path;
+ std::string _mimeType;
+ ::uint64_t _beyondLastByte{};
+ ::uint64_t _offset{};
};
diff --git a/src/libs/utils/include/utils/FileResourceHandlerCreator.hpp b/src/libs/utils/include/utils/FileResourceHandlerCreator.hpp
index 8f69e18a..00106721 100644
--- a/src/libs/utils/include/utils/FileResourceHandlerCreator.hpp
+++ b/src/libs/utils/include/utils/FileResourceHandlerCreator.hpp
@@ -21,8 +21,9 @@
#include
#include
+#include
#include "utils/IResourceHandler.hpp"
-std::unique_ptr createFileResourceHandler(const std::filesystem::path& path);
+std::unique_ptr createFileResourceHandler(const std::filesystem::path& path, std::string_view mimeType);
diff --git a/src/lms/ui/resource/AudioFileResource.cpp b/src/lms/ui/resource/AudioFileResource.cpp
index e7a8809b..293e7aac 100644
--- a/src/lms/ui/resource/AudioFileResource.cpp
+++ b/src/lms/ui/resource/AudioFileResource.cpp
@@ -23,9 +23,9 @@
#include
#include "av/IAudioFile.hpp"
+#include "av/RawResourceHandlerCreator.hpp"
#include "services/database/Session.hpp"
#include "services/database/Track.hpp"
-#include "utils/FileResourceHandlerCreator.hpp"
#include "utils/Logger.hpp"
#include "utils/String.hpp"
#include "LmsApplication.hpp"
@@ -94,16 +94,7 @@ AudioFileResource::handleRequest(const Wt::Http::Request& request,
if (!trackPath)
return;
- fileResourceHandler = createFileResourceHandler(*trackPath);
-
- const auto guessedAudioFormat {Av::guessAudioFileFormat(*trackPath)};
- if (guessedAudioFormat)
- {
- LOG(DEBUG) << "Set mime type to " << guessedAudioFormat->mimeType;
- response.setMimeType(guessedAudioFormat->mimeType);
- }
- else
- response.setMimeType("application/octet-stream");
+ fileResourceHandler = Av::createRawResourceHandler(*trackPath);
}
else
{