Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with HTTPS or Subversion.

Download ZIP
Newer
Older
100644 390 lines (353 sloc) 15.368 kb
8d1fbe7 @hzeller o Move fuse-convolve.c to fuse-convolve.cc. Make filter-interface
authored
1 // Copyright (C) 2012 Henner Zeller <h.zeller@acm.org>
2 //
3 // This program is free software; you can redistribute it and/or modify
4 // it under the terms of the GNU General Public License as published by
5 // the Free Software Foundation; either version 3 of the License, or
6 // (at your option) any later version.
7 //
8 // This program is distributed in the hope that it will be useful,
9 // but WITHOUT ANY WARRANTY; without even the implied warranty of
10 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11 // GNU General Public License for more details.
12 //
13 // You should have received a copy of the GNU General Public License
14 // along with this program. If not, see <http://www.gnu.org/licenses/>.
15
16 #include <arpa/inet.h>
17 #include <fcntl.h>
036c6e1 @hzeller o not wide cellspacing needed anymore.
authored
18 #include <math.h>
b5c1e96 @hzeller o more useful output on status server.
authored
19 #include <stdio.h>
8d1fbe7 @hzeller o Move fuse-convolve.c to fuse-convolve.cc. Make filter-interface
authored
20 #include <stdlib.h>
21 #include <sys/select.h>
22 #include <sys/socket.h>
23 #include <sys/time.h>
24 #include <sys/types.h>
25
26 #include <microhttpd.h>
27
1e9ff21 @hzeller o main: report if parameters are not directories.
authored
28 #include <boost/thread/locks.hpp>
29
a9d3e53 @hzeller o Found a project name: "Folve". Some renamings because of that.
authored
30 #include "folve-filesystem.h"
c1a03f2 @hzeller o Needed convenient sub-second resolution time. Added CurrentTime()
authored
31 #include "status-server.h"
32 #include "util.h"
8d1fbe7 @hzeller o Move fuse-convolve.c to fuse-convolve.cc. Make filter-interface
authored
33
8268c37 @hzeller o Bubble up error messages in status server.
authored
34 using folve::Appendf;
35
f1ef960 @hzeller o a bit HTML polishing.
authored
36 static const size_t kMaxRetired = 20;
b698853 @hzeller o README updates.
authored
37 static const int kProgressWidth = 300;
223f392 @hzeller o Have a separate HandlerStats object that contains relevant
authored
38 static const char kActiveProgress[] = "#7070ff";
39 static const char kRetiredProgress[] = "#d0d0d0";
249865a @hzeller o Make debug mode switchable in UI.
authored
40 static const char kSettingsUrl[] = "/settings";
223f392 @hzeller o Have a separate HandlerStats object that contains relevant
authored
41
78e66dd @hzeller o I need to find my browser-tab :) Add favicon.
authored
42 // Aaah, I need to find the right Browser-Tab :)
43 // Sneak in a favicon without another resource access.
44 // TODO: make a nice icon, recognizable as something that has to do with "
45 // files and music ...
a372a03 @hzeller o Make meta-refresh configurable.
authored
46 static const char kStartHtmlHeader[] = "<html><head>"
a9d3e53 @hzeller o Found a project name: "Folve". Some renamings because of that.
authored
47 "<title>Folve</title>\n"
e619ff2 @hzeller o Redirect to / after settings. That way, a reload won't change any
authored
48 "<link rel='icon' type='image/png' "
78e66dd @hzeller o I need to find my browser-tab :) Add favicon.
authored
49 "href='data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAIAAACQkWg2"
50 "AAAAAXNSR0IArs4c6QAAAAlwSFlzAAALEwAACxMBAJqcGAAAAAd0SU1FB9wJDwUlEA/UBrsA"
51 "AABSSURBVCjPrZIxDgAgDAKh8f9froOTirU1ssKFYqS7Q4mktAxFRQDJcsPORMDYsDCXhn331"
a372a03 @hzeller o Make meta-refresh configurable.
authored
52 "9GPwHJVuaFl3l4D1+h0UjIdbTh9SpP2KQ2AgSfVAdEQGx23tOopAAAAAElFTkSuQmCC'/>\n";
78e66dd @hzeller o I need to find my browser-tab :) Add favicon.
authored
53
adde81e @hzeller o some link prettify.
authored
54 // TODO: someone with a bit more stylesheet-fu can attempt to make this
55 // more pretty and the HTML more compact.
56 // First step: extract all css used below in style='xx' here. here.
57 // Also, maybe move to external file, makes editing much faster, then compile
58 // that into a C-string that we can include it in the binary.
59 #define SELECT_COLOR "#a0a0ff"
60 #define PRE_SELECT_COLOR "#e0e0ff"
537e34b @hzeller o cleanup UI: no radio buttons anymore, just simple links.
authored
61 static const char kCSS[] =
adde81e @hzeller o some link prettify.
authored
62 "<style type='text/css'>"
63 " a:link { text-decoration:none; }\n"
64 " a:visited { text-decoration:none; }\n"
65 " a:hover { text-decoration:underline; }\n"
66 " a:active { text-decoration:underline; }\n"
67 " .filter_sel { font-weight:bold; \n"
68 " padding: 5px 15px;\n"
69 " border-radius: 5px;\n"
70 " -moz-border-radius: 5px; }\n"
71 " .active { background-color:" SELECT_COLOR "; }\n"
72 " .inactive { background-color:#e0e0e0; }\n"
73 " .inactive:hover { background-color:" PRE_SELECT_COLOR ";\n"
74 " color: #000000;\n"
75 " text-decoration:none;}\n"
76 " .inactive:link { color: #000000;text-decoration:none;}\n"
77 " .inactive:visited { color: #000000;text-decoration:none;}\n"
537e34b @hzeller o cleanup UI: no radio buttons anymore, just simple links.
authored
78 "</style>";
79
b698853 @hzeller o README updates.
authored
80 // Callback function called by micro http daemon. Gets the StatusServer pointer
81 // in the user_argument.
8d1fbe7 @hzeller o Move fuse-convolve.c to fuse-convolve.cc. Make filter-interface
authored
82 int StatusServer::HandleHttp(void* user_argument,
83 struct MHD_Connection *connection,
84 const char *url, const char *method,
85 const char *version,
86 const char *upload_data, size_t *upload_size,
87 void**) {
88 StatusServer* server = (StatusServer*) user_argument;
e619ff2 @hzeller o Redirect to / after settings. That way, a reload won't change any
authored
89 struct MHD_Response *response;
90 int ret;
91
249865a @hzeller o Make debug mode switchable in UI.
authored
92 if (strcmp(url, kSettingsUrl) == 0) {
ee675fe @hzeller o Provide a way to select between different filter diretories.
authored
93 server->SetFilter(MHD_lookup_connection_value(connection,
94 MHD_GET_ARGUMENT_KIND, "f"));
249865a @hzeller o Make debug mode switchable in UI.
authored
95 server->SetDebug(MHD_lookup_connection_value(connection,
96 MHD_GET_ARGUMENT_KIND, "d"));
e619ff2 @hzeller o Redirect to / after settings. That way, a reload won't change any
authored
97 // We redirect to slash after this, to remove parameters from the GET-URL
98 response = MHD_create_response_from_data(0, (void*)"", MHD_NO, MHD_NO);
99 MHD_add_response_header(response, "Location", "/");
100 ret = MHD_queue_response(connection, 302, response);
101 } else {
102 const std::string &page = server->CreatePage();
103 response = MHD_create_response_from_data(page.length(), (void*) page.data(),
104 MHD_NO, MHD_NO);
105 MHD_add_response_header(response, "Content-Type",
106 "text/html; charset=utf-8");
107 ret = MHD_queue_response(connection, MHD_HTTP_OK, response);
ee675fe @hzeller o Provide a way to select between different filter diretories.
authored
108 }
e619ff2 @hzeller o Redirect to / after settings. That way, a reload won't change any
authored
109 // Tell aggressive cachers not to do so.
110 MHD_add_response_header(response, "Cache-Control", "no-cache");
111 MHD_add_response_header(response, "Expires", "24 Nov 1972 23:42:42 GMT");
8d1fbe7 @hzeller o Move fuse-convolve.c to fuse-convolve.cc. Make filter-interface
authored
112 MHD_destroy_response(response);
113 return ret;
114 }
115
a9d3e53 @hzeller o Found a project name: "Folve". Some renamings because of that.
authored
116 StatusServer::StatusServer(FolveFilesystem *fs)
1e9ff21 @hzeller o main: report if parameters are not directories.
authored
117 : expunged_retired_(0), total_seconds_filtered_(0),
118 total_seconds_music_seen_(0),
a372a03 @hzeller o Make meta-refresh configurable.
authored
119 meta_refresh_time_(-1),
ee675fe @hzeller o Provide a way to select between different filter diretories.
authored
120 filesystem_(fs), daemon_(NULL), filter_switched_(false) {
223f392 @hzeller o Have a separate HandlerStats object that contains relevant
authored
121 fs->handler_cache()->SetObserver(this);
8d1fbe7 @hzeller o Move fuse-convolve.c to fuse-convolve.cc. Make filter-interface
authored
122 }
123
ee675fe @hzeller o Provide a way to select between different filter diretories.
authored
124 void StatusServer::SetFilter(const char *filter) {
125 if (filter == NULL || *filter == '\0') return;
126 char *end;
127 int index = strtol(filter, &end, 10);
128 if (end == NULL || *end != '\0') return;
129 filter_switched_ = (index != filesystem_->current_cfg_index());
130 filesystem_->SwitchCurrentConfigIndex(index);
131 }
132
249865a @hzeller o Make debug mode switchable in UI.
authored
133 void StatusServer::SetDebug(const char *dbg) {
8c7e5c1 @hzeller o Only if -D is given, the debug toggle is active in the UI.
authored
134 if (!filesystem_->is_debug_ui_enabled()) return;
7689c9a @hzeller o preparation to extract classes from folve-filesystem into their
authored
135 folve::EnableDebugLog(dbg != NULL && *dbg == '1');
249865a @hzeller o Make debug mode switchable in UI.
authored
136 }
137
8d1fbe7 @hzeller o Move fuse-convolve.c to fuse-convolve.cc. Make filter-interface
authored
138 bool StatusServer::Start(int port) {
118a454 @hzeller o Show the filter used for a particular format.
authored
139 PrepareConfigDirectoriesForUI();
8d1fbe7 @hzeller o Move fuse-convolve.c to fuse-convolve.cc. Make filter-interface
authored
140 daemon_ = MHD_start_daemon(MHD_USE_SELECT_INTERNALLY, port, NULL, NULL,
141 &HandleHttp, this,
142 MHD_OPTION_END);
143 return daemon_ != NULL;
144 }
145
146 StatusServer::~StatusServer() {
b698853 @hzeller o README updates.
authored
147 if (daemon_) MHD_stop_daemon(daemon_);
8d1fbe7 @hzeller o Move fuse-convolve.c to fuse-convolve.cc. Make filter-interface
authored
148 }
149
223f392 @hzeller o Have a separate HandlerStats object that contains relevant
authored
150 // FileHandlerCache::Observer interface.
151 void StatusServer::RetireHandlerEvent(FileHandler *handler) {
152 HandlerStats stats;
153 handler->GetHandlerStatus(&stats); // Get last available stats.
154 if (stats.progress >= 0) {
8268c37 @hzeller o Bubble up error messages in status server.
authored
155 total_seconds_music_seen_ += stats.duration_seconds;
156 total_seconds_filtered_ += stats.duration_seconds * stats.progress;
223f392 @hzeller o Have a separate HandlerStats object that contains relevant
authored
157 }
a9d3e53 @hzeller o Found a project name: "Folve". Some renamings because of that.
authored
158 stats.last_access = folve::CurrentTime();
223f392 @hzeller o Have a separate HandlerStats object that contains relevant
authored
159 stats.status = HandlerStats::RETIRED;
1e9ff21 @hzeller o main: report if parameters are not directories.
authored
160 boost::lock_guard<boost::mutex> l(retired_mutex_);
223f392 @hzeller o Have a separate HandlerStats object that contains relevant
authored
161 retired_.push_front(stats);
1e9ff21 @hzeller o main: report if parameters are not directories.
authored
162 while (retired_.size() > kMaxRetired) {
163 ++expunged_retired_;
223f392 @hzeller o Have a separate HandlerStats object that contains relevant
authored
164 retired_.pop_back();
1e9ff21 @hzeller o main: report if parameters are not directories.
authored
165 }
223f392 @hzeller o Have a separate HandlerStats object that contains relevant
authored
166 }
bea11d6 @hzeller o Don't use snprintf, but use a new function Appendf() to assemble
authored
167
f1ef960 @hzeller o a bit HTML polishing.
authored
168 // As ugly #defines, so that gcc can warn about printf() format problems.
169 #define sMessageRowHtml \
08bbf28 @hzeller o First shot at gapless. Works pretty well for my test-case.
authored
170 "<td>%s</td><td colspan='3' style='font-size:small;'>%s</td>"
b5c1e96 @hzeller o more useful output on status server.
authored
171
f1ef960 @hzeller o a bit HTML polishing.
authored
172 #define sProgressRowHtml \
173 "<td>%s</td>" \
174 "<td>%s</td>" \
175 "<td><div style='background:white;width:%dpx;border:1px solid black;'>\n" \
b9ae86d @hzeller o Higher than percent resolution progress bar.
authored
176 " <div style='width:%dpx;background:%s;'>&nbsp;</div>\n</div></td>" \
08bbf28 @hzeller o First shot at gapless. Works pretty well for my test-case.
authored
177 "<td>%s</td>"
f1ef960 @hzeller o a bit HTML polishing.
authored
178
179 #define sTimeColumns \
180 "<td align='right'>%2d:%02d</td><td>/</td><td align='right'>%2d:%02d</td>"
181 #define sDecibelColumn \
182 "<td align='right' style='background:%s;'>%.1f dB</td>"
b5c1e96 @hzeller o more useful output on status server.
authored
183
118a454 @hzeller o Show the filter used for a particular format.
authored
184 void StatusServer::AppendFileInfo(const char *progress_style,
185 const HandlerStats &stats) {
186 content_.append("<tr style='text-wrap:none;white-space:nowrap;'>");
223f392 @hzeller o Have a separate HandlerStats object that contains relevant
authored
187 const char *status = "";
188 switch (stats.status) {
189 case HandlerStats::OPEN: status = "open"; break;
190 case HandlerStats::IDLE: status = "idle"; break;
bcb77e7 @hzeller o Ran with Amarok over my files. Looks like it sometimes only 'almost'
authored
191 case HandlerStats::RETIRED: status = "&nbsp;----&nbsp;"; break;
223f392 @hzeller o Have a separate HandlerStats object that contains relevant
authored
192 // no default to let the compiler detect new values.
193 }
f1ef960 @hzeller o a bit HTML polishing.
authored
194
8268c37 @hzeller o Bubble up error messages in status server.
authored
195 if (!stats.message.empty()) {
118a454 @hzeller o Show the filter used for a particular format.
authored
196 Appendf(&content_, sMessageRowHtml, status, stats.message.c_str());
8268c37 @hzeller o Bubble up error messages in status server.
authored
197 } else if (stats.progress == 0) {
118a454 @hzeller o Show the filter used for a particular format.
authored
198 Appendf(&content_, sMessageRowHtml, status, "Only header accessed");
b5c1e96 @hzeller o more useful output on status server.
authored
199 } else {
118a454 @hzeller o Show the filter used for a particular format.
authored
200 Appendf(&content_, sProgressRowHtml, status,
08bbf28 @hzeller o First shot at gapless. Works pretty well for my test-case.
authored
201 stats.in_gapless ? "&rarr;" : "",
b9ae86d @hzeller o Higher than percent resolution progress bar.
authored
202 kProgressWidth, (int) (kProgressWidth * stats.progress),
203 progress_style,
f1ef960 @hzeller o a bit HTML polishing.
authored
204 stats.out_gapless ? "&rarr;" : "");
205 }
206 const int secs = stats.duration_seconds;
207 const int fract_sec = stats.progress * secs;
6d4f28b @hzeller o if there is a time, show it.
authored
208 if (secs >= 0 && fract_sec >= 0) {
118a454 @hzeller o Show the filter used for a particular format.
authored
209 Appendf(&content_, sTimeColumns,
f1ef960 @hzeller o a bit HTML polishing.
authored
210 fract_sec / 60, fract_sec % 60,
211 secs / 60, secs % 60);
212 } else {
118a454 @hzeller o Show the filter used for a particular format.
authored
213 content_.append("<td colspan='3'>-</td>");
b5c1e96 @hzeller o more useful output on status server.
authored
214 }
f00e6a4 @hzeller o Don't do unprotected read on status information such as
authored
215
036c6e1 @hzeller o not wide cellspacing needed anymore.
authored
216 if (stats.max_output_value > 1e-6) {
118a454 @hzeller o Show the filter used for a particular format.
authored
217 Appendf(&content_, sDecibelColumn,
f1ef960 @hzeller o a bit HTML polishing.
authored
218 stats.max_output_value > 1.0 ? "#FF0505" : "white",
7b499ea @hzeller o Uh, log() is actually ln() and log10f() is log() :)
authored
219 20 * log10f(stats.max_output_value));
f1ef960 @hzeller o a bit HTML polishing.
authored
220 } else {
118a454 @hzeller o Show the filter used for a particular format.
authored
221 content_.append("<td>-</td>");
f1ef960 @hzeller o a bit HTML polishing.
authored
222 }
223
118a454 @hzeller o Show the filter used for a particular format.
authored
224 Appendf(&content_, "<td bgcolor='#c0c0c0'>&nbsp;%s (%s)&nbsp;</td>",
225 stats.format.c_str(), ui_config_directories_[stats.filter_id].c_str());
226 Appendf(&content_,"<td "
bea11d6 @hzeller o Don't use snprintf, but use a new function Appendf() to assemble
authored
227 "style='font-size:small;text-wrap:none;white-space:nowrap'>%s</td>",
228 stats.filename.c_str());
118a454 @hzeller o Show the filter used for a particular format.
authored
229 content_.append("</tr>\n");
b5c1e96 @hzeller o more useful output on status server.
authored
230 }
231
d280fce @hzeller o Reload page with a meta-refresn.
authored
232 void StatusServer::PrepareConfigDirectoriesForUI() {
233 // Essentially only keep the directory name.
234 if (!ui_config_directories_.empty()) return;
118a454 @hzeller o Show the filter used for a particular format.
authored
235 ui_config_directories_.push_back("None : Pass Through");
d280fce @hzeller o Reload page with a meta-refresn.
authored
236 for (size_t i = 1; i < filesystem_->config_dirs().size(); ++i) {
237 std::string d = filesystem_->config_dirs()[i];
238 while (d.length() > 0 && d[d.length() - 1] == '/') {
239 d.resize(d.length() - 1); // trim trailing slashes.
240 }
241 const std::string::size_type slash_pos = d.find_last_of('/');
242 if (slash_pos != std::string::npos) {
243 d = d.substr(slash_pos + 1);
244 }
245 ui_config_directories_.push_back(d);
246 }
247 }
248
249 static void CreateSelection(std::string *result,
250 const std::vector<std::string> &options,
251 int selected) {
252 if (options.size() == 1) {
253 result->append(options[0]); // no reason to make this a form :)
254 return;
255 }
256 for (size_t i = 0; i < options.size(); ++i) {
257 const std::string &c = options[i];
adde81e @hzeller o some link prettify.
authored
258 result->append("&nbsp;");
d280fce @hzeller o Reload page with a meta-refresn.
authored
259 const bool active = (int) i == selected;
537e34b @hzeller o cleanup UI: no radio buttons anymore, just simple links.
authored
260 if (active) {
adde81e @hzeller o some link prettify.
authored
261 Appendf(result, "<span class='filter_sel active'>%s</span>\n", c.c_str());
537e34b @hzeller o cleanup UI: no radio buttons anymore, just simple links.
authored
262 } else {
adde81e @hzeller o some link prettify.
authored
263 Appendf(result, "<a class='filter_sel inactive' href='%s?f=%zd'>%s</a>\n",
264 kSettingsUrl, i, c.c_str());
537e34b @hzeller o cleanup UI: no radio buttons anymore, just simple links.
authored
265 }
ee675fe @hzeller o Provide a way to select between different filter diretories.
authored
266 }
d280fce @hzeller o Reload page with a meta-refresn.
authored
267 }
268
269 void StatusServer::AppendSettingsForm() {
adde81e @hzeller o some link prettify.
authored
270 content_.append("<p>Config directory: ");
d280fce @hzeller o Reload page with a meta-refresn.
authored
271 CreateSelection(&content_, ui_config_directories_,
272 filesystem_->current_cfg_index());
ee675fe @hzeller o Provide a way to select between different filter diretories.
authored
273 if (filesystem_->config_dirs().size() == 1) {
d280fce @hzeller o Reload page with a meta-refresn.
authored
274 content_.append(" (This is a boring configuration, add filter directories "
537e34b @hzeller o cleanup UI: no radio buttons anymore, just simple links.
authored
275 "with -c &lt;dir&gt; [-c &lt;another-dir&gt; ...] :-) )");
ee675fe @hzeller o Provide a way to select between different filter diretories.
authored
276 } else if (filter_switched_) {
d280fce @hzeller o Reload page with a meta-refresn.
authored
277 content_.append("&nbsp;<span style='font-size:small;background:#FFFFa0;'>"
278 " (Affects re- or newly opened files.) </span>");
e619ff2 @hzeller o Redirect to / after settings. That way, a reload won't change any
authored
279 filter_switched_ = false; // only show once.
ee675fe @hzeller o Provide a way to select between different filter diretories.
authored
280 }
537e34b @hzeller o cleanup UI: no radio buttons anymore, just simple links.
authored
281 // TODO: re-add something for filesystem_->is_debug_ui_enabled()
adde81e @hzeller o some link prettify.
authored
282 content_.append("</p><hr/>");
ee675fe @hzeller o Provide a way to select between different filter diretories.
authored
283 }
284
223f392 @hzeller o Have a separate HandlerStats object that contains relevant
authored
285 struct CompareStats {
286 bool operator() (const HandlerStats &a, const HandlerStats &b) {
287 if (a.status < b.status) return true; // open before idle.
288 else if (a.status > b.status) return false;
289 return b.last_access < a.last_access; // reverse time.
290 }
291 };
292
1e9ff21 @hzeller o main: report if parameters are not directories.
authored
293 const std::string &StatusServer::CreatePage() {
a9d3e53 @hzeller o Found a project name: "Folve". Some renamings because of that.
authored
294 const double start = folve::CurrentTime();
b698853 @hzeller o README updates.
authored
295 // We re-use a string to avoid re-allocing memory every time we generate
296 // a page. Since we run with MHD_USE_SELECT_INTERNALLY, this is only accessed
297 // by one thread.
7d695c6 @hzeller o Rename current_page_ to content_ to be more generic.
authored
298 content_.clear();
a372a03 @hzeller o Make meta-refresh configurable.
authored
299 content_.append(kStartHtmlHeader);
300 if (meta_refresh_time_ > 0) {
301 Appendf(&content_, "<meta http-equiv='refresh' content='%d'>\n",
302 meta_refresh_time_);
303 }
537e34b @hzeller o cleanup UI: no radio buttons anymore, just simple links.
authored
304 content_.append(kCSS);
a372a03 @hzeller o Make meta-refresh configurable.
authored
305 content_.append("</head>\n");
306
7d695c6 @hzeller o Rename current_page_ to content_ to be more generic.
authored
307 content_.append("<body style='font-family:Sans-Serif;'>\n");
308 Appendf(&content_, "<center style='background-color:#A0FFA0;'>"
53130a3 @hzeller o link to github page
authored
309 "Welcome to "
ee675fe @hzeller o Provide a way to select between different filter diretories.
authored
310 "<a href='https://github.com/hzeller/folve#readme'>Folve</a> "
311 FOLVE_VERSION "</center>\n"
312 "Convolving audio files from <code>%s</code>\n",
313 filesystem_->underlying_dir().c_str());
223f392 @hzeller o Have a separate HandlerStats object that contains relevant
authored
314
d280fce @hzeller o Reload page with a meta-refresn.
authored
315 AppendSettingsForm();
27c44cd @hzeller o Use fuse option handling to extract our flags and options.
authored
316
223f392 @hzeller o Have a separate HandlerStats object that contains relevant
authored
317 std::vector<HandlerStats> stat_list;
318 filesystem_->handler_cache()->GetStats(&stat_list);
319
562b493 @hzeller o Print out config file name while spotting a problem
authored
320 // Get statistics of active files to add to the existing ones.
223f392 @hzeller o Have a separate HandlerStats object that contains relevant
authored
321 double active_music_seen = 0.0;
322 double active_filtered = 0.0;
323 for (size_t i = 0; i < stat_list.size(); ++i) {
324 const HandlerStats &stats = stat_list[i];
325 if (stats.progress >= 0) {
8268c37 @hzeller o Bubble up error messages in status server.
authored
326 active_music_seen += stats.duration_seconds;
327 active_filtered += stats.duration_seconds * stats.progress;
223f392 @hzeller o Have a separate HandlerStats object that contains relevant
authored
328 }
329 }
330 const int t_seen = total_seconds_music_seen_ + active_music_seen;
331 const int t_filtered = total_seconds_filtered_ + active_filtered;
7d695c6 @hzeller o Rename current_page_ to content_ to be more generic.
authored
332 Appendf(&content_, "Total opening files <b>%d</b> "
bea11d6 @hzeller o Don't use snprintf, but use a new function Appendf() to assemble
authored
333 ".. and re-opened from recency cache <b>%d</b><br/>",
334 filesystem_->total_file_openings(),
335 filesystem_->total_file_reopen());
7d695c6 @hzeller o Rename current_page_ to content_ to be more generic.
authored
336 Appendf(&content_, "Total music seen <b>%dd %d:%02d:%02d</b> ",
bea11d6 @hzeller o Don't use snprintf, but use a new function Appendf() to assemble
authored
337 t_seen / 86400, (t_seen % 86400) / 3600,
338 (t_seen % 3600) / 60, t_seen % 60);
7d695c6 @hzeller o Rename current_page_ to content_ to be more generic.
authored
339 Appendf(&content_, ".. and convolved <b>%dd %d:%02d:%02d</b> ",
bea11d6 @hzeller o Don't use snprintf, but use a new function Appendf() to assemble
authored
340 t_filtered / 86400, (t_filtered % 86400) / 3600,
341 (t_filtered % 3600) / 60, t_filtered % 60);
7d695c6 @hzeller o Rename current_page_ to content_ to be more generic.
authored
342 Appendf(&content_, "(%.1f%%)<br/>",
bea11d6 @hzeller o Don't use snprintf, but use a new function Appendf() to assemble
authored
343 (t_seen == 0) ? 0.0 : (100.0 * t_filtered / t_seen));
344
7d695c6 @hzeller o Rename current_page_ to content_ to be more generic.
authored
345 Appendf(&content_, "<h3>Accessed Recently</h3>\n%zd in recency cache\n",
bea11d6 @hzeller o Don't use snprintf, but use a new function Appendf() to assemble
authored
346 stat_list.size());
347
08bbf28 @hzeller o First shot at gapless. Works pretty well for my test-case.
authored
348 if (filesystem_->gapless_processing()) {
d93a35b @hzeller o Uh, typo in gapless message.
authored
349 content_.append("<br/>&rarr; : denotes gapless transfers\n");
08bbf28 @hzeller o First shot at gapless. Works pretty well for my test-case.
authored
350 }
036c6e1 @hzeller o not wide cellspacing needed anymore.
authored
351 content_.append("<table>\n");
08bbf28 @hzeller o First shot at gapless. Works pretty well for my test-case.
authored
352 Appendf(&content_, "<tr><th>Stat</th><td><!--gapless in--></td>"
353 "<th width='%dpx'>Progress</th>" // progress bar.
354 "<td><!-- gapless out --></td>"
f1e9f27 @hzeller o Explain filter in table header.
authored
355 "<th>Pos</th><td></td><th>Len</th><th>Max&nbsp;out</th><th>Format&nbsp;(used&nbsp;filter)</th>"
b698853 @hzeller o README updates.
authored
356 "<th align='left'>File</th></tr>\n", kProgressWidth);
223f392 @hzeller o Have a separate HandlerStats object that contains relevant
authored
357 CompareStats comparator;
358 std::sort(stat_list.begin(), stat_list.end(), comparator);
359 for (size_t i = 0; i < stat_list.size(); ++i) {
118a454 @hzeller o Show the filter used for a particular format.
authored
360 AppendFileInfo(kActiveProgress, stat_list[i]);
b5c1e96 @hzeller o more useful output on status server.
authored
361 }
7d695c6 @hzeller o Rename current_page_ to content_ to be more generic.
authored
362 content_.append("</table><hr/>\n");
223f392 @hzeller o Have a separate HandlerStats object that contains relevant
authored
363
364 if (retired_.size() > 0) {
7d695c6 @hzeller o Rename current_page_ to content_ to be more generic.
authored
365 content_.append("<h3>Retired</h3>\n");
366 content_.append("<table>\n");
1e9ff21 @hzeller o main: report if parameters are not directories.
authored
367 boost::lock_guard<boost::mutex> l(retired_mutex_);
b698853 @hzeller o README updates.
authored
368 for (RetiredList::const_iterator it = retired_.begin();
223f392 @hzeller o Have a separate HandlerStats object that contains relevant
authored
369 it != retired_.end(); ++it) {
118a454 @hzeller o Show the filter used for a particular format.
authored
370 AppendFileInfo(kRetiredProgress, *it);
223f392 @hzeller o Have a separate HandlerStats object that contains relevant
authored
371 }
7d695c6 @hzeller o Rename current_page_ to content_ to be more generic.
authored
372 content_.append("</table>\n");
1e9ff21 @hzeller o main: report if parameters are not directories.
authored
373 if (expunged_retired_ > 0) {
7d695c6 @hzeller o Rename current_page_ to content_ to be more generic.
authored
374 Appendf(&content_, "... (%d more)<p></p>", expunged_retired_);
1e9ff21 @hzeller o main: report if parameters are not directories.
authored
375 }
7d695c6 @hzeller o Rename current_page_ to content_ to be more generic.
authored
376 content_.append("<hr/>");
223f392 @hzeller o Have a separate HandlerStats object that contains relevant
authored
377 }
378
a9d3e53 @hzeller o Found a project name: "Folve". Some renamings because of that.
authored
379 const double duration = folve::CurrentTime() - start;
7d695c6 @hzeller o Rename current_page_ to content_ to be more generic.
authored
380 Appendf(&content_,
a9d3e53 @hzeller o Found a project name: "Folve". Some renamings because of that.
authored
381 "<span style='float:left;font-size:small;'>page-gen %.2fms</span>"
75867a2 @hzeller o legalese: add COPYING, provide "Appropriate Legal Notices" and
authored
382 "<span style='float:right;font-size:x-small;'>"
383 "&copy; 2012 Henner Zeller"
384 " | Folve is free software and comes with no warranty. "
385 " | Conveyed under the terms of the "
386 "<a href='http://www.gnu.org/licenses/gpl.html'>GPLv3</a>.</span>"
e619ff2 @hzeller o Redirect to / after settings. That way, a reload won't change any
authored
387 "</body></html>\n", duration * 1000.0);
7d695c6 @hzeller o Rename current_page_ to content_ to be more generic.
authored
388 return content_;
8d1fbe7 @hzeller o Move fuse-convolve.c to fuse-convolve.cc. Make filter-interface
authored
389 }
Something went wrong with that request. Please try again.