static void displayPipelineList(rtRemoteEnvironment *env, rtObjectRef ®istry) { getAvailablePipelines( env, registry ); printf("pipelines\n{\n"); pthread_mutex_lock( &gMutex ); int count= gAvailablePipelines.size(); for( int i= 0; i < count; ++i) { printf(" %d - %s\n", i, gAvailablePipelines[i].c_str()); } pthread_mutex_unlock( &gMutex ); printf("}\n"); }
int main( int argc, const char **argv ) { rtError rc; rtRemoteEnvironment *env= 0; const char* srcName= 0; const char* fileName= 0; const char* endpointName= 0; bool toFile= false; bool toEndpoint= false; int duration= -1; int len; printf("mediacapture-test v1.0\n"); if ( argc > 4 ) { showUsage(); } else { if ( argc > 1 ) { len= strlen(argv[1]); if ( (len == 4) && !strncmp( argv[1], "file", len) ) { toFile= true; } else if ( (len == 8) && !strncmp( argv[1], "endpoint", len) ) { toEndpoint= true; } } if ( argc > 2 ) { if ( toFile ) { fileName= argv[2]; } else if ( toEndpoint ) { endpointName= argv[2]; } } if ( argc > 3 ) { duration= atoi(argv[3]); } if ( !toFile && !toEndpoint ) { showUsage(); exit(0); } if ( duration < 0 ) { duration= 30000; } printf("will capture to %s (%s)\n", (toFile?"file":"endpoint"), (toFile?fileName:endpointName)); env= rtEnvironmentGetGlobal(); rc= rtRemoteInit(env); if ( rc == RT_OK ) { rtObjectRef registry; struct sigaction sigint; rc= rtRemoteLocateObject(env, "mediacaptureregistry", registry); if ( rc == RT_OK ) { sigint.sa_handler= signalHandler; sigemptyset(&sigint.sa_mask); sigint.sa_flags= SA_RESETHAND; sigaction(SIGINT, &sigint, NULL); setBlockingMode(NON_BLOCKING_ENABLED); listActions(); gRunning= true; while( gRunning ) { rtRemoteProcessSingleItem( env ); if ( isKeyHit() ) { int src= -1; int c= fgetc(stdin); switch( c ) { case '0': case '1': case '2': case '3': case '4': case '5': case '6': case '7': case '8': case '9': src= c-'0'; getAvailablePipelines(env, registry); if ( toFile ) { captureSourceToFile( src, fileName, duration, env ); } else { startCaptureSourceToEndpoint( src, endpointName, duration, env ); } break; case 's': if ( !toFile ) { if ( gSrcActive != -1 ) { stopCaptureSourceToEndpoint( gSrcActive, env ); } } break; case 'l': displayPipelineList(env, registry); break; case 'i': displayMediaConsumptionInfo(env, registry); break; case 'c': clearMediaConsumptionInfo(env, registry); break; case 'q': gRunning= false; break; default: listActions(); break; } } usleep( 10000 ); } setBlockingMode(NON_BLOCKING_DISABLED); } else { printf("error: unable to locate registry: %d", rc); } } else { printf("error: rtRemoteInit rc %d\n", rc); } } return 0; }
GUI::GUI() { mStreamingMode = STREAMING_MODE_STORE_ALL_FRAMES; QScreen* screen = QGuiApplication::primaryScreen(); menuWidth = screen->geometry().width()*(1.0f/6.0f); mPipelineWidget = nullptr; mStreamer = ImageFileStreamer::New(); QVBoxLayout* viewLayout = new QVBoxLayout; View* view = createView(); view->set2DMode(); view->setBackgroundColor(Color::Black()); setWidth(screen->geometry().width()); setHeight(screen->geometry().height()); enableMaximized(); setTitle("FAST - Viewer"); viewLayout->addWidget(view); menuLayout = new QVBoxLayout; menuLayout->setAlignment(Qt::AlignTop); // Logo QImage* image = new QImage; image->load((Config::getDocumentationPath() + "images/FAST_logo_square.png").c_str()); QLabel* logo = new QLabel; logo->setPixmap(QPixmap::fromImage(image->scaled(menuWidth, ((float)menuWidth/image->width())*image->height(), Qt::IgnoreAspectRatio, Qt::SmoothTransformation))); logo->adjustSize(); menuLayout->addWidget(logo); // Title label QLabel* title = new QLabel; title->setText("Viewer"); QFont font; font.setPixelSize(24 * getScalingFactor()); font.setWeight(QFont::Bold); title->setFont(font); title->setAlignment(Qt::AlignCenter); menuLayout->addWidget(title); // Quit button QPushButton* quitButton = new QPushButton; quitButton->setText("Quit (q)"); quitButton->setStyleSheet("QPushButton { background-color: red; color: white; }"); quitButton->setFixedWidth(menuWidth); menuLayout->addWidget(quitButton); // Connect the clicked signal of the quit button to the stop method for the window QObject::connect(quitButton, &QPushButton::clicked, std::bind(&Window::stop, this)); QLabel* inputListLabel = new QLabel; //inputListLabel->setFixedHeight(24); inputListLabel->setText("Input data"); inputListLabel->setStyleSheet("QLabel { font-weight: bold; }"); menuLayout->addWidget(inputListLabel); mList = new QListWidget; mList->setFixedWidth(menuWidth); mList->setSizePolicy(QSizePolicy::Minimum, QSizePolicy::Minimum); mList->setFixedHeight(200); mList->setSelectionMode(QAbstractItemView::ExtendedSelection); // Allow multiple items to be selected QObject::connect(mList, &QListWidget::itemSelectionChanged, std::bind(&GUI::selectInputData, this)); menuLayout->addWidget(mList); QPushButton* addButton = new QPushButton; addButton->setText("Add input data"); addButton->setFixedWidth(menuWidth); QObject::connect(addButton, &QPushButton::clicked, std::bind(&GUI::addInputData, this)); menuLayout->addWidget(addButton); QLabel* selectPipelineLabel = new QLabel; selectPipelineLabel->setText("Active pipeline"); selectPipelineLabel->setStyleSheet("QLabel { font-weight: bold; }"); //selectPipelineLabel->setFixedHeight(24); menuLayout->addWidget(selectPipelineLabel); mSelectPipeline = new QComboBox; mSelectPipeline->setFixedWidth(menuWidth); mPipelines = getAvailablePipelines(); int index = 0; int counter = 0; for(auto pipeline : mPipelines) { mSelectPipeline->addItem((pipeline.getName() + " (" + pipeline.getDescription() + ")").c_str()); if(pipeline.getName() == "Image renderer") { index = counter; } ++counter; } mSelectPipeline->setCurrentIndex(index); menuLayout->addWidget(mSelectPipeline); QObject::connect(mSelectPipeline, static_cast<void (QComboBox::*)(int)>(&QComboBox::activated), std::bind(&GUI::selectPipeline, this)); QPushButton* refreshPipeline = new QPushButton; refreshPipeline->setText("Refresh pipeline"); refreshPipeline->setStyleSheet("QPushButton { background-color: blue; color: white; }"); refreshPipeline->setFixedWidth(menuWidth); QObject::connect(refreshPipeline, &QPushButton::clicked, std::bind(&GUI::selectPipeline, this)); menuLayout->addWidget(refreshPipeline); QPushButton* editPipeline = new QPushButton; editPipeline->setText("Edit pipeline"); editPipeline->setStyleSheet("QPushButton { background-color: blue; color: white; }"); editPipeline->setFixedWidth(menuWidth); QObject::connect(editPipeline, &QPushButton::clicked, std::bind(&GUI::editPipeline, this)); menuLayout->addWidget(editPipeline); QPushButton* newPipeline = new QPushButton; newPipeline->setText("New pipeline"); newPipeline->setStyleSheet("QPushButton { background-color: blue; color: white; }"); newPipeline->setFixedWidth(menuWidth); QObject::connect(newPipeline, &QPushButton::clicked, std::bind(&GUI::newPipeline, this)); menuLayout->addWidget(newPipeline); // Playback QHBoxLayout* playbackLayout = new QHBoxLayout; mPlayPauseButton = new QPushButton; mPlayPauseButton->setText("Play"); mPlayPauseButton->setStyleSheet("QPushButton { background-color: green; color: white; }"); //mPlayPauseButton->setFixedHeight(100); QObject::connect(mPlayPauseButton, &QPushButton::clicked, std::bind(&GUI::playPause, this)); playbackLayout->addWidget(mPlayPauseButton); mTimestepSlider = new QSlider(Qt::Horizontal); // Improve style of slider mTimestepSlider->setStyleSheet("QSlider:horizontal { min-height: 50px; } QSlider::groove:horizontal {\n" " border: 1px solid #999999;\n" " height: 10px; /* the groove expands to the size of the slider by default. by giving it a height, it has a fixed size */\n" " background: qlineargradient(x1:0, y1:0, x2:0, y2:1, stop:0 #B1B1B1, stop:1 #c4c4c4);\n" " margin: 2px 0;\n" "}\n" "\n" "QSlider::handle:horizontal {\n" " background: qlineargradient(x1:0, y1:0, x2:1, y2:1, stop:0 #81BEF7, stop:1 #2E9AFE);\n" " border: 1px solid #5c5c5c;\n" " width: 18px;\n" " height: 25px;\n" " margin: -10px 0; /* handle is placed by default on the contents rect of the groove. Expand outside the groove */\n" " border-radius: 3px;\n" "}"); playbackLayout->addWidget(mTimestepSlider); mTimestepSlider->setTickPosition(QSlider::NoTicks); mTimestepSlider->setRange(0, 1234); mTimestepSlider->setPageStep(1); mTimestepSlider->setSingleStep(1); mTimestepSlider->setStyle(new MyStyle(mTimestepSlider->style())); // Fixes issues with direct jump with slider QObject::connect(mTimestepSlider, &QSlider::sliderMoved, std::bind(&GUI::setTimestep, this)); QObject::connect(mTimestepSlider, &QSlider::sliderPressed, std::bind(&GUI::setTimestep, this)); viewLayout->addLayout(playbackLayout); // Add menu and view to main layout QHBoxLayout* layout = new QHBoxLayout; layout->addLayout(menuLayout); layout->addLayout(viewLayout); mWidget->setLayout(layout); std::cout << "Finished viewer setup" << std::endl; }
void GUI::selectPipeline() { // Refresh available pipelines std::string currentPipeline = mSelectPipeline->currentText().toStdString(); mPipelines = getAvailablePipelines(); int index = 0; int counter = 0; mSelectPipeline->clear(); for(auto pipeline : mPipelines) { std::string label = pipeline.getName() + " (" + pipeline.getDescription() + ")"; mSelectPipeline->addItem((label).c_str()); if(label == currentPipeline) { index = counter; } ++counter; } mSelectPipeline->setCurrentIndex(index); mSelectPipeline->update(); // Stop computation thread before removing renderers stopComputationThread(); std::vector<std::string> inputData; for(QListWidgetItem* widget : mList->selectedItems()) { std::string asd = widget->text().toUtf8().constData(); inputData.push_back(asd); } mStreamer = ImageFileStreamer::New(); mStreamer->setFilenameFormats(inputData); mStreamer->setMainDevice(Host::getInstance()); getView(0)->removeAllRenderers(); int selectedPipeline = mSelectPipeline->currentIndex(); Pipeline pipeline = mPipelines.at(selectedPipeline); int nrOfFrames = 0; try { int inputsRequired = pipeline.parsePipelineFile(); std::vector<DataPort::pointer> inputs; while(inputsRequired--) inputs.push_back(mStreamer->getOutputPort()); // Preload the data mStreamer->update(0, STREAMING_MODE_STORE_ALL_FRAMES); while(!mStreamer->hasReachedEnd()) { std::this_thread::sleep_for(std::chrono::milliseconds(100)); } nrOfFrames = inputs[0]->getSize(); std::vector<SharedPointer<Renderer>> renderers = pipeline.setup(inputs); for(auto renderer : renderers) { // A hack for text renderer which needs a reference to the view if(renderer->getNameOfClass() == "TextRenderer") { TextRenderer::pointer textRenderer = std::dynamic_pointer_cast<TextRenderer>(renderer); textRenderer->setView(getView(0)); } getView(0)->addRenderer(renderer); } getView(0)->reinitialize(); } catch(Exception &e) { QMessageBox* message = new QMessageBox; message->setWindowTitle("Error"); message->setText(e.what()); message->show(); } startComputationThread(); mPlayPauseButton->setText("Pause"); mPlayPauseButton->setStyleSheet("QPushButton { background-color: red; color: white; }"); mThread->setTimestepLimit(nrOfFrames); mTimestepSlider->setRange(0, nrOfFrames - 1); mThread->setTimestepLoop(true); QObject::connect(mThread, &ComputationThread::timestepIncreased, std::bind(&GUI::increaseTimestep, this)); /* PipelineWidget* pipelineWidget = new PipelineWidget(pipeline, mWidget); pipelineWidget->setFixedWidth(menuWidth); if(mPipelineWidget == nullptr) { menuLayout->addWidget(pipelineWidget); } else { menuLayout->replaceWidget(mPipelineWidget, pipelineWidget); } mPipelineWidget = pipelineWidget; */ }