mirror of
https://github.com/brunoherbelin/vimix.git
synced 2025-12-12 18:59:59 +01:00
Integration of MultiFileRecorder in UI for sequence creation
This commit is contained in:
@@ -1155,6 +1155,14 @@ void ImGuiVisitor::visit (MultiFileSource& s)
|
||||
ImGui::SetCursorPos(pos);
|
||||
}
|
||||
|
||||
// Filename pattern
|
||||
ImGuiTextBuffer info;
|
||||
ImGui::PushStyleColor(ImGuiCol_FrameBg, ImVec4(0.14f, 0.14f, 0.14f, 0.9f));
|
||||
info.appendf("%s", SystemToolkit::base_filename(s.sequence().location).c_str());
|
||||
ImGui::SetNextItemWidth(IMGUI_RIGHT_ALIGN);
|
||||
ImGui::InputText("Filenames", (char *)info.c_str(), info.size(), ImGuiInputTextFlags_ReadOnly);
|
||||
ImGui::PopStyleColor(1);
|
||||
|
||||
// change range
|
||||
static int _begin = -1;
|
||||
if (_begin < 0 || id != s.id())
|
||||
|
||||
@@ -9,29 +9,23 @@
|
||||
#include "Log.h"
|
||||
#include "GstToolkit.h"
|
||||
#include "BaseToolkit.h"
|
||||
#include "Settings.h"
|
||||
#include "MediaPlayer.h"
|
||||
|
||||
#include "MultiFileRecorder.h"
|
||||
|
||||
MultiFileRecorder::MultiFileRecorder(const std::string &filename) : filename_(filename),
|
||||
MultiFileRecorder::MultiFileRecorder() :
|
||||
fps_(0), width_(0), height_(0), bpp_(3),
|
||||
pipeline_(nullptr), src_(nullptr), frame_count_(0), timestamp_(0), frame_duration_(0),
|
||||
endofstream_(false), accept_buffer_(false), progress_(0.f)
|
||||
cancel_(false), endofstream_(false), accept_buffer_(false), progress_(0.f)
|
||||
{
|
||||
// default
|
||||
// default profile
|
||||
profile_ = VideoRecorder::H264_STANDARD;
|
||||
|
||||
// set fps and frame duration
|
||||
// default fps and frame duration
|
||||
setFramerate(15);
|
||||
}
|
||||
|
||||
|
||||
inline void MultiFileRecorder::setFramerate (int fps)
|
||||
{
|
||||
fps_ = fps;
|
||||
frame_duration_ = gst_util_uint64_scale_int (1, GST_SECOND, fps_);
|
||||
}
|
||||
|
||||
MultiFileRecorder::~MultiFileRecorder ()
|
||||
{
|
||||
if (src_ != nullptr)
|
||||
@@ -41,11 +35,18 @@ MultiFileRecorder::~MultiFileRecorder ()
|
||||
gst_object_unref (pipeline_);
|
||||
}
|
||||
|
||||
void MultiFileRecorder::assembleImages(std::list<std::string> list, const std::string &filename)
|
||||
void MultiFileRecorder::setFramerate (int fps)
|
||||
{
|
||||
MultiFileRecorder recorder( filename );
|
||||
fps_ = fps;
|
||||
frame_duration_ = gst_util_uint64_scale_int (1, GST_SECOND, fps_);
|
||||
}
|
||||
|
||||
recorder.assemble( list );
|
||||
void MultiFileRecorder::setProfile (VideoRecorder::Profile p)
|
||||
{
|
||||
if (p < VideoRecorder::VP8)
|
||||
profile_ = p;
|
||||
else
|
||||
profile_ = VideoRecorder::H264_STANDARD;
|
||||
}
|
||||
|
||||
// appsrc needs data and we should start sending
|
||||
@@ -115,6 +116,7 @@ bool MultiFileRecorder::add_image (const std::string &image_filename)
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
bool MultiFileRecorder::start_record (const std::string &video_filename)
|
||||
{
|
||||
if ( video_filename.empty() ) {
|
||||
@@ -276,50 +278,87 @@ bool MultiFileRecorder::end_record ()
|
||||
|
||||
|
||||
|
||||
void MultiFileRecorder::assemble (std::list<std::string> list)
|
||||
void MultiFileRecorder::start ()
|
||||
{
|
||||
if ( promises_.empty() ) {
|
||||
filename_ = std::string();
|
||||
promises_.emplace_back( std::async(std::launch::async, assemble, this) );
|
||||
}
|
||||
}
|
||||
|
||||
void MultiFileRecorder::cancel ()
|
||||
{
|
||||
cancel_ = true;
|
||||
}
|
||||
|
||||
bool MultiFileRecorder::finished ()
|
||||
{
|
||||
if ( !promises_.empty() ) {
|
||||
// check that file dialog thread finished
|
||||
if (promises_.back().wait_for(std::chrono::milliseconds(4)) == std::future_status::ready ) {
|
||||
// get the filename from encoder
|
||||
filename_ = promises_.back().get();
|
||||
if (!filename_.empty()) {
|
||||
// save path location
|
||||
Settings::application.recentRecordings.push(filename_);
|
||||
}
|
||||
// done with this recoding
|
||||
promises_.pop_back();
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
std::string MultiFileRecorder::assemble (MultiFileRecorder *rec)
|
||||
{
|
||||
std::string filename;
|
||||
|
||||
// reset
|
||||
progress_ = 0.f;
|
||||
files_.clear();
|
||||
width_ = 0;
|
||||
height_ = 0;
|
||||
bpp_ = 0;
|
||||
rec->progress_ = 0.f;
|
||||
rec->width_ = 0;
|
||||
rec->height_ = 0;
|
||||
rec->bpp_ = 0;
|
||||
|
||||
// input files
|
||||
if ( list.size() < 1 ) {
|
||||
if ( rec->files_.size() < 1 ) {
|
||||
Log::Warning("MultiFileRecorder: No image given.");
|
||||
return;
|
||||
return filename;
|
||||
}
|
||||
|
||||
// set recorder resolution from first image
|
||||
stbi_info( list.front().c_str(), &width_, &height_, &bpp_);
|
||||
stbi_info( rec->files_.front().c_str(), &rec->width_, &rec->height_, &rec->bpp_);
|
||||
|
||||
if ( width_ < 10 || height_ < 10 || bpp_ < 3 ) {
|
||||
if ( rec->width_ < 10 || rec->height_ < 10 || rec->bpp_ < 3 ) {
|
||||
Log::Warning("MultiFileRecorder: invalid image.");
|
||||
return;
|
||||
|
||||
return filename;
|
||||
}
|
||||
Log::Info("MultiFileRecorder creating video %d x %d : %d.", width_, height_, bpp_);
|
||||
|
||||
Log::Info("MultiFileRecorder creating video %d x %d : %d.", rec->width_, rec->height_, rec->bpp_);
|
||||
|
||||
// progress increment
|
||||
float inc_ = 1.f / ( (float) list.size() + 2.f);
|
||||
float inc_ = 1.f / ( (float) rec->files_.size() + 2.f);
|
||||
|
||||
// initialize
|
||||
frame_count_ = 0;
|
||||
rec->frame_count_ = 0;
|
||||
filename = BaseToolkit::common_prefix (rec->files_);
|
||||
filename += "_sequence.mov";
|
||||
|
||||
if ( start_record( filename_ ) )
|
||||
if ( rec->start_record( filename ) )
|
||||
{
|
||||
// progressing
|
||||
progress_ += inc_;
|
||||
rec->progress_ += inc_;
|
||||
|
||||
// loop over images to open
|
||||
for (auto file = list.cbegin(); file != list.cend(); ++file) {
|
||||
for (auto file = rec->files_.cbegin(); file != rec->files_.cend(); ++file) {
|
||||
|
||||
if ( add_image( *file ) ) {
|
||||
if ( rec->cancel_ )
|
||||
break;
|
||||
|
||||
if ( rec->add_image( *file ) ) {
|
||||
|
||||
// validate file
|
||||
frame_count_++;
|
||||
files_.push_back( *file );
|
||||
rec->frame_count_++;
|
||||
}
|
||||
else {
|
||||
Log::Info("MultiFileRecorder could not include images %s.", file->c_str());
|
||||
@@ -327,22 +366,25 @@ void MultiFileRecorder::assemble (std::list<std::string> list)
|
||||
|
||||
// pause in case appsrc buffer is full
|
||||
int max = 100;
|
||||
while (!accept_buffer_ && --max > 0)
|
||||
while (!rec->accept_buffer_ && --max > 0)
|
||||
std::this_thread::sleep_for(std::chrono::milliseconds(10));
|
||||
|
||||
// progressing
|
||||
progress_ += inc_;
|
||||
rec->progress_ += inc_;
|
||||
}
|
||||
|
||||
// close file properly
|
||||
if ( end_record() ) {
|
||||
Log::Info("MultiFileRecorder %d images encoded (%ld s), saved in %s.", frame_count_, timestamp_, filename_.c_str());
|
||||
if ( rec->end_record() ) {
|
||||
Log::Info("MultiFileRecorder %d images encoded (%ld s), saved in %s.", rec->frame_count_, rec->timestamp_, filename.c_str());
|
||||
}
|
||||
}
|
||||
else
|
||||
filename = std::string();
|
||||
|
||||
// finished
|
||||
progress_ = 1.f;
|
||||
rec->progress_ = 1.f;
|
||||
|
||||
return filename;
|
||||
}
|
||||
|
||||
// alternative https://gstreamer.freedesktop.org/documentation/application-development/advanced/pipeline-manipulation.html?gi-language=c#changing-elements-in-a-pipeline
|
||||
|
||||
@@ -4,6 +4,8 @@
|
||||
#include <list>
|
||||
#include <string>
|
||||
#include <atomic>
|
||||
#include <vector>
|
||||
#include <future>
|
||||
|
||||
#include <gst/gst.h>
|
||||
#include <gst/app/gstappsrc.h>
|
||||
@@ -12,47 +14,35 @@
|
||||
|
||||
class MultiFileRecorder
|
||||
{
|
||||
std::string filename_;
|
||||
VideoRecorder::Profile profile_;
|
||||
int fps_;
|
||||
int width_;
|
||||
int height_;
|
||||
int bpp_;
|
||||
|
||||
GstElement *pipeline_;
|
||||
GstAppSrc *src_;
|
||||
guint64 frame_count_;
|
||||
GstClockTime timestamp_;
|
||||
GstClockTime frame_duration_;
|
||||
std::atomic<bool> endofstream_;
|
||||
std::atomic<bool> accept_buffer_;
|
||||
|
||||
float progress_;
|
||||
std::list<std::string> files_;
|
||||
|
||||
public:
|
||||
MultiFileRecorder(const std::string &filename);
|
||||
MultiFileRecorder();
|
||||
virtual ~MultiFileRecorder();
|
||||
|
||||
void setFramerate (int fps);
|
||||
inline int framerate () const { return fps_; }
|
||||
|
||||
void setProfile (VideoRecorder::Profile profil);
|
||||
void setProfile (VideoRecorder::Profile p);
|
||||
inline VideoRecorder::Profile profile () const { return profile_; }
|
||||
|
||||
void assemble (std::list<std::string> list);
|
||||
|
||||
inline float progress () const { return progress_; }
|
||||
inline void setFiles (std::list<std::string> list) { files_ = list; }
|
||||
inline std::list<std::string> files () const { return files_; }
|
||||
|
||||
// process control
|
||||
void start ();
|
||||
void cancel ();
|
||||
bool finished ();
|
||||
|
||||
// result
|
||||
inline std::string filename () const { return filename_; }
|
||||
inline int width () const { return width_; }
|
||||
inline int height () const { return height_; }
|
||||
inline float progress () const { return progress_; }
|
||||
inline guint64 numFrames () const { return frame_count_; }
|
||||
|
||||
// std::thread(MultiFileRecorder::assembleImages, sourceSequenceFiles, "/home/bhbn/test.mov").detach();
|
||||
static void assembleImages(std::list<std::string> list, const std::string &filename);
|
||||
|
||||
protected:
|
||||
// gstreamer functions
|
||||
static std::string assemble (MultiFileRecorder *rec);
|
||||
bool start_record (const std::string &video_filename);
|
||||
bool add_image (const std::string &image_filename);
|
||||
bool end_record();
|
||||
@@ -60,6 +50,31 @@ protected:
|
||||
// gstreamer callbacks
|
||||
static void callback_need_data (GstAppSrc *, guint, gpointer user_data);
|
||||
static void callback_enough_data (GstAppSrc *, gpointer user_data);
|
||||
|
||||
private:
|
||||
|
||||
// video properties
|
||||
std::string filename_;
|
||||
VideoRecorder::Profile profile_;
|
||||
int fps_;
|
||||
int width_;
|
||||
int height_;
|
||||
int bpp_;
|
||||
|
||||
// encoder
|
||||
std::list<std::string> files_;
|
||||
GstElement *pipeline_;
|
||||
GstAppSrc *src_;
|
||||
guint64 frame_count_;
|
||||
GstClockTime timestamp_;
|
||||
GstClockTime frame_duration_;
|
||||
std::atomic<bool> cancel_;
|
||||
std::atomic<bool> endofstream_;
|
||||
std::atomic<bool> accept_buffer_;
|
||||
|
||||
// progress and result
|
||||
float progress_;
|
||||
std::vector< std::future<std::string> >promises_;
|
||||
};
|
||||
|
||||
#endif // MULTIFILERECORDER_H
|
||||
|
||||
@@ -51,14 +51,6 @@ MultiFileSequence::MultiFileSequence(const std::list<std::string> &list_files)
|
||||
{
|
||||
location = BaseToolkit::common_numbered_pattern(list_files, &min, &max);
|
||||
|
||||
// sanity check: the location pattern looks like a filename and seems consecutive numbered
|
||||
if ( SystemToolkit::extension_filename(location).empty() ||
|
||||
SystemToolkit::path_filename(location) != SystemToolkit::path_filename(list_files.front()) ||
|
||||
list_files.size() != (size_t) (max - min) + 1 ) {
|
||||
Log::Info("MultiFileSequence '%s' invalid.", location.c_str());
|
||||
location.clear();
|
||||
}
|
||||
|
||||
if ( !location.empty() ) {
|
||||
MediaInfo media = MediaPlayer::UriDiscoverer( GstToolkit::filename_to_uri( list_files.front() ) );
|
||||
if (media.valid && media.isimage) {
|
||||
@@ -70,6 +62,14 @@ MultiFileSequence::MultiFileSequence(const std::list<std::string> &list_files)
|
||||
else
|
||||
Log::Info("MultiFileSequence '%s' does not list images.", location.c_str());
|
||||
}
|
||||
|
||||
// sanity check: the location pattern looks like a filename and seems consecutive numbered
|
||||
if ( SystemToolkit::extension_filename(location).empty() ||
|
||||
SystemToolkit::path_filename(location) != SystemToolkit::path_filename(list_files.front()) ||
|
||||
list_files.size() != (size_t) (max - min) + 1 ) {
|
||||
Log::Info("MultiFileSequence '%s' invalid.", location.c_str());
|
||||
location.clear();
|
||||
}
|
||||
}
|
||||
|
||||
bool MultiFileSequence::valid() const
|
||||
|
||||
@@ -115,7 +115,7 @@ struct History
|
||||
History() {
|
||||
path = IMGUI_LABEL_RECENT_FILES;
|
||||
front_is_valid = false;
|
||||
load_at_start = false;
|
||||
load_at_start = true;
|
||||
save_on_exit = true;
|
||||
changed = false;
|
||||
}
|
||||
|
||||
@@ -87,6 +87,7 @@ using namespace std;
|
||||
#include "NetworkSource.h"
|
||||
#include "SrtReceiverSource.h"
|
||||
#include "StreamSource.h"
|
||||
#include "MultiFileSource.h"
|
||||
#include "PickingVisitor.h"
|
||||
#include "ImageFilter.h"
|
||||
#include "ImageShader.h"
|
||||
@@ -104,6 +105,7 @@ TextEditor _editor;
|
||||
#define LABEL_AUTO_MEDIA_PLAYER ICON_FA_CARET_SQUARE_RIGHT " Dynamic selection"
|
||||
#define LABEL_STORE_SELECTION " Store selection"
|
||||
#define LABEL_EDIT_FADING ICON_FA_RANDOM " Fade in & out"
|
||||
#define LABEL_VIDEO_SEQUENCE " Encode an image sequence"
|
||||
|
||||
// utility functions
|
||||
void ShowAboutGStreamer(bool* p_open);
|
||||
@@ -6219,7 +6221,7 @@ void Navigator::RenderNewPannel()
|
||||
// News Source selection pannel
|
||||
//
|
||||
static const char* origin_names[SOURCE_TYPES] = { ICON_FA_PHOTO_VIDEO " File",
|
||||
ICON_FA_SORT_NUMERIC_DOWN " Sequence",
|
||||
ICON_FA_IMAGES " Sequence",
|
||||
ICON_FA_PLUG " Connected",
|
||||
ICON_FA_COG " Generated",
|
||||
ICON_FA_SYNC " Internal"
|
||||
@@ -6237,7 +6239,7 @@ void Navigator::RenderNewPannel()
|
||||
static DialogToolkit::OpenFolderDialog folderimportdialog("Select Folder");
|
||||
|
||||
// clic button to load file
|
||||
if ( ImGui::Button( ICON_FA_FILE_EXPORT " Open File", ImVec2(ImGui::GetContentRegionAvail().x IMGUI_RIGHT_ALIGN, 0)) )
|
||||
if ( ImGui::Button( ICON_FA_FOLDER_OPEN " Open File", ImVec2(ImGui::GetContentRegionAvail().x IMGUI_RIGHT_ALIGN, 0)) )
|
||||
fileimportdialog.open();
|
||||
// Indication
|
||||
ImGui::SameLine();
|
||||
@@ -6424,62 +6426,126 @@ void Navigator::RenderNewPannel()
|
||||
// Folder Source creator
|
||||
else if (Settings::application.source.new_type == SOURCE_SEQUENCE){
|
||||
|
||||
bool update_new_source = false;
|
||||
static DialogToolkit::MultipleImagesDialog _selectImagesDialog("Select Images");
|
||||
//static bool _create_video_sequence = false;
|
||||
static DialogToolkit::MultipleImagesDialog _selectImagesDialog("Select multiple images");
|
||||
static MultiFileSequence _numbered_sequence;
|
||||
static MultiFileRecorder _video_recorder;
|
||||
static int _fps = 25;
|
||||
|
||||
// clic button to load file
|
||||
if ( ImGui::Button( ICON_FA_IMAGES " Open images", ImVec2(ImGui::GetContentRegionAvail().x IMGUI_RIGHT_ALIGN, 0)) ) {
|
||||
if ( ImGui::Button( ICON_FA_FOLDER_OPEN " Open images", ImVec2(ImGui::GetContentRegionAvail().x IMGUI_RIGHT_ALIGN, 0)) ) {
|
||||
sourceSequenceFiles.clear();
|
||||
_selectImagesDialog.open();
|
||||
}
|
||||
|
||||
// Indication
|
||||
ImGui::SameLine();
|
||||
ImGuiToolkit::HelpToolTip("Create a source from a sequence of numbered images.");
|
||||
ImGuiToolkit::HelpToolTip("Create a source displaying a sequence of images (PNG, JPG, TIF);\n"
|
||||
ICON_FA_CARET_RIGHT " files numbered consecutively\n"
|
||||
ICON_FA_CARET_RIGHT " create a video from many images\n");
|
||||
|
||||
// return from thread for folder openning
|
||||
if (_selectImagesDialog.closed()) {
|
||||
// clear
|
||||
new_source_preview_.setSource();
|
||||
// store list of files from dialog
|
||||
sourceSequenceFiles = _selectImagesDialog.images();
|
||||
if (sourceSequenceFiles.empty())
|
||||
Log::Notify("No file selected.");
|
||||
// ask to reload the preview
|
||||
update_new_source = true;
|
||||
|
||||
// set sequence
|
||||
_numbered_sequence = MultiFileSequence(sourceSequenceFiles);
|
||||
|
||||
// automatically create a MultiFile Source if possible
|
||||
if (_numbered_sequence.valid()) {
|
||||
std::string label = BaseToolkit::transliterate( BaseToolkit::common_pattern(sourceSequenceFiles) );
|
||||
new_source_preview_.setSource( Mixer::manager().createSourceMultifile(sourceSequenceFiles, _fps), label);
|
||||
}
|
||||
}
|
||||
|
||||
// multiple files selected
|
||||
if (sourceSequenceFiles.size() > 1) {
|
||||
|
||||
// set framerate
|
||||
static int _fps = 30;
|
||||
static bool _fps_changed = false;
|
||||
ImGui::Text("\nCreate image sequence:");
|
||||
|
||||
// show info sequence
|
||||
ImGuiTextBuffer info;
|
||||
ImGui::PushStyleColor(ImGuiCol_FrameBg, ImVec4(0.14f, 0.14f, 0.14f, 0.9f));
|
||||
info.appendf("%d %s", (int) sourceSequenceFiles.size(), _numbered_sequence.codec.c_str());
|
||||
ImGui::SetNextItemWidth(IMGUI_RIGHT_ALIGN);
|
||||
if ( ImGui::SliderInt("Framerate", &_fps, 1, 30, "%d fps") ) {
|
||||
_fps_changed = true;
|
||||
}
|
||||
// only call for new source after mouse release to avoid repeating call to re-open the stream
|
||||
else if (_fps_changed && ImGui::IsMouseReleased(ImGuiMouseButton_Left)){
|
||||
update_new_source = true;
|
||||
_fps_changed = false;
|
||||
ImGui::InputText("Images", (char *)info.c_str(), info.size(), ImGuiInputTextFlags_ReadOnly);
|
||||
info.clear();
|
||||
if (_numbered_sequence.location.empty())
|
||||
info.append("Not consecutively numbered");
|
||||
else
|
||||
info.appendf("%s", SystemToolkit::base_filename(_numbered_sequence.location).c_str());
|
||||
ImGui::SetNextItemWidth(IMGUI_RIGHT_ALIGN);
|
||||
ImGui::InputText("Filenames", (char *)info.c_str(), info.size(), ImGuiInputTextFlags_ReadOnly);
|
||||
ImGui::PopStyleColor(1);
|
||||
|
||||
// offer to open file browser at location
|
||||
std::string path = SystemToolkit::path_filename(sourceSequenceFiles.front());
|
||||
std::string label = BaseToolkit::truncated(path, 25);
|
||||
label = BaseToolkit::transliterate(label);
|
||||
ImGuiToolkit::ButtonOpenUrl( label.c_str(), path.c_str(), ImVec2(IMGUI_RIGHT_ALIGN, 0) );
|
||||
ImGui::SameLine(0, IMGUI_SAME_LINE);
|
||||
ImGui::Text("Folder");
|
||||
|
||||
// set framerate
|
||||
ImGui::SetNextItemWidth(IMGUI_RIGHT_ALIGN);
|
||||
ImGui::SliderInt("Framerate", &_fps, 1, 30, "%d fps");
|
||||
if (ImGui::IsItemDeactivatedAfterEdit()){
|
||||
if (new_source_preview_.filled()) {
|
||||
std::string label = BaseToolkit::transliterate( BaseToolkit::common_pattern(sourceSequenceFiles) );
|
||||
new_source_preview_.setSource( Mixer::manager().createSourceMultifile(sourceSequenceFiles, _fps), label);
|
||||
}
|
||||
}
|
||||
|
||||
if (update_new_source) {
|
||||
std::string label = BaseToolkit::transliterate( BaseToolkit::common_pattern(sourceSequenceFiles) );
|
||||
new_source_preview_.setSource( Mixer::manager().createSourceMultifile(sourceSequenceFiles, _fps), label);
|
||||
ImGui::Spacing();
|
||||
|
||||
// Offer to create video from sequence
|
||||
if ( ImGui::Button( ICON_FA_FILM " Make a video", ImVec2(ImGui::GetContentRegionAvail().x, 0)) ) {
|
||||
// start video recorder
|
||||
_video_recorder.setFiles( sourceSequenceFiles );
|
||||
_video_recorder.setFramerate( _fps );
|
||||
_video_recorder.setProfile( (VideoRecorder::Profile) Settings::application.record.profile );
|
||||
_video_recorder.start();
|
||||
// dialog
|
||||
ImGui::OpenPopup(LABEL_VIDEO_SEQUENCE);
|
||||
}
|
||||
|
||||
// video recorder finished: inform and open pannel to import video source from recent recordings
|
||||
if ( _video_recorder.finished() ) {
|
||||
|
||||
Log::Notify("Image sequence saved to %s.", _video_recorder.filename().c_str());
|
||||
|
||||
if (Settings::application.recentRecordings.load_at_start)
|
||||
UserInterface::manager().navigator.setNewMedia(Navigator::MEDIA_RECORDING, _video_recorder.filename());
|
||||
|
||||
}
|
||||
else if (ImGui::BeginPopupModal(LABEL_VIDEO_SEQUENCE, NULL, ImGuiWindowFlags_NoResize))
|
||||
{
|
||||
ImGui::Spacing();
|
||||
ImGui::Text("Please wait while the video is being encoded...");
|
||||
ImGui::Spacing();
|
||||
ImGui::ProgressBar(_video_recorder.progress());
|
||||
|
||||
if (ImGui::Button("Cancel"))
|
||||
_video_recorder.cancel();
|
||||
|
||||
ImGui::EndPopup();
|
||||
}
|
||||
|
||||
}
|
||||
// single file selected
|
||||
else if (sourceSequenceFiles.size() > 0) {
|
||||
|
||||
ImGui::Text("Single file selected");
|
||||
|
||||
if (update_new_source) {
|
||||
std::string label = BaseToolkit::transliterate( sourceSequenceFiles.front() );
|
||||
new_source_preview_.setSource( Mixer::manager().createSourceFile(sourceSequenceFiles.front()), label);
|
||||
}
|
||||
|
||||
// open image file as source
|
||||
std::string label = BaseToolkit::transliterate( sourceSequenceFiles.front() );
|
||||
new_source_preview_.setSource( Mixer::manager().createSourceFile(sourceSequenceFiles.front()), label);
|
||||
// done with sequence
|
||||
sourceSequenceFiles.clear();
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
// Internal Source creator
|
||||
else if (Settings::application.source.new_type == SOURCE_INTERNAL){
|
||||
|
||||
Reference in New Issue
Block a user