1 |
<?xml version="1.0"?> |
2 |
<waf:logic xmlns:waf="http://www.saurik.com/menes/waf/0.9"> |
3 |
|
4 |
<waf:set-pch file="DecentralizedMedia.hh"/> |
5 |
|
6 |
<waf:include file="menes/net/http/urlencode.hpp"/> |
7 |
<waf:include file="menes/net/mime/application/x-www-form-urlencoded.hpp"/> |
8 |
|
9 |
static ext::Buffer amp(_B("&amp;")), reserved(_B("&\"=#")); |
10 |
DecentralizedMedia& media(*static_cast< DecentralizedMedia* >(& server)); |
11 |
const _S< net::Mime::Application::XWwwFormUrlencoded > query(_request.uri_.GetQuery()); |
12 |
_R< net::Mime::Document > document(_request.GetDocument()); |
13 |
_R< net::Mime::Application::XWwwFormUrlencoded > form; |
14 |
|
15 |
if (_request.method_ == _B("POST") && !document.IsEmpty()) |
16 |
form = dynamic_cast< net::Mime::Application::XWwwFormUrlencoded* >(document.GetValue()); |
17 |
|
18 |
<waf:set-status code="200"/> |
19 |
<waf:add-header name="Content-Type" value="text/html; charset=utf-8"/> |
20 |
|
21 |
<html> |
22 |
<head> |
23 |
<title>Decentralized Media | Select Media</title> |
24 |
<link rel="stylesheet" href="style.css" type="text/css" /> |
25 |
</head> |
26 |
<body> |
27 |
<h1>Select Media</h1> |
28 |
<form action="media.msp" method="post"> |
29 |
<table> |
30 |
<tr> |
31 |
<th/> |
32 |
<th colspan="2">File/Folder</th> |
33 |
<th>Artist</th> |
34 |
<th>Song Title</th> |
35 |
<th>Album</th> |
36 |
<th>Genre</th> |
37 |
</tr> |
38 |
<waf:logic> |
39 |
unsigned page, pages(1); |
40 |
|
41 |
try |
42 |
{ |
43 |
page = lexical_cast< unsigned >(query[_B("page")].First()); |
44 |
} |
45 |
catch (const ext::InvalidArgumentException& ) { page = 0; } |
46 |
catch (const ext::NotFoundException& ) { page = 0; } |
47 |
|
48 |
api::Path path(query.Contains(_B("folder")) ? query[_B("folder")].First() : cse::EmptyString); |
49 |
|
50 |
if (!query.Contains(_B("by"))) |
51 |
if(path.IsEmpty()) |
52 |
{ |
53 |
_foreach (const _L< MediaFolder >, folder, media.library.GetFolders(page)) |
54 |
{ |
55 |
<tr> |
56 |
<td><img src="folder.gif" alt="[folder]"/></td> |
57 |
<td colspan="2"><a href="media.msp?folder={ios::Filter< net::Http::QueryEncoder >(folder->path.GetPath(), reserved)}">{folder->GetName()}</a></td> |
58 |
<td colspan="4"/> |
59 |
</tr> |
60 |
} |
61 |
|
62 |
unsigned pages_(media.library.GetFoldersPages()); |
63 |
|
64 |
if (pages_ > pages) |
65 |
pages = pages_; |
66 |
} |
67 |
else |
68 |
{ |
69 |
MediaFolder folder(media.library.GetFolder(path)); |
70 |
|
71 |
<tr> |
72 |
<td><img src="up.gif" alt="[up]"/></td> |
73 |
<td colspan="6"> |
74 |
<waf:logic> |
75 |
if (folder.path != folder.root) |
76 |
{ |
77 |
<a href="media.msp?folder={ios::Filter< net::Http::QueryEncoder >(folder.path.GetParent().GetPath(), reserved)}">Up from {folder.GetName()}</a> |
78 |
} |
79 |
else |
80 |
{ |
81 |
<a href="media.msp">Up from {folder.GetName()}</a> |
82 |
} |
83 |
</waf:logic> |
84 |
</td> |
85 |
</tr> |
86 |
|
87 |
_foreach (const _L< MediaFolder >, folder_, folder.GetFolders(page)) |
88 |
{ |
89 |
<tr> |
90 |
<td><img src="folder.gif" alt="[folder]"/></td> |
91 |
<td colspan="2"><a href="media.msp?folder={ios::Filter< net::Http::QueryEncoder >(folder_->path.GetPath(), reserved)}">{folder_->GetName()}</a></td> |
92 |
<td colspan="4"/> |
93 |
</tr> |
94 |
} |
95 |
|
96 |
unsigned pages_(folder.GetFoldersPages()); |
97 |
|
98 |
if (pages_ > pages) |
99 |
pages = pages_; |
100 |
|
101 |
_foreach (const _L< MediaFile >, file, folder.GetFiles(page)) |
102 |
{ |
103 |
<tr> |
104 |
<td><img src="file.gif" alt="[file]"/></td> |
105 |
<td><input type="checkbox" name="file" value="{ios::Filter< net::Http::QueryEncoder >(file->path.GetPath(), reserved)}"/></td> |
106 |
<td>{file->path.GetName()}</td> |
107 |
<td>{file->artist}</td> |
108 |
<td>{file->title}</td> |
109 |
<td>{file->album}</td> |
110 |
<td>{file->genre}</td> |
111 |
</tr> |
112 |
} |
113 |
|
114 |
pages_ = folder.GetFilesPages(); |
115 |
|
116 |
if (pages_ > pages) |
117 |
pages = pages_; |
118 |
} |
119 |
|
120 |
_L< By > bys; |
121 |
|
122 |
try |
123 |
{ |
124 |
_foreach(const _L< cse::String >, by, query[_B("by")]) |
125 |
bys.InsertLast(*by); |
126 |
} |
127 |
catch (const ext::NotFoundException& ) {} |
128 |
|
129 |
if (!query.Contains(_B("folder"))) |
130 |
if (bys.IsEmpty()) |
131 |
_forall (By, by, By::ARTIST, By::LAST) |
132 |
{ |
133 |
<tr> |
134 |
<td><img src="by.gif" alt="[by]"/></td> |
135 |
<td colspan="2"><a href="media.msp?by={by}">By {by.GetName()}</a></td> |
136 |
<waf:logic> |
137 |
_forall (By, column, By::ARTIST, By::LAST) if (column == by) |
138 |
{ |
139 |
<th/> |
140 |
} |
141 |
else |
142 |
{ |
143 |
<td/> |
144 |
} |
145 |
</waf:logic> |
146 |
</tr> |
147 |
} |
148 |
else |
149 |
{ |
150 |
_S< ios::String > query_; |
151 |
_L< cse::String > items; |
152 |
ext::RedBlackMap< By, cse::String > bys_; |
153 |
|
154 |
if (!query.Contains(lexical_cast< cse::String >(bys.Last()))) |
155 |
{ |
156 |
_foreach (_L< By >, by, bys) if (by + 1 != _set.End() && query.Contains(lexical_cast< cse::String >(*by))) |
157 |
{ |
158 |
cse::String item(query[lexical_cast< cse::String >(*by)].First()); |
159 |
|
160 |
query_ << _B("by=") << *by << amp << *by << _B("=") << ios::Filter< net::Http::QueryEncoder >(item, reserved) << amp; |
161 |
|
162 |
items.InsertLast(item); |
163 |
bys_.Insert(*by, item); |
164 |
} |
165 |
|
166 |
By by(bys.Last()); |
167 |
|
168 |
<tr> |
169 |
<td><img src="up.gif" alt="[up]"/></td> |
170 |
<td colspan="6"> |
171 |
<waf:logic> |
172 |
if (!query_.IsEmpty()) |
173 |
{ |
174 |
<a href="media.msp?{query_.Substring(0, query_.GetSize() - 5)}">Up from By {by.GetName()}</a> |
175 |
} |
176 |
else |
177 |
{ |
178 |
<a href="media.msp">Up from By {by.GetName()}</a> |
179 |
} |
180 |
</waf:logic> |
181 |
</td> |
182 |
</tr> |
183 |
|
184 |
_S< ios::String > columns; |
185 |
|
186 |
_forall (By, column, By::ARTIST, By::LAST) |
187 |
if (column == by) |
188 |
columns << _B("<th/>"); |
189 |
else |
190 |
columns << _B("<td>") << bys_[column] << _B("</td>"); |
191 |
|
192 |
query_ << _B("by=") << by << amp << by; |
193 |
|
194 |
_foreach (const _L< cse::String >, item, media.library.GetItems(bys, items, page)) |
195 |
{ |
196 |
<tr> |
197 |
<td><img src="item.gif" alt="[item]"/></td> |
198 |
<td colspan="2"><a href="media.msp?{query_}={ios::Filter< net::Http::QueryEncoder >(*item, reserved)}">{*item}</a></td> |
199 |
{columns} |
200 |
</tr> |
201 |
} |
202 |
|
203 |
unsigned pages_(media.library.GetItemsPages(bys, items)); |
204 |
|
205 |
if (pages_ > pages) |
206 |
pages = pages_; |
207 |
} |
208 |
else |
209 |
{ |
210 |
_foreach (_L< By >, by, bys) if (query.Contains(lexical_cast< cse::String >(*by))) |
211 |
{ |
212 |
cse::String item(query[lexical_cast< cse::String >(*by)].First()); |
213 |
|
214 |
query_ << _B("by=") << *by; |
215 |
|
216 |
if (by + 1 != _set.End()) |
217 |
query_ << amp << *by << _B("=") << ios::Filter< net::Http::QueryEncoder >(item, reserved) << amp; |
218 |
|
219 |
items.InsertLast(item); |
220 |
bys_.Insert(*by, item); |
221 |
} |
222 |
|
223 |
By by(bys.Last()); |
224 |
cse::String item(items.Last()); |
225 |
|
226 |
<tr> |
227 |
<td><img src="up.gif" alt="[up]"/></td> |
228 |
<td colspan="6"><a href="media.msp?{query_}">Up from By {by.GetName()}: {item}</a></td> |
229 |
</tr> |
230 |
|
231 |
query_ << amp << by << _B("=") << ios::Filter< net::Http::QueryEncoder >(item, reserved) << amp; |
232 |
|
233 |
_forall (By, by_, By::ARTIST, By::LAST) if (by_ != by && bys_[by_].IsEmpty()) |
234 |
{ |
235 |
<tr> |
236 |
<td><img src="by.gif" alt="[by]"/></td> |
237 |
<td colspan="2"><a href="media.msp?{query_}by={by_}">By {by_.GetName()}</a></td> |
238 |
<waf:logic> |
239 |
_forall (By, column, By::ARTIST, By::LAST) if (column == by_) |
240 |
{ |
241 |
<th/> |
242 |
} |
243 |
else |
244 |
{ |
245 |
<td>{bys_[column]}</td> |
246 |
} |
247 |
</waf:logic> |
248 |
</tr> |
249 |
} |
250 |
|
251 |
_foreach (const _L< MediaFile >, file, media.library.GetFiles(bys, items, page)) |
252 |
{ |
253 |
<tr> |
254 |
<td><img src="file.gif" alt="[file]"/></td> |
255 |
<td><input type="checkbox" name="file" value="{ios::Filter< net::Http::QueryEncoder >(file->path.GetPath(), reserved)}"/></td> |
256 |
<td>{file->path.GetName()}</td> |
257 |
<td>{file->artist}</td> |
258 |
<td>{file->title}</td> |
259 |
<td>{file->album}</td> |
260 |
<td>{file->genre}</td> |
261 |
</tr> |
262 |
} |
263 |
|
264 |
unsigned pages_(media.library.GetFilesPages(bys, items)); |
265 |
|
266 |
if (pages_ > pages) |
267 |
pages = pages_; |
268 |
} |
269 |
} |
270 |
</waf:logic> |
271 |
</table> |
272 |
<p> |
273 |
<strong> |
274 |
<waf:logic> |
275 |
// XXX: hmm, this should be usable this way |
276 |
_S< net::Mime::Application::XWwwFormUrlencoded > query_(query); |
277 |
|
278 |
query_.Remove(_B("page")); |
279 |
|
280 |
if (page != 0) |
281 |
{ |
282 |
<waf:content> |
283 |
<a href="media.msp?page={page - 1}">« Previous</a> |
284 |
</waf:content> |
285 |
} |
286 |
else |
287 |
{ |
288 |
<waf:content> |
289 |
« Previous |
290 |
</waf:content> |
291 |
} |
292 |
|
293 |
_forall (unsigned, page_, 0, pages) if (page_ == page) |
294 |
{ |
295 |
<waf:content> |
296 |
{page_} |
297 |
</waf:content> |
298 |
} |
299 |
else |
300 |
{ |
301 |
<waf:content> |
302 |
<a href="media.msp?page={page_}">{page_}</a> |
303 |
</waf:content> |
304 |
} |
305 |
|
306 |
if (page + 1 != pages) |
307 |
{ |
308 |
<waf:content> |
309 |
<a href="media.msp?page={page + 1}">Next »</a> |
310 |
</waf:content> |
311 |
} |
312 |
else |
313 |
{ |
314 |
<waf:content> |
315 |
Next » |
316 |
</waf:content> |
317 |
} |
318 |
</waf:logic> |
319 |
</strong> |
320 |
</p> |
321 |
<p>{_request.uri_.GetQuery()}</p> |
322 |
</form> |
323 |
<p>$Id$</p> |
324 |
</body> |
325 |
</html> |
326 |
|
327 |
</waf:logic> |