diff --git a/applications/gui/src/media_panel.cpp b/applications/gui/src/media_panel.cpp index 1a6f288ce788f1b808c2eb0b42515b5b8ca37c83..19339104362d12941668362a42d30512d4013ac6 100644 --- a/applications/gui/src/media_panel.cpp +++ b/applications/gui/src/media_panel.cpp @@ -37,69 +37,70 @@ MediaPanel::MediaPanel(ftl::gui::Screen *screen, ftl::gui::SourceWindow *sourceW virtualCameraRecording_ = std::optional<ftl::gui::Camera*>(); sceneRecording_ = std::optional<ftl::Configurable*>(); - auto recordbutton = new PopupButton(this, "", ENTYPO_ICON_CONTROLLER_RECORD); - recordbutton->setTooltip("Record"); - recordbutton->setSide(Popup::Side::Right); - recordbutton->setChevronIcon(0); - auto recordpopup = recordbutton->popup(); + recordbutton_ = new PopupButton(this, "", ENTYPO_ICON_CONTROLLER_RECORD); + recordbutton_->setTooltip("Record"); + recordbutton_->setSide(Popup::Side::Right); + recordbutton_->setChevronIcon(0); + auto recordpopup = recordbutton_->popup(); recordpopup->setLayout(new GroupLayout()); recordpopup->setTheme(screen->toolbuttheme); recordpopup->setAnchorHeight(150); auto itembutton = new Button(recordpopup, "2D snapshot (.png)"); - itembutton->setCallback([this,recordbutton]() { + itembutton->setCallback([this]() { char timestamp[18]; std::time_t t=std::time(NULL); std::strftime(timestamp, sizeof(timestamp), "%F-%H%M%S", std::localtime(&t)); screen_->activeCamera()->snapshot(std::string(timestamp) + ".png"); - recordbutton->setPushed(false); + recordbutton_->setPushed(false); }); itembutton = new Button(recordpopup, "Virtual camera recording (.ftl)"); - itembutton->setCallback([this,recordbutton]() { + itembutton->setCallback([this]() { char timestamp[18]; std::time_t t=std::time(NULL); std::strftime(timestamp, sizeof(timestamp), "%F-%H%M%S", std::localtime(&t)); auto filename = std::string(timestamp) + ".ftl"; - toggleVirtualCameraRecording(screen_->activeCamera(), filename); - recordbutton->setTextColor(nanogui::Color(1.0f,0.1f,0.1f,1.0f)); - recordbutton->setPushed(false); + startRecording2D(screen_->activeCamera(), filename); + recordbutton_->setTextColor(nanogui::Color(1.0f,0.1f,0.1f,1.0f)); + recordbutton_->setPushed(false); }); itembutton = new Button(recordpopup, "3D scene snapshot (.ftl)"); - itembutton->setCallback([this,recordbutton]() { + itembutton->setCallback([this]() { char timestamp[18]; std::time_t t=std::time(NULL); std::strftime(timestamp, sizeof(timestamp), "%F-%H%M%S", std::localtime(&t)); snapshot3D(screen_->activeCamera(), std::string(timestamp) + ".ftl"); - recordbutton->setPushed(false); + recordbutton_->setPushed(false); }); itembutton = new Button(recordpopup, "3D scene recording (.ftl)"); - itembutton->setCallback([this,recordbutton]() { + itembutton->setCallback([this]() { char timestamp[18]; std::time_t t=std::time(NULL); std::strftime(timestamp, sizeof(timestamp), "%F-%H%M%S", std::localtime(&t)); startRecording3D(screen_->activeCamera(), std::string(timestamp) + ".ftl"); - recordbutton->setTextColor(nanogui::Color(1.0f,0.1f,0.1f,1.0f)); - recordbutton->setPushed(false); + recordbutton_->setTextColor(nanogui::Color(1.0f,0.1f,0.1f,1.0f)); + recordbutton_->setPushed(false); }); itembutton = new Button(recordpopup, "Detailed recording options"); - itembutton->setCallback([this,sourceWindow,recordbutton] { + itembutton->setCallback([this,sourceWindow] { auto record_window = new RecordWindow(screen_, screen_, sourceWindow->getCameras(), this); record_window->setTheme(screen_->windowtheme); - recordbutton->setPushed(false); + recordbutton_->setPushed(false); + recordbutton_->setEnabled(false); }); - recordbutton->setCallback([this,recordbutton](){ + recordbutton_->setCallback([this](){ if (virtualCameraRecording_) { virtualCameraRecording_.value()->stopVideoRecording(); - recordbutton->setTextColor(nanogui::Color(1.0f,1.0f,1.0f,1.0f)); + recordbutton_->setTextColor(nanogui::Color(1.0f,1.0f,1.0f,1.0f)); // Prevents the popup from being opened, though it is shown while the button // is being pressed. - recordbutton->setPushed(false); + recordbutton_->setPushed(false); virtualCameraRecording_ = std::nullopt; } else if (sceneRecording_) { sceneRecording_.value()->set("record", false); - recordbutton->setTextColor(nanogui::Color(1.0f,1.0f,1.0f,1.0f)); - recordbutton->setPushed(false); + recordbutton_->setTextColor(nanogui::Color(1.0f,1.0f,1.0f,1.0f)); + recordbutton_->setPushed(false); sceneRecording_ = std::nullopt; } }); @@ -294,9 +295,10 @@ void MediaPanel::cameraChanged() { } } -void MediaPanel::toggleVirtualCameraRecording(ftl::gui::Camera *camera, const std::string &filename) { +void MediaPanel::startRecording2D(ftl::gui::Camera *camera, const std::string &filename) { camera->startVideoRecording(filename); virtualCameraRecording_ = std::optional<ftl::gui::Camera*>(camera); + recordbutton_->setTextColor(nanogui::Color(1.0f,0.1f,0.1f,1.0f)); } void MediaPanel::snapshot3D(ftl::gui::Camera *camera, const std::string &filename) { @@ -321,6 +323,11 @@ void MediaPanel::startRecording3D(ftl::gui::Camera *camera, const std::string &f configurable->set("record-name", filename); configurable->set("record", true); sceneRecording_ = std::optional<ftl::Configurable*>(configurable); + recordbutton_->setTextColor(nanogui::Color(1.0f,0.1f,0.1f,1.0f)); } } +} + +void MediaPanel::recordWindowClosed() { + recordbutton_->setEnabled(true); } \ No newline at end of file diff --git a/applications/gui/src/media_panel.hpp b/applications/gui/src/media_panel.hpp index a71ee81838d87bd9af4183e60e45dd4c7dfd92b1..211b84c6e0beecdcfd5fd51cb3f413e628d31d87 100644 --- a/applications/gui/src/media_panel.hpp +++ b/applications/gui/src/media_panel.hpp @@ -24,12 +24,14 @@ class MediaPanel : public nanogui::Window { void cameraChanged(); - void toggleVirtualCameraRecording(ftl::gui::Camera *camera, const std::string &filename); + void startRecording2D(ftl::gui::Camera *camera, const std::string &filename); void snapshot3D(ftl::gui::Camera *camera, const std::string &filename); void startRecording3D(ftl::gui::Camera *camera, const std::string &filename); + void recordWindowClosed(); + private: ftl::gui::Screen *screen_; @@ -40,6 +42,7 @@ class MediaPanel : public nanogui::Window { nanogui::PopupButton *button_channels_; nanogui::Button *right_button_; nanogui::Button *depth_button_; + nanogui::PopupButton *recordbutton_; /** * These members indicate which type of recording is active, if any. diff --git a/applications/gui/src/record_window.cpp b/applications/gui/src/record_window.cpp index 50cdf9d3ed7e0a5277a52b976108deae4c82adc0..87fbb9dc0e50562abe10b932b05f728f4e24208e 100644 --- a/applications/gui/src/record_window.cpp +++ b/applications/gui/src/record_window.cpp @@ -23,17 +23,23 @@ RecordWindow::RecordWindow(nanogui::Widget *parent, ftl::gui::Screen *screen, co char timestamp[18]; std::time_t t = std::time(NULL); std::strftime(timestamp, sizeof(timestamp), "%F-%H%M%S", std::localtime(&t)); - // TODO: Change the file type specifier to be set based on the type of the recording. - auto fileName = new TextBox(this, std::string(timestamp) + ".ftl"); + Widget *fileNameBox = new Widget(this); + fileNameBox->setLayout(new BoxLayout(Orientation::Horizontal, Alignment::Middle, 0, 6)); + auto fileName = new TextBox(fileNameBox, std::string(timestamp)); + fileName->setFixedWidth(350); fileName->setEditable(true); + auto extension = new Label(fileNameBox, ".png", "sans-bold"); new Label(this, "Select stream", "sans-bold"); auto streamNames = std::vector<std::string>(); streamNames.reserve(streams.size()); + std::optional<int> ix; for (const auto s : streams) { + if (s == screen->activeCamera()) { + ix = std::optional<int>(streamNames.size()); + } streamNames.push_back(s->source()->getURI()); } auto streamSelect = new ComboBox(this, streamNames); - // TODO: Set the default stream to be the active stream if there is one. // TODO: The function availableChannels() only finds those channels that // have been set in camera.cpp. The only channels that are set in // camera.cpp currently are Colour and Depth. This means that currently, @@ -51,11 +57,20 @@ RecordWindow::RecordWindow(nanogui::Widget *parent, ftl::gui::Screen *screen, co snapshot3D->setLayout(new GroupLayout()); recording3D->setLayout(new GroupLayout()); - new Label(snapshot2D, "Select channel (in addition to Left)", "sans-bold"); - auto snapshotChannel = snapshot2D->add<ComboBox>(); + // Set the file name extension based on the type of recording chosen. + tabWidget->setCallback([tabWidget,snapshot2D,extension](int ix) { + if (tabWidget->tab(ix) == snapshot2D) { + extension->setCaption(".png"); + } else { + extension->setCaption(".ftl"); + } + }); + + tabWidget->setActiveTab(0); + new Label(recording2D, "Select channel (in addition to Left)", "sans-bold"); auto recordingChannel = recording2D->add<ComboBox>(); - streamSelect->setCallback([this,streams,snapshotChannel,recordingChannel](int ix) { + auto streamCallback = [this,streams,recordingChannel](int ix) { channels_ = std::vector<ftl::codecs::Channel>(); channel_names_ = std::vector<std::string>(); ftl::codecs::Channels availableChannels = streams[ix]->availableChannels(); @@ -63,39 +78,44 @@ RecordWindow::RecordWindow(nanogui::Widget *parent, ftl::gui::Screen *screen, co channels_.push_back(c); channel_names_.push_back(ftl::codecs::name(c)); } - snapshotChannel->setItems(channel_names_); recordingChannel->setItems(channel_names_); - }); + }; + streamSelect->setCallback(streamCallback); + + // Set the selection to the active stream and set the channel list + // to be the channels available in that stream. The callback must + // be called explicitly, since setSelectedIndex() does not trigger it. + if (ix) { + streamSelect->setSelectedIndex(ix.value()); + streamCallback(ix.value()); + } Widget *actionButtons = new Widget(this); actionButtons->setLayout(new BoxLayout(Orientation::Horizontal)); auto button = new Button(actionButtons, "Start"); - button->setCallback([this,streams,streamSelect,screen,media_panel,fileName,tabWidget,snapshot2D,recording2D,snapshot3D,recording3D,snapshotChannel,recordingChannel]() { + button->setCallback([this,streams,streamSelect,screen,media_panel,fileName,extension,tabWidget,snapshot2D,recording2D,snapshot3D,recording3D,recordingChannel]() { // Check the chosen stream type and channels, then record them. + std::string name = fileName->value() + extension->caption(); auto stream = streams[streamSelect->selectedIndex()]; auto tab = tabWidget->tab(tabWidget->activeTab()); if (tab == snapshot2D) { - // If the channel isn't the same as the one that was active - // previously, the channel won't have an image. - // One possible solution is to set the channels immediately - // as they are chosen in the recording window. - // Alternatively, 2D snapshots might not need a channel option at all. - stream->setChannel(channels_[snapshotChannel->selectedIndex()]); - stream->snapshot(fileName->value()); + stream->snapshot(name); } else if (tab == recording2D) { stream->setChannel(channels_[recordingChannel->selectedIndex()]); screen->setActiveCamera(stream); - media_panel->toggleVirtualCameraRecording(stream, fileName->value()); + media_panel->startRecording2D(stream, name); } else if (tab == snapshot3D) { - media_panel->snapshot3D(stream, fileName->value()); + media_panel->snapshot3D(stream, name); } else if (tab == recording3D) { - media_panel->startRecording3D(stream, fileName->value()); + media_panel->startRecording3D(stream, name); } dispose(); + media_panel->recordWindowClosed(); }); button = new Button(actionButtons, "Cancel"); - button->setCallback([this]() { + button->setCallback([this,media_panel]() { dispose(); + media_panel->recordWindowClosed(); }); }