From 19ddb9be0b370e6d15377d81297d49ce1249345f Mon Sep 17 00:00:00 2001 From: kdeng00 Date: Sun, 8 Sep 2019 18:48:14 -0400 Subject: [PATCH] Added song streamingh endpoint and removed redundant making oatpp::String shared when it already is a shared object #61 --- CMakeLists.txt | 2 + include/callback/StreamCallback.h | 27 +++++++ include/controller/SongController.hpp | 108 +++----------------------- include/model/Models.h | 4 +- src/Main.cpp | 2 +- src/callback/StreamCallback.cpp | 42 ++++++++++ 6 files changed, 83 insertions(+), 102 deletions(-) create mode 100644 include/callback/StreamCallback.h create mode 100644 src/callback/StreamCallback.cpp diff --git a/CMakeLists.txt b/CMakeLists.txt index f8783b5..f3c9e42 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -6,6 +6,7 @@ set(CMAKE_CXX_STANDARD_REQUIRED ON) set(CMAKE_CXX_STANDARD 17) set(SOURCES + src/callback/StreamCallback.cpp src/database/AlbumRepository.cpp src/database/ArtistRepository.cpp src/database/BaseRepository.cpp @@ -26,6 +27,7 @@ set(SOURCES src/utility/MetadataRetriever.cpp ) set(HEADERS + include/callback/StreamCallback.h include/component/AppComponent.hpp include/controller/AlbumController.hpp include/controller/ArtistController.hpp diff --git a/include/callback/StreamCallback.h b/include/callback/StreamCallback.h new file mode 100644 index 0000000..c1d665a --- /dev/null +++ b/include/callback/StreamCallback.h @@ -0,0 +1,27 @@ +#ifndef STREAMCALLBACK_H_ +#define STREAMCALLBACK_H_ + +#include + +#include "oatpp/core/data/stream/FileStream.hpp" +#include "oatpp/web/protocol/http/outgoing/ChunkedBody.hpp" + +namespace callback +{ + class StreamCallback : public oatpp::data::stream::ReadCallback + { + public: + StreamCallback(); + StreamCallback(const std::string&); + + oatpp::data::v_io_size read(void*, oatpp::data::v_io_size); + private: + std::string m_songPath; + + long m_bytesRead; + long m_counter; + long m_fileSize; + }; +} + +#endif diff --git a/include/controller/SongController.hpp b/include/controller/SongController.hpp index 0aa9f70..b46cdfd 100644 --- a/include/controller/SongController.hpp +++ b/include/controller/SongController.hpp @@ -9,15 +9,16 @@ #include #include -#include "oatpp/web/protocol/http/outgoing/ChunkedBody.hpp" #include "oatpp/core/data/stream/ChunkedBuffer.hpp" #include "oatpp/core/data/stream/FileStream.hpp" #include "oatpp/core/macro/codegen.hpp" #include "oatpp/core/macro/component.hpp" #include "oatpp/web/mime/multipart/InMemoryPartReader.hpp" #include "oatpp/web/mime/multipart/Reader.hpp" +#include "oatpp/web/protocol/http/outgoing/ChunkedBody.hpp" #include "oatpp/web/server/api/ApiController.hpp" +#include "callback/StreamCallback.h" #include "database/SongRepository.h" #include "dto/SongDto.hpp" #include "manager/SongManager.h" @@ -30,93 +31,6 @@ namespace fs = std::filesystem; namespace controller { - class myCallback : public oatpp::data::stream::ReadCallback - { - public: - myCallback() - { - std::cout << "the non desired constructor chosen" << std::endl; - std::exit(-1); - } - - myCallback(const std::string& songPath) - : m_songPath(songPath.c_str()), - m_counter(0) - { - std::cout << "the desired constructor chosen" << std::endl; - auto b = oatpp::base::StrBuffer::loadFromFile(m_songPath.c_str()); - m_fileSize = b->getSize(); - } - - myCallback(myCallback& c) = default; - - - // I know, bad naming convention - oatpp::data::v_io_size demoStreamZero(void *buff, oatpp::data::v_io_size count) - { - oatpp::data::stream::FileInputStream rs(m_songPath.c_str()); - - return rs.read(buff, count); - } - - oatpp::data::v_io_size demoStreamOne(void *buff, oatpp::data::v_io_size count) - { - std::cout << "file size " << m_fileSize << std::endl; - std::cout << "getting file input stream" << std::endl; - - oatpp::data::stream::FileInputStream rs(m_songPath.c_str()); - - std::cout << "retrieving file" << std::endl; - auto f = rs.getFile(); - std::cout << "file retrieved" << std::endl; - - std::cout << "starting m_counter val " << m_counter << std::endl;; - auto newPos = m_counter * count; - auto bytesLeft = m_fileSize - m_bytesRead; - - std::cout << "bytes left " << bytesLeft << std::endl; - - //if (newPos >= m_fileSize) { - if (bytesLeft <= 0) { - std::cout << "pos " << newPos << std::endl; - std::cout << "done reading" << std::endl; - return 0; - } - - auto fPos = std::ftell(f); - std::cout << "current file position indicator " << fPos << std::endl; - - std::fseek(f, newPos, SEEK_SET); - - fPos = std::ftell(f); - std::cout << "current file position indicator " << fPos << std::endl; - - buff = malloc(count); - std::fgets((char*)buff, count, f); - - std::cout << "ending m_counter val " << m_counter << std::endl; - - m_bytesRead += count; - ++m_counter; - - return count; - } - - oatpp::data::v_io_size read(void *buff, oatpp::data::v_io_size count) - { - - return demoStreamZero(buff, count); - } - private: - std::string m_songPath; - - long m_fileSize; - long m_bytesRead = 0; - long m_counter; - - int m_iterations; - }; - class SongController : public oatpp::web::server::api::ApiController { public: @@ -242,9 +156,7 @@ namespace controller // TODO: work on this to handle the database records ENDPOINT("DELETE", "api/v1/song/data/{id}", songDelete, PATH(Int32, id)) { - - model::Song song; - song.id = id; + model::Song song(id); manager::SongManager sngMgr(m_bConf); sngMgr.deleteSong(song); @@ -255,21 +167,17 @@ namespace controller // TODO: create endpoint for streaming songs ENDPOINT("GET", "/api/v1/song/stream/{id}", streamSong, PATH(Int32, id)) { - database::SongRepository songRepo(m_bConf); model::Song songDb(id); songDb = songRepo.retrieveRecord(songDb, type::SongFilter::id); - myCallback cb(songDb.songPath); - auto cb_sh = std::make_shared(cb); - auto dSize = 1024; - dSize = 100000; - auto db = std::make_shared(oatpp::web::protocol::http::outgoing::ChunkedBody(cb_sh, nullptr, dSize)); + oatpp::data::v_io_size dSize = 1024; + + auto db = std::make_shared( + std::make_shared(songDb.songPath), nullptr, dSize); auto response = OutgoingResponse::createShared(Status::CODE_200, db); - //auto response = createResponse(Status::CODE_200, ""); response->putHeader(Header::CONNECTION, Header::Value::CONNECTION_KEEP_ALIVE); - response->putHeader("Accept-Ranges", "bytes"); response->putHeader(Header::CONTENT_TYPE, "audio/mpeg"); return response; @@ -278,7 +186,9 @@ namespace controller #include OATPP_CODEGEN_END(ApiController) private: std::string m_exe_path; + model::BinaryPath m_bConf; + const long m_dataSize = std::numeric_limits::max(); }; } diff --git a/include/model/Models.h b/include/model/Models.h index 8e21dba..50949ea 100644 --- a/include/model/Models.h +++ b/include/model/Models.h @@ -112,8 +112,8 @@ namespace model { BinaryPath() = default; BinaryPath(const char *p) : path(std::move(p)) { } - BinaryPath(std::string& p) : path(std::move(p)) { } - BinaryPath(const std::string& p) : path(std::move(p)) { } + BinaryPath(std::string& p) : path(p) { } + BinaryPath(const std::string& p) : path(p) { } std::string path; }; diff --git a/src/Main.cpp b/src/Main.cpp index 768f741..526197f 100644 --- a/src/Main.cpp +++ b/src/Main.cpp @@ -5,7 +5,7 @@ #include #include -#include "oatpp/network/server/Server.hpp" +#include #include "oatpp/network/server/SimpleTCPConnectionProvider.hpp" #include "oatpp/web/server/HttpConnectionHandler.hpp" diff --git a/src/callback/StreamCallback.cpp b/src/callback/StreamCallback.cpp new file mode 100644 index 0000000..44deb40 --- /dev/null +++ b/src/callback/StreamCallback.cpp @@ -0,0 +1,42 @@ +#include "callback/StreamCallback.h" + +#include +#include +#include + +callback::StreamCallback::StreamCallback() : + m_counter(0) { } + +callback::StreamCallback::StreamCallback(const std::string& songPath) : + m_songPath(songPath), + m_counter(0), + m_bytesRead(0) +{ + // getting file size + std::ifstream song(m_songPath.c_str(), std::ios::binary | std::ios::in | std::ios::ate); + m_fileSize = song.tellg(); + std::cout << "file size is " << m_fileSize << " bytes" << std::endl; +} + + +oatpp::data::v_io_size callback::StreamCallback::read(void *buff, oatpp::data::v_io_size count) +{ + if (m_counter >= m_fileSize) { + std::cout << "done streaming song" << std::endl; + return 0; + } + + std::fstream song(m_songPath.c_str(), std::ios::binary | std::ios::in); + song.seekg(m_counter); + + std::unique_ptr data(new char[count]); + + song.read(data.get(), count); + std::memcpy(buff, data.get(), count); + + m_counter += count; + + song.close(); + + return count; +}