99 ui.actionTest->setVisible(
true);
102 QString verString(GIT_CURRENT_SHA1
"/" GIT_CURRENT_BRANCH);
108 ui.localPreviewBar->addWidget(&
rtcpRr);
109 ui.localPreviewBar->setAlignment(&
rtcpRr, Qt::AlignBottom);
112 ui.remotePreviewBar->setAlignment(&
receiverLoss, Qt::AlignBottom);
117 ui.vuMeter->setOnRightSide(
true);
119 ui.vuMeterSend->setParsePrefix(
"stats ASEND");
121 using namespace std::placeholders;
126 auto ctx = std::make_unique<LaunchContext>();
128 ctx->args = QStringList() <<
"--capabilities";
132 QLabel queryMsg = QLabel(
"Querying UltraGrid capabilities...");
134 bool safeMode =
false;
135 std::string currentQuery;
137 std::vector<std::string> safeModeQueue;
138 std::vector<std::string> safeModeFails;
141 ctx->extraData = std::make_unique<QueryData>();
142 auto extraPtr =
static_cast<QueryData *
>(ctx->extraData.get());
144 ui.statusbar->addWidget(&extraPtr->queryMsg);
147 connect(&ctx->process, &QProcess::started,
150 ui.startButton->setEnabled(false);
151 ui.startButton->setText(
"Querying...");
155 [=](
int ec, QProcess::ExitStatus es,
bool requested)
157 ui.startButton->setEnabled(true);
158 ui.startButton->setText(
"Start");
160 if(!requested && (es == QProcess::ExitStatus::CrashExit || ec != 0)){
161 if(!extraPtr->safeMode){
162 extraPtr->safeMode = true;
163 ui.statusbar->showMessage(
"Capabilities querying in safe mode...");
164 for(int i = 0; i < SettingType::SETTING_TYPE_COUNT; i++){
165 SettingType type = static_cast<SettingType>(i);
166 for(const auto& mod : availableSettings.getAvailableSettings(type)){
167 std::string item = settingTypeToStr(type);
170 extraPtr->safeModeQueue.push_back(std::move(item));
173 extraPtr->safeModeQueue.emplace_back(
"noprobe");
174 availableSettings.queryBegin();
176 extraPtr->safeModeFails.push_back(extraPtr->currentQuery);
180 if(extraPtr->safeMode && !extraPtr->safeModeQueue.empty()){
181 auto next_ctx = launchMngr.extractCurrentCtx();
183 auto modToQuery = std::move(extraPtr->safeModeQueue.back());
184 extraPtr->safeModeQueue.pop_back();
186 extraPtr->currentQuery =
"--capabilities=" + modToQuery;
188 next_ctx->args = QStringList()
189 << QString::fromStdString(extraPtr->currentQuery);
191 availableSettings.queryBeginPass();
192 launchMngr.reLaunch(std::move(next_ctx));
197 if(extraPtr->safeMode && !extraPtr->safeModeFails.empty()){
199 std::string msg =
"Ultragrid crashed when querying the following modules."
200 " Some options may be missing as a result.\n";
202 for(const auto& i : extraPtr->safeModeFails){
206 msgBox.setText(QString::fromStdString(
msg));
207 msgBox.setIcon(QMessageBox::Warning);
211 availableSettings.queryEnd();
212 settings.populateSettingsFromCapabilities(&availableSettings);
213 settingsUi.refreshAll();
219 [=](std::string_view line) { availableSettings.queryLine(line); });
221 launchMngr.launch(std::move(ctx));
246 QMessageBox warningBox(
this);
247 warningBox.setWindowTitle(
"Preview disabled");
248 warningBox.setText(
"Preview is disabled, because UltraGrid was compiled"
249 " without preview and multiplier displays."
250 " Please build UltraGrid configured with the --enable-qt flag"
251 " to enable preview.");
252 warningBox.setStandardButtons(QMessageBox::Ok);
253 warningBox.setIcon(QMessageBox::Warning);
259 QOpenGLFunctions_3_3_Core* funcs =
260#if QT_VERSION < QT_VERSION_CHECK(6, 0, 0)
261 ctx.versionFunctions<QOpenGLFunctions_3_3_Core>();
263 QOpenGLVersionFunctionsFactory::get<QOpenGLFunctions_3_3_Core>(&ctx);
269 QMessageBox warningBox(
this);
270 warningBox.setWindowTitle(
"Preview disabled");
271 warningBox.setText(
"OpenGL 3.3 is not supported, disabling preview.");
272 warningBox.setStandardButtons(QMessageBox::Ok);
273 warningBox.setIcon(QMessageBox::Warning);
278 ui.previewCheckBox->setChecked(
false);
279 ui.previewCheckBox->setEnabled(
false);
312 auto ctx = std::make_unique<LaunchContext>();
317 connect(&ctx->process, &QProcess::started,
320 ui.startButton->setText(
"Stop");
321 ui.startButton->setEnabled(true);
322 processStatus.setText(
"UG: Running");
323 ui.actionRefresh->setEnabled(false);
327 [=](
int ec, QProcess::ExitStatus es,
bool requested)
329 ui.startButton->setText(
"Start");
330 ui.startButton->setEnabled(true);
331 ui.actionRefresh->setEnabled(true);
332 receiverLoss.reset();
334 ui.send_bandwidth->reset();
336 if(!requested && (es == QProcess::ExitStatus::CrashExit || ec != 0)){
337 processStatus.setText(
"UG: Crashed");
339 log.write(
"Process exited with code: " + QString::number(ec) +
"\n\n");
340 QMessageBox msgBox(this);
341 msgBox.setIcon(QMessageBox::Critical);
342 msgBox.setWindowTitle(
"UltraGrid error!");
343 msgBox.setText(
"Ultragrid has exited with an error! If you need help, please send an email "
344 "to ultragrid-dev@cesnet.cz with log attached.");
345 QPushButton *showLogBtn = msgBox.addButton(tr(
"Show log"), QMessageBox::ActionRole);
346 msgBox.addButton(tr(
"Dismiss"), QMessageBox::RejectRole);
349 if(msgBox.clickedButton() == showLogBtn){
354 processStatus.setText(
"UG: Stopped");
360 [=](QString str) { log.write(str); });
363 [=](std::string_view sv)
365 rtcpRr.parseLine(sv);
366 controlPort.parseLine(sv);
367 receiverLoss.parseLine(sv);
370 ui.startButton->setText(
"Starting...");
371 processStatus.setText(
"UG: Starting");
372 ui.startButton->setEnabled(
false);
373 launchMngr.launch(std::move(ctx));
392 if(!
ui.previewCheckBox->isEnabled()
393 || !
ui.previewCheckBox->isChecked())
398 auto ctx = std::make_unique<LaunchContext>();
404 log.
write(
"Preview: " + argListToString(ctx->args) +
"\n\n");
407 connect(&ctx->process, &QProcess::started,
408 [=]() { previewStatus.setText(
"Preview: Running"); });
411 [=](
int ec, QProcess::ExitStatus es,
bool requested)
413 if(!requested && (es == QProcess::ExitStatus::CrashExit || ec != 0)){
414 previewStatus.setText(
"Preview: Crashed");
416 previewStatus.setText(
"Preview: Stopped");
421 [=](std::string_view sv) { controlPort.parseLine(sv); });
423 launchMngr.launch(std::move(ctx));
464 connect(
ui.actionAbout_UltraGrid, SIGNAL(triggered()),
this, SLOT(
about()));
465 connect(
ui.startButton, SIGNAL(clicked()),
this, SLOT(
startStop()));
467 connect(
ui.arguments, SIGNAL(textChanged(
const QString &)),
this, SLOT(
editArgs(
const QString &)));
468 connect(
ui.editCheckBox, SIGNAL(toggled(
bool)),
this, SLOT(
setArgs()));
470 connect(
ui.actionShow_Terminal, SIGNAL(triggered()),
this, SLOT(
showLog()));
471 connect(
ui.actionSettings, SIGNAL(triggered()),
this, SLOT(
showSettings()));
472 connect(
ui.previewCheckBox, SIGNAL(toggled(
bool)),
this, SLOT(
enablePreview(
bool)));
474 connect(
ui.actionRefresh, SIGNAL(triggered()),
this, SLOT(
refresh()));
476 connect(
ui.actionSave, SIGNAL(triggered()),
this, SLOT(
saveSettings()));
477 connect(
ui.actionLoad, SIGNAL(triggered()),
this, SLOT(
loadSettings()));
482 connect(
ui.fecToolBtn, SIGNAL(clicked()),
this, SLOT(
showSettings()));
499 QString filename = QFileDialog::getSaveFileName(
this,
"Save Settings",
"",
"Json (*.json)");
500 if(!filename.endsWith(QString(
".json"))){
501 filename.append(QString(
".json"));
504 QFile outFile(filename);
506 if (!outFile.open(QIODevice::WriteOnly)) {
507 qWarning(
"Couldn't open save file.");
513 for(
const auto &keyValPair : optMap){
514 jsonObj[QString::fromStdString(keyValPair.first)] =
515 QString::fromStdString(keyValPair.second->getValue());
518 QJsonDocument jsonDoc(jsonObj);
520 outFile.write(jsonDoc.toJson());
575 QStringList args = QCoreApplication::arguments();
576 int index = args.indexOf(
"--with-uv");
577 if(index != -1 && args.size() >= index + 1) {
579 return args.at(index + 1);
582 CFBundleRef mainBundle = CFBundleGetMainBundle();
583 CFURLRef cfURL = CFBundleCopyBundleURL(mainBundle);
584 CFStringRef cfPath = CFURLCopyFileSystemPath(cfURL, kCFURLPOSIXPathStyle);
585 CFStringEncoding encodingMethod = CFStringGetSystemEncoding();
586 QString bundlePath(CFStringGetCStringPtr(cfPath, encodingMethod));
589 return bundlePath +
"/Contents/MacOS/uv";
591 return QString(
"uv");
void processOutputLine(std::string_view sv)
void processTerminated(int code, QProcess::ExitStatus es, bool wasRequested)
void processOutputRead(QString str)