ViewVC Help
View File | Revision Log | Show Annotations | Download File | View Changeset | Root Listing
root/repos/DecentralizedMedia/DecentralizedMedia.cpp
Revision: 534
Committed: 2005-06-29T23:01:02-07:00 (19 years, 11 months ago) by douglas
File size: 5825 byte(s)
Log Message:
So long ext::String, we'll miss you, but not much we really still have you as cse::String. Also, other stuff.

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

Properties

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