Haiku support (#596)

* Don't apply Wayland videodriver workaround on Haiku

* dirent.d_type-less type detecting in IGFD

The Dumb Way(tm). `stat`'s `st_mode` should be nicer?

* CMake check for dirent.d_type, stat-based fallback

* Move config dir setup to separate function

Nicer to work with than macro kerfuffle.

* Default sysFileDialog to off on Haiku

* Logging stuff

* Honour CMAKE_INSTALL_BINDIR

* Use find_directory on Haiku

Includes forgotten configPath line when home==NULL.

* Address PR review notes
This commit is contained in:
Christoph Neidahl 2022-07-24 05:11:30 +02:00 committed by GitHub
parent de77d51d7a
commit e08399156a
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
8 changed files with 152 additions and 97 deletions

View file

@ -583,6 +583,13 @@ if (NOT WIN32 AND NOT APPLE)
endif() endif()
endif() endif()
if (NOT WIN32)
try_compile(HAVE_DIRENT_TYPE ${CMAKE_BINARY_DIR}/check SOURCES ${CMAKE_SOURCE_DIR}/src/check/check_dirent_type.c)
if (HAVE_DIRENT_TYPE)
list(APPEND DEPENDENCIES_DEFINES HAVE_DIRENT_TYPE)
endif()
endif()
set(USED_SOURCES ${ENGINE_SOURCES} ${AUDIO_SOURCES} src/main.cpp) set(USED_SOURCES ${ENGINE_SOURCES} ${AUDIO_SOURCES} src/main.cpp)
if (USE_BACKWARD) if (USE_BACKWARD)
@ -692,10 +699,9 @@ if (PKG_CONFIG_FOUND AND (SYSTEM_FMT OR SYSTEM_LIBSNDFILE OR SYSTEM_ZLIB OR SYST
endif() endif()
if (NOT ANDROID OR TERMUX) if (NOT ANDROID OR TERMUX)
install(TARGETS furnace RUNTIME DESTINATION bin)
if (NOT WIN32 AND NOT APPLE) if (NOT WIN32 AND NOT APPLE)
include(GNUInstallDirs) include(GNUInstallDirs)
install(TARGETS furnace RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR})
install(FILES res/furnace.desktop DESTINATION ${CMAKE_INSTALL_DATADIR}/applications) install(FILES res/furnace.desktop DESTINATION ${CMAKE_INSTALL_DATADIR}/applications)
install(FILES res/furnace.appdata.xml DESTINATION ${CMAKE_INSTALL_DATADIR}/metainfo) install(FILES res/furnace.appdata.xml DESTINATION ${CMAKE_INSTALL_DATADIR}/metainfo)
install(DIRECTORY papers DESTINATION ${CMAKE_INSTALL_DOCDIR}) install(DIRECTORY papers DESTINATION ${CMAKE_INSTALL_DOCDIR})
@ -708,6 +714,8 @@ if (NOT ANDROID OR TERMUX)
install(FILES res/icon.iconset/icon_${res}@2x.png RENAME furnace.png DESTINATION ${CMAKE_INSTALL_DATADIR}/icons/hicolor/${res}@2/apps) install(FILES res/icon.iconset/icon_${res}@2x.png RENAME furnace.png DESTINATION ${CMAKE_INSTALL_DATADIR}/icons/hicolor/${res}@2/apps)
endforeach() endforeach()
install(FILES res/logo.png RENAME furnace.png DESTINATION ${CMAKE_INSTALL_DATADIR}/icons/hicolor/1024x1024/apps) install(FILES res/logo.png RENAME furnace.png DESTINATION ${CMAKE_INSTALL_DATADIR}/icons/hicolor/1024x1024/apps)
else()
install(TARGETS furnace RUNTIME DESTINATION bin)
endif() endif()
set(CPACK_PACKAGE_NAME "Furnace") set(CPACK_PACKAGE_NAME "Furnace")

View file

@ -58,7 +58,7 @@ SOFTWARE.
#ifndef PATH_MAX #ifndef PATH_MAX
#define PATH_MAX 260 #define PATH_MAX 260
#endif // PATH_MAX #endif // PATH_MAX
#elif defined(__linux__) || defined(__FreeBSD__) || defined(__NetBSD__) || defined(__APPLE__) || defined (__EMSCRIPTEN__) #elif defined(__linux__) || defined(__FreeBSD__) || defined(__NetBSD__) || defined(__APPLE__) || defined (__EMSCRIPTEN__) || defined(__HAIKU__)
#define UNIX #define UNIX
#define stricmp strcasecmp #define stricmp strcasecmp
#include <sys/types.h> #include <sys/types.h>
@ -1547,8 +1547,11 @@ namespace IGFD
for (i = 0; i < n; i++) for (i = 0; i < n; i++)
{ {
struct dirent* ent = files[i]; struct dirent* ent = files[i];
std::string where = path + std::string("/") + std::string(ent->d_name);
char fileType = 0; char fileType = 0;
#ifdef HAVE_DIRENT_TYPE
if (ent->d_type != DT_UNKNOWN)
{
switch (ent->d_type) switch (ent->d_type)
{ {
case DT_REG: case DT_REG:
@ -1556,20 +1559,42 @@ namespace IGFD
case DT_DIR: case DT_DIR:
fileType = 'd'; break; fileType = 'd'; break;
case DT_LNK: case DT_LNK:
std::string where = path+std::string("/")+std::string(ent->d_name);
DIR* dirTest = opendir(where.c_str()); DIR* dirTest = opendir(where.c_str());
if (dirTest==NULL) { if (dirTest == NULL)
if (errno==ENOTDIR) { {
if (errno == ENOTDIR)
{
fileType = 'f'; fileType = 'f';
} else { }
else
{
fileType = 'l'; fileType = 'l';
} }
} else { }
else
{
fileType = 'd'; fileType = 'd';
closedir(dirTest); closedir(dirTest);
} }
break; break;
} }
}
else
#endif // HAVE_DIRENT_TYPE
{
struct stat filestat;
if (stat(where.c_str(), &filestat) == 0)
{
if (S_ISDIR(filestat.st_mode))
{
fileType = 'd';
}
else
{
fileType = 'f';
}
}
}
auto fileNameExt = ent->d_name; auto fileNameExt = ent->d_name;

View file

@ -0,0 +1,7 @@
#include <dirent.h>
int main(int, char**) {
struct dirent deTest = { };
unsigned char deType = deTest.d_type;
return 0;
}

View file

@ -23,11 +23,84 @@
#include <fmt/printf.h> #include <fmt/printf.h>
#ifdef _WIN32 #ifdef _WIN32
#include "winStuff.h"
#define CONFIG_FILE "\\furnace.cfg" #define CONFIG_FILE "\\furnace.cfg"
#else #else
#ifdef __HAIKU__
#include <support/SupportDefs.h>
#include <storage/FindDirectory.h>
#endif
#include <unistd.h>
#include <pwd.h>
#include <sys/stat.h>
#define CONFIG_FILE "/furnace.cfg" #define CONFIG_FILE "/furnace.cfg"
#endif #endif
void DivEngine::initConfDir() {
#ifdef _WIN32
// maybe move this function in here instead?
configPath=getWinConfigPath();
#elif defined (IS_MOBILE)
configPath=SDL_GetPrefPath();
#else
#ifdef __HAIKU__
char userSettingsDir[PATH_MAX];
status_t findUserDir = find_directory(B_USER_SETTINGS_DIRECTORY,0,true,userSettingsDir,PATH_MAX);
if (findUserDir==B_OK) {
configPath=userSettingsDir;
} else {
logW("unable to find/create user settings directory (%s)!",strerror(findUserDir));
configPath=".";
return;
}
#else
// TODO this should check XDG_CONFIG_HOME first
char* home=getenv("HOME");
if (home==NULL) {
int uid=getuid();
struct passwd* entry=getpwuid(uid);
if (entry==NULL) {
logW("unable to determine home directory (%s)!",strerror(errno));
configPath=".";
return;
} else {
configPath=entry->pw_dir;
}
} else {
configPath=home;
}
#ifdef __APPLE__
configPath+="/Library/Application Support";
#else
// FIXME this doesn't honour XDG_CONFIG_HOME *at all*
configPath+="/.config";
#endif // __APPLE__
#endif // __HAIKU__
#ifdef __APPLE__
configPath+="/Furnace";
#else
configPath+="/furnace";
#endif // __APPLE__
struct stat st;
std::string pathSep="/";
configPath+=pathSep;
size_t sepPos=configPath.find(pathSep,1);
while (sepPos!=std::string::npos) {
std::string subpath=configPath.substr(0,sepPos++);
if (stat(subpath.c_str(),&st)!=0) {
logI("creating config path element %s ...",subpath.c_str());
if (mkdir(subpath.c_str(),0755)!=0) {
logW("could not create config path element %s! (%s)",subpath.c_str(),strerror(errno));
configPath=".";
return;
}
}
sepPos=configPath.find(pathSep,sepPos);
}
configPath.resize(configPath.length()-pathSep.length());
#endif // _WIN32
}
bool DivEngine::saveConf() { bool DivEngine::saveConf() {
configFile=configPath+String(CONFIG_FILE); configFile=configPath+String(CONFIG_FILE);
FILE* f=ps_fopen(configFile.c_str(),"wb"); FILE* f=ps_fopen(configFile.c_str(),"wb");

View file

@ -27,11 +27,6 @@
#include "../audio/sdlAudio.h" #include "../audio/sdlAudio.h"
#endif #endif
#include <stdexcept> #include <stdexcept>
#ifndef _WIN32
#include <unistd.h>
#include <pwd.h>
#include <sys/stat.h>
#endif
#ifdef HAVE_JACK #ifdef HAVE_JACK
#include "../audio/jack.h" #include "../audio/jack.h"
#endif #endif
@ -2989,36 +2984,6 @@ void DivEngine::quitDispatch() {
BUSY_END; BUSY_END;
} }
#define CHECK_CONFIG_DIR_MAC() \
configPath+="/Library/Application Support/Furnace"; \
if (stat(configPath.c_str(),&st)<0) { \
logI("creating config dir..."); \
if (mkdir(configPath.c_str(),0755)<0) { \
logW("could not make config dir! (%s)",strerror(errno)); \
configPath="."; \
} \
}
#define CHECK_CONFIG_DIR() \
configPath+="/.config"; \
if (stat(configPath.c_str(),&st)<0) { \
logI("creating user config dir..."); \
if (mkdir(configPath.c_str(),0755)<0) { \
logW("could not make user config dir! (%s)",strerror(errno)); \
configPath="."; \
} \
} \
if (configPath!=".") { \
configPath+="/furnace"; \
if (stat(configPath.c_str(),&st)<0) { \
logI("creating config dir..."); \
if (mkdir(configPath.c_str(),0755)<0) { \
logW("could not make config dir! (%s)",strerror(errno)); \
configPath="."; \
} \
} \
}
bool DivEngine::initAudioBackend() { bool DivEngine::initAudioBackend() {
// load values // load values
if (audioEngine==DIV_AUDIO_NULL) { if (audioEngine==DIV_AUDIO_NULL) {
@ -3148,45 +3113,12 @@ bool DivEngine::deinitAudioBackend() {
return true; return true;
} }
#ifdef _WIN32
#include "winStuff.h"
#endif
bool DivEngine::init() { bool DivEngine::init() {
// register systems // register systems
if (!systemsRegistered) registerSystems(); if (!systemsRegistered) registerSystems();
// init config // init config
#ifdef _WIN32 initConfDir();
configPath=getWinConfigPath();
#elif defined(IS_MOBILE)
configPath=SDL_GetPrefPath("tildearrow","furnace");
#else
struct stat st;
char* home=getenv("HOME");
if (home==NULL) {
int uid=getuid();
struct passwd* entry=getpwuid(uid);
if (entry==NULL) {
logW("unable to determine config directory! (%s)",strerror(errno));
configPath=".";
} else {
configPath=entry->pw_dir;
#ifdef __APPLE__
CHECK_CONFIG_DIR_MAC();
#else
CHECK_CONFIG_DIR();
#endif
}
} else {
configPath=home;
#ifdef __APPLE__
CHECK_CONFIG_DIR_MAC();
#else
CHECK_CONFIG_DIR();
#endif
}
#endif
logD("config path: %s",configPath.c_str()); logD("config path: %s",configPath.c_str());
loadConf(); loadConf();

View file

@ -485,6 +485,9 @@ class DivEngine {
// returns the minimum VGM version which may carry the specified system, or 0 if none. // returns the minimum VGM version which may carry the specified system, or 0 if none.
int minVGMVersion(DivSystem which); int minVGMVersion(DivSystem which);
// determine and setup config dir
void initConfDir();
// save config // save config
bool saveConf(); bool saveConf();

View file

@ -39,6 +39,13 @@
#define POWER_SAVE_DEFAULT 0 #define POWER_SAVE_DEFAULT 0
#endif #endif
#ifdef __HAIKU__
// NFD doesn't support Haiku
#define SYS_FILE_DIALOG_DEFAULT 0
#else
#define SYS_FILE_DIALOG_DEFAULT 1
#endif
const char* mainFonts[]={ const char* mainFonts[]={
"IBM Plex Sans", "IBM Plex Sans",
"Liberation Sans", "Liberation Sans",
@ -2062,7 +2069,7 @@ void FurnaceGUI::syncSettings() {
settings.insFocusesPattern=e->getConfInt("insFocusesPattern",1); settings.insFocusesPattern=e->getConfInt("insFocusesPattern",1);
settings.stepOnInsert=e->getConfInt("stepOnInsert",0); settings.stepOnInsert=e->getConfInt("stepOnInsert",0);
settings.unifiedDataView=e->getConfInt("unifiedDataView",0); settings.unifiedDataView=e->getConfInt("unifiedDataView",0);
settings.sysFileDialog=e->getConfInt("sysFileDialog",1); settings.sysFileDialog=e->getConfInt("sysFileDialog",SYS_FILE_DIALOG_DEFAULT);
settings.roundedWindows=e->getConfInt("roundedWindows",1); settings.roundedWindows=e->getConfInt("roundedWindows",1);
settings.roundedButtons=e->getConfInt("roundedButtons",1); settings.roundedButtons=e->getConfInt("roundedButtons",1);
settings.roundedMenus=e->getConfInt("roundedMenus",0); settings.roundedMenus=e->getConfInt("roundedMenus",0);

View file

@ -295,7 +295,7 @@ int main(int argc, char** argv) {
logE("CoInitializeEx failed!"); logE("CoInitializeEx failed!");
} }
#endif #endif
#if !(defined(__APPLE__) || defined(_WIN32) || defined(ANDROID)) #if !(defined(__APPLE__) || defined(_WIN32) || defined(ANDROID) || defined(__HAIKU__))
// workaround for Wayland HiDPI issue // workaround for Wayland HiDPI issue
if (getenv("SDL_VIDEODRIVER")==NULL) { if (getenv("SDL_VIDEODRIVER")==NULL) {
setenv("SDL_VIDEODRIVER","x11",1); setenv("SDL_VIDEODRIVER","x11",1);