diff options
-rw-r--r-- | css/styles.css | 10 | ||||
-rw-r--r-- | epg_events.cpp | 22 | ||||
-rw-r--r-- | epg_events.h | 13 | ||||
-rw-r--r-- | i18n.cpp | 310 | ||||
-rw-r--r-- | images/Makefile | 2 | ||||
-rw-r--r-- | images/on_dvd.png | bin | 0 -> 821 bytes | |||
-rw-r--r-- | javascript/vdr_status.js | 2 | ||||
-rw-r--r-- | pages/pageelems.ecpp | 47 | ||||
-rw-r--r-- | pages/recordings.ecpp | 184 | ||||
-rw-r--r-- | pages/tooltip.ecpp | 8 | ||||
-rw-r--r-- | recordings.cpp | 68 | ||||
-rw-r--r-- | recordings.h | 12 |
12 files changed, 434 insertions, 244 deletions
diff --git a/css/styles.css b/css/styles.css index 2cfce95..734788b 100644 --- a/css/styles.css +++ b/css/styles.css @@ -34,6 +34,15 @@ img { } /* ###################### + # global style properties + ###################### +*/ + +.bold { + font-weight: bold; +} + +/* ###################### # Tooltip style for hints ###################### */ @@ -591,6 +600,7 @@ div.boxheader div div { */ div.recordings { + border: 1px solid black; } .recordings ul { diff --git a/epg_events.cpp b/epg_events.cpp index ec95fde..2d5237c 100644 --- a/epg_events.cpp +++ b/epg_events.cpp @@ -1,6 +1,7 @@ #include <time.h> #include "tools.h" +#include "recordings.h" #include "epg_events.h" @@ -18,6 +19,7 @@ namespace vdrlive m_title(title), m_short_descr(short_descr), m_long_descr(long_descr), + m_archived(), m_start_time(start_time), m_end_time(end_time) { @@ -29,11 +31,31 @@ namespace vdrlive m_title(event->Title() ? event->Title() : ""), m_short_descr(event->ShortText() ? event->ShortText() : ""), m_long_descr(event->Description() ? event->Description() : ""), + m_archived(), m_start_time(event->StartTime()), m_end_time(event->EndTime()) { } + EpgEvent::EpgEvent(const std::string& id, + const std::string& caption, + const std::string& title, + const std::string& short_descr, + const std::string& long_descr, + const std::string& archived, + time_t start_time, + time_t end_time) : + m_eventId(id), + m_caption(caption), + m_title(title), + m_short_descr(short_descr), + m_long_descr(long_descr), + m_archived(archived), + m_start_time(start_time), + m_end_time(end_time) + { + } + EpgEvent::~EpgEvent() { } diff --git a/epg_events.h b/epg_events.h index 330f7ba..03c7947 100644 --- a/epg_events.h +++ b/epg_events.h @@ -15,7 +15,6 @@ namespace vdrlive { - class EpgEvent { public: @@ -31,6 +30,15 @@ namespace vdrlive const cEvent* event, const char* channelName = ""); + EpgEvent(const std::string& id, + const std::string& caption, + const std::string& title, + const std::string& short_descr, + const std::string& long_descr, + const std::string& archived, + time_t start_time, + time_t end_time); + virtual ~EpgEvent(); const std::string& Id() const { return m_eventId; } @@ -43,6 +51,8 @@ namespace vdrlive const std::string& LongDescr() const { return m_long_descr; } + const std::string& Archived() const { return m_archived; } + const std::string StartTime(const char* format) const; const std::string EndTime(const char* format) const; @@ -59,6 +69,7 @@ namespace vdrlive std::string m_title; std::string m_short_descr; std::string m_long_descr; + std::string m_archived; time_t m_start_time; time_t m_end_time; }; @@ -201,6 +201,50 @@ const tI18nPhrase Phrases[] = { "", // Dansk "", // Czech }, + { "List of recordings", // English + "Liste der Aufnahmen", // Deutsch + "", // Slovenski + "", // Italiano + "", // Nederlands + "", // Português + "", // Français + "", // Norsk + "", // Finnish + "", // Polski + "", // Español + "", // Greek + "", // Svenska + "", // Românã + "", // Magyar + "", // Català + "", // Russian + "", // Hrvatski + "", // Eesti + "", // Dansk + "", // Czech + }, + { "No recordings found", // English + "Keine Aufnahmen vorhanden", // Deutsch + "", // Slovenski + "", // Italiano + "", // Nederlands + "", // Português + "", // Français + "", // Norsk + "", // Finnish + "", // Polski + "", // Español + "", // Greek + "", // Svenska + "", // Românã + "", // Magyar + "", // Català + "", // Russian + "", // Hrvatski + "", // Eesti + "", // Dansk + "", // Czech + }, { "Remote Control", // English "Fernbedienung", // Deutsch "", // Slovenski @@ -2669,26 +2713,26 @@ const tI18nPhrase Phrases[] = { "", }, { "Delete this search timer?", // English - "Diesen Suchtimer löschen?", // Deutsch - "", // Slovenski - "", // Italiano - "", // Nederlands - "", // Português - "", // Français - "", // Norsk - "", // Finnish - "", // Polski - "", // Español - "", // Greek - "", // Svenska - "", // Românã - "", // Magyar - "", // Català - "", // Russian - "", // Hrvatski - "", // Eesti - "", // Dansk - "", // Czech + "Diesen Suchtimer löschen?", // Deutsch + "", // Slovenski + "", // Italiano + "", // Nederlands + "", // Português + "", // Français + "", // Norsk + "", // Finnish + "", // Polski + "", // Español + "", // Greek + "", // Svenska + "", // Românã + "", // Magyar + "", // Català + "", // Russian + "", // Hrvatski + "", // Eesti + "", // Dansk + "", // Czech }, { "Cancel", "Abbrechen", @@ -2735,7 +2779,7 @@ const tI18nPhrase Phrases[] = { "", "", }, - { "Test", // English + { "Test", // English "Testen", // Deutsch "", // Slovenski "", // Italiano @@ -2756,8 +2800,8 @@ const tI18nPhrase Phrases[] = { "", // Eesti "", // Dansk "", // Czech - }, - { "The time the show may start at the latest", // English + }, + { "The time the show may start at the latest", // English "Die Zeit, zu der die Sendung spätestens angefangen haben muss", // Deutsch "", // Slovenski "", // Italiano @@ -2778,8 +2822,8 @@ const tI18nPhrase Phrases[] = { "", // Eesti "", // Dansk "", // Czech - }, - { "The time the show may start at the earliest", // English + }, + { "The time the show may start at the earliest", // English "Die Zeit, zu der die Sendung frühestens anfangen darf", // Deutsch "", // Slovenski "", // Italiano @@ -2800,31 +2844,31 @@ const tI18nPhrase Phrases[] = { "", // Eesti "", // Dansk "", // Czech - }, + }, { "Search text too short - use anyway?", - "Suchtext zu kurz - trotzdem verwenden?", - "",// TODO - "Il testo da cercare è troppo corto. Continuare lo stesso?",// Italiano - "Zoek tekst tekort - toch gebruiken?", - "",// TODO - "Texte de recherche est trop court - l'utiliser comme même?", - "",// TODO - "Liian suppea hakuehto - etsitäänkö silti?", - "",// TODO - "",// TODO - "",// TODO - "",// TODO - "",// TODO - "",// TODO - "",// TODO - "",// TODO - "",// TODO - "",// TODO Eesti - "",// TODO Dansk - "",// TODO Èesky (Czech) + "Suchtext zu kurz - trotzdem verwenden?", + "",// TODO + "Il testo da cercare è troppo corto. Continuare lo stesso?",// Italiano + "Zoek tekst tekort - toch gebruiken?", + "",// TODO + "Texte de recherche est trop court - l'utiliser comme même?", + "",// TODO + "Liian suppea hakuehto - etsitäänkö silti?", + "",// TODO + "",// TODO + "",// TODO + "",// TODO + "",// TODO + "",// TODO + "",// TODO + "",// TODO + "",// TODO + "",// TODO Eesti + "",// TODO Dansk + "",// TODO Èesky (Czech) }, - { "User", // English + { "User", // English "Benutzer", // Deutsch "", // Slovenski "", // Italiano @@ -2845,8 +2889,8 @@ const tI18nPhrase Phrases[] = { "", // Eesti "", // Dansk "", // Czech - }, - { "Password", // English + }, + { "Password", // English "Passwort", // Deutsch "", // Slovenski "", // Italiano @@ -2867,8 +2911,8 @@ const tI18nPhrase Phrases[] = { "", // Eesti "", // Dansk "", // Czech - }, - { "Last channel to display", // English + }, + { "Last channel to display", // English "Letzer angezeigter Kanal", // Deutsch "", // Slovenski "", // Italiano @@ -2889,8 +2933,8 @@ const tI18nPhrase Phrases[] = { "", // Eesti "", // Dansk "", // Czech - }, - { "Use authentication", // English + }, + { "Use authentication", // English "Authentifizierung nutzen", // Deutsch "", // Slovenski "", // Italiano @@ -2911,8 +2955,8 @@ const tI18nPhrase Phrases[] = { "", // Eesti "", // Dansk "", // Czech - }, - { "No Limit", // English + }, + { "No Limit", // English "Alle zeigen", // Deutsch "", // Slovenski "", // Italiano @@ -2933,8 +2977,8 @@ const tI18nPhrase Phrases[] = { "", // Eesti "", // Dansk "", // Czech - }, - { "Admin login", // English + }, + { "Admin login", // English "Admin Login", // Deutsch "", // Slovenski "", // Italiano @@ -2955,8 +2999,8 @@ const tI18nPhrase Phrases[] = { "", // Eesti "", // Dansk "", // Czech - }, - { "Admin password", // English + }, + { "Admin password", // English "Admin Passwort", // Deutsch "", // Slovenski "", // Italiano @@ -2977,8 +3021,8 @@ const tI18nPhrase Phrases[] = { "", // Eesti "", // Dansk "", // Czech - }, - { "VDR Live Login", // English + }, + { "VDR Live Login", // English "VDR Live Login", // Deutsch "", // Slovenski "", // Italiano @@ -2999,7 +3043,7 @@ const tI18nPhrase Phrases[] = { "", // Eesti "", // Dansk "", // Czech - }, + }, { "Logout", // English "Abmelden", // Deutsch "", // Slovenski @@ -3045,70 +3089,92 @@ const tI18nPhrase Phrases[] = { "", // Czech }, { "Search", // English - "Suchen", // Deutsch - "", // Slovenski - "", // Italiano - "", // Nederlands - "", // Português - "", // Français - "", // Norsk - "", // Finnish - "", // Polski - "", // Español - "", // Greek - "", // Svenska - "", // Românã - "", // Magyar - "", // Català - "", // Russian - "", // Hrvatski - "", // Eesti - "", // Dansk - "", // Czech + "Suchen", // Deutsch + "", // Slovenski + "", // Italiano + "", // Nederlands + "", // Português + "", // Français + "", // Norsk + "", // Finnish + "", // Polski + "", // Español + "", // Greek + "", // Svenska + "", // Românã + "", // Magyar + "", // Català + "", // Russian + "", // Hrvatski + "", // Eesti + "", // Dansk + "", // Czech }, { "Extended search", // English - "Erweiterte Suche", // Deutsch - "", // Slovenski - "", // Italiano - "", // Nederlands - "", // Português - "", // Français - "", // Norsk - "", // Finnish - "", // Polski - "", // Español - "", // Greek - "", // Svenska - "", // Românã - "", // Magyar - "", // Català - "", // Russian - "", // Hrvatski - "", // Eesti - "", // Dansk - "", // Czech + "Erweiterte Suche", // Deutsch + "", // Slovenski + "", // Italiano + "", // Nederlands + "", // Português + "", // Français + "", // Norsk + "", // Finnish + "", // Polski + "", // Español + "", // Greek + "", // Svenska + "", // Românã + "", // Magyar + "", // Català + "", // Russian + "", // Hrvatski + "", // Eesti + "", // Dansk + "", // Czech }, { "Search settings", // English - "Einstellungen zur Suche", // Deutsch - "", // Slovenski - "", // Italiano - "", // Nederlands - "", // Português - "", // Français - "", // Norsk - "", // Finnish - "", // Polski - "", // Español - "", // Greek - "", // Svenska - "", // Românã - "", // Magyar - "", // Català - "", // Russian - "", // Hrvatski - "", // Eesti - "", // Dansk - "", // Czech + "Einstellungen zur Suche", // Deutsch + "", // Slovenski + "", // Italiano + "", // Nederlands + "", // Português + "", // Français + "", // Norsk + "", // Finnish + "", // Polski + "", // Español + "", // Greek + "", // Svenska + "", // Românã + "", // Magyar + "", // Català + "", // Russian + "", // Hrvatski + "", // Eesti + "", // Dansk + "", // Czech + }, + { "On archive DVD No.", // English + "Auf Archiv-DVD Nr.", // Deutsch + "", // Slovenski + "", // Italiano + "", // Nederlands + "", // Português + "", // Français + "", // Norsk + "", // Finnish + "", // Polski + "", // Español + "", // Greek + "", // Svenska + "", // Românã + "", // Magyar + "", // Català + "", // Russian + "", // Hrvatski + "", // Eesti + "", // Dansk + "", // Czech }, /* { "", // English diff --git a/images/Makefile b/images/Makefile index abfd360..098a701 100644 --- a/images/Makefile +++ b/images/Makefile @@ -23,7 +23,7 @@ OBJS = logo.o record.o active.o inactive.o button_blue.o \ reload.o stop.o one_uparrow.o one_downarrow.o tv.o \ remotecontrol.o search.o record_timer.o button_red.o \ button_green.o button_new.o help.o logo_login.o \ - button_yellow.o arrow.o + button_yellow.o arrow.o on_dvd.o ### Default rules: diff --git a/images/on_dvd.png b/images/on_dvd.png Binary files differnew file mode 100644 index 0000000..13c1168 --- /dev/null +++ b/images/on_dvd.png diff --git a/javascript/vdr_status.js b/javascript/vdr_status.js index 829b19c..073d568 100644 --- a/javascript/vdr_status.js +++ b/javascript/vdr_status.js @@ -31,7 +31,7 @@ function LiveStatusRequest(url, containerid) } status.onerror = function(message) { - vst_reload = false; + LiveStatusToggleUpdate(); LiveStatusReportError(message, containerid); } status.request("update", vst_reload ? "1" : "0"); diff --git a/pages/pageelems.ecpp b/pages/pageelems.ecpp index 7acf72a..a7fcf33 100644 --- a/pages/pageelems.ecpp +++ b/pages/pageelems.ecpp @@ -79,7 +79,7 @@ using namespace vdrlive; string progress = "0"; string id; </%args> -<div class="__progress"><div class="__elapsed" <? !id.empty() ? "id=" + id ?> style="width: <$ progress $>px"></div></div> +<div class="__progress"><div class="__elapsed" <%cpp> if (!id.empty()) { </%cpp>id="<$ id $>"<%cpp> } </%cpp> style="width: <$ progress $>px"></div></div> </%def> <# ---------------------------------------------------------------------- #> @@ -90,7 +90,7 @@ using namespace vdrlive; tEventID eventid; </%args> <%cpp> const cTimer* timer = LiveTimerManager().GetTimer(eventid, channelid); - if (timer) { + if (timer) { </%cpp> <a href="edit_timer.html?timerid=<$ LiveTimerManager().GetTimers().GetTimerId(*timer) $>"> <img src="record_timer.png" alt="" <& tooltip.hint text=(tr("Edit this")) &> /> @@ -104,8 +104,8 @@ using namespace vdrlive; <# ---------------------------------------------------------------------- #> <%def ajax_js> - <script type="text/javascript" language="javascript" src="ajax.js"></script> - <script type="text/javascript" language="javascript" src="vdr_status.js"></script> + <script type="text/javascript" src="ajax.js"></script> + <script type="text/javascript" src="vdr_status.js"></script> </%def> <# ---------------------------------------------------------------------- #> @@ -119,7 +119,7 @@ using namespace vdrlive; string alt; string id; </%args> -<%cpp> { </%cpp> <a <? !id.empty() ? "id=" + id ?> <& hide_element hide=(!id.empty()) &> href="javascript:LiveSimpleAjaxRequest('<$ action $>.xml', 'param', '<$ param $>');" <%cpp>if (!tip.empty()) { </%cpp><& tooltip.hint text=(tip) &> <%cpp> } </%cpp>><img src="<$ image $>" alt="<$ alt $>"></img></a> <%cpp> } </%cpp> +<%cpp> { </%cpp> <a <%cpp> if (!id.empty()) { </%cpp> id="<$ id $>" <%cpp> } </%cpp><& hide_element hide=(!id.empty()) &> href="javascript:LiveSimpleAjaxRequest('<$ action $>.xml', 'param', '<$ param $>');" <%cpp>if (!tip.empty()) { </%cpp><& tooltip.hint text=(tip) &> <%cpp> } </%cpp>><img src="<$ image $>" alt="<$ alt $>"></img></a> <%cpp> } </%cpp> </%def> <# ---------------------------------------------------------------------- #> @@ -133,6 +133,7 @@ using namespace vdrlive; string title; string short_descr; string long_descr; + string archived; int elapsed = -1; </%args> <div class="epg_description" id="<$ (boxId) $>"> @@ -141,50 +142,20 @@ using namespace vdrlive; </div> <div class="epg_content"> <div class="epg_tools"> - <& (tools_comp) id=(boxId) &> + <& (tools_comp) id=(boxId) archived=(archived) &> </div> <div> - <div class="info"><$ (time) $></div> + <div class="info"><%cpp> if (!archived.empty()) { </%cpp><span class="bold"><$ (archived + " ") $></span><%cpp> } </%cpp><$ (time) $></div> % if (elapsed >= 0) { <div class="progress"><div><& pageelems.progressbar progress=(elapsed) &></div></div> % } <div class="title"><$ (title) $></div> <div class="short"><$ (short_descr) $></div> <div class="description"> - <{ reply.out() << StringEscapeAndBreak(long_descr); }> + <%cpp> reply.out() << StringEscapeAndBreak(long_descr); </%cpp> </div> </div> </div> </div> </%def> -<# ---------------------------------------------------------------------- #> - -<%def status_box> -<%args> - string type; - string currentTime; - string caption; - string title; - string duration; - int elapsed; - string prev_chan; - string next_chan; -</%args> - <div class="statuscontent"> - <div class="st_header"> - <div class="caption"><$ caption $></div> - <div class="now"> <$ currentTime $></div> - </div> - <div class="st_content"> - <div class="name"><$ title $></div> - <div class="duration"> <$ duration $></div> - </div> - <div class="st_controls"> - <div class="st_btns"><a href="javascript:LiveStatusToggleUpdate()" <& tooltip.hint text=(tr("Stop updates")) &>><img id="statusReloadBtn" src="stop.png" alt=""></img></a><%cpp>if (!prev_chan.empty()) { </%cpp><& ajax_action_href action=("switch_channel") param=(prev_chan) image=("one_downarrow.png") tip=(tr("previous channel")) &><%cpp> } if (!next_chan.empty()) { </%cpp><& ajax_action_href action=("switch_channel") param=(next_chan) image=("one_uparrow.png") tip=(tr("next channel")) &><%cpp> } </%cpp></div> -% if (elapsed >= 0) { - <div class="st_pbar"><& pageelems.progressbar progress=(elapsed) &></div> -% } - </div> - </div> -</%def> diff --git a/pages/recordings.ecpp b/pages/recordings.ecpp index 87c534e..c9f9432 100644 --- a/pages/recordings.ecpp +++ b/pages/recordings.ecpp @@ -16,7 +16,7 @@ using namespace std; <%args> </%args> <%session scope="global"> -bool logged_in(false); + bool logged_in(false); </%session> <%request scope="page"> RecordingsTree recordingsTree(LiveRecordingsManager()); @@ -36,17 +36,20 @@ if (!logged_in && LiveSetup().UseAuth()) return reply.redirect("login.html"); <link rel="stylesheet" type="text/css" href="styles.css" /> <& tooltip.javascript var=("domTT_styleClass") value=("domTTepg") &> <& pageelems.ajax_js &> - <script type="text/javascript" language="javascript" src="treeview.js"></script> + <script type="text/javascript" src="treeview.js"></script> </head> <body onload="<& pageelems.infobox_start_update &>"> <& pageelems.logo &> <& menu active=("recordings") &> <div class="inhalt"> + <div class="boxheader"><div><div><$ tr("List of recordings") $></div></div></div> % if (Recordings.Count() == 0) { - Keine Aufnahmen vorhanden + <$ tr("No recordings found") $> % } else { <div class="recordings"> + <ul class="recordingslist" style="display: block;"> <& recordings.recordings_item &> + </ul> </div> <div class="epg_data" style="display: none;"> <& recordings.recordings_data &> @@ -57,123 +60,152 @@ if (!logged_in && LiveSetup().UseAuth()) return reply.redirect("login.html"); </html> <%include>page_exit.eh</%include> +<# ---------------------------------------------------------------------- #> + <%def recordings_item> <%args> -path[]; -int level = 0; + path[]; + int level = 0; </%args> -<{ -if (level > 0) { -}> - <ul class="recordingslist" style="display: none;"> -<{ -} -else { -}> - <ul class="recordingslist" style="display: block;"> -<{ -} // if (level > 0) +<%cpp> RecordingsTree::Map::iterator iter; RecordingsTree::Map::iterator end = recordingsTree.end(path); -}> - <li class="recording"> -<{ + for (iter = recordingsTree.begin(path); iter != end; ++iter) { RecordingsTree::RecordingsItemPtr recItem = iter->second; string folderimg("folder_closed.png"); string collapseimg("plus.png"); if (recItem->IsDir()) { - reply.out() << string("\t\t\t") - + string("<div class=\"recording_item\" onclick=\"Toggle(this)\">\n") - + string("\t\t\t<div class=\"recording_imgs\">") - + StringRepeat(level, "<img src=\"transparent.png\" alt=\"\" width=\"16px\" height=\"16px\" />") - + string("<img class=\"recording_expander\" src=\"") + collapseimg + string("\" alt=\"\" />") - + string("<img class=\"recording_folder\" src=\"") + folderimg + string("\" alt=\"\" />") - + string("</div>"); -}> - <div class="recording_spec"> - <div class="recording_name"><$ recItem->Name() $></div> - </div> - <div class="recording_actions"> </div> - </div> -<{ +</%cpp> + <li class="recording"> + <& rec_item_dir name=(recItem->Name()) level=(level) &> +<%cpp> cxxtools::QueryParams recItemParams(qparam, false); 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)); - callComp("recordings.recordings_item", request, reply, recItemParams); - } -} +</%cpp> + <ul class="recordingslist" style="display: none;"> +% callComp("recordings.recordings_item", request, reply, recItemParams); + </ul> + </li> +% } +%} +<%cpp> for (iter = recordingsTree.begin(path); iter != end; ++iter) { RecordingsTree::RecordingsItemPtr recItem = iter->second; - string folderimg("folder_closed.png"); - string collapseimg("plus.png"); if (!recItem->IsDir()) { - const cRecordingInfo* info = recItem->RecInfo(); - if (info) { - EpgEventPtr epgEvent(new EpgEvent(recItem->Id(), - recItem->Name(), - info->Title() ? info->Title() : recItem->Name(), - info->ShortText() ? info->ShortText() : "", - info->Description() ? info->Description() : "", - recItem->StartTime(), - recItem->StartTime())); + EpgEventPtr epgEvent(RecordingsTree::CreateEpgEvent(recItem)); + if (epgEvent) { epgEvents.push_back(epgEvent); } string day(FormatDateTime("%a,", recItem->StartTime())); string dayLen(lexical_cast<string, int>(day.length() - 1) + ".25em;"); - reply.out() << string("\t\t\t") - + string("<div class=\"recording_item\">\n") - + string("\t\t\t<div class=\"recording_imgs\">") - + StringRepeat(level, "<img src=\"transparent.png\" alt=\"\" width=\"16px\" height=\"16px\" />") - + string("<img src=\"transparent.png\" alt=\"\" width=\"16px\" height=\"16px\" />") - + string("<img src=\"movie.png\" alt=\"movie\" />") - + string("</div>"); - - string shortDescr(tr("Click to view details.")); if (info && info->ShortText()) shortDescr = (string("") + info->ShortText() + string("<br />") + shortDescr); -}> - <div class="recording_spec"> - <div class="recording_day" style="width: <$ dayLen $>"><$ day $></div> - <div class="recording_date"><$ FormatDateTime(tr("%b %d %y"), recItem->StartTime()) $></div> - <div class="recording_time"><$ FormatDateTime(tr("%I:%M %p"), recItem->StartTime()) $></div> - <div class="recording_name" <& tooltip.hint text=(shortDescr) &><& tooltip.display domId=(recItem->Id()) &>><$ recItem->Name() $></div> - </div> - <div class="recording_actions"> - <& pageelems.ajax_action_href action="play_recording" param=(recItem->Id()) tip=(tr("play this recording.")) image="play.png" alt="" &> - <img src="edit.png" alt="" /> - <img src="del.png" alt="" /> - </div> - </div> -% } - </li> -<{ + string shortDescr(tr("Click to view details.")); if (epgEvent && !epgEvent->ShortDescr().empty()) shortDescr = (epgEvent->ShortDescr() + string("<br />") + shortDescr); +</%cpp> + <li class="recording"> + <& rec_item_file name=(recItem->Name()) level=(level) id=(recItem->Id()) day=(day) dayLen=(dayLen) startTime=(recItem->StartTime()) shortDescr=(shortDescr) archived=(epgEvent ? epgEvent->Archived() : "") archiveId=(recItem->ArchiveId()) &> + </li> +<%cpp> + } } -}> - </ul> +</%cpp> </%def> +<# ---------------------------------------------------------------------- #> <%def recordings_data> <{ - // create hidden div for the tooltip hints. for (vector<EpgEventPtr>::iterator i = epgEvents.begin(); i != epgEvents.end(); ++i) { EpgEventPtr epg = *i; string start(epg->StartTime("%a,") + string(" ") + epg->StartTime(tr("%b %d %y")) + string(" ") + epg->StartTime(tr("%I:%M %p"))); + string tools_component = epg->Archived().empty() ? "recordings.rec_tools" : "recordings.archived_disc" ; }> - <& pageelems.epg_tt_box boxId=(epg->Id()) caption=(epg->Caption()) tools_comp=("recordings.rec_tools") time=(start) title=(epg->Title()) short_descr=(epg->ShortDescr()) long_descr=(epg->LongDescr()) elapsed=(epg->Elapsed()) &> + <& pageelems.epg_tt_box boxId=(epg->Id()) caption=(epg->Caption()) tools_comp=(tools_component) time=(start) title=(epg->Title()) short_descr=(epg->ShortDescr()) long_descr=(epg->LongDescr()) archived=(epg->Archived()) elapsed=(epg->Elapsed()) &> <{ } }> </%def> +<# ---------------------------------------------------------------------- #> + <%def rec_tools> <%args> string id; </%args> <& pageelems.ajax_action_href action="play_recording" param=(id) tip=(tr("play this recording.")) image="play.png" alt="" &> </%def> + +<# ---------------------------------------------------------------------- #> + +<%def archived_disc> +<%args> + string archived; +</%args> +<img src="on_dvd.png" alt="on_dvd" <& tooltip.hint text=(archived) &> /> +</%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=\"transparent.png\" alt=\"\" width=\"16px\" height=\"16px\" />"); </%cpp><img class="recording_expander" src="<$ collapseimg $>" alt="" /><img class="recording_folder" src="<$ 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 shortDescr; + string archived; + string archiveId; +</%args> + <div class="recording_item"> + <div class="recording_imgs"><%cpp> reply.out() << StringRepeat(level + 1, "<img src=\"transparent.png\" alt=\"\" width=\"16px\" height=\"16px\" />"); </%cpp><%cpp> if (!archived.empty()) { </%cpp><& archived_disc archived=(archived) &><%cpp> } else { </%cpp><img src="movie.png" alt="movie" /><%cpp> } </%cpp></div> + <div class="recording_spec"> + <div class="recording_day" style="width: <$ dayLen $>"><$ day $></div> + <div class="recording_date"><$ FormatDateTime(tr("%b %d %y"), startTime) $></div> + <div class="recording_time"><$ FormatDateTime(tr("%I:%M %p"), startTime) $></div> + <div class="recording_name" <& tooltip.hint text=(shortDescr) &><& tooltip.display domId=(id) &>><$ name $></div> + <%cpp> if (! archived.empty()) { </%cpp><div><$ archived $></div><%cpp> } </%cpp> + </div> + <div class="recording_actions"> +<%cpp> + if (archived.empty()) { +</%cpp> + <& pageelems.ajax_action_href action="play_recording" param=(id) tip=(tr("play this recording.")) image="play.png" alt="" &> +<%cpp> + } + else { +</%cpp> + <img src="transparent.png" alt="" width="16px" height="16px" /> +<%cpp> + } +</%cpp> + <img src="edit.png" alt="" /> + <img src="del.png" alt="" /> + </div> + </div> +</%def> diff --git a/pages/tooltip.ecpp b/pages/tooltip.ecpp index a52eb7b..47af850 100644 --- a/pages/tooltip.ecpp +++ b/pages/tooltip.ecpp @@ -4,10 +4,10 @@ styleClass="domTThint"; var[]; value[]; </%args> - <script type="text/javascript" language="javascript" src="domLib.js"></script> - <script type="text/javascript" language="javascript" src="domTT.js"></script> - <script type="text/javascript" language="javascript" src="domTT_drag.js"></script> - <script type="text/javascript" language="javascript"> + <script type="text/javascript" src="domLib.js"></script> + <script type="text/javascript" src="domTT.js"></script> + <script type="text/javascript" src="domTT_drag.js"></script> + <script type="text/javascript"> var domTT_styleClass = "<$ styleClass $>"; % int idx = 0; % for (var_type::const_iterator it = var.begin(); it != var.end(); ++it, idx++) { diff --git a/recordings.cpp b/recordings.cpp index 4c8aba8..72178c1 100644 --- a/recordings.cpp +++ b/recordings.cpp @@ -1,10 +1,13 @@ +#include <unistd.h> #include <cstring> #include <openssl/md5.h> #include <boost/shared_ptr.hpp> #include <boost/weak_ptr.hpp> #include <string> #include <sstream> +#include <fstream> #include "tools.h" +#include "epg_events.h" #include "recordings.h" @@ -25,7 +28,7 @@ namespace vdrlive { MD5(reinterpret_cast<const unsigned char*>(fileName), strlen(fileName), md5); ostringstream hashStr; - hashStr << hex; + hashStr << "MD5" << hex; for (size_t i = 0; i < MD5_DIGEST_LENGTH; i++) hashStr << (0 + md5[i]); return hashStr.str(); @@ -190,6 +193,69 @@ namespace vdrlive { return m_recording->start; } + bool RecordingsTree::RecordingsItemRec::IsArchived() const + { + string filename = m_recording->FileName(); + + string vdrFile = filename + "/001.vdr"; + if (0 == access(vdrFile.c_str(), R_OK)) + return false; + + filename += "/dvd.vdr"; + return (0 == access(filename.c_str(), R_OK)); + } + + const std::string RecordingsTree::RecordingsItemRec::ArchiveId() const + { + string filename = m_recording->FileName(); + + filename += "/dvd.vdr"; + ifstream dvd(filename.c_str()); + + if (dvd) { + string archiveDisc; + string videoDisc; + dvd >> archiveDisc; + if ("0000" == archiveDisc) { + dvd >> videoDisc; + return videoDisc; + } + return archiveDisc; + } + return ""; + } + + EpgEventPtr RecordingsTree::CreateEpgEvent(const RecordingsItemPtr recItem) + { + const cRecordingInfo* info = recItem->RecInfo(); + if (info) { + std::string archived; + if (recItem->IsArchived()) { + archived += " ["; + archived += tr("On archive DVD No."); + archived += ": "; + archived += recItem->ArchiveId(); + archived += "]"; + } + EpgEventPtr epgEvent( + new EpgEvent( + recItem->Id(), + recItem->Name(), + info->Title() ? info->Title() : recItem->Name(), + info->ShortText() ? info->ShortText() : "", + info->Description() ? info->Description() : "", + archived, + recItem->StartTime(), + recItem->StartTime() + ) + ); + return epgEvent; + } + else { + return EpgEventPtr(); + } + } + RecordingsManagerPtr LiveRecordingsManager() { static weak_ptr<RecordingsManager> livingRecMan; diff --git a/recordings.h b/recordings.h index 5bea835..1e4b57b 100644 --- a/recordings.h +++ b/recordings.h @@ -9,6 +9,10 @@ namespace vdrlive { + // Forward declations from epg_events.h + class EpgEvent; + typedef boost::shared_ptr<EpgEvent> EpgEventPtr; + class RecordingsManager; typedef boost::shared_ptr<RecordingsManager> RecordingsManagerPtr; @@ -54,8 +58,10 @@ namespace vdrlive { virtual time_t StartTime() const = 0; virtual bool IsDir() const = 0; + virtual bool IsArchived() const = 0; virtual const std::string& Name() const { return m_name; } virtual const std::string Id() const = 0; + virtual const std::string ArchiveId() const = 0; virtual const cRecording* Recording() const { return 0; } virtual const cRecordingInfo* RecInfo() const { return 0; } @@ -78,7 +84,9 @@ namespace vdrlive { virtual time_t StartTime() const { return 0; } virtual bool IsDir() const { return true; } + virtual bool IsArchived() const { return false; } virtual const std::string Id() const { std::string e; return e; } + virtual const std::string ArchiveId() const { std::string e; return e; } private: int m_level; @@ -93,7 +101,9 @@ namespace vdrlive { virtual time_t StartTime() const; virtual bool IsDir() const { return false; } + virtual bool IsArchived() const ; virtual const std::string Id() const { return m_id; } + virtual const std::string ArchiveId() const; virtual const cRecording* Recording() const { return m_recording; } virtual const cRecordingInfo* RecInfo() const { return m_recording->Info(); } @@ -112,6 +122,8 @@ namespace vdrlive { int MaxLevel() const { return m_maxLevel; } + static EpgEventPtr CreateEpgEvent(const RecordingsItemPtr recItem); + private: int m_maxLevel; RecordingsItemPtr m_root; |