#include "music.h" #include "decoder.h" #include "encoder.h" #include "transcode.h" #include "tag.h" #include "config.h" #include #include #include #include #include #include #include #include fs::path music::root_directory; void music::init(std::string root) { // remove trailing slash if(boost::algorithm::ends_with(root, "/")) root = root.substr(0, root.size()-1); root_directory = root; } MusicListing::p music::get(const std::vector& path) { // prefix path with our root_directory fs::path p = root_directory; for(std::vector::const_iterator it = path.begin(); it != path.end(); it++) { // don't allow requests with /../ in the path if(*it == "..") { return MusicListing::p(); } p /= *it; } if(fs::is_directory(p)) { boost::shared_ptr ml(new MusicDirectory(p)); return ml; } else if(fs::is_regular_file(p)) { boost::shared_ptr ml(new MusicTrack(p)); return ml; } return MusicListing::p(); } MusicListing::p music::get(const std::string& path) { std::vector path_vector; boost::algorithm::split(path_vector, path, boost::algorithm::is_any_of("/\\")); return get(path_vector); } MusicDirectory::p music::get_directory(const std::string& path) { MusicListing::p ml = get(path); if(!ml || !fs::is_directory(ml->path)) { return MusicDirectory::p(); } MusicDirectory::p dir(boost::dynamic_pointer_cast(ml)); return dir; } std::vector music::find_artist(const std::string artist) { soci::session sql(config::vm["audist.database"].as()); soci::rowset rs = (sql.prepare << "SELECT file_name FROM tracks WHERE artist_id IN (SELECT id FROM artists WHERE name LIKE :name)", soci::use("%"+artist+"%")); std::vector results; for(soci::rowset::const_iterator it = rs.begin(); it != rs.end(); it++) { boost::shared_ptr ml(new MusicTrack(*it)); results.push_back(ml); } return results; } void music::begin_update(const std::string path) { MusicDirectory::p dir = get_directory(path); std::cout << boost::format("updater(%s) called") % path << std::endl; if(dir) { update(dir->path); } } void music::update(const MusicDirectory& dir) { BOOST_FOREACH(fs::path t, dir.tracks) { std::cout << "track " << t << std::endl; } std::for_each(dir.directories.begin(), dir.directories.end(), update); } void MusicDirectory::render(HTTP::Connection::p req, HTTPResponse& res) { res.add_header("content-type", "text/html"); for(PathListings::iterator it = directories.begin(); it != directories.end(); it++) { std::string rel_path = it->string().substr(music::root_directory.string().size()); res.write(boost::str(boost::format("%s
") % rel_path % rel_path)); } for(PathListings::iterator it = tracks.begin(); it != tracks.end(); it++) { std::string rel_path = it->string().substr(music::root_directory.string().size()); res.write(boost::str(boost::format("%s
") % rel_path % rel_path)); } } MusicTrack::MusicTrack(const fs::path path) { std::cout << path << std::endl; this->path = path; } MusicDirectory::MusicDirectory(const fs::path root) { this->path = root; std::cout << this->path << std::endl; fs::directory_iterator end_itr; for(fs::directory_iterator it(this->path); it != end_itr; it++) { if(fs::is_directory(it->status())) { directories.push_back(it->path()); } else if(fs::is_regular_file(it->status())) { tracks.push_back(it->path()); } } } void MusicTrack::render(HTTP::Connection::p req, HTTPResponse& res) { res.add_header("content-type", "application/octet-stream"); // tag test Tag *t = new ID3Tag(path.string()); delete t; if(req->args.count("decoder") && req->args.count("encoder")) { DecoderBase *d = decoder::get_decoder(req->args["decoder"]); EncoderBase *e = encoder::get_encoder(req->args["encoder"]); Transcoder t(path.string(), res, *d, *e); t.run(); delete d; delete e; } else { fs::ifstream is(path, std::ios::in | std::ios::binary); is.seekg(0, std::ios::end); res.add_header("content-length", boost::str(boost::format("%d") % is.tellg())); is.seekg(0, std::ios::beg); char data[0x1000]; while(is.good()) { is.read(data, 0x1000); res.write(data, is.gcount()); } } }