Update New Source panel for Media

Added list of recent files, recent recordings, and folders list of media files. All saved in settings. Connect list of recent recordings with recorder.
This commit is contained in:
Bruno Herbelin
2021-12-05 18:41:58 +01:00
parent 923d84f378
commit ffe05368e8
7 changed files with 335 additions and 75 deletions

View File

@@ -462,6 +462,8 @@ void VideoRecorder::terminate()
Log::Info("Video Recording : try a lower resolution / a lower framerate / a larger buffer size / a faster codec.");
}
// remember and inform
Settings::application.recentRecordings.push(filename_);
Log::Notify("Video Recording %s is ready.", filename_.c_str());
}

View File

@@ -12,11 +12,12 @@
class PNGRecorder : public FrameGrabber
{
std::string filename_;
std::string filename_;
public:
PNGRecorder();
std::string filename() const { return filename_; }
protected:
@@ -28,7 +29,7 @@ protected:
class VideoRecorder : public FrameGrabber
{
std::string filename_;
std::string filename_;
std::string init(GstCaps *caps) override;
void terminate() override;
@@ -58,7 +59,7 @@ public:
VideoRecorder();
std::string info() const override;
std::string filename() const { return filename_; }
};

View File

@@ -238,6 +238,29 @@ void Settings::Save(uint64_t runtime)
}
recent->InsertEndChild(recentmedia);
// recent import folders
XMLElement *recentimportfolder = xmlDoc.NewElement( "ImportFolder" );
recentmedia->SetAttribute("path", application.recentImportFolders.path.c_str());
for(auto it = application.recentImportFolders.filenames.cbegin();
it != application.recentImportFolders.filenames.cend(); ++it) {
XMLElement *pathNode = xmlDoc.NewElement("path");
XMLText *text = xmlDoc.NewText( (*it).c_str() );
pathNode->InsertEndChild( text );
recentimportfolder->InsertFirstChild(pathNode);
}
recent->InsertEndChild(recentimportfolder);
// recent recordings
XMLElement *recentrecord = xmlDoc.NewElement( "Record" );
for(auto it = application.recentRecordings.filenames.cbegin();
it != application.recentRecordings.filenames.cend(); ++it) {
XMLElement *pathNode = xmlDoc.NewElement("path");
XMLText *text = xmlDoc.NewText( (*it).c_str() );
pathNode->InsertEndChild( text );
recentrecord->InsertFirstChild(pathNode);
}
recent->InsertEndChild(recentrecord);
// recent dialog path
XMLElement *recentdialogpath = xmlDoc.NewElement( "Dialog" );
for(auto it = application.dialogRecentFolder.cbegin();
@@ -517,6 +540,37 @@ void Settings::Load()
application.recentImport.push( std::string (p) );
}
}
// recent import folders
XMLElement * pImportFolder = pElement->FirstChildElement("ImportFolder");
if (pImportFolder)
{
const char *path_ = pImportFolder->Attribute("path");
if (path_)
application.recentImportFolders.path = std::string(path_);
application.recentImportFolders.filenames.clear();
XMLElement* path = pImportFolder->FirstChildElement("path");
for( ; path ; path = path->NextSiblingElement())
{
const char *p = path->GetText();
if (p)
application.recentImportFolders.push( std::string (p) );
}
}
// recent recordings
XMLElement * pRecord = pElement->FirstChildElement("Record");
if (pRecord)
{
application.recentRecordings.filenames.clear();
XMLElement* path = pRecord->FirstChildElement("path");
for( ; path ; path = path->NextSiblingElement())
{
const char *p = path->GetText();
if (p)
application.recentRecordings.push( std::string (p) );
}
}
// recent dialog path
XMLElement * pDialog = pElement->FirstChildElement("Dialog");
if (pDialog)
@@ -582,6 +636,37 @@ void Settings::History::validate()
}
}
// TODO unified history function saving
//void load_history(Settings::History &h, XMLElement *root)
//{
// XMLElement * pElement = root->FirstChildElement("Import");
// if (pElement)
// {
// h.filenames.clear();
// XMLElement* path = pElement->FirstChildElement("path");
// for( ; path ; path = path->NextSiblingElement())
// {
// const char *p = path->GetText();
// if (p)
// h.push( std::string (p) );
// }
// }
//}
//XMLElement *save_history(Settings::History &h, XMLDocument &xmlDoc)
//{
// XMLElement *pElement = xmlDoc.NewElement( "Import" );
// for(auto it = h.filenames.cbegin();
// it != h.filenames.cend(); ++it) {
// XMLElement *fileNode = xmlDoc.NewElement("path");
// XMLText *text = xmlDoc.NewText( (*it).c_str() );
// fileNode->InsertEndChild( text );
// pElement->InsertFirstChild(fileNode);
// }
// return pElement;
//}
void Settings::Lock()
{

View File

@@ -243,6 +243,8 @@ struct Application
History recentSessions;
History recentFolders;
History recentImport;
History recentImportFolders;
History recentRecordings;
std::map< std::string, std::string > dialogRecentFolder;
// Metronome & stopwatch

View File

@@ -111,8 +111,8 @@ std::string readable_date_time_string(std::string date){
// globals
const std::chrono::milliseconds timeout = std::chrono::milliseconds(4);
std::vector< std::future<FrameGrabber *> > _video_recorders;
FrameGrabber *delayTrigger(FrameGrabber *g, std::chrono::milliseconds delay) {
std::vector< std::future<VideoRecorder *> > _video_recorders;
VideoRecorder *delayTrigger(VideoRecorder *g, std::chrono::milliseconds delay) {
std::this_thread::sleep_for (delay);
return g;
}
@@ -324,17 +324,20 @@ void UserInterface::handleKeyboard()
FrameGrabbing::manager().add(new PNGRecorder);
}
else {
// toggle recording
// toggle recording stop / start
if (video_recorder_) {
// allow 'save & continue' for Ctrl+Alt+R if no timeout for recording
// 'save & continue' for Ctrl+Alt+R if no timeout for recording
if (alt_modifier_active && Settings::application.record.timeout == RECORD_MAX_TIMEOUT) {
VideoRecorder *rec = new VideoRecorder;
FrameGrabbing::manager().chain(video_recorder_, rec);
video_recorder_ = rec;
}
// normal case: Ctrl+R stop recording
else
else {
// prepare for next open new source panel to show the recording
navigator.setNewMedia(Navigator::MEDIA_RECORDING, video_recorder_->filename());
video_recorder_->stop();
}
}
else {
_video_recorders.emplace_back( std::async(std::launch::async, delayTrigger, new VideoRecorder,
@@ -795,7 +798,7 @@ void UserInterface::Render()
}
}
// verify the video recorder is valid (change to nullptr if invalid)
FrameGrabbing::manager().verify(&video_recorder_);
FrameGrabbing::manager().verify( (FrameGrabber**) &video_recorder_);
if (video_recorder_ // if there is an ongoing recorder
&& Settings::application.record.timeout < RECORD_MAX_TIMEOUT // and if the timeout is valid
&& video_recorder_->duration() > Settings::application.record.timeout ) // and the timeout is reached
@@ -1340,12 +1343,18 @@ void UserInterface::RenderPreview()
ImGui::PushStyleColor(ImGuiCol_Text, ImVec4(IMGUI_COLOR_RECORD, 0.8f));
if ( ImGui::MenuItem( ICON_FA_SQUARE " Stop Record", CTRL_MOD "R") ) {
video_recorder_->stop();
// prepare for next open new source panel to show the recording
navigator.setNewMedia(Navigator::MEDIA_RECORDING, video_recorder_->filename());
}
// offer the 'save & continue' recording for undefined duration
if (Settings::application.record.timeout == RECORD_MAX_TIMEOUT) {
if ( ImGui::MenuItem( ICON_FA_ARROW_ALT_CIRCLE_DOWN " Save & continue", CTRL_MOD "Alt+R") ) {
// prepare for next open new source panel to show the recording
navigator.setNewMedia(Navigator::MEDIA_RECORDING, video_recorder_->filename());
// create a new recorder chainned to the current one
VideoRecorder *rec = new VideoRecorder;
FrameGrabbing::manager().chain(video_recorder_, rec);
// swap recorder
video_recorder_ = rec;
}
}
@@ -3700,6 +3709,9 @@ Navigator::Navigator()
pannel_visible_ = false;
view_pannel_visible = false;
clearButtonSelection();
new_media_mode = MEDIA_RECENT;
new_media_mode_changed = true;
}
void Navigator::applyButtonSelection(int index)
@@ -3724,7 +3736,8 @@ void Navigator::clearButtonSelection()
// clear new source pannel
new_source_preview_.setSource();
pattern_type = -1;
_selectedFiles.clear();
sourceSequenceFiles.clear();
setNewMedia(new_media_mode);
}
void Navigator::showPannelSource(int index)
@@ -4037,6 +4050,43 @@ void Navigator::RenderSourcePannel(Source *s)
}
}
void Navigator::setNewMedia(MediaCreateMode mode, std::string path)
{
// switch new source to Media pannel
Settings::application.source.new_type = SOURCE_FILE;
// change mode
new_media_mode = mode;
new_media_mode_changed = true;
// mode dependent actions
switch (new_media_mode) {
case MEDIA_RECENT:
// set filename
sourceMediaFileCurrent = path;
// set combo to 'recent files'
Settings::application.recentImportFolders.path = IMGUI_LABEL_RECENT_FILES;
break;
case MEDIA_RECORDING:
// set filename
sourceMediaFileCurrent = path;
// set combo to 'recent recordings'
Settings::application.recentImportFolders.path = IMGUI_LABEL_RECENT_RECORDS;
break;
default:
case MEDIA_FOLDER:
// reset filename
sourceMediaFileCurrent.clear();
// set combo: a path was selected
if (!path.empty())
Settings::application.recentImportFolders.path.assign(path);
break;
}
// clear preview
new_source_preview_.setSource();
}
void Navigator::RenderNewPannel()
{
// Next window is a side pannel
@@ -4058,7 +4108,7 @@ void Navigator::RenderNewPannel()
//
// News Source selection pannel
//
static const char* origin_names[5] = { ICON_FA_PHOTO_VIDEO " File",
static const char* origin_names[SOURCE_TYPES] = { ICON_FA_PHOTO_VIDEO " File",
ICON_FA_SORT_NUMERIC_DOWN " Sequence",
ICON_FA_PLUG " Connected",
ICON_FA_COG " Generated",
@@ -4071,66 +4121,157 @@ void Navigator::RenderNewPannel()
ImGui::SetCursorPosY(2.f * width_);
// File Source creation
if (Settings::application.source.new_type == 0) {
if (Settings::application.source.new_type == SOURCE_FILE) {
static DialogToolkit::OpenMediaDialog fileimportdialog("Open Media");
static DialogToolkit::OpenFolderDialog folderimportdialog("Select Folder");
// clic button to load file
if ( ImGui::Button( ICON_FA_FILE_EXPORT " Open media", ImVec2(ImGui::GetContentRegionAvail().x IMGUI_RIGHT_ALIGN, 0)) )
if ( ImGui::Button( ICON_FA_FILE_EXPORT " Open File", ImVec2(ImGui::GetContentRegionAvail().x IMGUI_RIGHT_ALIGN, 0)) )
fileimportdialog.open();
// Indication
ImGui::SameLine();
ImGuiToolkit::HelpMarker("Create a source from a file:\n"
ICON_FA_CARET_RIGHT " Video (*.mpg, *mov, *.avi, etc.)\n"
ICON_FA_CARET_RIGHT " Image (*.jpg, *.png, etc.)\n"
ICON_FA_CARET_RIGHT " Vector graphics (*.svg)\n"
ICON_FA_CARET_RIGHT " vimix session (*.mix)\n\n"
"(Equivalent to dropping the file in the workspace)");
ICON_FA_CARET_RIGHT " Video (*.mpg, *mov, *.avi, etc.)\n"
ICON_FA_CARET_RIGHT " Image (*.jpg, *.png, etc.)\n"
ICON_FA_CARET_RIGHT " Vector graphics (*.svg)\n"
ICON_FA_CARET_RIGHT " vimix session (*.mix)\n"
"\nNB: Equivalent to dropping the file in the workspace");
// get media file if dialog finished
if (fileimportdialog.closed()){
// get the filename from this file dialog
std::string open_filename = fileimportdialog.path();
// create a source with this file
if (open_filename.empty()) {
new_source_preview_.setSource();
Log::Notify("No file selected.");
} else {
std::string label = BaseToolkit::transliterate( open_filename );
label = BaseToolkit::trunc_string(label, 35);
new_source_preview_.setSource( Mixer::manager().createSourceFile(open_filename), label);
std::string importpath = fileimportdialog.path();
// switch to recent files
setNewMedia(MEDIA_RECENT, importpath);
// open file
if (!importpath.empty()) {
std::string label = BaseToolkit::transliterate( sourceMediaFileCurrent );
new_source_preview_.setSource( Mixer::manager().createSourceFile(sourceMediaFileCurrent), label);
}
}
// combo of recent media filenames
// combo to offer lists
ImGui::SetNextItemWidth(IMGUI_RIGHT_ALIGN);
if (ImGui::BeginCombo("##RecentImport", IMGUI_LABEL_RECENT_FILES))
if (ImGui::BeginCombo("##SelectionNewMedia", BaseToolkit::trunc_string(Settings::application.recentImportFolders.path, 25).c_str() ))
{
std::list<std::string> recent = Settings::application.recentImport.filenames;
for (std::list<std::string>::iterator path = recent.begin(); path != recent.end(); ++path )
{
std::string recentpath(*path);
if ( SystemToolkit::file_exists(recentpath)) {
std::string label = BaseToolkit::transliterate( recentpath );
label = BaseToolkit::trunc_string(label, 35);
if (ImGui::Selectable( label.c_str() )) {
new_source_preview_.setSource( Mixer::manager().createSourceFile(recentpath.c_str()), label);
}
// Mode MEDIA_RECENT : recent files
if (ImGui::Selectable( ICON_FA_LIST_OL IMGUI_LABEL_RECENT_FILES) ) {
setNewMedia(MEDIA_RECENT);
}
// Mode MEDIA_RECORDING : recent recordings
if (ImGui::Selectable( ICON_FA_LIST_UL IMGUI_LABEL_RECENT_RECORDS) ) {
setNewMedia(MEDIA_RECORDING);
}
// Mode MEDIA_FOLDER : known folders
for(auto foldername = Settings::application.recentImportFolders.filenames.begin();
foldername != Settings::application.recentImportFolders.filenames.end(); foldername++) {
std::string f = std::string(ICON_FA_FOLDER) + " " + BaseToolkit::trunc_string( *foldername, 40);
if (ImGui::Selectable( f.c_str() )) {
setNewMedia(MEDIA_FOLDER, *foldername);
}
}
// Add a folder for MEDIA_FOLDER
if (ImGui::Selectable( ICON_FA_FOLDER_PLUS " Add Folder") ) {
folderimportdialog.open();
}
ImGui::EndCombo();
}
// return from thread for folder openning
if (folderimportdialog.closed() && !folderimportdialog.path().empty()) {
Settings::application.recentImportFolders.push(folderimportdialog.path());
setNewMedia(MEDIA_FOLDER, folderimportdialog.path());
}
// icons to clear lists or discarc folder
ImVec2 pos_top = ImGui::GetCursorPos();
ImGui::SameLine();
ImGui::PushStyleVar(ImGuiStyleVar_Alpha, 0.7);
if ( new_media_mode == MEDIA_FOLDER ) {
if (ImGuiToolkit::IconButton( ICON_FA_FOLDER_MINUS, "Discard folder")) {
Settings::application.recentImportFolders.filenames.remove(Settings::application.recentImportFolders.path);
if (Settings::application.recentImportFolders.filenames.empty())
// revert mode RECENT
setNewMedia(MEDIA_RECENT);
else
setNewMedia(MEDIA_FOLDER, Settings::application.recentImportFolders.filenames.front());
}
}
else if ( new_media_mode == MEDIA_RECORDING ) {
if (ImGuiToolkit::IconButton( ICON_FA_BACKSPACE, "Clear list")) {
Settings::application.recentRecordings.filenames.clear();
Settings::application.recentRecordings.front_is_valid = false;
setNewMedia(MEDIA_RECORDING);
}
}
else if ( new_media_mode == MEDIA_RECENT ) {
if (ImGuiToolkit::IconButton( ICON_FA_BACKSPACE, "Clear list")) {
Settings::application.recentImport.filenames.clear();
Settings::application.recentImport.front_is_valid = false;
setNewMedia(MEDIA_RECENT);
}
}
ImGui::PopStyleVar();
ImGui::SetCursorPos(pos_top);
// change session list if changed
if (new_media_mode_changed || Settings::application.recentImport.changed || Settings::application.recentRecordings.changed) {
// MODE RECENT
if ( new_media_mode == MEDIA_RECENT) {
// show list of recent imports
Settings::application.recentImport.validate();
sourceMediaFiles = Settings::application.recentImport.filenames;
Settings::application.recentImport.changed = false;
}
// MODE RECORDINGS
else if ( new_media_mode == MEDIA_RECORDING) {
// show list of recent records
Settings::application.recentRecordings.validate();
sourceMediaFiles = Settings::application.recentRecordings.filenames;
Settings::application.recentRecordings.changed = false;
}
// MODE LIST FOLDER
else if ( new_media_mode == MEDIA_FOLDER) {
// show list of media files in folder
sourceMediaFiles = SystemToolkit::list_directory( Settings::application.recentImportFolders.path, { MEDIA_FILES_PATTERN });
}
// indicate the list changed (do not change at every frame)
new_media_mode_changed = false;
}
// different labels for each mode
static const char *listboxname[3] = { "##NewSourceMediaRecent", "##NewSourceMediaRecording", "##NewSourceMediafolder"};
// display the import-list and detect if one was selected
ImGui::SetNextItemWidth(IMGUI_RIGHT_ALIGN);
if (ImGui::ListBoxHeader(listboxname[new_media_mode], sourceMediaFiles.size(), CLAMP(sourceMediaFiles.size(), 4, 6)) ) {
// loop over list of files
for(auto it = sourceMediaFiles.begin(); it != sourceMediaFiles.end(); ++it) {
// build displayed file name
std::string filename = BaseToolkit::transliterate(*it);
std::string label = BaseToolkit::trunc_string(SystemToolkit::filename(filename), 25);
// add selectable item to ListBox; open if clickec
if (ImGui::Selectable( label.c_str(), sourceMediaFileCurrent.compare(*it) == 0 )) {
// set new source preview
new_source_preview_.setSource( Mixer::manager().createSourceFile(*it), filename);
// remember current list item
sourceMediaFileCurrent = *it;
}
}
ImGui::ListBoxFooter();
}
}
// Folder Source creator
else if (Settings::application.source.new_type == 1){
else if (Settings::application.source.new_type == SOURCE_SEQUENCE){
bool update_new_source = false;
static DialogToolkit::MultipleImagesDialog _selectImagesDialog("Select Images");
// clic button to load file
if ( ImGui::Button( ICON_FA_IMAGES " Open images", ImVec2(ImGui::GetContentRegionAvail().x IMGUI_RIGHT_ALIGN, 0)) ) {
_selectedFiles.clear();
sourceSequenceFiles.clear();
_selectImagesDialog.open();
}
@@ -4140,15 +4281,15 @@ void Navigator::RenderNewPannel()
// return from thread for folder openning
if (_selectImagesDialog.closed()) {
_selectedFiles = _selectImagesDialog.images();
if (_selectedFiles.empty())
sourceSequenceFiles = _selectImagesDialog.images();
if (sourceSequenceFiles.empty())
Log::Notify("No file selected.");
// ask to reload the preview
update_new_source = true;
}
// multiple files selected
if (_selectedFiles.size() > 1) {
if (sourceSequenceFiles.size() > 1) {
// set framerate
static int _fps = 30;
@@ -4164,27 +4305,27 @@ void Navigator::RenderNewPannel()
}
if (update_new_source) {
std::string label = BaseToolkit::transliterate( BaseToolkit::common_pattern(_selectedFiles) );
std::string label = BaseToolkit::transliterate( BaseToolkit::common_pattern(sourceSequenceFiles) );
label = BaseToolkit::trunc_string(label, 35);
new_source_preview_.setSource( Mixer::manager().createSourceMultifile(_selectedFiles, _fps), label);
new_source_preview_.setSource( Mixer::manager().createSourceMultifile(sourceSequenceFiles, _fps), label);
}
}
// single file selected
else if (_selectedFiles.size() > 0) {
else if (sourceSequenceFiles.size() > 0) {
ImGui::Text("Single file selected");
if (update_new_source) {
std::string label = BaseToolkit::transliterate( _selectedFiles.front() );
std::string label = BaseToolkit::transliterate( sourceSequenceFiles.front() );
label = BaseToolkit::trunc_string(label, 35);
new_source_preview_.setSource( Mixer::manager().createSourceFile(_selectedFiles.front()), label);
new_source_preview_.setSource( Mixer::manager().createSourceFile(sourceSequenceFiles.front()), label);
}
}
}
// Internal Source creator
else if (Settings::application.source.new_type == 4){
else if (Settings::application.source.new_type == SOURCE_INTERNAL){
// fill new_source_preview with a new source
ImGui::SetNextItemWidth(IMGUI_RIGHT_ALIGN);
@@ -4213,7 +4354,7 @@ void Navigator::RenderNewPannel()
ICON_FA_CARET_RIGHT " Clone other sources");
}
// Generated Source creator
else if (Settings::application.source.new_type == 3){
else if (Settings::application.source.new_type == SOURCE_GENERATED){
bool update_new_source = false;
@@ -4255,7 +4396,7 @@ void Navigator::RenderNewPannel()
}
}
// External source creator
else if (Settings::application.source.new_type == 2){
else if (Settings::application.source.new_type == SOURCE_CONNECTED){
ImGui::SetNextItemWidth(IMGUI_RIGHT_ALIGN);
if (ImGui::BeginCombo("##External", "Select device"))
@@ -4290,7 +4431,7 @@ void Navigator::RenderNewPannel()
// if a new source was added
if (new_source_preview_.filled()) {
// show preview
new_source_preview_.Render(ImGui::GetContentRegionAvail().x IMGUI_RIGHT_ALIGN, Settings::application.source.new_type != 2);
new_source_preview_.Render(ImGui::GetContentRegionAvail().x IMGUI_RIGHT_ALIGN);
// ask to import the source in the mixer
ImGui::NewLine();
if (new_source_preview_.ready() && ImGui::Button( ICON_FA_CHECK " Create", ImVec2(pannel_width_ - padding_width_, 0)) ) {
@@ -4340,13 +4481,13 @@ void Navigator::RenderMainPannelVimix()
ImGui::SetNextItemWidth(IMGUI_RIGHT_ALIGN);
if (ImGui::BeginCombo("##SelectionSession", BaseToolkit::trunc_string(Settings::application.recentFolders.path, 25).c_str() )) {
// Option 0 : recent files
if (ImGui::Selectable( ICON_FA_CLOCK IMGUI_LABEL_RECENT_FILES) ) {
// Mode 0 : recent files
if (ImGui::Selectable( ICON_FA_LIST_OL IMGUI_LABEL_RECENT_FILES) ) {
Settings::application.recentFolders.path = IMGUI_LABEL_RECENT_FILES;
selection_session_mode = 0;
selection_session_mode_changed = true;
}
// Options 1 : known folders
// Mode 1 : known folders
for(auto foldername = Settings::application.recentFolders.filenames.begin();
foldername != Settings::application.recentFolders.filenames.end(); foldername++) {
std::string f = std::string(ICON_FA_FOLDER) + " " + BaseToolkit::trunc_string( *foldername, 40);
@@ -4358,7 +4499,7 @@ void Navigator::RenderMainPannelVimix()
selection_session_mode_changed = true;
}
}
// Option 2 : add a folder
// Add a folder
if (ImGui::Selectable( ICON_FA_FOLDER_PLUS " Add Folder") )
customFolder.open();
ImGui::EndCombo();
@@ -4390,7 +4531,7 @@ void Navigator::RenderMainPannelVimix()
}
}
else {
if (ImGuiToolkit::IconButton( ICON_FA_BACKSPACE, "Clear history")) {
if (ImGuiToolkit::IconButton( ICON_FA_BACKSPACE, "Clear list")) {
Settings::application.recentSessions.filenames.clear();
Settings::application.recentSessions.front_is_valid = false;
// reload the list next time
@@ -4690,7 +4831,7 @@ void Navigator::RenderMainPannelVimix()
ImGui::SameLine();
ImGui::PushStyleVar(ImGuiStyleVar_Alpha, 0.7);
if (ImGuiToolkit::IconButton( ICON_FA_BACKSPACE, "Clear undo")) {
if (ImGuiToolkit::IconButton( ICON_FA_BACKSPACE, "Clear history")) {
Action::manager().init();
}
ImGui::PopStyleVar();
@@ -5226,7 +5367,7 @@ void SourcePreview::setSource(Source *s, const string &label)
delete source_;
source_ = s;
label_ = label;
label_ = BaseToolkit::trunc_string(label, 35);
reset_ = true;
}
@@ -5237,7 +5378,7 @@ Source * SourcePreview::getSource()
return s;
}
void SourcePreview::Render(float width, bool controlbutton)
void SourcePreview::Render(float width)
{
if(source_) {
// cancel if failed
@@ -5270,15 +5411,21 @@ void SourcePreview::Render(float width, bool controlbutton)
FrameBuffer *frame = source_->frame();
ImVec2 preview_size(width, width / frame->aspectRatio());
ImGui::Image((void*)(uintptr_t) frame->texture(), preview_size);
if (controlbutton && source_->ready()) {
ImVec2 pos = ImGui::GetCursorPos();
ImGui::SameLine();
bool active = source_->active();
if (ImGuiToolkit::IconToggle(12,7,1,8, &active))
source_->setActive(active);
ImGui::SetCursorPos(pos);
// if the source is playable and once its ready
if (source_->playable() && source_->ready()) {
// activate the source on mouse over
bool activate = ImGui::IsItemHovered();
if (source_->active() != activate)
source_->setActive(activate);
// show icon '>' to indicate if we can activate it
if (!activate) {
ImVec2 pos = ImGui::GetCursorPos();
ImGui::SetCursorPos(pos + preview_size * ImVec2(0.5f, -0.6f));
ImGuiToolkit::Icon(12,7);
ImGui::SetCursorPos(pos);
}
}
// information text
ImGuiToolkit::Icon(source_->icon().x, source_->icon().y);
ImGui::SameLine(0, 10);
ImGui::Text("%s", label_.c_str());

View File

@@ -20,6 +20,7 @@ struct ImVec2;
class MediaPlayer;
class FrameBufferImage;
class FrameGrabber;
class VideoRecorder;
class SourcePreview {
@@ -33,7 +34,7 @@ public:
void setSource(Source *s = nullptr, const std::string &label = "");
Source *getSource();
void Render(float width, bool controlbutton = false);
void Render(float width);
bool ready() const;
inline bool filled() const { return source_ != nullptr; }
};
@@ -67,7 +68,6 @@ class Navigator
bool view_pannel_visible;
bool selected_button[NAV_COUNT];
int pattern_type;
std::list<std::string> _selectedFiles;
void clearButtonSelection();
void applyButtonSelection(int index);
@@ -80,8 +80,6 @@ class Navigator
void RenderNewPannel();
void RenderViewPannel(ImVec2 draw_pos, ImVec2 draw_size);
SourcePreview new_source_preview_;
public:
Navigator();
@@ -92,7 +90,31 @@ public:
void togglePannelNew();
void showConfig();
typedef enum {
MEDIA_RECENT = 0,
MEDIA_RECORDING,
MEDIA_FOLDER
} MediaCreateMode;
void setNewMedia(MediaCreateMode mode, std::string path = std::string());
void Render();
private:
// for new source panel
typedef enum {
SOURCE_FILE = 0,
SOURCE_SEQUENCE,
SOURCE_CONNECTED,
SOURCE_GENERATED,
SOURCE_INTERNAL,
SOURCE_TYPES
} NewSourceType;
SourcePreview new_source_preview_;
std::list<std::string> sourceSequenceFiles;
std::list<std::string> sourceMediaFiles;
std::string sourceMediaFileCurrent;
MediaCreateMode new_media_mode;
bool new_media_mode_changed;
};
class ToolBox
@@ -199,7 +221,7 @@ class UserInterface
unsigned int screenshot_step;
// frame grabbers
FrameGrabber *video_recorder_;
VideoRecorder *video_recorder_;
#if defined(LINUX)
FrameGrabber *webcam_emulator_;

View File

@@ -72,6 +72,7 @@
#define IMGUI_TITLE_PREVIEW ICON_FA_DESKTOP " Ouput"
#define IMGUI_TITLE_DELETE ICON_FA_BROOM " Delete?"
#define IMGUI_LABEL_RECENT_FILES " Recent files"
#define IMGUI_LABEL_RECENT_RECORDS " Recent recordings"
#define IMGUI_RIGHT_ALIGN -3.5f * ImGui::GetTextLineHeightWithSpacing()
#define IMGUI_TOP_ALIGN 10
#define IMGUI_COLOR_OVERLAY IM_COL32(5, 5, 5, 150)