diff --git a/src/core/Track.cpp b/src/core/Track.cpp index b767c8c24..eb01ea886 100644 --- a/src/core/Track.cpp +++ b/src/core/Track.cpp @@ -544,3 +544,21 @@ void Track::SetThumbnail(const char *data,unsigned int size){ TrackPtr Track::Copy(){ return TrackPtr(new Track(this->id)); } + +bool Track::GetFileData(DBINT id,db::Connection &db){ + this->InitMeta(NULL); + + this->id = id; + + db::CachedStatement stmt("SELECT t.filename,t.filesize,t.filetime,p.path||f.relative_path||'/'||t.filename FROM tracks t,folders f,paths p WHERE t.folder_id=f.id AND f.path_id=p.id AND t.id=?",db); + stmt.BindInt(0,id); + + if(stmt.Step()==db::Row){ + this->SetValue("filename" ,stmt.ColumnTextUTF(0)); + this->SetValue("filesize" ,stmt.ColumnTextUTF(1)); + this->SetValue("filetime" ,stmt.ColumnTextUTF(2)); + this->SetValue("path" ,stmt.ColumnTextUTF(3)); + return true; + } + return false; +} diff --git a/src/core/Track.h b/src/core/Track.h index 6d9d30ea6..0b00b7e2d 100644 --- a/src/core/Track.h +++ b/src/core/Track.h @@ -56,6 +56,9 @@ namespace musik{ namespace core{ namespace db{ class Connection; } + namespace http{ + class Responder; + } } } ////////////////////////////////////////////////////////////////////////////// @@ -144,6 +147,10 @@ class Track : public ITrack { bool Save(db::Connection &dbConnection,utfstring libraryDirectory,DBINT folderId); DBINT _GetGenre(db::Connection &dbConnection,utfstring genre,bool addRelation,bool aggregated=false); DBINT _GetArtist(db::Connection &dbConnection,utfstring artist,bool addRelation,bool aggregated=false); + + private: + friend class http::Responder; + bool GetFileData(DBINT id,db::Connection &db); }; diff --git a/src/core/core.vcproj b/src/core/core.vcproj index fed409874..8710625b8 100644 --- a/src/core/core.vcproj +++ b/src/core/core.vcproj @@ -617,6 +617,18 @@ + + + + + + @@ -659,6 +671,14 @@ RelativePath=".\http\Server.h" > + + + + diff --git a/src/core/http/IRequestParser.h b/src/core/http/IRequestParser.h new file mode 100644 index 000000000..073d60ec9 --- /dev/null +++ b/src/core/http/IRequestParser.h @@ -0,0 +1,58 @@ +////////////////////////////////////////////////////////////////////////////// +// +// License Agreement: +// +// The following are Copyright © 2008, Daniel Önnerby +// +// All rights reserved. +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are met: +// +// * Redistributions of source code must retain the above copyright notice, +// this list of conditions and the following disclaimer. +// +// * Redistributions in binary form must reproduce the above copyright +// notice, this list of conditions and the following disclaimer in the +// documentation and/or other materials provided with the distribution. +// +// * Neither the name of the author nor the names of other contributors may +// be used to endorse or promote products derived from this software +// without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +// ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE +// LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF +// SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS +// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN +// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +// POSSIBILITY OF SUCH DAMAGE. +// +////////////////////////////////////////////////////////////////////////////// + +#pragma once + +#include + +////////////////////////////////////////////////////////////////////////////// + +namespace musik{ namespace core{ namespace http{ + +////////////////////////////////////////////////////////////////////////////// + +class IRequestParser{ + public: + virtual const char* Attribute(const char* key)=0; + virtual const char* Path()=0; + virtual const char* SubPath(int position)=0; +}; + +////////////////////////////////////////////////////////////////////////////// +} } } // musik::core:http +////////////////////////////////////////////////////////////////////////////// + + diff --git a/src/core/http/IRequestPlugin.h b/src/core/http/IRequestPlugin.h new file mode 100644 index 000000000..bc4772c26 --- /dev/null +++ b/src/core/http/IRequestPlugin.h @@ -0,0 +1,61 @@ +////////////////////////////////////////////////////////////////////////////// +// +// License Agreement: +// +// The following are Copyright © 2008, Daniel Önnerby +// +// All rights reserved. +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are met: +// +// * Redistributions of source code must retain the above copyright notice, +// this list of conditions and the following disclaimer. +// +// * Redistributions in binary form must reproduce the above copyright +// notice, this list of conditions and the following disclaimer in the +// documentation and/or other materials provided with the distribution. +// +// * Neither the name of the author nor the names of other contributors may +// be used to endorse or promote products derived from this software +// without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +// ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE +// LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF +// SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS +// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN +// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +// POSSIBILITY OF SUCH DAMAGE. +// +////////////////////////////////////////////////////////////////////////////// + +#pragma once + +#include +#include +#include +#include + +////////////////////////////////////////////////////////////////////////////// + +namespace musik{ namespace core{ namespace http{ + +////////////////////////////////////////////////////////////////////////////// + +class IRequestPlugin{ + public: + virtual void Destroy()=0; + virtual const char* WatchPath()=0; + virtual void Execute(musik::core::http::IResponder* responder,const musik::core::http::IRequestParser* request,const musik::core::ITrack* track)=0; +}; + +////////////////////////////////////////////////////////////////////////////// +} } } +////////////////////////////////////////////////////////////////////////////// + + diff --git a/src/core/http/IResponder.h b/src/core/http/IResponder.h new file mode 100644 index 000000000..6d259035f --- /dev/null +++ b/src/core/http/IResponder.h @@ -0,0 +1,57 @@ +////////////////////////////////////////////////////////////////////////////// +// +// License Agreement: +// +// The following are Copyright © 2008, Daniel Önnerby +// +// All rights reserved. +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are met: +// +// * Redistributions of source code must retain the above copyright notice, +// this list of conditions and the following disclaimer. +// +// * Redistributions in binary form must reproduce the above copyright +// notice, this list of conditions and the following disclaimer in the +// documentation and/or other materials provided with the distribution. +// +// * Neither the name of the author nor the names of other contributors may +// be used to endorse or promote products derived from this software +// without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +// ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE +// LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF +// SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS +// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN +// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +// POSSIBILITY OF SUCH DAMAGE. +// +////////////////////////////////////////////////////////////////////////////// + +#pragma once + +#include + +////////////////////////////////////////////////////////////////////////////// + +namespace musik{ namespace core{ namespace http{ + +////////////////////////////////////////////////////////////////////////////// + +class IResponder{ + public: + virtual void SendContent(const char* buffer,const int bufferSize)=0; + virtual bool Exited()=0; +}; + +////////////////////////////////////////////////////////////////////////////// +} } } +////////////////////////////////////////////////////////////////////////////// + + diff --git a/src/core/http/RequestParser.cpp b/src/core/http/RequestParser.cpp index 760956270..0ae72dcd9 100644 --- a/src/core/http/RequestParser.cpp +++ b/src/core/http/RequestParser.cpp @@ -37,9 +37,7 @@ #include "pch.hpp" #include - -#include -#include +#include using namespace musik::core::http; @@ -69,7 +67,8 @@ void RequestParser::Parse(const std::string &request){ int questionMark( this->fullRequest.find("?") ); if(questionMark!=std::string::npos){ - this->path.assign(this->fullRequest.substr(questionMark)); + this->path.assign(this->fullRequest.substr(0,questionMark)); + this->ParseAttributes( this->fullRequest.substr(questionMark+1) ); }else{ this->path.assign(this->fullRequest); } @@ -79,31 +78,58 @@ void RequestParser::Parse(const std::string &request){ } void RequestParser::SplitPath(){ - int startSearch(0); + if(!this->path.empty()){ + boost::algorithm::split(this->splitPath,this->path,boost::algorithm::is_any_of("/")); + } +} - while(startSearch!=std::string::npos){ - int firstSlash( this->path.find("/",startSearch) ); - if(firstSlash==std::string::npos){ - if(this->path.size()-startSearch!=0){ - std::string matchPath; - matchPath.assign(this->path,startSearch,this->path.size()-startSearch); - this->splitPath.push_back(matchPath); - } - startSearch = std::string::npos; - }else{ - if(firstSlash-startSearch!=0){ - std::string matchPath; - matchPath.assign(this->path,startSearch,firstSlash-startSearch); - this->splitPath.push_back(matchPath); - } - startSearch = firstSlash+1; +void RequestParser::ParseAttributes(std::string attributeString){ + StringVector attributes; + boost::algorithm::split(attributes,attributeString,boost::algorithm::is_any_of("&")); + + for(StringVector::iterator attribute=attributes.begin();attribute!=attributes.end();++attribute){ + std::string::size_type eqSign( attribute->find("=") ); + if(eqSign!=std::string::npos){ + this->attributes[ attribute->substr(0,eqSign) ] = attribute->substr(eqSign+1); } } } + void RequestParser::Clear(){ this->path.clear(); this->fullRequest.clear(); this->splitPath.clear(); } + +const RequestParser::StringVector& RequestParser::SplitPaths() const{ + return this->splitPath; +} + +const char* RequestParser::Path(){ + return this->path.c_str(); +} + +const RequestParser::AttributeMap& RequestParser::Attributes() const{ + return this->attributes; +} + +const char* RequestParser::Attribute(const char* key){ + if(key){ + AttributeMap::iterator attrib = this->attributes.find(key); + if(attrib!=this->attributes.end()){ + return attrib->second.c_str(); + } + } + return NULL; +} + +const char* RequestParser::SubPath(int position){ + + if(positionsplitPath.size()){ + return this->splitPath[position].c_str(); + } + + return NULL; +} diff --git a/src/core/http/RequestParser.h b/src/core/http/RequestParser.h index 42ada73f0..e5b295b6c 100644 --- a/src/core/http/RequestParser.h +++ b/src/core/http/RequestParser.h @@ -37,9 +37,11 @@ #pragma once #include +#include #include #include +#include ////////////////////////////////////////////////////////////////////////////// @@ -47,19 +49,31 @@ namespace musik{ namespace core{ namespace http{ ////////////////////////////////////////////////////////////////////////////// -class RequestParser{ +class RequestParser : public IRequestParser{ public: RequestParser(); void Parse(const std::string &request); ~RequestParser(); - std::string fullRequest; - std::string path; - std::vector splitPath; + virtual const char* Attribute(const char* key); + virtual const char* Path(); + virtual const char* SubPath(int position); + + typedef std::vector StringVector; + typedef std::map AttributeMap; + + const StringVector& SplitPaths() const; + const AttributeMap& Attributes() const; + private: void SplitPath(); + void ParseAttributes(std::string attributeString); void Clear(); + std::string fullRequest; + std::string path; + StringVector splitPath; + AttributeMap attributes; }; ////////////////////////////////////////////////////////////////////////////// diff --git a/src/core/http/Responder.cpp b/src/core/http/Responder.cpp index 4743fee30..c4b3c1a2f 100644 --- a/src/core/http/Responder.cpp +++ b/src/core/http/Responder.cpp @@ -47,6 +47,7 @@ #include #include #include +#include using namespace musik::core::http; @@ -93,8 +94,46 @@ void Responder::ThreadLoop(){ // First, read request if(this->ReadRequest(request)){ - // Second, Find out what is requested. + // Find out what is requested. requester.Parse(request); + + // Check if there is a related Track + musik::core::TrackPtr track; + const char* trackId = requester.Attribute("track_id"); + if(trackId){ + try{ + track.reset(new musik::core::Track()); + if(!track->GetFileData( boost::lexical_cast(trackId),this->db)){ + track.reset(); + } + } + catch(...){ + // lexical cast fail + track.reset(); + } + } + + // Lets see what plugin can handle the request + std::string rootPath; + if(requester.SubPath(0)){ + rootPath = requester.SubPath(0); + } + Server::PluginPathMap::iterator plugin = this->server.requestPlugins.find(rootPath); + if(plugin!=this->server.requestPlugins.end()){ + + // Execute the plugin + plugin->second->Execute(this,&requester,track.get()); + + }else{ + // Send 404 error + std::string send("HTTP/1.1 404 OK\r\nContent-Type: text/html\r\n\r\nERROR: "); + send += "
";
+                    send    += request;
+                    send    += "
"; + boost::asio::write(this->socket,boost::asio::buffer(send.c_str(),send.size())); + } + + /* utfstring fileName; int fileSize(0); @@ -134,7 +173,7 @@ void Responder::ThreadLoop(){ send += ""; boost::asio::write(this->socket,boost::asio::buffer(send.c_str(),send.size())); - } + }*/ } } @@ -147,10 +186,13 @@ void Responder::ThreadLoop(){ } } - +void Responder::SendContent(const char* buffer,const int bufferSize){ + boost::asio::write(this->socket,boost::asio::buffer(buffer,bufferSize)); +} +/* bool Responder::GetFileName(utfstring &fileName,int &fileSize,const RequestParser &request){ - if(request.splitPath.size()>0){ - std::string sRequestId = request.splitPath.front(); + if(request.SplitPaths().size()>0){ + std::string sRequestId = request.SplitPaths().front(); int requestId = atoi(sRequestId.c_str()); musik::core::db::CachedStatement stmt("SELECT t.id,(p.path||f.relative_path||'/'||t.filename) AS file,t.filesize FROM tracks t,folders f,paths p WHERE t.id=? AND t.folder_id=f.id AND f.path_id=p.id",this->db); @@ -166,7 +208,7 @@ bool Responder::GetFileName(utfstring &fileName,int &fileSize,const RequestParse } } return false; -} +}*/ bool Responder::ReadRequest(std::string &request){ char buffer[512]; @@ -194,13 +236,6 @@ bool Responder::ReadRequest(std::string &request){ void Responder::CloseSocket(){ // Close socket -/* int iError = shutdown(this->iSocket,SHUT_RDWR); - ASSERT(iError==0); - iError = closesocket(this->iSocket); - ASSERT(iError==0); - - this->iSocket = -1; -*/ this->socket.close(); } diff --git a/src/core/http/Responder.h b/src/core/http/Responder.h index 2098c94e7..5b18dc8f4 100644 --- a/src/core/http/Responder.h +++ b/src/core/http/Responder.h @@ -37,6 +37,7 @@ #pragma once #include +#include #include #include @@ -65,22 +66,23 @@ namespace musik{ namespace core{ namespace http{ ////////////////////////////////////////////////////////////////////////////// -class Responder : private boost::noncopyable{ +class Responder : public IResponder{ public: Responder(Server &server,boost::asio::io_service &ioService,utfstring dbFilename); ~Responder(); bool Startup(); + virtual void SendContent(const char* buffer,const int bufferSize); + virtual bool Exited(); private: friend class Server; void Exit(); - bool Exited(); void ThreadLoop(); bool ReadRequest(std::string &request); void CloseSocket(); - bool GetFileName(utfstring &fileName,int &fileSize,const RequestParser &request); +// bool GetFileName(utfstring &fileName,int &fileSize,const RequestParser &request); bool exited; diff --git a/src/core/http/Server.cpp b/src/core/http/Server.cpp index 93da8d10f..f25698031 100644 --- a/src/core/http/Server.cpp +++ b/src/core/http/Server.cpp @@ -38,11 +38,16 @@ #include #include +#include +#include +#include #include + using namespace musik::core::http; + Server::Server(int port,utfstring dbFilename) :acceptor(ioService,boost::asio::ip::tcp::endpoint(boost::asio::ip::tcp::v4(), port)) ,thread(NULL) @@ -51,6 +56,24 @@ Server::Server(int port,utfstring dbFilename) ,port(port) ,dbFilename(dbFilename) { + // Check for plugins + typedef IRequestPlugin PluginType; + typedef boost::shared_ptr PluginPtr; + typedef PluginFactory::DestroyDeleter Deleter; + typedef std::vector PluginVector; + // + PluginVector plugins = PluginFactory::Instance().QueryInterface("GetHTTPRequestPlugin"); + + for(PluginVector::iterator plugin=plugins.begin();plugin!=plugins.end();++plugin){ + if((*plugin)->WatchPath()){ + this->requestPlugins[(*plugin)->WatchPath()] = *plugin; + }else{ + this->requestPlugins[""] = *plugin; + } + } + + // Lets always add the TrackSender + this->requestPlugins["track"] = PluginPtr(new TrackSender()); } diff --git a/src/core/http/Server.h b/src/core/http/Server.h index 6e2568b29..025e8688e 100644 --- a/src/core/http/Server.h +++ b/src/core/http/Server.h @@ -38,6 +38,7 @@ #include #include +#include #include #include @@ -94,6 +95,10 @@ class Server : private boost::noncopyable{ friend class Responder; void FreeResponder(Responder *responder); +// + typedef std::map> PluginPathMap; + + PluginPathMap requestPlugins; }; ////////////////////////////////////////////////////////////////////////////// diff --git a/src/core/http/TrackSender.cpp b/src/core/http/TrackSender.cpp new file mode 100644 index 000000000..908bb8233 --- /dev/null +++ b/src/core/http/TrackSender.cpp @@ -0,0 +1,88 @@ +////////////////////////////////////////////////////////////////////////////// +// +// License Agreement: +// +// The following are Copyright © 2008, Daniel Önnerby +// +// All rights reserved. +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are met: +// +// * Redistributions of source code must retain the above copyright notice, +// this list of conditions and the following disclaimer. +// +// * Redistributions in binary form must reproduce the above copyright +// notice, this list of conditions and the following disclaimer in the +// documentation and/or other materials provided with the distribution. +// +// * Neither the name of the author nor the names of other contributors may +// be used to endorse or promote products derived from this software +// without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +// ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE +// LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF +// SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS +// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN +// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +// POSSIBILITY OF SUCH DAMAGE. +// +////////////////////////////////////////////////////////////////////////////// + +#include "pch.hpp" +#include +#include + + +using namespace musik::core::http; + +TrackSender::TrackSender() + :watchPath("track") +{ +} + + +const char* TrackSender::WatchPath(){ + return this->watchPath.c_str(); +} + +void TrackSender::Execute(musik::core::http::IResponder* responder,const musik::core::http::IRequestParser* request,const musik::core::ITrack* track){ + #define BUFFER_SIZE 4096 + char buffer[BUFFER_SIZE]; + int buffersize(0); + + // TODO: Should rewrite this in a multiplatform manner + if(track && responder){ + FILE *file = _wfopen(track->GetValue("path"),UTF("rb")); + + if(file){ + // Send header + std::string header( "HTTP/1.1 200 OK\r\nContent-Type: audio/mpeg\r\nContent-Length: " ); + header.append( musik::core::ConvertUTF8(track->GetValue("filesize")) ); + header.append("\r\n\r\n"); + + responder->SendContent(header.c_str(),header.size()); + + while(!feof(file) && file && !responder->Exited()){ + buffersize=0; + while(buffersizeSendContent(buffer,buffersize); + + } + fclose(file); + } + } +} + +void TrackSender::Destroy(){ + delete this; +} diff --git a/src/core/http/TrackSender.h b/src/core/http/TrackSender.h new file mode 100644 index 000000000..8251b4ddb --- /dev/null +++ b/src/core/http/TrackSender.h @@ -0,0 +1,63 @@ +////////////////////////////////////////////////////////////////////////////// +// +// License Agreement: +// +// The following are Copyright © 2008, Daniel Önnerby +// +// All rights reserved. +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are met: +// +// * Redistributions of source code must retain the above copyright notice, +// this list of conditions and the following disclaimer. +// +// * Redistributions in binary form must reproduce the above copyright +// notice, this list of conditions and the following disclaimer in the +// documentation and/or other materials provided with the distribution. +// +// * Neither the name of the author nor the names of other contributors may +// be used to endorse or promote products derived from this software +// without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +// ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE +// LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF +// SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS +// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN +// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +// POSSIBILITY OF SUCH DAMAGE. +// +////////////////////////////////////////////////////////////////////////////// + +#pragma once + +#include +#include +#include + +////////////////////////////////////////////////////////////////////////////// + +namespace musik{ namespace core{ namespace http { + +////////////////////////////////////////////////////////////////////////////// +class TrackSender : public IRequestPlugin{ + public: + TrackSender(); + + virtual void Destroy(); + virtual const char* WatchPath(); + virtual void Execute(musik::core::http::IResponder* responder,const musik::core::http::IRequestParser* request,const musik::core::ITrack* track); + + private: + std::string watchPath; +}; + +////////////////////////////////////////////////////////////////////////////// +} } } // musik::core::http +////////////////////////////////////////////////////////////////////////////// +