diff --git a/largeString.h b/largeString.h index 2c9f9fbd..83bc4129 100644 --- a/largeString.h +++ b/largeString.h @@ -64,6 +64,12 @@ class cLargeString { *(m_string_end++) = c; return *this; } + cLargeString &append(size_t count, char c) { + appendLen(count); + memset(m_string_end, c, count); + m_string_end += count; + return *this; + } cLargeString &append(const char (&s)[1]) { // note: every other specific implementation is too slow. memcpy is too fast :) return *this; @@ -116,6 +122,10 @@ template, bool> = true> const char *nameData() const { return m_nameData; } int nameLen() const { return m_nameLen; } }; +template, bool> = true> +void stringAppend(cLargeString &s, T i) { + s.append(i); +} inline void append_csv(cLargeString &str, cSv s1) { str.append(s1); } template diff --git a/live/js/live/createHtml.js b/live/js/live/createHtml.js index 0bf26cef..8d8beda5 100644 --- a/live/js/live/createHtml.js +++ b/live/js/live/createHtml.js @@ -144,19 +144,19 @@ function addColEventRec(s, times, eventprefix, eventid, title, folder, shortText s.a += '' } -function injectHdSdIcon(elementId, sdhd, channelName) { +function injectHdSdIcon(elementId, sdhd, channelName, frameParams) { const s = Object.create(null); s.a = ""; - addHdSdIcon(s, sdhd, channelName); + addHdSdIcon(s, sdhd, channelName, frameParams); document.getElementById(elementId).innerHTML = s.a; if (typeof liveEnhanced !== 'undefined') liveEnhanced.domReadySetup(); } -function injectErrorHdSdIcon(elementId, numErrors, durationDeviation, sdhd, channelName, duration, numTsFiles) { +function injectErrorHdSdIcon(elementId, numErrors, durationDeviation, sdhd, channelName, duration, numTsFiles, frameParams) { const s = Object.create(null); s.a = ""; addErrorIcon(s, numErrors, durationDeviation, duration, numTsFiles); - addHdSdIcon(s, sdhd, channelName); + addHdSdIcon(s, sdhd, channelName, frameParams); document.getElementById(elementId).innerHTML = s.a; if (typeof liveEnhanced !== 'undefined') liveEnhanced.domReadySetup(); } diff --git a/live/themes/veltliner/css/theme.css b/live/themes/veltliner/css/theme.css index 775e7f11..3ebbc942 100644 --- a/live/themes/veltliner/css/theme.css +++ b/live/themes/veltliner/css/theme.css @@ -185,7 +185,7 @@ div.__progress div.__elapsed { background-color: #FFCC00; } img.channel_logo { - background-color: #FFCC00; + background-color: #FFCC0000; } diff --git a/pages/pageelems.ecpp b/pages/pageelems.ecpp index 4a0bae05..37d5f607 100644 --- a/pages/pageelems.ecpp +++ b/pages/pageelems.ecpp @@ -102,10 +102,14 @@ function addErrorIcon(s, numErrors, durationDeviation, duration, numTsFiles) { s.a += '\" /> ' } -function addHdSdIcon(s, hdsd, toolTip) { +function addHdSdIcon(s, hdsd, toolTip, frameParams) { s.a += '
' s.a += hdsd s.a += '.png\" width = \"25px\" title=\"' + if (frameParams.length != 0) { + s.a += frameParams + s.a += '<$$lf$>' + } s.a += toolTip s.a += '\" />
' } @@ -234,7 +238,7 @@ function existingRecordingSR(s, col_span1, bottomrow, imdb_id, id, archiveDescr, s.a += '
' addErrorIcon(s, errors, durationDeviation, duration, numTsFiles) s.a += '' - addHdSdIcon(s, hd_sd, channel_name) + addHdSdIcon(s, hd_sd, channel_name, \"\") s.a += '
' <%cpp> #endif @@ -581,12 +585,9 @@ if (LiveSetup().GetUseStreamdev() && LiveFeatures(). % if (detail > 1) { -<# -")"/> -#> <%cpp> if (sdhd) { <%cpp> } diff --git a/pages/recordings.ecpp b/pages/recordings.ecpp index 3f88e5fe..3f4ed167 100644 --- a/pages/recordings.ecpp +++ b/pages/recordings.ecpp @@ -180,6 +180,7 @@ function RecordingActionS(s, id, A, Img, Title) { // [19] : duration // [20] : size // [21] : numTsFiles +// [22] : frame parameter text // befor calling, make sure that all recs[obj_i] exist! #> function RecordingsSt_int(s, level, displayFolder, data) { @@ -225,7 +226,7 @@ function RecordingsSt_int(s, level, displayFolder, data) { s.a += obj[20] s.a += '' addErrorIcon(s, obj[10], obj[17], obj[19], obj[21]) - addHdSdIcon(s, obj[11], obj[12]) + addHdSdIcon(s, obj[11], obj[12], obj[22]) s.a += '' // end column with error / sd/hd image s.a += '
Info() ) { recordingErrors = recording->Info()->Errors(); #endif const char *sdhd = nullptr; + cToSvConcat frameParams; #if VDRVERSNUM >= 20605 + StringAppendFrameParams(frameParams, recording); switch (recording->Info()->FrameWidth()) { case 720: sdhd = "720x576"; @@ -754,7 +757,7 @@ if (recording && recording->Info() ) { <%cpp> } diff --git a/recman.cpp b/recman.cpp index ec3261b5..240d5dc2 100644 --- a/recman.cpp +++ b/recman.cpp @@ -24,6 +24,33 @@ namespace vdrlive { +template +void StringAppendFrameParams(T &s, const cRecording *rec) { +#if VDRVERSNUM >= 20605 + if (!rec || ! rec->Info() ) return; + if (rec->Info()->FrameWidth() && rec->Info()->FrameHeight() ) { + stringAppend(s, rec->Info()->FrameWidth() ); + s.append("x"); + stringAppend(s, rec->Info()->FrameHeight() ); + + if (rec->Info()->FramesPerSecond() > 0) { + s.append("/"); + stringAppendFormated(s, "%.2g", rec->Info()->FramesPerSecond() ); + if (rec->Info()->ScanType() != stUnknown) + s.append(1, rec->Info()->ScanTypeChar()); + } + if (rec->Info()->AspectRatio() != arUnknown) { + s.append(" "); + s.append(cSv(rec->Info()->AspectRatioText())); + } + } +#endif +} + +template void StringAppendFrameParams(std::string &s, const cRecording *rec); +template void StringAppendFrameParams(cLargeString &s, const cRecording *rec); +template void StringAppendFrameParams>(cToSvConcat<0> &s, const cRecording *rec); +template void StringAppendFrameParams>(cToSvConcat<255> &s, const cRecording *rec); /** * Implementation of class RecordingsManager: @@ -966,6 +993,10 @@ void AppendScraperData(cLargeString &target, cSv s_IMDB_ID, const cTvMedia &s_im target.append("\","); // [21] numTsFiles target.append(NumberTsFiles() ); +// [22] frame parameter text + target.append(",\""); + StringAppendFrameParams(target, m_recording); + target.append("\""); } void RecordingsItemRec::AppendAsJSArray(cLargeString &target, std::vector::const_iterator recIterFirst, std::vector::const_iterator recIterLast, bool &first, cSv filter, bool reverse) { diff --git a/recman.h b/recman.h index 68bc4598..7629461a 100644 --- a/recman.h +++ b/recman.h @@ -26,6 +26,8 @@ namespace vdrlive { +template + void StringAppendFrameParams(T &s, const cRecording *rec); // Forward declations from epg_events.h class EpgInfo; typedef std::shared_ptr EpgInfoPtr; diff --git a/stringhelpers.h b/stringhelpers.h index 30c095fe..58ea7d4c 100644 --- a/stringhelpers.h +++ b/stringhelpers.h @@ -866,6 +866,15 @@ template, bool> = true> return *this; } // ======================= +// #include + +// ========================================================= +// some performance improvemnt, to get string presentation for channel +// you can also use channelID.ToString() +// in struct tChannelID { (in vdr): +// static tChannelID FromString(const char *s); +// cString ToString(void) const; +// ========================================================= // append tChannelID cToSvConcat &concat(const tChannelID &channelID) { int st_Mask = 0xFF000000; @@ -953,19 +962,6 @@ class cToSvFormated: public cToSvConcat { } }; -/* - * channel helper functions (for vdr tChannelID) - * -*/ -// #include - -// ========================================================= -// some performance improvemnt, to get string presentation for channel -// you can also use channelID.ToString() -// in struct tChannelID { (in vdr): -// static tChannelID FromString(const char *s); -// cString ToString(void) const; -// ========================================================= class cToSvChannel: public cToSvConcat<255> { public: @@ -974,42 +970,23 @@ class cToSvChannel: public cToSvConcat<255> { // ========================================================= // ========================================================= -// Chapter 5: change string: mainly: append to string +// stringAppend: for std::string & cToSvConcat // ========================================================= // ========================================================= -inline void StringRemoveTrailingWhitespace(std::string &str) { - str.erase(remove_trailing_whitespace(str).length()); -} - -inline int stringAppendAllASCIICharacters(std::string &target, const char *str) { -// append all characters > 31 (signed !!!!). Unsigned: 31 < character < 128 -// return number of appended characters - int i = 0; - for (; reinterpret_cast(str)[i] > 31; i++); - target.append(str, i); - return i; +template, bool> = true> +inline void stringAppend(std::string &str, T i) { + char buf[20]; // unsigned int 64: max. 20. (18446744073709551615) signed int64: max. 19 (+ sign) + str.append(buf, stringhelpers_internal::itoa(buf, i) - buf); } -inline void stringAppendRemoveControlCharacters(std::string &target, const char *str) { -// we replace control characters with " " and invalid UTF8 with "?" -// and remove trailing whitespace - for(;;) { - str += stringAppendAllASCIICharacters(target, str); - wint_t cp = getNextUtfCodepoint(str); - if (cp == 0) { StringRemoveTrailingWhitespace(target); return; } - if (cp > 31) stringAppendUtfCodepoint(target, cp); - else target.append(" "); - } +template, bool> = true> +inline void stringAppend(cToSvConcat &s, T i) { + s.concat(i); } -inline void stringAppendRemoveControlCharactersKeepNl(std::string &target, const char *str) { - for(;;) { - str += stringAppendAllASCIICharacters(target, str); - wint_t cp = getNextUtfCodepoint(str); - if (cp == 0) { StringRemoveTrailingWhitespace(target); return; } - if (cp == '\n') { StringRemoveTrailingWhitespace(target); target.append("\n"); continue; } - if (cp > 31) stringAppendUtfCodepoint(target, cp); - else target.append(" "); - } + +template +inline void stringAppendFormated(cToSvConcat &s, const char *fmt, Args&&... args) { + s.appendFormated(fmt, std::forward(args)...); } // __attribute__ ((format (printf, 2, 3))) can not be used, but should work starting with gcc 13.1 @@ -1070,19 +1047,13 @@ void stringAppendFormated_slow(std::string &str, const char *fmt, Args&&... args // =========== stringAppend == for many data types // ========================================================= -template, bool> = true> -inline void stringAppend(std::string &str, T i) { - char buf[20]; // unsigned int 64: max. 20. (18446744073709551615) signed int64: max. 19 (+ sign) - str.append(buf, stringhelpers_internal::itoa(buf, i) - buf); -} - // strings inline void stringAppend(std::string &str, const char *s) { if(s) str.append(s); } inline void stringAppend(std::string &str, const std::string &s) { str.append(s); } inline void stringAppend(std::string &str, std::string_view s) { str.append(s); } inline void stringAppend(std::string &str, const tChannelID &channelID) { - str.append(cToSvChannel(channelID)); + str.append(cToSvConcat(channelID)); } template void stringAppend(std::string &str, const T &n, const U &u, Args&&... args) { @@ -1090,6 +1061,46 @@ void stringAppend(std::string &str, const T &n, const U &u, Args&&... args) { stringAppend(str, u, std::forward(args)...); } +// ========================================================= +// ========================================================= +// Chapter 5: change string: mainly: append to string +// ========================================================= +// ========================================================= + +inline void StringRemoveTrailingWhitespace(std::string &str) { + str.erase(remove_trailing_whitespace(str).length()); +} + +inline int stringAppendAllASCIICharacters(std::string &target, const char *str) { +// append all characters > 31 (signed !!!!). Unsigned: 31 < character < 128 +// return number of appended characters + int i = 0; + for (; reinterpret_cast(str)[i] > 31; i++); + target.append(str, i); + return i; +} +inline void stringAppendRemoveControlCharacters(std::string &target, const char *str) { +// we replace control characters with " " and invalid UTF8 with "?" +// and remove trailing whitespace + for(;;) { + str += stringAppendAllASCIICharacters(target, str); + wint_t cp = getNextUtfCodepoint(str); + if (cp == 0) { StringRemoveTrailingWhitespace(target); return; } + if (cp > 31) stringAppendUtfCodepoint(target, cp); + else target.append(" "); + } +} +inline void stringAppendRemoveControlCharactersKeepNl(std::string &target, const char *str) { + for(;;) { + str += stringAppendAllASCIICharacters(target, str); + wint_t cp = getNextUtfCodepoint(str); + if (cp == 0) { StringRemoveTrailingWhitespace(target); return; } + if (cp == '\n') { StringRemoveTrailingWhitespace(target); target.append("\n"); continue; } + if (cp > 31) stringAppendUtfCodepoint(target, cp); + else target.append(" "); + } +} + // ========================================================= // =========== concatenate ================================= // ========================================================= diff --git a/tools.h b/tools.h index 7499f94c..f13bcf56 100644 --- a/tools.h +++ b/tools.h @@ -29,7 +29,7 @@ std::istream& operator>>( std::istream& is, tChannelID& ret ); inline std::ostream& operator<<( std::ostream& os, tChannelID const& id ) { - return os << cToSvChannel(id); + return os << cToSvConcat(id); } template void stringAppendFormated(cLargeString &target, const char *format, Args&&... args) {