ViewVC Help
View File | Revision Log | Show Annotations | Download File | View Changeset | Root Listing
root/repos/DecentralizedMedia/DecentralizedMedia.cpp
Revision: 517
Committed: 2005-06-20T21:43:06-07:00 (20 years ago) by douglas
File size: 5949 byte(s)
Log Message:
This is probably a better way of doing the precompiled header thing, it doesn't cause menes to be almost completely rebuilt every time something changes.

File Contents

# User Rev Content
1 douglas 464 // Decentralized Media
2     //
3     // Douglas Thrift
4     //
5     // $Id$
6    
7 douglas 470 #include <menes/standard.hh>
8 douglas 464
9 douglas 474 #include <menes-api/pcre/regex.hpp>
10 douglas 497 #include <menes-api/realpath.hpp>
11 douglas 471 #include <menes-app/simple.hpp>
12 douglas 484 #include <menes-dbi/driver.hpp>
13     #include <menes-dbi/resultset.hpp>
14 douglas 471 #include <menes-etl/fnbind.hpp>
15 douglas 474 #include <menes-ios/helpers.hpp>
16 douglas 471 #include <menes-net/http/request.hpp>
17     #include <menes-net/http/response.hpp>
18 douglas 507 #include <menes-xml/document.hpp>
19     #include <menes-xml/parse.hpp>
20 douglas 470
21 douglas 471 #include "DecentralizedMedia.hpp"
22 douglas 464
23 douglas 471 int Main(const app::Options& options)
24 douglas 464 {
25 douglas 491 ext::RedBlackSet<ext::String> extensions, locals;
26 douglas 474 api::Pcre::RegEx extension(_B("^-extension=(.+)$")), local(_B("^-local=(.+)$"));
27 douglas 464
28 douglas 474 _foreach (const app::ArgumentList, arg, app::GetArguments())
29     {
30     api::Pcre::RegEx::Match match;
31    
32     if (match = extension(*arg))
33 douglas 491 extensions.Insert(match[1]);
34 douglas 474 else if (match = local(*arg))
35 douglas 497 locals.Insert(api::RealPath(match[1]));
36 douglas 474 }
37    
38     if (extensions.IsEmpty())
39 douglas 491 extensions.Insert(_B("mp3"));
40 douglas 474
41 douglas 493 if (!api::Path(_B("Media")).Exists())
42     api::Posix::CheckError(::mkdir("Media", 0755));
43 douglas 491
44 douglas 497 locals.Insert(api::RealPath(_B("Media")));
45 douglas 493
46 douglas 481 _S<DecentralizedMedia> media(extensions, locals);
47 douglas 474
48 douglas 472 media.Block();
49    
50 douglas 471 return 0;
51     }
52 douglas 469
53 douglas 516 DecentralizedMedia::DecentralizedMedia(const ext::RedBlackSet<ext::String>& extensions, const ext::RedBlackSet<ext::String>& locals) : waf::Server(_B("Web")), process(bmp.IsRunning() ? NULL : new api::Process(_B("/usr/X11R6/bin/beep-media-player"))), connection(dbi::GetDriver("dbi::PgSql::Driver")->Connect("", "douglas", "", "media")), extensions(extensions)
54 douglas 471 {
55 douglas 517 if (!process.IsEmpty())
56     {
57     process->ClearReader();
58     process->ClearWriter();
59     }
60    
61 douglas 503 connection->Execute(_B("UPDATE files SET live = FALSE"));
62    
63 douglas 474 {
64 douglas 507 _L<ext::String> args;
65 douglas 474
66 douglas 491 _foreach (const ext::RedBlackSet<ext::String>, extension, extensions)
67 douglas 507 args.InsertLast(_S<ios::String>() << "-extension=" << *extension);
68 douglas 474
69 douglas 507 _foreach (const ext::RedBlackSet<ext::String>, local, locals)
70     args.InsertLast(_S<ios::String>() << "-local=" << *local);
71 douglas 474
72 douglas 517 _S<api::Process> media(_B("Util/media"), args);
73 douglas 474
74 douglas 517 Media(*media.GetReader());
75 douglas 503
76 douglas 517 media.Join();
77 douglas 474 }
78    
79 douglas 517 {
80     _L<ext::String> args;
81    
82     args.InsertLast(_B("-s"));
83     args.InsertLast(_B("object/DecentralizedMedia.hh.gch"));
84    
85     _S<api::Process> make(CFG_GNU_MAKE, args);
86    
87     make.ClearWriter();
88    
89     _S<ios::String> error;
90    
91     ios::ReadToWrite(*make.GetReader(), error);
92    
93     if (make.Join() != 0)
94     throw ext::StringException(error);
95     }
96    
97 douglas 471 AddPort(6996);
98     }
99 douglas 469
100 douglas 471 DecentralizedMedia::~DecentralizedMedia()
101 douglas 469 {
102 douglas 471 if (!process.IsEmpty())
103     {
104     _H<api::Thread> thread(new api::Thread(etl::BindAll(&DecentralizedMedia::Destroy, this)));
105 douglas 470
106 douglas 471 bmp.Quit();
107 douglas 469
108 douglas 471 thread->Join();
109     }
110 douglas 464 }
111 douglas 471
112 douglas 491 _L<ext::String> DecentralizedMedia::GetArtists() const
113     {
114     _H<dbi::ResultSet> artists_(connection->Execute(_B("SELECT DISTINCT artist FROM files WHERE live = TRUE")));
115     _L<ext::String> artists;
116    
117     while (artists_->MoveNext())
118     artists.InsertLast(artists_->GetString(_B("artist")));
119    
120     return artists;
121     }
122    
123     _L<ext::String> DecentralizedMedia::GetTitles() const
124     {
125     _H<dbi::ResultSet> titles_(connection->Execute(_B("SELECT DISTINCT title FROM files WHERE live = TRUE")));
126     _L<ext::String> titles;
127    
128     while (titles_->MoveNext())
129     titles.InsertLast(titles_->GetString(_B("title")));
130    
131     return titles;
132     }
133    
134     _L<ext::String> DecentralizedMedia::GetAlbums() const
135     {
136     _H<dbi::ResultSet> albums_(connection->Execute(_B("SELECT DISTINCT album FROM files WHERE live = TRUE")));
137     _L<ext::String> albums;
138    
139     while (albums_->MoveNext())
140     albums.InsertLast(albums_->GetString(_B("album")));
141    
142     return albums;
143     }
144    
145     _L<ext::String> DecentralizedMedia::GetGenres() const
146     {
147     _H<dbi::ResultSet> genres_(connection->Execute(_B("SELECT DISTINCT album FROM files WHERE live = TRUE")));
148     _L<ext::String> genres;
149    
150     while (genres_->MoveNext())
151     genres.InsertLast(genres_->GetString(_B("genre")));
152    
153     return genres;
154     }
155    
156     _L<MediaFolder> DecentralizedMedia::GetFolders() const
157     {
158     _H<dbi::ResultSet> paths(connection->Execute(_B("SELECT DISTINCT root FROM files WHERE live = TRUE")));
159     _L<MediaFolder> folders;
160    
161     while (paths->MoveNext())
162     folders.InsertLast(MediaFolder(connection, paths->GetString(_B("path"))));
163    
164     return folders;
165     }
166    
167 douglas 471 void DecentralizedMedia::Process(const net::Http::Request& request, net::Http::Response& response)
168     {
169 douglas 515 if (request.method_ == _B("EXTENSIONS") || request.method_ == _B("GET") && request.uri_.GetUri().IsEmpty())
170 douglas 474 {
171 douglas 507 api::Cout << "EXTENSIONS" << ios::NewLine;
172    
173 douglas 474 response.SetStatus(200);
174    
175 douglas 492 _foreach (const ext::RedBlackSet<ext::String>, extension, extensions)
176 douglas 476 response << *extension << ios::NewLineNoFlush;
177 douglas 474 }
178 douglas 515 else if (request.method_ == _B("MEDIA") || request.method_ == _B("POST") && request.uri_.GetUri().IsEmpty())
179 douglas 474 {
180 douglas 507 api::Cout << "MEDIA" << ios::NewLine;
181    
182 douglas 508 if (!request.content_.IsEmpty())
183 douglas 509 {
184     Media(*request.content_);
185 douglas 508
186 douglas 509 response.SetStatus(204);
187     }
188     else
189     response.SetStatus(402);
190 douglas 474 }
191 douglas 471 else
192     waf::Server::Process(request, response);
193     }
194 douglas 507
195     void DecentralizedMedia::Media(ios::Reader& media)
196     {
197     _H<xml::Document> document(xml::Parse(media));
198     api::Pcre::RegEx share("^//(.+)/(.+)$");
199    
200     _foreach (const xml::NodeSet, folder, *document/"media"/"folder")
201     {
202     ext::String path(**folder/"path");
203    
204 douglas 514 if (api::Pcre::RegEx::Match match = share(path))
205     {
206     _H<Share> share(new Share(connection, match[1], match[2]));
207    
208     path = share->path.GetPath();
209    
210     // XXX: these are probably going to need read/write locking
211     sharesByPath[path] = share;
212     sharesByHost[match[1]][match[2]] = share;
213    
214     share->Mount();
215     }
216    
217     Media(*folder, path, path);
218 douglas 507 }
219     }
220    
221     void DecentralizedMedia::Media(const _H<xml::Node>& folder, const api::Path& path, const api::Path& root)
222     {
223     MediaFolder(connection, path, root);
224    
225     _foreach (const xml::NodeSet, file, *folder/"file")
226     MediaFile(connection, path.GetChild(**file/"path"), **file/"artist", **file/"title", **file/"album", **file/"genre", root);
227    
228     _foreach (const xml::NodeSet, folder_, *folder/"folder")
229     Media(*folder_, path.GetChild(**folder_/"path"), root);
230     }

Properties

Name Value
svn:eol-style native
svn:keywords Id