ViewVC Help
View File | Revision Log | Show Annotations | Download File | View Changeset | Root Listing
root/repos/DecentralizedMedia/DecentralizedMedia.cpp
Revision: 509
Committed: 2005-06-19T04:29:32-07:00 (20 years ago) by douglas
File size: 5996 byte(s)
Log Message:
Getting somewhere, it would seem.

File Contents

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

Properties

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