Add portal support and update .gitignore
This commit is contained in:
parent
d46032e3bd
commit
b012069269
9 changed files with 264 additions and 22 deletions
5
.gitignore
vendored
5
.gitignore
vendored
|
@ -1,12 +1,9 @@
|
|||
assets/*.h
|
||||
build*
|
||||
.vscode
|
||||
subprojects/*/
|
||||
.cache
|
||||
compile_commands.json
|
||||
!subprojects/SDL-Mixer-X/
|
||||
!subprojects/jsoncpp/
|
||||
.flatpak-builder
|
||||
flatpak-repo
|
||||
*.flatpak
|
||||
!build-file.sh
|
||||
!build*.sh
|
||||
|
|
175
file_browser.cpp
Normal file
175
file_browser.cpp
Normal file
|
@ -0,0 +1,175 @@
|
|||
#include "file_browser.h"
|
||||
#include "imfilebrowser.h"
|
||||
|
||||
|
||||
FileBrowser::FileBrowser(bool save) {
|
||||
#ifdef PORTALS
|
||||
g_set_application_name("Neko Player");
|
||||
main_context = g_main_context_default();
|
||||
main_loop = g_main_loop_new(main_context, true);
|
||||
portal = xdp_portal_new();
|
||||
type = g_variant_type_new("a(sa(us))");
|
||||
inner_filter_type = g_variant_type_new("a(us)");
|
||||
#endif
|
||||
this->save = save;
|
||||
fallback = ImGui::FileBrowser(save ? ImGuiFileBrowserFlags_CreateNewDir|ImGuiFileBrowserFlags_EnterNewFilename : 0);
|
||||
}
|
||||
void FileBrowser::SetTypeFilters(string name, vector<string> filters) {
|
||||
filter_name = name;
|
||||
this->filters = filters;
|
||||
#ifdef PORTALS
|
||||
if (variant != NULL) {
|
||||
g_variant_unref(variant);
|
||||
}
|
||||
GVariantBuilder builder;
|
||||
GVariantBuilder inner_filter_builder;
|
||||
g_variant_builder_init(&builder, type);
|
||||
g_variant_builder_init(&inner_filter_builder, inner_filter_type);
|
||||
GVariant *name_variant = g_variant_new_string((const gchar*)name.c_str());
|
||||
for (auto filter : filters) {
|
||||
GVariant *id = g_variant_new_uint32(0);
|
||||
GVariant *filter_variant = g_variant_new_string((const gchar*)(string("*") + filter).c_str());
|
||||
GVariant **filter_children = new GVariant*[2] {id, filter_variant};
|
||||
GVariant *filter_tuple = g_variant_new_tuple(filter_children, 2);
|
||||
g_variant_builder_add_value(&inner_filter_builder, filter_tuple);
|
||||
}
|
||||
GVariant *inner_filters = g_variant_builder_end(&inner_filter_builder);
|
||||
GVariant **outer_filter_children = new GVariant*[2] {name_variant, inner_filters};
|
||||
GVariant *outer_filter_tuple = g_variant_new_tuple(outer_filter_children, 2);
|
||||
g_variant_builder_add_value(&builder, outer_filter_tuple);
|
||||
variant = g_variant_builder_end(&builder);
|
||||
g_variant_ref(variant);
|
||||
#endif
|
||||
fallback.SetTypeFilters(filters);
|
||||
}
|
||||
void FileBrowser::SetPwd(path path) {
|
||||
pwd = path;
|
||||
#ifndef PORTALS
|
||||
fallback.SetPwd(path);
|
||||
#endif
|
||||
}
|
||||
bool FileBrowser::HasSelected() {
|
||||
#ifdef PORTALS
|
||||
return selected.has_value();
|
||||
#else
|
||||
return fallback.HasSelected();
|
||||
#endif
|
||||
}
|
||||
path FileBrowser::GetSelected() {
|
||||
#ifdef PORTALS
|
||||
return selected.value_or(path());
|
||||
#else
|
||||
return fallback.GetSelected();
|
||||
#endif
|
||||
}
|
||||
void FileBrowser::SetWindowSize(int w, int h) {
|
||||
fallback.SetWindowSize(w, h);
|
||||
}
|
||||
void FileBrowser::SetWindowPos(int x, int y) {
|
||||
fallback.SetWindowPos(x, y);
|
||||
}
|
||||
void FileBrowser::Open() {
|
||||
#ifdef PORTALS
|
||||
open = true;
|
||||
if (save) {
|
||||
xdp_portal_save_file(portal, NULL, title.c_str(), "", pwd.c_str(), "", variant, NULL, NULL, XDP_SAVE_FILE_FLAG_NONE, NULL, &FileBrowser::FileBrowserSaveCallback, this);
|
||||
} else {
|
||||
xdp_portal_open_file(portal, NULL, title.c_str(), variant, NULL, NULL, XDP_OPEN_FILE_FLAG_NONE, NULL, &FileBrowser::FileBrowserOpenCallback, this);
|
||||
}
|
||||
#else
|
||||
fallback.Open();
|
||||
#endif
|
||||
}
|
||||
#ifdef PORTALS
|
||||
void FileBrowser::FileBrowserOpenCallback(GObject *src, GAsyncResult *res, gpointer data) {
|
||||
(void)src;
|
||||
FileBrowser *self = (FileBrowser*)data;
|
||||
GVariant *variant = xdp_portal_open_file_finish(self->portal, res, NULL);
|
||||
if (variant == NULL) {
|
||||
printf("Cancelled.\n");
|
||||
return;
|
||||
}
|
||||
GVariant *uris = g_variant_lookup_value(variant, "uris", G_VARIANT_TYPE_STRING_ARRAY);
|
||||
GVariant *first_uri = g_variant_get_child_value(uris, 0);
|
||||
gsize length;
|
||||
const gchar* c_str_without_terminater = g_variant_get_string(first_uri, &length);
|
||||
vector<char> c_str_vec;
|
||||
c_str_vec.reserve(length + 1);
|
||||
for (gsize i = 0; i < length; i++) {
|
||||
c_str_vec.push_back(c_str_without_terminater[i]);
|
||||
}
|
||||
c_str_vec.push_back('\0');
|
||||
const char *c_str = c_str_vec.data();
|
||||
printf("Selected file %s\n", c_str);
|
||||
string str = c_str;
|
||||
if (str.starts_with("file://")) {
|
||||
str = str.substr(string("file://").length());
|
||||
}
|
||||
self->open = false;
|
||||
self->selected = path(str);
|
||||
}
|
||||
|
||||
void FileBrowser::FileBrowserSaveCallback(GObject *src, GAsyncResult *res, gpointer data) {
|
||||
(void)src;
|
||||
FileBrowser *self = (FileBrowser*)data;
|
||||
self->open = false;
|
||||
GVariant *variant = xdp_portal_save_file_finish(self->portal, res, NULL);
|
||||
if (variant == NULL) {
|
||||
printf("Variant was null.\n");
|
||||
return;
|
||||
}
|
||||
GVariant *first_index = g_variant_get_child_value(variant, 0);
|
||||
if (first_index == NULL) {
|
||||
printf("Variant had no first index.\n");
|
||||
return;
|
||||
}
|
||||
const char *c_str = (const char*)g_variant_get_bytestring(first_index);
|
||||
string str = c_str;
|
||||
if (str.starts_with("file://")) {
|
||||
str = str.substr(string("file://").length());
|
||||
}
|
||||
self->selected = path(str);
|
||||
}
|
||||
#endif
|
||||
|
||||
void FileBrowser::Display() {
|
||||
#ifdef PORTALS
|
||||
g_main_context_iteration(main_context, false);
|
||||
#else
|
||||
fallback.Display()
|
||||
#endif
|
||||
}
|
||||
|
||||
void FileBrowser::ClearSelected() {
|
||||
selected = optional<path>();
|
||||
#ifndef PORTALS
|
||||
fallback.ClearSelected();
|
||||
#endif
|
||||
}
|
||||
void FileBrowser::SetTitle(string title) {
|
||||
this->title = title;
|
||||
#ifndef PORTALS
|
||||
fallback.SetTitle(title);
|
||||
#endif
|
||||
}
|
||||
bool FileBrowser::IsOpened() {
|
||||
#ifdef PORTALS
|
||||
return open;
|
||||
#else
|
||||
return fallback.IsOpened();
|
||||
#endif
|
||||
}
|
||||
FileBrowser::~FileBrowser() {
|
||||
#ifdef PORTALS
|
||||
if (variant != NULL) {
|
||||
g_variant_unref(variant);
|
||||
}
|
||||
if (type != NULL) {
|
||||
g_variant_type_free(type);
|
||||
}
|
||||
if (inner_filter_type != NULL) {
|
||||
g_variant_type_free(inner_filter_type);
|
||||
}
|
||||
g_main_loop_quit(main_loop);
|
||||
#endif
|
||||
}
|
51
file_browser.h
Normal file
51
file_browser.h
Normal file
|
@ -0,0 +1,51 @@
|
|||
#pragma once
|
||||
#include <string>
|
||||
#include <vector>
|
||||
#include <filesystem>
|
||||
#include <optional>
|
||||
#ifdef PORTALS
|
||||
#include <libportal/portal.h>
|
||||
#include <libportal/filechooser.h>
|
||||
#endif
|
||||
#include "imgui.h"
|
||||
#include "imfilebrowser.h"
|
||||
|
||||
using std::string;
|
||||
using std::vector;
|
||||
using std::optional;
|
||||
using namespace std::filesystem;
|
||||
|
||||
class FileBrowser {
|
||||
#ifdef PORTALS
|
||||
XdpPortal *portal;
|
||||
GVariant *variant = NULL;
|
||||
GVariantType *type = NULL;
|
||||
GVariantType *inner_filter_type = NULL;
|
||||
GMainLoop *main_loop;
|
||||
GMainContext *main_context;
|
||||
static void FileBrowserOpenCallback(GObject *src, GAsyncResult *res, gpointer data);
|
||||
static void FileBrowserSaveCallback(GObject *src, GAsyncResult *res, gpointer data);
|
||||
bool open = false;
|
||||
#endif
|
||||
bool save;
|
||||
ImGui::FileBrowser fallback;
|
||||
path pwd;
|
||||
string filter_name;
|
||||
vector<string> filters;
|
||||
string title;
|
||||
optional<path> selected;
|
||||
public:
|
||||
void SetTitle(string title);
|
||||
void SetTypeFilters(string name, vector<string> filters);
|
||||
void SetPwd(path path);
|
||||
bool HasSelected();
|
||||
path GetSelected();
|
||||
void SetWindowSize(int width, int height);
|
||||
void SetWindowPos(int x, int y);
|
||||
void Display();
|
||||
void Open();
|
||||
void ClearSelected();
|
||||
bool IsOpened();
|
||||
FileBrowser(bool save);
|
||||
~FileBrowser();
|
||||
};
|
22
main.cpp
22
main.cpp
|
@ -1,7 +1,7 @@
|
|||
#include "imgui.h"
|
||||
#include "imgui_impl_sdl2.h"
|
||||
#include "imgui_impl_opengl3.h"
|
||||
#include "imfilebrowser.h"
|
||||
#include "file_browser.h"
|
||||
#include "playback.h"
|
||||
#include "theme.h"
|
||||
#include "icon.h"
|
||||
|
@ -177,9 +177,9 @@ int main(int, char**)
|
|||
bool show_demo_window = false;
|
||||
ImVec4 clear_color = ImVec4(0.45f, 0.55f, 0.60f, 1.00f);
|
||||
|
||||
ImGui::FileBrowser fileDialog;
|
||||
FileBrowser fileDialog(false);
|
||||
fileDialog.SetTitle("Open...");
|
||||
fileDialog.SetTypeFilters({ ".wav", ".ogg", ".mp3", ".qoa", ".flac", ".xm", ".mod"});
|
||||
fileDialog.SetTypeFilters("Audio files", { ".wav", ".ogg", ".mp3", ".qoa", ".flac", ".xm", ".mod"});
|
||||
std::string userdir = std::getenv(
|
||||
#ifdef _WIN32
|
||||
"UserProfile"
|
||||
|
@ -269,8 +269,16 @@ int main(int, char**)
|
|||
ImGui_ImplSDL2_ProcessEvent(&event);
|
||||
if (event.type == SDL_QUIT)
|
||||
done = true;
|
||||
if (event.type == SDL_WINDOWEVENT && event.window.event == SDL_WINDOWEVENT_CLOSE && event.window.windowID == SDL_GetWindowID(window))
|
||||
done = true;
|
||||
if (event.type == SDL_WINDOWEVENT) {
|
||||
if (event.window.event == SDL_WINDOWEVENT_RESIZED) {
|
||||
window_width = event.window.data1;
|
||||
window_height = event.window.data2;
|
||||
//SDL_GetWindowSize(window, &window_width, &window_height);
|
||||
}
|
||||
if (event.window.event == SDL_WINDOWEVENT_CLOSE && event.window.windowID == SDL_GetWindowID(window)) {
|
||||
done = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Start the Dear ImGui frame
|
||||
|
@ -398,6 +406,10 @@ int main(int, char**)
|
|||
Theme::ShowEditor(&theme_editor, theme);
|
||||
theme->Apply(accent_color);
|
||||
}
|
||||
if (fileDialog.IsOpened()) {
|
||||
fileDialog.SetWindowSize(window_width, window_height);
|
||||
fileDialog.SetWindowPos(0, 0);
|
||||
}
|
||||
fileDialog.Display();
|
||||
|
||||
if (fileDialog.HasSelected()) {
|
||||
|
|
20
meson.build
20
meson.build
|
@ -9,27 +9,34 @@ endif
|
|||
if get_option('gles')
|
||||
add_global_arguments('-DIMGUI_IMPL_OPENGL_ES2', language: 'cpp')
|
||||
endif
|
||||
# SDL Mixer X
|
||||
smx_opts = cmake.subproject_options()
|
||||
smx_opts.add_cmake_defines({'SDL_MIXER_X_STATIC': true, 'SDL_MIXER_X_SHARED': false, 'USE_MIDI_NATIVE_ALT': false, 'USE_MIDI_NATIVE': false})
|
||||
smx_opts.set_override_option('c_std', 'c99')
|
||||
smx_subproj = cmake.subproject('SDL-Mixer-X', options: smx_opts)
|
||||
#raudio_lib = static_library('raudio', 'raudio/src/raudio.c', c_args: ['-DRAUDIO_STANDALONE', '-DSUPPORT_MODULE_RAUDIO', '-DSUPPORT_FILEFORMAT_WAV', '-DSUPPORT_FILEFORMAT_OGG', '-DSUPPORT_FILEFORMAT_MP3', '-DSUPPORT_FILEFORMAT_QOA', '-DSUPPORT_FILEFORMAT_FLAC', '-DSUPPORT_FILEFORMAT_XM', '-DSUPPORT_FILEFORMAT_MOD', '-w'])
|
||||
#raudio_include = include_directories('raudio/src')
|
||||
#raudio_dep = declare_dependency(include_directories: raudio_include, link_with: raudio_lib)
|
||||
|
||||
opts = []
|
||||
|
||||
deps = [
|
||||
dependency('sdl2'),
|
||||
dependency('SDL2_image'),
|
||||
dependency('gl'),
|
||||
subproject('jsoncpp').get_variable('jsoncpp_dep'),
|
||||
dependency('soundtouch'),
|
||||
#raudio_dep,
|
||||
smx_subproj.dependency('SDL2_mixer_ext_Static'),
|
||||
smx_subproj.dependency('SDL2_mixer_ext_Static')
|
||||
]
|
||||
|
||||
if get_option('portals') and host_machine.system() == 'linux'
|
||||
# Dbus CXX
|
||||
deps += dependency('libportal')
|
||||
opts += '-DPORTALS'
|
||||
endif
|
||||
|
||||
srcs = [
|
||||
'main.cpp',
|
||||
'playback.cpp',
|
||||
'theme.cpp',
|
||||
'file_browser.cpp',
|
||||
'imgui/imgui.cpp',
|
||||
'imgui/imgui_widgets.cpp',
|
||||
'imgui/imgui_tables.cpp',
|
||||
|
@ -66,4 +73,5 @@ install_data('assets/com.experimentalcraft.NekoPlayer.metainfo.xml', install_dir
|
|||
exe = executable('neko-player', srcs,
|
||||
dependencies: deps,
|
||||
include_directories: include_dirs,
|
||||
install : true)
|
||||
install : true,
|
||||
cpp_args: opts)
|
||||
|
|
|
@ -1 +0,0 @@
|
|||
option('gles', type: 'boolean', value: false)
|
|
@ -1 +1,2 @@
|
|||
option('gles', type: 'boolean', value: false)
|
||||
option('portals', type: 'boolean', value: true)
|
|
@ -27,8 +27,8 @@ ImVec4 change_accent_color(ImVec4 in, float hue) {
|
|||
return out;
|
||||
}
|
||||
bool Theme::ShowEditor(bool* open, Theme* &theme) {
|
||||
static ImGui::FileBrowser importDialog;
|
||||
static ImGui::FileBrowser exportDialog;
|
||||
static FileBrowser importDialog(false);
|
||||
static FileBrowser exportDialog(true);
|
||||
static bool loadOpen = false;
|
||||
static bool saveAsOpen = false;
|
||||
ImGui::Begin("Theme Editor", open);
|
||||
|
@ -54,7 +54,7 @@ bool Theme::ShowEditor(bool* open, Theme* &theme) {
|
|||
}
|
||||
if (ImGui::Button("Import...", buttonSize)) {
|
||||
importDialog.SetTitle("Import theme...");
|
||||
importDialog.SetTypeFilters({ ".json"});
|
||||
importDialog.SetTypeFilters("Theme JSON files", { ".json"});
|
||||
std::string userdir = std::getenv(
|
||||
#ifdef _WIN32
|
||||
"UserProfile"
|
||||
|
@ -67,9 +67,8 @@ bool Theme::ShowEditor(bool* open, Theme* &theme) {
|
|||
}
|
||||
ImGui::SameLine();
|
||||
if (ImGui::Button("Export...", buttonSize)) {
|
||||
exportDialog = ImGui::FileBrowser(ImGuiFileBrowserFlags_EnterNewFilename|ImGuiFileBrowserFlags_CreateNewDir);
|
||||
exportDialog.SetTitle("Export theme...");
|
||||
exportDialog.SetTypeFilters({ ".json"});
|
||||
exportDialog.SetTypeFilters("Theme JSON files", { ".json"});
|
||||
std::string userdir = std::getenv(
|
||||
#ifdef _WIN32
|
||||
"UserProfile"
|
||||
|
|
2
theme.h
2
theme.h
|
@ -2,7 +2,7 @@
|
|||
#include "imgui.h"
|
||||
#include <set>
|
||||
#include <string>
|
||||
#include "imfilebrowser.h"
|
||||
#include "file_browser.h"
|
||||
#include <filesystem>
|
||||
using std::string;
|
||||
using namespace std::filesystem;
|
||||
|
|
Loading…
Reference in a new issue