mirror of
https://github.com/brunoherbelin/vimix.git
synced 2025-12-11 18:34:58 +01:00
Implementation of Main pannel selection of sessions from recent history
AND from folder listing. Re-implementation in C++17 style of SystemToolkit.
This commit is contained in:
@@ -227,7 +227,7 @@ Source * Mixer::createSourceFile(std::string path)
|
|||||||
|
|
||||||
// test type of file by extension
|
// test type of file by extension
|
||||||
std::string ext = SystemToolkit::extension_filename(path);
|
std::string ext = SystemToolkit::extension_filename(path);
|
||||||
if ( ext == "mix" )
|
if ( ext == ".mix" )
|
||||||
{
|
{
|
||||||
// create a session source
|
// create a session source
|
||||||
SessionSource *ss = new SessionSource();
|
SessionSource *ss = new SessionSource();
|
||||||
|
|||||||
29
Settings.cpp
29
Settings.cpp
@@ -56,6 +56,7 @@ void Settings::Save()
|
|||||||
applicationNode->SetAttribute("scale", application.scale);
|
applicationNode->SetAttribute("scale", application.scale);
|
||||||
applicationNode->SetAttribute("accent_color", application.accent_color);
|
applicationNode->SetAttribute("accent_color", application.accent_color);
|
||||||
applicationNode->SetAttribute("pannel_stick", application.pannel_stick);
|
applicationNode->SetAttribute("pannel_stick", application.pannel_stick);
|
||||||
|
applicationNode->SetAttribute("smooth_transition", application.smooth_transition);
|
||||||
pRoot->InsertEndChild(applicationNode);
|
pRoot->InsertEndChild(applicationNode);
|
||||||
|
|
||||||
// Widgets
|
// Widgets
|
||||||
@@ -122,6 +123,16 @@ void Settings::Save()
|
|||||||
};
|
};
|
||||||
recent->InsertEndChild(recentsession);
|
recent->InsertEndChild(recentsession);
|
||||||
|
|
||||||
|
XMLElement *recentfolder = xmlDoc.NewElement( "Folder" );
|
||||||
|
for(auto it = application.recentFolders.filenames.begin();
|
||||||
|
it != application.recentFolders.filenames.end(); it++) {
|
||||||
|
XMLElement *fileNode = xmlDoc.NewElement("path");
|
||||||
|
XMLText *text = xmlDoc.NewText( (*it).c_str() );
|
||||||
|
fileNode->InsertEndChild( text );
|
||||||
|
recentfolder->InsertFirstChild(fileNode);
|
||||||
|
};
|
||||||
|
recent->InsertEndChild(recentfolder);
|
||||||
|
|
||||||
XMLElement *recentmedia = xmlDoc.NewElement( "Import" );
|
XMLElement *recentmedia = xmlDoc.NewElement( "Import" );
|
||||||
recentmedia->SetAttribute("path", application.recentImport.path.c_str());
|
recentmedia->SetAttribute("path", application.recentImport.path.c_str());
|
||||||
for(auto it = application.recentImport.filenames.begin();
|
for(auto it = application.recentImport.filenames.begin();
|
||||||
@@ -139,7 +150,7 @@ void Settings::Save()
|
|||||||
|
|
||||||
// First save : create filename
|
// First save : create filename
|
||||||
if (settingsFilename.empty())
|
if (settingsFilename.empty())
|
||||||
settingsFilename = SystemToolkit::settings_prepend_path(APP_SETTINGS);
|
settingsFilename = SystemToolkit::full_filename(SystemToolkit::settings_path(), APP_SETTINGS);
|
||||||
|
|
||||||
XMLError eResult = xmlDoc.SaveFile(settingsFilename.c_str());
|
XMLError eResult = xmlDoc.SaveFile(settingsFilename.c_str());
|
||||||
XMLResultError(eResult);
|
XMLResultError(eResult);
|
||||||
@@ -149,7 +160,7 @@ void Settings::Load()
|
|||||||
{
|
{
|
||||||
XMLDocument xmlDoc;
|
XMLDocument xmlDoc;
|
||||||
if (settingsFilename.empty())
|
if (settingsFilename.empty())
|
||||||
settingsFilename = SystemToolkit::settings_prepend_path(APP_SETTINGS);
|
settingsFilename = SystemToolkit::full_filename(SystemToolkit::settings_path(), APP_SETTINGS);
|
||||||
XMLError eResult = xmlDoc.LoadFile(settingsFilename.c_str());
|
XMLError eResult = xmlDoc.LoadFile(settingsFilename.c_str());
|
||||||
|
|
||||||
// do not warn if non existing file
|
// do not warn if non existing file
|
||||||
@@ -171,6 +182,7 @@ void Settings::Load()
|
|||||||
applicationNode->QueryFloatAttribute("scale", &application.scale);
|
applicationNode->QueryFloatAttribute("scale", &application.scale);
|
||||||
applicationNode->QueryIntAttribute("accent_color", &application.accent_color);
|
applicationNode->QueryIntAttribute("accent_color", &application.accent_color);
|
||||||
applicationNode->QueryBoolAttribute("pannel_stick", &application.pannel_stick);
|
applicationNode->QueryBoolAttribute("pannel_stick", &application.pannel_stick);
|
||||||
|
applicationNode->QueryBoolAttribute("smooth_transition", &application.smooth_transition);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Widgets
|
// Widgets
|
||||||
@@ -272,6 +284,19 @@ void Settings::Load()
|
|||||||
application.recentSessions.push( std::string (p) );
|
application.recentSessions.push( std::string (p) );
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
// recent session filenames
|
||||||
|
XMLElement * pFolder = pElement->FirstChildElement("Folder");
|
||||||
|
if (pFolder)
|
||||||
|
{
|
||||||
|
application.recentFolders.filenames.clear();
|
||||||
|
XMLElement* path = pFolder->FirstChildElement("path");
|
||||||
|
for( ; path ; path = path->NextSiblingElement())
|
||||||
|
{
|
||||||
|
const char *p = path->GetText();
|
||||||
|
if (p)
|
||||||
|
application.recentFolders.push( std::string (p) );
|
||||||
|
}
|
||||||
|
}
|
||||||
// recent media uri
|
// recent media uri
|
||||||
XMLElement * pImport = pElement->FirstChildElement("Import");
|
XMLElement * pImport = pElement->FirstChildElement("Import");
|
||||||
if (pImport)
|
if (pImport)
|
||||||
|
|||||||
@@ -64,6 +64,7 @@ struct History
|
|||||||
bool save_on_exit;
|
bool save_on_exit;
|
||||||
|
|
||||||
History() {
|
History() {
|
||||||
|
path = "Recent Files";
|
||||||
load_at_start = false;
|
load_at_start = false;
|
||||||
save_on_exit = false;
|
save_on_exit = false;
|
||||||
}
|
}
|
||||||
@@ -98,6 +99,7 @@ struct Application
|
|||||||
float scale;
|
float scale;
|
||||||
int accent_color;
|
int accent_color;
|
||||||
bool pannel_stick;
|
bool pannel_stick;
|
||||||
|
bool smooth_transition;
|
||||||
|
|
||||||
// Settings of widgets
|
// Settings of widgets
|
||||||
WidgetsConfig widget;
|
WidgetsConfig widget;
|
||||||
@@ -116,12 +118,14 @@ struct Application
|
|||||||
|
|
||||||
// recent files histories
|
// recent files histories
|
||||||
History recentSessions;
|
History recentSessions;
|
||||||
|
History recentFolders;
|
||||||
History recentImport;
|
History recentImport;
|
||||||
|
|
||||||
Application() : name(APP_NAME){
|
Application() : name(APP_NAME){
|
||||||
scale = 1.f;
|
scale = 1.f;
|
||||||
accent_color = 0;
|
accent_color = 0;
|
||||||
pannel_stick = false;
|
pannel_stick = false;
|
||||||
|
smooth_transition = true;
|
||||||
|
|
||||||
current_view = 1;
|
current_view = 1;
|
||||||
render_view_ar = 3;
|
render_view_ar = 3;
|
||||||
|
|||||||
@@ -5,83 +5,75 @@
|
|||||||
#include <iomanip>
|
#include <iomanip>
|
||||||
#include <ctime>
|
#include <ctime>
|
||||||
#include <chrono>
|
#include <chrono>
|
||||||
|
#include <filesystem>
|
||||||
|
|
||||||
using namespace std;
|
using namespace std;
|
||||||
|
|
||||||
#ifdef WIN32
|
#ifdef WIN32
|
||||||
#include <windows.h>
|
#include <windows.h>
|
||||||
#define mkdir(dir, mode) _mkdir(dir)
|
|
||||||
#include <include/dirent.h>
|
|
||||||
#define PATH_SEP '\\'
|
|
||||||
#elif defined(LINUX) or defined(APPLE)
|
#elif defined(LINUX) or defined(APPLE)
|
||||||
#include <sys/types.h>
|
|
||||||
#include <sys/stat.h>
|
|
||||||
#include <pwd.h>
|
#include <pwd.h>
|
||||||
#include <dirent.h>
|
|
||||||
#define PATH_SEP '/'
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#ifdef WIN32
|
|
||||||
#define PATH_SETTINGS "\\\AppData\\Roaming\\"
|
|
||||||
#elif defined(APPLE)
|
|
||||||
#define PATH_SETTINGS "/Library/Application Support/"
|
|
||||||
#elif defined(LINUX)
|
|
||||||
#define PATH_SETTINGS "/.config/"
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#include "defines.h"
|
#include "defines.h"
|
||||||
#include "SystemToolkit.h"
|
#include "SystemToolkit.h"
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
string SystemToolkit::date_time_string()
|
string SystemToolkit::date_time_string()
|
||||||
{
|
{
|
||||||
chrono::system_clock::time_point now = chrono::system_clock::now();
|
chrono::system_clock::time_point now = chrono::system_clock::now();
|
||||||
time_t t = chrono::system_clock::to_time_t(now);
|
time_t t = chrono::system_clock::to_time_t(now);
|
||||||
std::tm* datetime = std::localtime(&t);
|
tm* datetime = localtime(&t);
|
||||||
|
|
||||||
auto duration = now.time_since_epoch();
|
auto duration = now.time_since_epoch();
|
||||||
auto millis = chrono::duration_cast<chrono::milliseconds>(duration).count() % 1000;
|
auto millis = chrono::duration_cast<chrono::milliseconds>(duration).count() % 1000;
|
||||||
|
|
||||||
ostringstream oss;
|
ostringstream oss;
|
||||||
oss << setw(4) << setfill('0') << std::to_string(datetime->tm_year + 1900);
|
oss << setw(4) << setfill('0') << to_string(datetime->tm_year + 1900);
|
||||||
oss << setw(2) << setfill('0') << std::to_string(datetime->tm_mon + 1);
|
oss << setw(2) << setfill('0') << to_string(datetime->tm_mon + 1);
|
||||||
oss << setw(2) << setfill('0') << std::to_string(datetime->tm_mday );
|
oss << setw(2) << setfill('0') << to_string(datetime->tm_mday );
|
||||||
oss << setw(2) << setfill('0') << std::to_string(datetime->tm_hour );
|
oss << setw(2) << setfill('0') << to_string(datetime->tm_hour );
|
||||||
oss << setw(2) << setfill('0') << std::to_string(datetime->tm_min );
|
oss << setw(2) << setfill('0') << to_string(datetime->tm_min );
|
||||||
oss << setw(2) << setfill('0') << std::to_string(datetime->tm_sec );
|
oss << setw(2) << setfill('0') << to_string(datetime->tm_sec );
|
||||||
oss << setw(3) << setfill('0') << std::to_string(millis);
|
oss << setw(3) << setfill('0') << to_string(millis);
|
||||||
|
|
||||||
// fixed length string (17 chars) YYYYMMDDHHmmssiii
|
// fixed length string (17 chars) YYYYMMDDHHmmssiii
|
||||||
return oss.str();
|
return oss.str();
|
||||||
}
|
}
|
||||||
|
|
||||||
std::string SystemToolkit::base_filename(const std::string& filename)
|
string SystemToolkit::filename(const string& path)
|
||||||
{
|
{
|
||||||
std::string basefilename = filename.substr(filename.find_last_of(PATH_SEP) + 1);
|
return filesystem::path(path).filename();
|
||||||
const size_t period_idx = basefilename.rfind('.');
|
|
||||||
if (std::string::npos != period_idx)
|
|
||||||
{
|
|
||||||
basefilename.erase(period_idx);
|
|
||||||
}
|
|
||||||
return basefilename;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
std::string SystemToolkit::path_filename(const std::string& filename)
|
string SystemToolkit::base_filename(const string& path)
|
||||||
{
|
{
|
||||||
std::string path = filename.substr(0, filename.find_last_of(PATH_SEP) + 1);
|
return filesystem::path(path).stem();
|
||||||
return path;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
std::string SystemToolkit::extension_filename(const std::string& filename)
|
string SystemToolkit::path_filename(const string& path)
|
||||||
{
|
{
|
||||||
std::string ext = filename.substr(filename.find_last_of(".") + 1);
|
return filesystem::path(path).parent_path();
|
||||||
return ext;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
std::string SystemToolkit::home_path()
|
string SystemToolkit::trunc_filename(const string& path, int lenght)
|
||||||
{
|
{
|
||||||
// 1. find home
|
string trunc = path;
|
||||||
|
int l = path.size();
|
||||||
|
if ( l > lenght ) {
|
||||||
|
trunc = string("...") + path.substr( l - lenght + 3 );
|
||||||
|
}
|
||||||
|
return trunc;
|
||||||
|
}
|
||||||
|
|
||||||
|
string SystemToolkit::extension_filename(const string& filename)
|
||||||
|
{
|
||||||
|
return filesystem::path(filename).extension();
|
||||||
|
}
|
||||||
|
|
||||||
|
string SystemToolkit::home_path()
|
||||||
|
{
|
||||||
|
// find home
|
||||||
char *mHomePath;
|
char *mHomePath;
|
||||||
// try the system user info
|
// try the system user info
|
||||||
struct passwd* pwd = getpwuid(getuid());
|
struct passwd* pwd = getpwuid(getuid());
|
||||||
@@ -93,61 +85,65 @@ std::string SystemToolkit::home_path()
|
|||||||
mHomePath = getenv("HOME");
|
mHomePath = getenv("HOME");
|
||||||
}
|
}
|
||||||
|
|
||||||
return string(mHomePath) + PATH_SEP;
|
return filesystem::path(mHomePath).string();
|
||||||
}
|
}
|
||||||
|
|
||||||
string SystemToolkit::settings_path()
|
string SystemToolkit::settings_path()
|
||||||
{
|
{
|
||||||
string home(home_path());
|
filesystem::path settings(home_path());
|
||||||
|
|
||||||
// 2. try to access user settings folder
|
// platform dependent location of settings
|
||||||
string settingspath = home + PATH_SETTINGS;
|
#ifdef WIN32
|
||||||
if (SystemToolkit::file_exists(settingspath)) {
|
settings /= "AppData";
|
||||||
// good, we have a place to put the settings file
|
settings /= "Roaming";
|
||||||
// settings should be in 'vmix' subfolder
|
#elif defined(APPLE)
|
||||||
settingspath += APP_NAME;
|
settings /= "Library";
|
||||||
|
settings /= "Application Support";
|
||||||
|
#elif defined(LINUX)
|
||||||
|
settings /= ".config";
|
||||||
|
#endif
|
||||||
|
|
||||||
// 3. create the vmix subfolder in settings folder if not existing already
|
// append folder location for vimix settings
|
||||||
if ( !SystemToolkit::file_exists(settingspath)) {
|
settings /= APP_NAME;
|
||||||
if ( !SystemToolkit::create_directory(settingspath) )
|
|
||||||
// fallback to home if settings path cannot be created
|
// create folder if not existint
|
||||||
settingspath = home;
|
if (!filesystem::exists(settings)) {
|
||||||
|
if (!filesystem::create_directories(settings) )
|
||||||
|
return home_path();
|
||||||
}
|
}
|
||||||
|
|
||||||
return settingspath;
|
return settings.string();
|
||||||
}
|
|
||||||
else {
|
|
||||||
// fallback to home if settings path does not exists
|
|
||||||
return home;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
string SystemToolkit::full_filename(const std::string& path, const string &filename)
|
||||||
|
|
||||||
string SystemToolkit::settings_prepend_path(const string &basefilename)
|
|
||||||
{
|
{
|
||||||
string path = SystemToolkit::settings_path();
|
filesystem::path fullfilename( path );
|
||||||
path += PATH_SEP;
|
fullfilename /= filename;
|
||||||
path += basefilename;
|
|
||||||
|
|
||||||
return path;
|
return fullfilename.string();
|
||||||
}
|
}
|
||||||
|
|
||||||
bool SystemToolkit::file_exists(const string& path)
|
bool SystemToolkit::file_exists(const string& path)
|
||||||
{
|
{
|
||||||
return access(path.c_str(), R_OK) == 0;
|
return filesystem::exists( filesystem::status(path) );
|
||||||
|
|
||||||
// TODO : WIN32 implementation
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
list<string> SystemToolkit::list_directory(const string& path, const string& filter)
|
||||||
bool SystemToolkit::create_directory(const string& path)
|
|
||||||
{
|
{
|
||||||
return !mkdir(path.c_str(), 0755) || errno == EEXIST;
|
list<string> ls;
|
||||||
|
// loop over elements of the directory
|
||||||
// TODO : verify WIN32 implementation
|
for (const auto & entry : filesystem::directory_iterator(path)) {
|
||||||
|
// list only files, not directories
|
||||||
|
if ( filesystem::is_regular_file(entry)) {
|
||||||
|
// add the path if no filter, or if filter is matching
|
||||||
|
if (filter.empty() || entry.path().extension() == filter )
|
||||||
|
ls.push_back( entry.path().string() );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return ls;
|
||||||
}
|
}
|
||||||
|
|
||||||
void SystemToolkit::open(const std::string& url)
|
void SystemToolkit::open(const string& url)
|
||||||
{
|
{
|
||||||
#ifdef WIN32
|
#ifdef WIN32
|
||||||
ShellExecuteA( nullptr, nullptr, url.c_str(), nullptr, nullptr, 0 );
|
ShellExecuteA( nullptr, nullptr, url.c_str(), nullptr, nullptr, 0 );
|
||||||
|
|||||||
@@ -22,23 +22,29 @@ namespace SystemToolkit
|
|||||||
std::string settings_path();
|
std::string settings_path();
|
||||||
|
|
||||||
// builds the OS dependent complete file name for a settings file
|
// builds the OS dependent complete file name for a settings file
|
||||||
std::string settings_prepend_path(const std::string& basefilename);
|
std::string full_filename(const std::string& path, const std::string& filename);
|
||||||
|
|
||||||
|
// extract the filename from a full path / URI (e.g. file:://home/me/toto.mpg -> toto.mpg)
|
||||||
|
std::string filename(const std::string& path);
|
||||||
|
|
||||||
// extract the base filename from a full path / URI (e.g. file:://home/me/toto.mpg -> toto)
|
// extract the base filename from a full path / URI (e.g. file:://home/me/toto.mpg -> toto)
|
||||||
std::string base_filename(const std::string& filename);
|
std::string base_filename(const std::string& path);
|
||||||
|
|
||||||
// extract the path of a filename from a full URI (e.g. file:://home/me/toto.mpg -> file:://home/me/)
|
// extract the path of a filename from a full URI (e.g. file:://home/me/toto.mpg -> file:://home/me/)
|
||||||
std::string path_filename(const std::string& filename);
|
std::string path_filename(const std::string& path);
|
||||||
|
|
||||||
|
// Truncate a full filename to display the right part (e.g. file:://home/me/toto.mpg -> ...ome/me/toto.mpg)
|
||||||
|
std::string trunc_filename(const std::string& path, int lenght);
|
||||||
|
|
||||||
// extract the extension of a filename
|
// extract the extension of a filename
|
||||||
std::string extension_filename(const std::string& filename);
|
std::string extension_filename(const std::string& filename);
|
||||||
|
|
||||||
|
// list all files of a directory mathing the given filter extension (if any)
|
||||||
|
std::list<std::string> list_directory(const std::string& path, const std::string& filter = "");
|
||||||
|
|
||||||
// true of file exists
|
// true of file exists
|
||||||
bool file_exists(const std::string& path);
|
bool file_exists(const std::string& path);
|
||||||
|
|
||||||
// true if directory could be created
|
|
||||||
bool create_directory(const std::string& path);
|
|
||||||
|
|
||||||
// try to open the file with system
|
// try to open the file with system
|
||||||
void open(const std::string& path);
|
void open(const std::string& path);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -116,7 +116,10 @@ static void ImportFileDialogOpen(char *filename, std::atomic<bool> *success, con
|
|||||||
char const * open_pattern[18] = { "*.mix", "*.mp4", "*.mpg", "*.avi", "*.mov", "*.mkv", "*.webm", "*.mod", "*.wmv", "*.mxf", "*.ogg", "*.flv", "*.asf", "*.jpg", "*.png", "*.gif", "*.tif", "*.svg" };
|
char const * open_pattern[18] = { "*.mix", "*.mp4", "*.mpg", "*.avi", "*.mov", "*.mkv", "*.webm", "*.mod", "*.wmv", "*.mxf", "*.ogg", "*.flv", "*.asf", "*.jpg", "*.png", "*.gif", "*.tif", "*.svg" };
|
||||||
char const * open_file_name;
|
char const * open_file_name;
|
||||||
|
|
||||||
|
if (SystemToolkit::file_exists(path))
|
||||||
open_file_name = tinyfd_openFileDialog( "Import a file", path.c_str(), 18, open_pattern, "All supported formats", 0);
|
open_file_name = tinyfd_openFileDialog( "Import a file", path.c_str(), 18, open_pattern, "All supported formats", 0);
|
||||||
|
else
|
||||||
|
open_file_name = tinyfd_openFileDialog( "Import a file", SystemToolkit::home_path().c_str(), 18, open_pattern, "All supported formats", 0);
|
||||||
|
|
||||||
if (open_file_name) {
|
if (open_file_name) {
|
||||||
sprintf(filename, "%s", open_file_name);
|
sprintf(filename, "%s", open_file_name);
|
||||||
@@ -129,6 +132,30 @@ static void ImportFileDialogOpen(char *filename, std::atomic<bool> *success, con
|
|||||||
fileDialogPending_ = false;
|
fileDialogPending_ = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void FolderDialogOpen(char *folder, std::atomic<bool> *success, const std::string &path)
|
||||||
|
{
|
||||||
|
if (fileDialogPending_)
|
||||||
|
return;
|
||||||
|
fileDialogPending_ = true;
|
||||||
|
|
||||||
|
char const * open_file_name;
|
||||||
|
if (SystemToolkit::file_exists(path))
|
||||||
|
open_file_name = tinyfd_selectFolderDialog("Select a folder", path.c_str());
|
||||||
|
else
|
||||||
|
open_file_name = tinyfd_selectFolderDialog("Select a folder", SystemToolkit::home_path().c_str());
|
||||||
|
|
||||||
|
if (open_file_name) {
|
||||||
|
sprintf(folder, "%s", open_file_name);
|
||||||
|
*success = true;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
*success = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
fileDialogPending_ = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
UserInterface::UserInterface()
|
UserInterface::UserInterface()
|
||||||
{
|
{
|
||||||
show_about = false;
|
show_about = false;
|
||||||
@@ -195,7 +222,7 @@ bool UserInterface::Init()
|
|||||||
ImGui::SetClipboardText("");
|
ImGui::SetClipboardText("");
|
||||||
|
|
||||||
// setup settings filename
|
// setup settings filename
|
||||||
std::string inifile = SystemToolkit::settings_prepend_path("imgui.ini");
|
std::string inifile = SystemToolkit::full_filename(SystemToolkit::settings_path(), "imgui.ini");
|
||||||
char *inifilepath = (char *) malloc( (inifile.size() + 1) * sizeof(char) );
|
char *inifilepath = (char *) malloc( (inifile.size() + 1) * sizeof(char) );
|
||||||
std::sprintf(inifilepath, "%s", inifile.c_str() );
|
std::sprintf(inifilepath, "%s", inifile.c_str() );
|
||||||
io.IniFilename = inifilepath;
|
io.IniFilename = inifilepath;
|
||||||
@@ -649,7 +676,7 @@ void UserInterface::handleScreenshot()
|
|||||||
case 3:
|
case 3:
|
||||||
{
|
{
|
||||||
if ( Rendering::manager().currentScreenshot()->IsFull() ){
|
if ( Rendering::manager().currentScreenshot()->IsFull() ){
|
||||||
std::string filename = SystemToolkit::home_path() + SystemToolkit::date_time_string() + "_vmixcapture.png";
|
std::string filename = SystemToolkit::full_filename( SystemToolkit::home_path(), SystemToolkit::date_time_string() + "_vmixcapture.png" );
|
||||||
Rendering::manager().currentScreenshot()->SaveFile( filename.c_str() );
|
Rendering::manager().currentScreenshot()->SaveFile( filename.c_str() );
|
||||||
Rendering::manager().currentScreenshot()->Clear();
|
Rendering::manager().currentScreenshot()->Clear();
|
||||||
Log::Notify("Screenshot saved %s", filename.c_str() );
|
Log::Notify("Screenshot saved %s", filename.c_str() );
|
||||||
@@ -845,10 +872,11 @@ void UserInterface::RenderMediaPlayer()
|
|||||||
if (ImGui::IsItemHovered()) {
|
if (ImGui::IsItemHovered()) {
|
||||||
|
|
||||||
ImDrawList* draw_list = ImGui::GetWindowDrawList();
|
ImDrawList* draw_list = ImGui::GetWindowDrawList();
|
||||||
draw_list->AddRectFilled(tooltip_pos, ImVec2(tooltip_pos.x + width, tooltip_pos.y + 2.f * ImGui::GetTextLineHeightWithSpacing()), IM_COL32(55, 55, 55, 200));
|
draw_list->AddRectFilled(tooltip_pos, ImVec2(tooltip_pos.x + width, tooltip_pos.y + 3.f * ImGui::GetTextLineHeightWithSpacing()), IM_COL32(55, 55, 55, 200));
|
||||||
|
|
||||||
ImGui::SetCursorScreenPos(tooltip_pos);
|
ImGui::SetCursorScreenPos(tooltip_pos);
|
||||||
ImGui::Text(" %s (%s)", SystemToolkit::base_filename(mp->uri()).c_str(), mp->codec().c_str());
|
ImGui::Text(" %s", SystemToolkit::filename(mp->uri()).c_str());
|
||||||
|
ImGui::Text(" %s", mp->codec().c_str());
|
||||||
if ( mp->frameRate() > 0.f )
|
if ( mp->frameRate() > 0.f )
|
||||||
ImGui::Text(" %d x %d px, %.2f / %.2f fps", mp->width(), mp->height(), mp->updateFrameRate() , mp->frameRate() );
|
ImGui::Text(" %d x %d px, %.2f / %.2f fps", mp->width(), mp->height(), mp->updateFrameRate() , mp->frameRate() );
|
||||||
else
|
else
|
||||||
@@ -1090,7 +1118,7 @@ void Navigator::clearButtonSelection()
|
|||||||
selected_button[i] = false;
|
selected_button[i] = false;
|
||||||
|
|
||||||
// clear new source pannel
|
// clear new source pannel
|
||||||
sprintf(new_source_filename_, " ");
|
sprintf(file_browser_path_, " ");
|
||||||
new_source_preview_.setSource();
|
new_source_preview_.setSource();
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1365,11 +1393,11 @@ void Navigator::RenderNewPannel()
|
|||||||
if ( ImGui::Button( ICON_FA_FILE_IMPORT " Open", ImVec2(ImGui::GetContentRegionAvail().x IMGUI_RIGHT_ALIGN, 0)) ) {
|
if ( ImGui::Button( ICON_FA_FILE_IMPORT " Open", ImVec2(ImGui::GetContentRegionAvail().x IMGUI_RIGHT_ALIGN, 0)) ) {
|
||||||
// clear string before selection
|
// clear string before selection
|
||||||
file_selected = false;
|
file_selected = false;
|
||||||
std::thread (ImportFileDialogOpen, new_source_filename_, &file_selected, Settings::application.recentImport.path).detach();
|
std::thread (ImportFileDialogOpen, file_browser_path_, &file_selected, Settings::application.recentImport.path).detach();
|
||||||
}
|
}
|
||||||
if ( file_selected ) {
|
if ( file_selected ) {
|
||||||
file_selected = false;
|
file_selected = false;
|
||||||
std::string open_filename(new_source_filename_);
|
std::string open_filename(file_browser_path_);
|
||||||
// create a source with this file
|
// create a source with this file
|
||||||
std::string label = open_filename.substr( open_filename.size() - MIN( 35, open_filename.size()) );
|
std::string label = open_filename.substr( open_filename.size() - MIN( 35, open_filename.size()) );
|
||||||
new_source_preview_.setSource( Mixer::manager().createSourceFile(open_filename), label);
|
new_source_preview_.setSource( Mixer::manager().createSourceFile(open_filename), label);
|
||||||
@@ -1472,24 +1500,123 @@ void Navigator::RenderMainPannel()
|
|||||||
ImGui::EndMenu();
|
ImGui::EndMenu();
|
||||||
}
|
}
|
||||||
|
|
||||||
// combo box with list of recent session files from Settings
|
static bool selection_session_mode_changed = true;
|
||||||
static bool recentselected = false;
|
static int selection_session_mode = 0;
|
||||||
recentselected = false;
|
|
||||||
ImGui::SetNextItemWidth(IMGUI_RIGHT_ALIGN);
|
//
|
||||||
if (ImGui::BeginCombo("##Recent", "Open recent"))
|
// Session quick selection pannel
|
||||||
{
|
//
|
||||||
std::for_each(Settings::application.recentSessions.filenames.begin(),
|
|
||||||
Settings::application.recentSessions.filenames.end(), [](std::string& filename) {
|
// return from thread for folder openning
|
||||||
int right = MIN( 40, filename.size());
|
static std::atomic<bool> folder_selected = false;
|
||||||
if (ImGui::Selectable( filename.substr( filename.size() - right ).c_str() )) {
|
if (folder_selected) {
|
||||||
Mixer::manager().open( filename );
|
folder_selected = false;
|
||||||
recentselected = true;
|
selection_session_mode = 1;
|
||||||
|
selection_session_mode_changed = true;
|
||||||
|
Settings::application.recentFolders.push(file_browser_path_);
|
||||||
|
Settings::application.recentFolders.path.assign(file_browser_path_);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Show combo box of quick selection modes
|
||||||
|
ImGui::SetNextItemWidth(IMGUI_RIGHT_ALIGN);
|
||||||
|
if (ImGui::BeginCombo("##SelectionSession", SystemToolkit::trunc_filename(Settings::application.recentFolders.path, 25).c_str() )) {
|
||||||
|
|
||||||
|
// Option 0 : recent files
|
||||||
|
if (ImGui::Selectable( ICON_FA_HISTORY " Recent Files") ) {
|
||||||
|
Settings::application.recentFolders.path = "Recent Files";
|
||||||
|
selection_session_mode = 0;
|
||||||
|
selection_session_mode_changed = true;
|
||||||
|
}
|
||||||
|
// Options 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) + " " + SystemToolkit::trunc_filename( *foldername, 40);
|
||||||
|
if (ImGui::Selectable( f.c_str() )) {
|
||||||
|
// remember which path was selected
|
||||||
|
Settings::application.recentFolders.path.assign(*foldername);
|
||||||
|
// set mode
|
||||||
|
selection_session_mode = 1;
|
||||||
|
selection_session_mode_changed = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// Option 2 : add a folder
|
||||||
|
if (ImGui::Selectable( ICON_FA_FOLDER_PLUS " Add Folder") ){
|
||||||
|
std::thread (FolderDialogOpen, file_browser_path_, &folder_selected, Settings::application.recentFolders.path).detach();
|
||||||
}
|
}
|
||||||
});
|
|
||||||
ImGui::EndCombo();
|
ImGui::EndCombo();
|
||||||
}
|
}
|
||||||
if (recentselected)
|
|
||||||
|
// helper
|
||||||
|
ImGui::SameLine();
|
||||||
|
ImGui::SetCursorPosX(pannel_width_ + IMGUI_RIGHT_ALIGN);
|
||||||
|
ImGuiToolkit::HelpMarker("Quick access of Session files.\nSelect from the history of recently\nopened files or from a folder.\nDouble clic on a filename to open it.");
|
||||||
|
|
||||||
|
// fill the session list depending on the mode
|
||||||
|
static std::list<std::string> sessions_list;
|
||||||
|
// change session list if changed
|
||||||
|
if (selection_session_mode_changed) {
|
||||||
|
|
||||||
|
// selection MODE 0 ; RECENT sessions
|
||||||
|
if ( selection_session_mode == 0) {
|
||||||
|
// show list of recent sessions
|
||||||
|
sessions_list = Settings::application.recentSessions.filenames;
|
||||||
|
}
|
||||||
|
// selection MODE 1 : LIST FOLDER
|
||||||
|
else if ( selection_session_mode == 1) {
|
||||||
|
// show list of vimix files in folder
|
||||||
|
sessions_list = SystemToolkit::list_directory( Settings::application.recentFolders.path, ".mix");
|
||||||
|
}
|
||||||
|
// indicate the list changed (do not change at every frame)
|
||||||
|
selection_session_mode_changed = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
// display the sessions list and detect if one was selected (double clic)
|
||||||
|
bool session_selected = false;
|
||||||
|
ImGui::SetNextItemWidth(IMGUI_RIGHT_ALIGN);
|
||||||
|
ImGui::ListBoxHeader("##Sessions", Settings::application.recentSessions.filenames.size());
|
||||||
|
for(auto filename = sessions_list.begin(); filename != sessions_list.end(); filename++) {
|
||||||
|
if (ImGui::Selectable( SystemToolkit::filename(*filename).c_str(), false, ImGuiSelectableFlags_AllowDoubleClick )) {
|
||||||
|
if (ImGui::IsMouseDoubleClicked(0)) {
|
||||||
|
Mixer::manager().open( *filename );
|
||||||
|
session_selected = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
ImGui::ListBoxFooter();
|
||||||
|
|
||||||
|
// icon to remove this folder from the list
|
||||||
|
if ( selection_session_mode == 1) {
|
||||||
|
ImVec2 pos = ImGui::GetCursorPos();
|
||||||
|
ImGui::SameLine();
|
||||||
|
ImGui::PushStyleVar(ImGuiStyleVar_Alpha, 0.7);
|
||||||
|
bool reset = false;
|
||||||
|
ImGuiToolkit::IconToggle(12,14,11,14, &reset);
|
||||||
|
if (reset) {
|
||||||
|
Settings::application.recentFolders.filenames.remove(Settings::application.recentFolders.path);
|
||||||
|
if (Settings::application.recentFolders.filenames.empty()) {
|
||||||
|
Settings::application.recentFolders.path.assign("Recent Files");
|
||||||
|
selection_session_mode = 0;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
Settings::application.recentFolders.path = Settings::application.recentFolders.filenames.front();
|
||||||
|
// reload the list next time
|
||||||
|
selection_session_mode_changed = true;
|
||||||
|
}
|
||||||
|
ImGui::PopStyleVar();
|
||||||
|
ImGui::SetCursorPos(pos);
|
||||||
|
}
|
||||||
|
|
||||||
|
// done the selection !
|
||||||
|
if (session_selected) {
|
||||||
|
// close pannel
|
||||||
hidePannel();
|
hidePannel();
|
||||||
|
// reload the list next time
|
||||||
|
selection_session_mode_changed = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Continue Main pannel
|
||||||
|
ImGui::Text(" ");
|
||||||
|
ImGuiToolkit::ButtonSwitch( "Smooth transition", &Settings::application.smooth_transition);
|
||||||
ImGuiToolkit::ButtonSwitch( "Load most recent on start", &Settings::application.recentSessions.load_at_start);
|
ImGuiToolkit::ButtonSwitch( "Load most recent on start", &Settings::application.recentSessions.load_at_start);
|
||||||
ImGuiToolkit::ButtonSwitch( "Save on exit", &Settings::application.recentSessions.save_on_exit);
|
ImGuiToolkit::ButtonSwitch( "Save on exit", &Settings::application.recentSessions.save_on_exit);
|
||||||
|
|
||||||
|
|||||||
@@ -49,7 +49,7 @@ class Navigator
|
|||||||
|
|
||||||
void RenderNewPannel();
|
void RenderNewPannel();
|
||||||
int new_source_type_;
|
int new_source_type_;
|
||||||
char new_source_filename_[2048];
|
char file_browser_path_[2048];
|
||||||
|
|
||||||
SourcePreview new_source_preview_;
|
SourcePreview new_source_preview_;
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user