<%pre> #include <string> #ifdef HAVE_LIBPCRECPP #include <pcrecpp.h> #endif #include <vdr/plugin.h> #include <vdr/config.h> #include <vdr/videodir.h> #include "exception.h" #include "epg_events.h" #include "setup.h" #include "tasks.h" #include "tools.h" #include "i18n.h" #include "users.h" #include "recman.h" #define MB_PER_MINUTE 25.75 // this is just an estimate! using namespace vdrlive; using namespace std; </%pre> <%args> string sort; string todel; string diskinfo; string filter; string deletions[]; </%args> <%session scope="global"> bool logged_in(false); </%session> <%request scope="page"> string currentSort; string deleteResult; string currentFilter; </%request> <%include>page_init.eh</%include> <%cpp> if (!logged_in && LiveSetup().UseAuth()) return reply.redirect("login.html"); currentSort = LiveSetup().GetLastSortingMode(); if (!sort.empty()) { if (sort == "date") currentSort = (currentSort == "dateasc") ? "datedesc" : "dateasc"; else if (sort == "name") currentSort = (currentSort == "nameasc") ? "namedesc" : "nameasc"; LiveSetup().SetLastSortingMode(currentSort); } currentFilter = filter; pageTitle = tr("Recordings"); deleteResult = ""; if (!todel.empty()) { if (!cUser::CurrentUserHasRightTo(UR_DELRECS)) throw HtmlError( tr("Sorry, no permission. Please contact your administrator!") ); deletions.push_back(todel); } for (deletions_type::const_iterator it = deletions.begin(); it != deletions.end(); ++it) { RemoveRecordingTask task(*it); LiveTaskManager().Execute(task); if (!task.Result()) deleteResult += string() + tr("ERROR:") + " " + task.Error() + "<br/>"; else deleteResult += string() + tr("Deleted recording:") + " " + StringReplace(task.RecName(), "~", "/") + "<br/>"; } deletions.clear(); int FreeMB, UsedMB; int Percent = VideoDiskSpace(&FreeMB, &UsedMB); int Minutes = int(double(FreeMB) / MB_PER_MINUTE); int Hours = Minutes / 60; Minutes %= 60; diskinfo = cString::sprintf("%s %d%% - %2d:%02d %s", trVDR("Disk"), Percent, Hours, Minutes, trVDR("free")); </%cpp> <& pageelems.doc_type &> <html> <head> <title>VDR-Live - <$ pageTitle $></title> <& pageelems.stylesheets &> <& pageelems.ajax_js &> <script type="text/javascript" src="treeview.js"></script> <script type="text/javascript"><!-- function filterRecordings(filter) { window.location.href = "recordings.html?sort=<$ currentSort $>&filter=" + encodeURIComponent(filter.value); } function ExpandAll() { recordingNodes = window.document.getElementsBySelector("ul.recordingslist"); for (idx = 0; idx < recordingNodes.length; idx++) { if (recordingNodes[idx].parentNode.className != 'recordings') { recordingNodes[idx].style.display = 'block'; } } expandNodes = window.document.getElementsBySelector("img.recording_expander"); for (idx = 0; idx < expandNodes.length; idx++) { expandNodes[idx].src = "img/minus.png"; } folderNodes = window.document.getElementsBySelector("img.recording_folder"); for (idx = 0; idx < folderNodes.length; idx++) { folderNodes[idx].src = "img/folder_open.png"; } } function CollapseAll() { recordingNodes = window.document.getElementsBySelector("ul.recordingslist"); for (idx = 0; idx < recordingNodes.length; idx++) { if (recordingNodes[idx].parentNode.className != 'recordings') { recordingNodes[idx].style.display = 'none'; } } expandNodes = window.document.getElementsBySelector("img.recording_expander"); for (idx = 0; idx < expandNodes.length; idx++) { expandNodes[idx].src = "img/plus.png"; } folderNodes = window.document.getElementsBySelector("img.recording_folder"); for (idx = 0; idx < folderNodes.length; idx++) { folderNodes[idx].src = "img/folder_closed.png"; } } //--></script> </head> <body> <& pageelems.logo &> <%cpp> if (!deleteResult.empty()) { </%cpp> <& menu active=("recordings") component=("recordings.delete_error") &> <%cpp> } else { </%cpp> <& menu active=("recordings") component=("recordings.sort_options") &> <%cpp> } </%cpp> <div class="inhalt"> <div class="boxheader"><div><div><$ string(tr("List of recordings")) + " (" + diskinfo + ")" $></div></div></div> <%cpp> if (Recordings.Count() == 0) { // Access VDRs global cRecordings Recordings instance. </%cpp> <$ tr("No recordings found") $> <%cpp> } else { </%cpp> <form method="post" name="recordings" action="recordings.ecpp"> <div class="recordings"> <ul class="recordingslist" style="display: block;"> <& recordings.recordings_item filter=(currentFilter) &> </ul> </div> <div class="withmargin"> <button class="red" type="submit"><$ tr("Delete selected") $></button> </div> </form> <%cpp> } </%cpp> </div> </body> </html> <%include>page_exit.eh</%include> <# ---------------------------------------------------------------------- #> <%def recordings_item> <%args> filter; path[]; int level = 0; </%args> <%cpp> RecordingsTreePtr recordingsTree(LiveRecordingsManager()->GetRecordingsTree()); RecordingsMap::iterator iter; RecordingsMap::iterator end = recordingsTree->end(path); list<RecordingsItemPtr> recItems; list<RecordingsItemPtr>::iterator recIter; for (iter = recordingsTree->begin(path); iter != end; ++iter) { RecordingsItemPtr recItem = iter->second; if (recItem->IsDir()) { recItems.push_back(recItem); } } if (currentSort == "namedesc") recItems.sort(RecordingsItemPtrCompare::ByDescendingName); else recItems.sort(RecordingsItemPtrCompare::ByAscendingName); for (recIter = recItems.begin(); recIter != recItems.end(); ++recIter) { RecordingsItemPtr recItem = *recIter; </%cpp> <li class="recording"> <& rec_item_dir name=(recItem->Name()) level=(level) &> <%cpp> #if TNT_HAS_QUERYPARAMS tnt::QueryParams recItemParams(qparam, false); #else cxxtools::QueryParams recItemParams(qparam, false); #endif for (path_type::const_iterator i = path.begin(); i != path.end(); ++i) { recItemParams.add("path", *i); } recItemParams.add("path", recItem->Name()); recItemParams.add("level", lexical_cast<string, int>(level + 1)); recItemParams.add("filter", filter); </%cpp> <ul class="recordingslist" style="display: none;"> <%cpp> callComp("recordings.recordings_item", request, reply, recItemParams); </%cpp> </ul> </li> <%cpp> } recItems.clear(); for (iter = recordingsTree->begin(path); iter != end; ++iter) { RecordingsItemPtr recItem = iter->second; if (!recItem->IsDir()) { recItems.push_back(recItem); } } if (currentSort == "dateasc") recItems.sort(RecordingsItemPtrCompare::ByAscendingDate); else if (currentSort == "datedesc") recItems.sort(RecordingsItemPtrCompare::ByDescendingDate); else if (currentSort == "namedesc") recItems.sort(RecordingsItemPtrCompare::ByDescendingName); else recItems.sort(RecordingsItemPtrCompare::ByAscendingName); for (recIter = recItems.begin(); recIter != recItems.end(); ++recIter) { RecordingsItemPtr recItem = *recIter; // xgettext:no-c-format string day(FormatDateTime(tr("%a,"), recItem->StartTime())); string dayLen(lexical_cast<string, int>(day.length() - 1) + ".25em;"); // TRANSLATORS: recording duration format HH:MM string duration(recItem->Duration() < 0 ? "" : FormatDuration(tr("(%d:%02d)"), recItem->Duration() / 60, recItem->Duration() % 60)); string shortDescr(recItem->RecInfo()->ShortText() ? recItem->RecInfo()->ShortText() : ""); string description(recItem->RecInfo()->Description() ? recItem->RecInfo()->Description() : ""); string hint(tr("Click to view details.")); if (!shortDescr.empty()) hint = shortDescr + "<br />" + hint; else if (!description.empty()) hint = description + "<br />" + hint; #ifdef HAVE_LIBPCRECPP pcrecpp::RE re(filter.c_str(), pcrecpp::UTF8()); if (filter.empty() || re.PartialMatch(recItem->Name()) || re.PartialMatch(shortDescr) || re.PartialMatch(description)) #endif { </%cpp> <li class="recording"> <& rec_item_file name=(recItem->Name()) level=(level) id=(recItem->Id()) day=(day) dayLen=(dayLen) startTime=(recItem->StartTime()) duration=(duration) hint=(hint) shortDescr=(shortDescr) archived=(RecordingsManager::GetArchiveDescr(recItem->Recording())) &> </li> <%cpp> } } </%cpp> </%def> <# ---------------------------------------------------------------------- #> <%def sort_options> <%cpp> { </%cpp> <a href="recordings.html?sort=name&filter=<? currentFilter != "" ? currentFilter ?>" alt="" /><$ tr("Sort by name") $></a> <span class="sep">|</span> <a href="recordings.html?sort=date&filter=<? currentFilter != "" ? currentFilter ?>" alt="" /><$ tr("Sort by date") $></a> <%cpp> #ifdef HAVE_LIBPCRECPP </%cpp> <span class="sep">|</span> <span class="label bold"><$ tr("Filter") $>: <input type="text" name="filter" value="<$ currentFilter $>" id="filter" onchange="filterRecordings(this)" /> <& tooltip.help text=(tr("Look in recordings titles and subtitles for the given string and display only the matching ones. You may also use perl compatible regular expressions (PCRE).")) &></span> <%cpp> #endif </%cpp> <span class="sep">|</span> <img onclick="ExpandAll()" src="<$ LiveSetup().GetThemedLink("img", "plus.png") $>" alt="" <& tooltip.hint text=(tr("Expand all folders")) &>/> <img onclick="CollapseAll()" src="<$ LiveSetup().GetThemedLink("img", "minus.png") $>" alt="" <& tooltip.hint text=(tr("Collapse all folders")) &>/> <br /> <%cpp> } </%cpp> </%def> <# ---------------------------------------------------------------------- #> <%def del_rec> <%args> string id; </%args> <%cpp> { </%cpp><a href="recordings.html?todel=<$ id $>" <& tooltip.hint text=(tr("Delete this recording from hard disc!")) &>><img src="<$ LiveSetup().GetThemedLink("img", "del.png") $>" alt="" /></a><%cpp> } </%cpp> </%def> <# ---------------------------------------------------------------------- #> <%def edit_rec> <%args> string id; </%args> <%cpp> { </%cpp><a href="edit_recording.html?recid=<$ id $>"><img src="<$ LiveSetup().GetThemedLink("img", "edit.png") $>" alt="" <& tooltip.hint text=(tr("Edit recording")) &> /></a><%cpp> } </%cpp> </%def> <# ---------------------------------------------------------------------- #> <%def rec_tools> <%args> string id; string title; </%args> <& pageelems.ajax_action_href action="play_recording" param=(id) tip=(tr("play this recording.")) image="play.png" alt="" &> <& pageelems.vlc_stream_recording recid=(id) &> <& pageelems.imdb_info_href title=(title) &> <& recordings.edit_rec id=(id) &> <& recordings.del_rec id=(id) &> </%def> <# ---------------------------------------------------------------------- #> <%def archived_disc> <%args> string archived; string title; </%args> <img src="<$ LiveSetup().GetThemedLink("img", "on_dvd.png") $>" alt="on_dvd" <& tooltip.hint text=(archived) &> /> <& pageelems.imdb_info_href title=(title) &> </%def> <# ---------------------------------------------------------------------- #> <%def rec_item_dir> <%args> string name; int level; string collapseimg = "plus.png"; string folderimg = "folder_closed.png"; </%args> <div class="recording_item" onclick="Toggle(this)"> <div class="recording_imgs"><%cpp> reply.out() << StringRepeat(level, "<img src=\"img/transparent.png\" alt=\"\" width=\"16px\" height=\"16px\" />"); </%cpp><img class="recording_expander" src="<$ LiveSetup().GetThemedLink("img", collapseimg) $>" alt="" /><img class="recording_folder" src="<$ LiveSetup().GetThemedLink("img", folderimg) $>" alt="" /></div> <div class="recording_spec"> <div class="recording_name"><$ name $></div> </div> <div class="recording_actions"> </div> </div> </%def> <# ---------------------------------------------------------------------- #> <%def rec_item_file> <%args> string name; int level; string id; string day; string dayLen; time_t startTime; string duration; string hint; string shortDescr; string archived; </%args> <div class="recording_item"> <div class="recording_imgs"><%cpp> reply.out() << StringRepeat(level + 1, "<img src=\"img/transparent.png\" alt=\"\" width=\"16px\" height=\"16px\" />"); </%cpp><%cpp> if (!archived.empty()) { </%cpp><img src="<$ LiveSetup().GetThemedLink("img", "on_dvd.png") $>" alt="on_dvd" <& tooltip.hint text=(archived) &> /><%cpp> } else { </%cpp><input type="checkbox" name="deletions" value="<$ id $>" /><%cpp> } </%cpp></div> <div class="recording_spec"> <div class="recording_day"><$ FormatDateTime(tr("%a,"), startTime) + string(" ") + FormatDateTime(tr("%b %d %y"), startTime) + string(" ") + FormatDateTime(tr("%I:%M %p"), startTime) $></div> <div class="recording_duration"><$ duration $></div> <div class="recording_name"><a <& tooltip.hint text=(hint) &><& tooltip.display domId=(id) &>><$ name $><br /><%cpp>if ((name != shortDescr) && (!shortDescr.empty())) {</%cpp><span><$ shortDescr $></span><%cpp> } else { </%cpp><span> </span><%cpp> } </%cpp></a></div> </div> <div class="recording_actions"> <%cpp> if (archived.empty()) { </%cpp> <& recordings.rec_tools id=(id) title=(name)&> <%cpp> } else { </%cpp> <img src="img/transparent.png" alt="" width="16px" height="16px" /> <& pageelems.imdb_info_href title=(name) &> <%cpp> } </%cpp> </div> <%cpp> if (! archived.empty()) { </%cpp> <div class="recording_arch"><$ archived $></div> <%cpp> } </%cpp> </div> </%def> <# ---------------------------------------------------------------------- #> <%def delete_error> <& recordings.sort_options &> <%cpp> { reply.out() << deleteResult; } </%cpp> </%def>