mirror of
https://github.com/brunoherbelin/vimix.git
synced 2025-12-11 18:34:58 +01:00
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:
@@ -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());
|
||||
}
|
||||
|
||||
|
||||
@@ -17,6 +17,7 @@ class PNGRecorder : public FrameGrabber
|
||||
public:
|
||||
|
||||
PNGRecorder();
|
||||
std::string filename() const { return filename_; }
|
||||
|
||||
protected:
|
||||
|
||||
@@ -58,7 +59,7 @@ public:
|
||||
|
||||
VideoRecorder();
|
||||
std::string info() const override;
|
||||
|
||||
std::string filename() const { return filename_; }
|
||||
};
|
||||
|
||||
|
||||
|
||||
85
Settings.cpp
85
Settings.cpp
@@ -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()
|
||||
{
|
||||
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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,18 +324,21 @@ 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,
|
||||
std::chrono::seconds(Settings::application.record.delay)) );
|
||||
@@ -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 " 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()) {
|
||||
// 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::SameLine();
|
||||
bool active = source_->active();
|
||||
if (ImGuiToolkit::IconToggle(12,7,1,8, &active))
|
||||
source_->setActive(active);
|
||||
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());
|
||||
|
||||
@@ -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_;
|
||||
|
||||
@@ -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)
|
||||
|
||||
Reference in New Issue
Block a user