Go to the documentation of this file.
9 #include "mythconfig.h"
19 #include <sys/types.h>
25 #if HAVE_POSIX_FADVISE < 1
27 #define POSIX_FADV_SEQUENTIAL 0
28 #define POSIX_FADV_WILLNEED 0
29 #define POSIX_FADV_DONTNEED 0
44 #define LOC QString("FileRingBuf(%1): ").arg(m_filename)
46 static const QStringList
kSubExt {
".ass",
".srt",
".ssa",
".sub",
".txt"};
47 static const QStringList
kSubExtNoCheck {
".ass",
".srt",
".ssa",
".sub",
".txt",
".gif",
".png"};
64 LOG(VB_GENERAL, LOG_ERR,
LOC + QString(
"Failed to open remote file (%1) for write").
arg(
m_filename));
87 else if (Timeout >= 0ms)
119 LOG(VB_GENERAL, LOG_ERR, QString(
"FileRingBuf(%1): File exists but is not readable by MythTV!")
129 [Extension] (
const QString& ext) ->
bool
130 {return ext.contains(Extension);});
131 return (it !=
nullptr);
137 QString vidFileName =
FileInfo.fileName();
138 QString dirName =
FileInfo.absolutePath();
141 int suffixPos = vidFileName.lastIndexOf(QChar(
'.'));
143 baseName = vidFileName.left(suffixPos);
149 const QString findBaseName =
baseName.replace(
"[",
"?")
154 for (
const auto & ext :
kSubExt)
155 list += findBaseName + ext;
161 dir.setPath(dirName);
162 const QStringList candidates =
dir.entryList(list);
163 for (
const auto & candidate : candidates)
165 QFileInfo
file(dirName +
"/" + candidate);
167 return file.absoluteFilePath();
175 LOG(VB_PLAYBACK, LOG_INFO,
LOC + QString(
"OpenFile(%1, %2 ms)")
176 .
arg(Filename).
arg(Retry.count()));
196 bool islocal = (!
m_filename.startsWith(
"/dev")) &&
201 std::array<char,kReadTestSize> buf {};
207 uint openAttempts = 0;
228 ssize_t ret =
read(
m_fd2, buf.data(), buf.size());
251 LOG(VB_FILE, LOG_DEBUG,
LOC +
252 QString(
"OpenFile(): fadvise sequential "
257 LOG(VB_FILE, LOG_DEBUG,
LOC +
258 QString(
"OpenFile(): fadvise willneed "
270 }
while (openTimer.
elapsed() < Retry);
278 QString extension =
file.completeSuffix().toLower();
284 LOG(VB_GENERAL, LOG_ERR,
LOC + QString(
"OpenFile(): Could not open."));
289 LOG(VB_GENERAL, LOG_ERR,
LOC + QString(
"OpenFile(): File too small (%1B).")
295 LOG(VB_GENERAL, LOG_ERR,
LOC +
"OpenFile(): Improper permissions.");
299 LOG(VB_GENERAL, LOG_ERR,
LOC +
"OpenFile(): Cannot seek in file.");
304 LOG(VB_FILE, LOG_INFO,
LOC + QString(
"OpenFile() made %1 attempts in %2 ms")
310 QString dirName =
".";
312 int dirPos =
m_filename.lastIndexOf(QChar(
'/'));
319 QStringList auxFiles;
321 int suffixPos = tmpSubName.lastIndexOf(QChar(
'.'));
324 QString
baseName = tmpSubName.left(suffixPos);
325 int extnleng = tmpSubName.size() -
baseName.size() - 1;
326 QString extension = tmpSubName.right(extnleng);
330 for (
const auto & ext :
kSubExt)
338 LOG(VB_GENERAL, LOG_ERR,
LOC + QString(
"RingBuffer::RingBuffer(): Failed to open remote file (%1)")
367 LOG(VB_GENERAL, LOG_ERR,
LOC +
"Tried to ReOpen a read only file.");
428 LOG(VB_GENERAL, LOG_ERR,
LOC +
"Invalid file descriptor in 'safe_read()'");
439 uint toread = Size - tot;
446 int ret = fstat(
m_fd2, &sb);
447 if (ret == 0 && S_ISREG(sb.st_mode))
454 LOG(VB_FILE, LOG_DEBUG,
LOC +
"not reading, reached EOF");
458 toread =
static_cast<uint>(std::min(sb.st_size - (
m_internalReadPos + tot),
static_cast<long long>(toread)));
459 if (toread < (Size - tot))
462 LOG(VB_FILE, LOG_DEBUG,
LOC + QString(
"About to reach EOF, reading %1 wanted %2")
463 .
arg(toread).
arg(Size-tot));
470 LOG(VB_FILE, LOG_DEBUG,
LOC + QString(
"read(%1) -- begin").
arg(toread));
471 ret =
static_cast<int>(
read(
m_fd2,
static_cast<char*
>(
Buffer) + tot, toread));
472 LOG(VB_FILE, LOG_DEBUG,
LOC + QString(
"read(%1) -> %2 end").
arg(toread).
arg(ret));
479 LOG(VB_GENERAL, LOG_ERR,
LOC +
"File I/O problem in 'safe_read()'" +
ENO);
487 tot +=
static_cast<uint>(ret);
519 return static_cast<int>(tot);
532 int ret = Remote->
Read(
Buffer,
static_cast<int>(Size));
535 LOG(VB_GENERAL, LOG_ERR,
LOC +
"safe_read(RemoteFile* ...): read failed");
538 LOG(VB_GENERAL, LOG_ERR,
LOC +
"safe_read() failed to seek reset");
544 LOG(VB_FILE, LOG_INFO,
LOC +
"safe_read(RemoteFile* ...): at EOF");
561 long long result = -1;
572 result = fstat(
m_fd2, &sb);
573 if (result == 0 && S_ISREG(sb.st_mode))
600 (Whence == SEEK_CUR && Position == 0)))
608 long long newposition = (SEEK_SET==Whence) ? Position :
m_readPos + Position;
616 LOG(VB_FILE, LOG_INFO,
LOC +
617 QString(
"Seek(): rbrpos: %1 rbwpos: %2\n\t\t\treadpos: %3 internalreadpos: %4")
619 bool used_opt =
false;
626 internal_backbuf = std::min(internal_backbuf, free - min_safety);
628 LOG(VB_FILE, LOG_INFO,
LOC + QString(
"Seek(): internal_backbuf: %1 sba: %2")
629 .
arg(internal_backbuf).
arg(sba));
630 if (internal_backbuf >= sba)
635 LOG(VB_FILE, LOG_INFO,
LOC +
636 QString(
"Seek(): OPT1 rbrPos: %1 rbwPos: %2"
637 "\n\t\t\treadpos: %3 internalreadpos: %4")
646 LOG(VB_FILE, LOG_INFO,
LOC + QString(
"Seek(): OPT2 rbrPos: %1 sba: %2")
666 LOG(VB_FILE, LOG_DEBUG,
LOC + QString(
"Seek(): fadvise willneed failed: ") +
ENO);
669 LOG(VB_FILE, LOG_INFO,
LOC + QString(
"Seek to %1 from ignore pos %2 returned %3")
707 long long off_end = 0xDEADBEEF;
708 if (SEEK_END == Whence)
718 newposition = fi.size() - off_end;
730 off_end =
file.size() - newposition;
734 if (off_end != 0xDEADBEEF)
736 LOG(VB_FILE, LOG_INFO,
LOC + QString(
"Seek(): Offset from end: %1").
arg(off_end));
739 if (off_end == 250000)
741 LOG(VB_FILE, LOG_INFO,
LOC +
742 QString(
"Seek(): offset from end: %1").
arg(off_end) +
743 "\n\t\t\t -- ignoring read ahead thread until next seek.");
755 QString cmd = QString(
"Seek(%1, SEEK_SET) ign ")
760 LOG(VB_GENERAL, LOG_ERR,
LOC + cmd +
" Failed" +
ENO);
769 QString cmd2 = QString(
"Seek(%1, SEEK_SET) int ")
771 LOG(VB_GENERAL, LOG_ERR,
LOC + cmd2 +
" Failed" +
ENO);
775 QString cmd2 = QString(
"Seek(%1, %2) int ")
777 .arg((SEEK_SET == Whence) ?
"SEEK_SET" :
778 ((SEEK_CUR == Whence) ?
"SEEK_CUR" :
"SEEK_END"));
779 LOG(VB_GENERAL, LOG_ERR,
LOC + cmd2 +
" succeeded");
812 ret = lseek64(
m_fd2, Position, Whence);
825 QString cmd = QString(
"Seek(%1, %2)").arg(Position)
826 .arg((Whence == SEEK_SET) ?
"SEEK_SET" :
827 ((Whence == SEEK_CUR) ?
"SEEK_CUR" :
"SEEK_END"));
828 LOG(VB_GENERAL, LOG_ERR,
LOC + cmd +
" Failed" +
ENO);
std::chrono::milliseconds elapsed(void)
Returns milliseconds elapsed since last start() or restart()
bool ReOpen(const QString &Filename="") override
MythFileBuffer(const QString &Filename, bool Write, bool UseReadAhead, std::chrono::milliseconds Timeout)
QFileInfo fileInfo(filename)
#define ENO
This can be appended to the LOG args with "+".
long long GetFileSize(void) const
GetFileSize: returns the remote file's size at the time it was first opened Will query the server in ...
static bool IsSubtitlePossible(const QString &Extension)
bool ReOpen(const QString &newFilename)
A QElapsedTimer based timer to replace use of QTime as a timer.
long long GetRealFileSizeInternal(void) const override
def read(device=None, features=[])
static bool CheckPermissions(const QString &Filename)
static void usleep(std::chrono::microseconds time)
arg(title).arg(filename).arg(doDelete))
void start(void)
starts measuring elapsed time.
#define LOG(_MASK_, _LEVEL_, _QSTRING_)
int SafeRead(void *Buffer, uint Size) override
bool OpenFile(const QString &Filename, std::chrono::milliseconds Retry=kDefaultOpenTimeout) override
#define POSIX_FADV_WILLNEED
long long SeekInternal(long long Position, int Whence) override
bool IsRegisteredFileForWrite(const QString &file)
long long GetReadPosition(void) const override
long long Seek(long long pos, int whence, long long curpos=-1)
static QString LocalSubtitleFilename(QFileInfo &FileInfo)
static int posix_fadvise(int, off_t, off_t, int)
#define POSIX_FADV_SEQUENTIAL
QStringList GetAuxiliaryFiles(void) const
MythCoreContext * gCoreContext
This global variable contains the MythCoreContext instance for the app.
static const QStringList kSubExt
This class supports the writing of recordings to disk.
std::chrono::seconds secsInPast(const QDateTime &past)
bool ReOpen(const QString &newFilename="")
Reopens the file we are writing to or opens a new file.
static const QStringList kSubExtNoCheck
~MythFileBuffer() override
bool Open(void)
Opens the file we will be writing to.
bool IsOpen(void) const override
int Read(void *data, int size)
long long GetRealFileSize(void)
GetRealFileSize: returns the current remote file's size.