UI: Estimate recording time left until disk is full

master
Clayton Groeneveld 2019-03-13 05:27:36 -05:00
parent 49d178d593
commit 171f811669
3 changed files with 87 additions and 4 deletions

View File

@ -87,6 +87,7 @@ VerticalLayout="Vertical Layout"
Group="Group"
DoNotShowAgain="Do not show again"
Default="(Default)"
Calculating="Calculating..."
# warning if program already open
AlreadyRunning.Title="OBS is already running"
@ -200,6 +201,7 @@ Basic.Stats.Status.Inactive="Inactive"
Basic.Stats.DroppedFrames="Dropped Frames (Network)"
Basic.Stats.MegabytesSent="Total Data Output"
Basic.Stats.Bitrate="Bitrate"
Basic.Stats.DiskFullIn="Disk full in (approx.)"
ResetUIWarning.Title="Are you sure you want to reset the UI?"
ResetUIWarning.Text="Resetting the UI will hide additional docks. You will need to unhide these docks from the view menu if you want them to be visible.\n\nAre you sure you want to reset the UI?"

View File

@ -4,6 +4,7 @@
#include "window-basic-main.hpp"
#include "platform.hpp"
#include "obs-app.hpp"
#include "qt-wrappers.hpp"
#include <QDesktopWidget>
#include <QPushButton>
@ -15,6 +16,7 @@
#include <string>
#define TIMER_INTERVAL 2000
#define REC_TIME_LEFT_INTERVAL 30000
static void setThemeID(QWidget *widget, const QString &themeID)
{
@ -28,15 +30,32 @@ static void setThemeID(QWidget *widget, const QString &themeID)
}
}
void OBSBasicStats::OBSFrontendEvent(enum obs_frontend_event event, void *ptr)
{
OBSBasicStats *stats = reinterpret_cast<OBSBasicStats *>(ptr);
switch ((int)event) {
case OBS_FRONTEND_EVENT_RECORDING_STARTED:
stats->StartRecTimeLeft();
break;
case OBS_FRONTEND_EVENT_RECORDING_STOPPED:
stats->ResetRecTimeLeft();
break;
}
}
OBSBasicStats::OBSBasicStats(QWidget *parent, bool closeable)
: QWidget (parent),
cpu_info (os_cpu_usage_info_start()),
timer (this)
timer (this),
recTimeLeft (this)
{
QVBoxLayout *mainLayout = new QVBoxLayout();
QGridLayout *topLayout = new QGridLayout();
outputLayout = new QGridLayout();
bitrates.reserve(REC_TIME_LEFT_INTERVAL / TIMER_INTERVAL);
int row = 0;
auto newStatBare = [&] (QString name, QWidget *label, int col)
@ -57,10 +76,12 @@ OBSBasicStats::OBSBasicStats(QWidget *parent, bool closeable)
cpuUsage = new QLabel(this);
hddSpace = new QLabel(this);
recordTimeLeft = new QLabel(this);
memUsage = new QLabel(this);
newStat("CPUUsage", cpuUsage, 0);
newStat("HDDSpaceAvailable", hddSpace, 0);
newStat("DiskFullIn", recordTimeLeft, 0);
newStat("MemoryUsage", memUsage, 0);
fps = new QLabel(this);
@ -152,6 +173,11 @@ OBSBasicStats::OBSBasicStats(QWidget *parent, bool closeable)
Update();
QObject::connect(&recTimeLeft, &QTimer::timeout, this,
&OBSBasicStats::RecordingTimeLeft);
recTimeLeft.setInterval(REC_TIME_LEFT_INTERVAL);
recTimeLeft.start();
OBSBasic *main = reinterpret_cast<OBSBasic*>(App()->GetMainWindow());
const char *geometry = config_get_string(main->Config(),
@ -170,6 +196,8 @@ OBSBasicStats::OBSBasicStats(QWidget *parent, bool closeable)
size(), rect));
}
}
obs_frontend_add_event_callback(OBSFrontendEvent, this);
}
void OBSBasicStats::closeEvent(QCloseEvent *event)
@ -280,7 +308,7 @@ void OBSBasicStats::Update()
#define MBYTE (1024ULL * 1024ULL)
#define GBYTE (1024ULL * 1024ULL * 1024ULL)
#define TBYTE (1024ULL * 1024ULL * 1024ULL * 1024ULL)
uint64_t num_bytes = os_get_free_disk_space(path);
num_bytes = os_get_free_disk_space(path);
QString abrv = QStringLiteral(" MB");
long double num;
@ -393,6 +421,45 @@ void OBSBasicStats::Update()
outputLabels[0].Update(strOutput, false);
outputLabels[1].Update(recOutput, true);
if (obs_output_active(recOutput)) {
long double kbps = outputLabels[1].kbps;
bitrates.push_back(kbps);
}
}
void OBSBasicStats::StartRecTimeLeft()
{
recordTimeLeft->setText(QTStr("Calculating"));
recTimeLeft.start();
}
void OBSBasicStats::ResetRecTimeLeft()
{
bitrates.clear();
recTimeLeft.stop();
recordTimeLeft->setText(QTStr(""));
}
void OBSBasicStats::RecordingTimeLeft()
{
long double averageBitrate = accumulate(bitrates.begin(),
bitrates.end(), 0.0) /
(long double)bitrates.size();
long double bytesPerSec = (averageBitrate / 8.0l) * 1000.0l;
long double secondsUntilFull = (long double)num_bytes / bytesPerSec;
bitrates.clear();
int totalMinutes = (int)secondsUntilFull / 60;
int minutes = totalMinutes % 60;
int hours = totalMinutes / 60;
QString text;
text.sprintf("%d %s, %d %s", hours, QT_TO_UTF8(QTStr("Hours")),
minutes, QT_TO_UTF8(QTStr("Minutes")));
recordTimeLeft->setText(text);
recordTimeLeft->setMinimumWidth(recordTimeLeft->width());
}
void OBSBasicStats::Reset()
@ -428,8 +495,7 @@ void OBSBasicStats::OutputLabels::Update(obs_output_t *output, bool rec)
uint64_t bitsBetween = (bytesSent - lastBytesSent) * 8;
long double timePassed = (long double)(curTime - lastBytesSentTime) /
1000000000.0l;
long double kbps = (long double)bitsBetween /
timePassed / 1000.0l;
kbps = (long double)bitsBetween / timePassed / 1000.0l;
if (timePassed < 0.01l)
kbps = 0.0l;

