aboutsummaryrefslogtreecommitdiff
path: root/visualization/renderer/qmpvisrendercore.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'visualization/renderer/qmpvisrendercore.cpp')
-rw-r--r--visualization/renderer/qmpvisrendercore.cpp126
1 files changed, 100 insertions, 26 deletions
diff --git a/visualization/renderer/qmpvisrendercore.cpp b/visualization/renderer/qmpvisrendercore.cpp
index fb1a7ef..a2733a7 100644
--- a/visualization/renderer/qmpvisrendercore.cpp
+++ b/visualization/renderer/qmpvisrendercore.cpp
@@ -8,11 +8,12 @@
#include <dlfcn.h>
#include <QProcess>
+#include <QCommandLineParser>
#include <QDebug>
#include <QThread>
qmpVisRenderCore *qmpVisRenderCore::inst=nullptr;
-qmpVisRenderCore::qmpVisRenderCore():QObject(nullptr)
+qmpVisRenderCore::qmpVisRenderCore(QCommandLineParser *_clp):QObject(nullptr),clp(_clp)
{
inst=this;
player=new CMidiPlayer();
@@ -21,17 +22,21 @@ qmpVisRenderCore::qmpVisRenderCore():QObject(nullptr)
msettings->registerOptionEnumInt("MIDI","Text encoding","Midi/TextEncoding",{"Unicode","Big5","Big5-HKSCS","CP949","EUC-JP","EUC-KR","GB18030","KOI8-R","KOI8-U","Macintosh","Shift-JIS"},0);
}
-void qmpVisRenderCore::loadVisualizationLibrary()
+bool qmpVisRenderCore::loadVisualizationLibrary()
{
mp=dlopen("libvisualization.so",RTLD_LAZY);
- if(!mp)fprintf(stderr,"failed to load visualization module!\n");
+ if(!mp)
+ {
+ fprintf(stderr,"failed to load the visualization module!\n");
+ return false;
+ }
GetInterface_func getintf=reinterpret_cast<GetInterface_func>(dlsym(mp,"qmpPluginGetInterface"));
SwitchMode_func switchmode=reinterpret_cast<SwitchMode_func>(dlsym(mp,"switchToRenderMode"));
vf=nullptr;
vp=getintf(api);
- switchmode(&qmpVisRenderCore::framefunc,false);
+ switchmode(&qmpVisRenderCore::framefunc,!clp->isSet("show-window"));
vp->init();
- msettings->load("/home/chrisoft/.config/qmprc");
+ return true;
}
void qmpVisRenderCore::unloadVisualizationLibrary()
@@ -40,6 +45,21 @@ void qmpVisRenderCore::unloadVisualizationLibrary()
dlclose(mp);
}
+void qmpVisRenderCore::loadSettings()
+{
+ if(clp->isSet("config"))
+ msettings->load(clp->value("config").toStdString().c_str());
+ for(auto &o:clp->values("option"))
+ {
+ int sp=o.indexOf('=');
+ if(!~sp)
+ qDebug("invalid option pair: %s",o.toStdString().c_str());
+ QString key=o.left(sp);
+ QString value=o.mid(sp+1);
+ msettings->setopt(key.toStdString(),value.toStdString());
+ }
+}
+
void qmpVisRenderCore::setMIDIFile(const char *url)
{
player->playerLoadFile(url);
@@ -51,38 +71,92 @@ void qmpVisRenderCore::startRender()
ffmpegproc=new QProcess();
ffmpegproc->setProgram("ffmpeg");
QStringList arguments;
+ arguments.append(split_arguments(clp->value("ffmpeg-pre-args")));
arguments
<<"-f"<<"rawvideo"
<<"-pixel_format"<<"rgba"
- <<"-video_size"<<"1600x900"
- <<"-framerate"<<"60"
+ <<"-video_size"<<QString("%1x%2").arg(msettings->getOptionInt("Visualization/wwidth")).arg(msettings->getOptionInt("Visualization/wheight"))
+ <<"-framerate"<<QString::number(msettings->getOptionInt("Visualization/tfps"))
<<"-i"<<"pipe:";
- arguments
- <<"-vf"<<"vflip"
- <<"-pix_fmt"<<"yuv420p"
- <<"-c:v"<<"libx264"
- <<"-preset"<<"fast"
- <<"-crf"<<"22";
- arguments<<"output.mp4";
+ arguments.append(split_arguments(clp->value("ffmpeg-args")));
+ arguments<<clp->value("output-file");
ffmpegproc->setArguments(arguments);
- ffmpegproc->start();
+ QMetaObject::Connection frameconn=connect(this,&qmpVisRenderCore::frameRendered,this,
+ [this,&frameconn](void* px,size_t sz,uint32_t c,uint32_t t)
+ {
+ if(sz)
+ {
+ if(!ffmpegproc->isOpen())return;
+ ffmpegproc->write(static_cast<const char*>(px),static_cast<qint64>(sz));
+ while(ffmpegproc->bytesToWrite()>1<<26)
+ ffmpegproc->waitForBytesWritten();
+ }
+ fprintf(stderr,"Rendered tick %u of %u, %.2f%% done.\r",c,t,100.*c/t);
+ if(c>t)
+ {
+ this->ffmpegproc->closeWriteChannel();
+ disconnect(frameconn);
+ qApp->exit(0);
+ }
+ },Qt::ConnectionType::BlockingQueuedConnection);
connect(ffmpegproc,QOverload<int,QProcess::ExitStatus>::of(&QProcess::finished),
- [this](int x,QProcess::ExitStatus){qDebug("%d",x);qDebug()<<this->ffmpegproc->readAllStandardError();});
- vf->show();
- startcb(nullptr,nullptr);
+ [this,&frameconn](int x,QProcess::ExitStatus st){
+ qDebug("%s",this->ffmpegproc->readAllStandardError().data());
+ disconnect(frameconn);
+ if(x||st==QProcess::ExitStatus::CrashExit)
+ qApp->exit(1);
+ else
+ qApp->exit(0);
+ });
+ QMetaObject::invokeMethod(this,[this](){
+ ffmpegproc->start();
+ vf->show();
+ startcb(nullptr,nullptr);
+ },Qt::ConnectionType::QueuedConnection);
}
-void qmpVisRenderCore::framefunc(void *px, size_t sz)
+QStringList qmpVisRenderCore::split_arguments(QString a)
{
- if(sz)
+ QStringList ret;
+ QString buf;
+ bool escaped=false;
+ for(int i=0;i<a.length();++i)
{
- inst->ffmpegproc->write((const char*)px,sz);
- while(inst->ffmpegproc->bytesToWrite()>1<<26)
+ if(a[i]=='\\')
+ {
+ if(escaped)
+ {
+ buf+='\\';
+ escaped=false;
+ }
+ else escaped=true;
+ }
+ else if(a[i]==' ')
{
- inst->ffmpegproc->waitForBytesWritten();
- QThread::yieldCurrentThread();
+ if(escaped)buf+=' ';
+ else
+ {
+ ret.append(buf);
+ buf.clear();
+ }
+ escaped=false;
+ }
+ else
+ {
+ if(escaped)
+ {
+ buf+='\\';
+ escaped=false;
+ }
+ buf+=a[i];
}
}
- else
- inst->ffmpegproc->closeWriteChannel();
+ if(buf.length())
+ ret.append(buf);
+ return ret;
+}
+
+void qmpVisRenderCore::framefunc(void *px, size_t sz,uint32_t curf,uint32_t totf)
+{
+ emit inst->frameRendered(px,sz,curf,totf);
}