View File

@ -17,6 +17,7 @@ class OBSBasicStats : public QWidget {
QLabel *fps = nullptr;
QLabel *cpuUsage = nullptr;
QLabel *hddSpace = nullptr;
QLabel *recordTimeLeft = nullptr;
QLabel *memUsage = nullptr;
QLabel *renderTime = nullptr;
@ -28,6 +29,9 @@ class OBSBasicStats : public QWidget {
os_cpu_usage_info_t *cpu_info = nullptr;
QTimer timer;
QTimer recTimeLeft;
uint64_t num_bytes = 0;
std::vector<long double> bitrates;
struct OutputLabels {
QPointer<QLabel> name;
@ -44,6 +48,8 @@ class OBSBasicStats : public QWidget {
void Update(obs_output_t *output, bool rec);
void Reset(obs_output_t *output);
long double kbps = 0.0l;
};
QList<OutputLabels> outputLabels;
@ -54,14 +60,23 @@ class OBSBasicStats : public QWidget {
virtual void closeEvent(QCloseEvent *event) override;
static void OBSFrontendEvent(enum obs_frontend_event event, void *ptr);
public:
OBSBasicStats(QWidget *parent = nullptr, bool closable = true);
~OBSBasicStats();
static void InitializeValues();
void StartRecTimeLeft();
void ResetRecTimeLeft();
private:
QPointer<QObject> shortcutFilter;
private slots:
void RecordingTimeLeft();
protected:
virtual void showEvent(QShowEvent *event) override;
virtual void hideEvent(QHideEvent *event) override;