2010-06-22 23:55:25 +00:00
|
|
|
/* ScummVM - Graphic Adventure Engine
|
|
|
|
*
|
|
|
|
* ScummVM is the legal property of its developers, whose names
|
|
|
|
* are too numerous to list here. Please refer to the COPYRIGHT
|
|
|
|
* file distributed with this source distribution.
|
|
|
|
*
|
|
|
|
* This program is free software; you can redistribute it and/or
|
|
|
|
* modify it under the terms of the GNU General Public License
|
|
|
|
* as published by the Free Software Foundation; either version 2
|
|
|
|
* of the License, or (at your option) any later version.
|
2014-02-18 02:34:24 +01:00
|
|
|
*
|
2010-06-22 23:55:25 +00:00
|
|
|
* This program is distributed in the hope that it will be useful,
|
|
|
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
|
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
|
|
* GNU General Public License for more details.
|
2014-02-18 02:34:24 +01:00
|
|
|
*
|
2010-06-22 23:55:25 +00:00
|
|
|
* You should have received a copy of the GNU General Public License
|
|
|
|
* along with this program; if not, write to the Free Software
|
|
|
|
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
|
|
|
*
|
|
|
|
*/
|
|
|
|
|
2011-05-23 19:11:19 +02:00
|
|
|
#define FORBIDDEN_SYMBOL_EXCEPTION_getenv
|
2011-05-02 14:42:08 +02:00
|
|
|
#define FORBIDDEN_SYMBOL_EXCEPTION_mkdir
|
2011-06-04 15:07:12 +02:00
|
|
|
#define FORBIDDEN_SYMBOL_EXCEPTION_exit
|
|
|
|
#define FORBIDDEN_SYMBOL_EXCEPTION_unistd_h
|
2011-05-08 01:25:09 +02:00
|
|
|
#define FORBIDDEN_SYMBOL_EXCEPTION_time_h //On IRIX, sys/stat.h includes sys/time.h
|
2016-09-09 23:51:40 +01:00
|
|
|
#define FORBIDDEN_SYMBOL_EXCEPTION_system
|
2011-05-02 14:42:08 +02:00
|
|
|
|
2010-11-29 16:18:43 +00:00
|
|
|
#include "common/scummsys.h"
|
|
|
|
|
2011-05-05 15:38:54 +02:00
|
|
|
#ifdef POSIX
|
2010-06-23 21:07:03 +00:00
|
|
|
|
|
|
|
#include "backends/platform/sdl/posix/posix.h"
|
2010-06-22 23:55:25 +00:00
|
|
|
#include "backends/saves/posix/posix-saves.h"
|
|
|
|
#include "backends/fs/posix/posix-fs-factory.h"
|
2016-01-29 20:09:29 +01:00
|
|
|
#include "backends/fs/posix/posix-fs.h"
|
2011-04-01 08:01:53 -04:00
|
|
|
#include "backends/taskbar/unity/unity-taskbar.h"
|
2010-06-22 23:55:25 +00:00
|
|
|
|
2015-09-27 18:02:21 -04:00
|
|
|
#ifdef USE_LINUXCD
|
|
|
|
#include "backends/audiocd/linux/linux-audiocd.h"
|
|
|
|
#endif
|
|
|
|
|
2016-09-09 23:51:40 +01:00
|
|
|
#include "common/textconsole.h"
|
|
|
|
|
|
|
|
#include <stdlib.h>
|
2015-09-27 18:02:21 -04:00
|
|
|
#include <errno.h>
|
2010-11-29 18:30:23 +00:00
|
|
|
#include <sys/stat.h>
|
2011-06-04 15:07:12 +02:00
|
|
|
#include <sys/wait.h>
|
|
|
|
#include <unistd.h>
|
2010-11-29 18:30:23 +00:00
|
|
|
|
2017-12-14 13:51:04 -06:00
|
|
|
#include <spawn.h>
|
|
|
|
extern char **environ;
|
|
|
|
|
2010-06-27 05:12:37 +00:00
|
|
|
OSystem_POSIX::OSystem_POSIX(Common::String baseConfigName)
|
|
|
|
:
|
|
|
|
_baseConfigName(baseConfigName) {
|
2010-06-24 17:37:09 +00:00
|
|
|
}
|
|
|
|
|
2010-06-24 23:51:02 +00:00
|
|
|
void OSystem_POSIX::init() {
|
2010-06-23 19:34:07 +00:00
|
|
|
// Initialze File System Factory
|
2010-06-22 23:55:25 +00:00
|
|
|
_fsFactory = new POSIXFilesystemFactory();
|
2010-06-24 17:37:09 +00:00
|
|
|
|
2014-01-21 19:01:28 +01:00
|
|
|
#if defined(USE_TASKBAR) && defined(USE_UNITY)
|
2011-04-04 12:35:19 -04:00
|
|
|
// Initialize taskbar manager
|
|
|
|
_taskbarManager = new UnityTaskbarManager();
|
2011-04-01 08:01:53 -04:00
|
|
|
#endif
|
|
|
|
|
2010-06-24 17:37:09 +00:00
|
|
|
// Invoke parent implementation of this method
|
|
|
|
OSystem_SDL::init();
|
2010-06-22 23:55:25 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
void OSystem_POSIX::initBackend() {
|
2010-06-23 19:34:07 +00:00
|
|
|
// Create the savefile manager
|
|
|
|
if (_savefileManager == 0)
|
2010-06-22 23:55:25 +00:00
|
|
|
_savefileManager = new POSIXSaveFileManager();
|
|
|
|
|
|
|
|
// Invoke parent implementation of this method
|
2010-06-23 19:34:07 +00:00
|
|
|
OSystem_SDL::initBackend();
|
2011-04-04 12:35:19 -04:00
|
|
|
|
2014-01-21 19:01:28 +01:00
|
|
|
#if defined(USE_TASKBAR) && defined(USE_UNITY)
|
2011-04-04 12:35:19 -04:00
|
|
|
// Register the taskbar manager as an event source (this is necessary for the glib event loop to be run)
|
|
|
|
_eventManager->getEventDispatcher()->registerSource((UnityTaskbarManager *)_taskbarManager, false);
|
|
|
|
#endif
|
2010-06-22 23:55:25 +00:00
|
|
|
}
|
|
|
|
|
2011-06-04 15:07:12 +02:00
|
|
|
bool OSystem_POSIX::hasFeature(Feature f) {
|
2016-09-09 23:51:40 +01:00
|
|
|
if (f == kFeatureDisplayLogFile || f == kFeatureOpenUrl)
|
2011-06-04 15:07:12 +02:00
|
|
|
return true;
|
|
|
|
return OSystem_SDL::hasFeature(f);
|
|
|
|
}
|
|
|
|
|
2010-06-22 23:55:25 +00:00
|
|
|
Common::String OSystem_POSIX::getDefaultConfigFileName() {
|
2013-11-14 18:35:03 +00:00
|
|
|
Common::String configFile;
|
2010-06-22 23:55:25 +00:00
|
|
|
|
2016-01-29 19:56:20 +01:00
|
|
|
Common::String prefix;
|
|
|
|
#ifdef MACOSX
|
|
|
|
prefix = getenv("HOME");
|
|
|
|
#elif !defined(SAMSUNGTV)
|
|
|
|
const char *envVar;
|
|
|
|
// Our old configuration file path for POSIX systems was ~/.scummvmrc.
|
|
|
|
// If that file exists, we still use it.
|
|
|
|
envVar = getenv("HOME");
|
|
|
|
if (envVar && *envVar) {
|
|
|
|
configFile = envVar;
|
|
|
|
configFile += '/';
|
|
|
|
configFile += ".scummvmrc";
|
|
|
|
|
|
|
|
if (configFile.size() < MAXPATHLEN) {
|
|
|
|
struct stat sb;
|
|
|
|
if (stat(configFile.c_str(), &sb) == 0) {
|
|
|
|
return configFile;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// On POSIX systems we follow the XDG Base Directory Specification for
|
|
|
|
// where to store files. The version we based our code upon can be found
|
|
|
|
// over here: http://standards.freedesktop.org/basedir-spec/basedir-spec-0.8.html
|
|
|
|
envVar = getenv("XDG_CONFIG_HOME");
|
|
|
|
if (!envVar || !*envVar) {
|
|
|
|
envVar = getenv("HOME");
|
|
|
|
if (!envVar) {
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
2016-01-29 20:09:29 +01:00
|
|
|
if (Posix::assureDirectoryExists(".config", envVar)) {
|
2016-01-29 19:56:20 +01:00
|
|
|
prefix = envVar;
|
|
|
|
prefix += "/.config";
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
prefix = envVar;
|
|
|
|
}
|
|
|
|
|
2016-01-29 20:09:29 +01:00
|
|
|
if (!prefix.empty() && Posix::assureDirectoryExists("scummvm", prefix.c_str())) {
|
2016-01-29 19:56:20 +01:00
|
|
|
prefix += "/scummvm";
|
|
|
|
}
|
|
|
|
#endif
|
|
|
|
|
|
|
|
if (!prefix.empty() && (prefix.size() + 1 + _baseConfigName.size()) < MAXPATHLEN) {
|
|
|
|
configFile = prefix;
|
|
|
|
configFile += '/';
|
|
|
|
configFile += _baseConfigName;
|
2013-11-14 18:35:03 +00:00
|
|
|
} else {
|
|
|
|
configFile = _baseConfigName;
|
|
|
|
}
|
2010-06-22 23:55:25 +00:00
|
|
|
|
|
|
|
return configFile;
|
|
|
|
}
|
2010-06-23 21:07:03 +00:00
|
|
|
|
2016-07-29 09:59:06 +02:00
|
|
|
void OSystem_POSIX::addSysArchivesToSearchSet(Common::SearchSet &s, int priority) {
|
2016-08-04 16:19:12 +02:00
|
|
|
#ifdef DATA_PATH
|
2016-07-29 09:59:06 +02:00
|
|
|
const char *snap = getenv("SNAP");
|
|
|
|
if (snap) {
|
|
|
|
Common::String dataPath = Common::String(snap) + DATA_PATH;
|
|
|
|
Common::FSNode dataNode(dataPath);
|
|
|
|
if (dataNode.exists() && dataNode.isDirectory()) {
|
|
|
|
// This is the same priority which is used for the data path (below),
|
|
|
|
// but we insert this one first, so it will be searched first.
|
|
|
|
s.add(dataPath, new Common::FSDirectory(dataNode, 4), priority);
|
|
|
|
}
|
|
|
|
}
|
2016-08-04 16:19:12 +02:00
|
|
|
#endif
|
2016-07-29 09:59:06 +02:00
|
|
|
|
|
|
|
// For now, we always add the data path, just in case SNAP doesn't make sense.
|
|
|
|
OSystem_SDL::addSysArchivesToSearchSet(s, priority);
|
|
|
|
}
|
|
|
|
|
2010-11-29 18:30:23 +00:00
|
|
|
Common::WriteStream *OSystem_POSIX::createLogFile() {
|
2011-06-03 12:08:37 +02:00
|
|
|
// Start out by resetting _logFilePath, so that in case
|
|
|
|
// of a failure, we know that no log file is open.
|
|
|
|
_logFilePath.clear();
|
|
|
|
|
2016-01-29 19:09:46 +01:00
|
|
|
const char *prefix = nullptr;
|
2016-01-29 18:57:43 +01:00
|
|
|
Common::String logFile;
|
2010-11-29 19:54:55 +00:00
|
|
|
#ifdef MACOSX
|
2016-01-29 19:09:46 +01:00
|
|
|
prefix = getenv("HOME");
|
|
|
|
if (prefix == nullptr) {
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
2016-01-29 18:57:43 +01:00
|
|
|
logFile = "Library/Logs";
|
|
|
|
#elif SAMSUNGTV
|
2016-01-29 19:09:46 +01:00
|
|
|
prefix = nullptr;
|
2011-05-23 18:11:40 +02:00
|
|
|
logFile = "/mtd_ram";
|
2016-01-29 18:57:43 +01:00
|
|
|
#else
|
2016-01-29 19:26:05 +01:00
|
|
|
// On POSIX systems we follow the XDG Base Directory Specification for
|
|
|
|
// where to store files. The version we based our code upon can be found
|
|
|
|
// over here: http://standards.freedesktop.org/basedir-spec/basedir-spec-0.8.html
|
|
|
|
prefix = getenv("XDG_CACHE_HOME");
|
|
|
|
if (prefix == nullptr || !*prefix) {
|
|
|
|
prefix = getenv("HOME");
|
|
|
|
if (prefix == nullptr) {
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
logFile = ".cache/";
|
2016-01-29 19:09:46 +01:00
|
|
|
}
|
|
|
|
|
2016-01-29 19:26:05 +01:00
|
|
|
logFile += "scummvm/logs";
|
2011-05-23 18:11:40 +02:00
|
|
|
#endif
|
2010-11-29 18:30:23 +00:00
|
|
|
|
2016-01-29 20:09:29 +01:00
|
|
|
if (!Posix::assureDirectoryExists(logFile, prefix)) {
|
2010-11-29 18:30:23 +00:00
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
2016-01-29 19:09:46 +01:00
|
|
|
if (prefix) {
|
|
|
|
logFile = Common::String::format("%s/%s", prefix, logFile.c_str());
|
2010-11-29 18:30:23 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
logFile += "/scummvm.log";
|
|
|
|
|
|
|
|
Common::FSNode file(logFile);
|
2011-06-03 12:08:37 +02:00
|
|
|
Common::WriteStream *stream = file.createWriteStream();
|
|
|
|
if (stream)
|
|
|
|
_logFilePath = logFile;
|
|
|
|
return stream;
|
2010-11-29 18:30:23 +00:00
|
|
|
}
|
|
|
|
|
2011-06-04 15:07:12 +02:00
|
|
|
bool OSystem_POSIX::displayLogFile() {
|
|
|
|
if (_logFilePath.empty())
|
|
|
|
return false;
|
|
|
|
|
|
|
|
// FIXME: This may not work perfectly when in fullscreen mode.
|
|
|
|
// On my system it drops from fullscreen without ScummVM noticing,
|
|
|
|
// so the next Alt-Enter does nothing, going from windowed to windowed.
|
|
|
|
// (wjp, 20110604)
|
|
|
|
|
|
|
|
pid_t pid = fork();
|
|
|
|
if (pid < 0) {
|
|
|
|
// failed to fork
|
|
|
|
return false;
|
|
|
|
} else if (pid == 0) {
|
|
|
|
|
|
|
|
// Try xdg-open first
|
2012-02-15 09:53:31 -06:00
|
|
|
execlp("xdg-open", "xdg-open", _logFilePath.c_str(), (char *)0);
|
2011-06-04 15:07:12 +02:00
|
|
|
|
|
|
|
// If we're here, that clearly failed.
|
2011-06-04 16:39:15 +02:00
|
|
|
|
|
|
|
// TODO: We may also want to try detecting the case where
|
|
|
|
// xdg-open is successfully executed but returns an error code.
|
|
|
|
|
2011-06-04 15:07:12 +02:00
|
|
|
// Try xterm+less next
|
|
|
|
|
2012-02-15 09:53:31 -06:00
|
|
|
execlp("xterm", "xterm", "-e", "less", _logFilePath.c_str(), (char *)0);
|
2011-06-04 15:07:12 +02:00
|
|
|
|
|
|
|
// TODO: If less does not exist we could fall back to 'more'.
|
|
|
|
// However, we'll have to use 'xterm -hold' for that to prevent the
|
|
|
|
// terminal from closing immediately (for short log files) or
|
|
|
|
// unexpectedly.
|
|
|
|
|
|
|
|
exit(127);
|
|
|
|
}
|
|
|
|
|
|
|
|
int status;
|
|
|
|
// Wait for viewer to close.
|
|
|
|
// (But note that xdg-open may have spawned a viewer in the background.)
|
2011-06-04 16:39:15 +02:00
|
|
|
|
|
|
|
// FIXME: We probably want the viewer to always open in the background.
|
|
|
|
// This may require installing a SIGCHLD handler.
|
2011-06-04 15:07:12 +02:00
|
|
|
pid = waitpid(pid, &status, 0);
|
|
|
|
|
|
|
|
if (pid < 0) {
|
|
|
|
// Probably nothing sensible to do in this error situation
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
return WIFEXITED(status) && WEXITSTATUS(status) == 0;
|
|
|
|
}
|
|
|
|
|
2016-09-09 23:51:40 +01:00
|
|
|
bool OSystem_POSIX::openUrl(const Common::String &url) {
|
|
|
|
// inspired by Qt's "qdesktopservices_x11.cpp"
|
|
|
|
|
|
|
|
// try "standards"
|
|
|
|
if (launchBrowser("xdg-open", url))
|
|
|
|
return true;
|
|
|
|
if (launchBrowser(getenv("DEFAULT_BROWSER"), url))
|
|
|
|
return true;
|
|
|
|
if (launchBrowser(getenv("BROWSER"), url))
|
|
|
|
return true;
|
|
|
|
|
|
|
|
// try desktop environment specific tools
|
|
|
|
if (launchBrowser("gnome-open", url)) // gnome
|
|
|
|
return true;
|
2017-12-14 13:51:04 -06:00
|
|
|
if (launchBrowser("kfmclient", url)) // kde
|
2016-09-09 23:51:40 +01:00
|
|
|
return true;
|
|
|
|
if (launchBrowser("exo-open", url)) // xfce
|
|
|
|
return true;
|
|
|
|
|
|
|
|
// try browser names
|
|
|
|
if (launchBrowser("firefox", url))
|
|
|
|
return true;
|
|
|
|
if (launchBrowser("mozilla", url))
|
|
|
|
return true;
|
|
|
|
if (launchBrowser("netscape", url))
|
|
|
|
return true;
|
|
|
|
if (launchBrowser("opera", url))
|
|
|
|
return true;
|
|
|
|
if (launchBrowser("chromium-browser", url))
|
|
|
|
return true;
|
|
|
|
if (launchBrowser("google-chrome", url))
|
|
|
|
return true;
|
|
|
|
|
|
|
|
warning("openUrl() (POSIX) failed to open URL");
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
2017-12-14 13:51:04 -06:00
|
|
|
bool OSystem_POSIX::launchBrowser(const Common::String &client, const Common::String &url) {
|
|
|
|
pid_t pid;
|
|
|
|
const char *argv[] = {
|
|
|
|
client.c_str(),
|
|
|
|
url.c_str(),
|
|
|
|
NULL,
|
|
|
|
NULL
|
|
|
|
};
|
|
|
|
if (client == "kfmclient") {
|
|
|
|
argv[2] = argv[1];
|
|
|
|
argv[1] = "openURL";
|
|
|
|
}
|
|
|
|
if (posix_spawnp(&pid, client.c_str(), NULL, NULL, const_cast<char **>(argv), environ) != 0) {
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
return (waitpid(pid, NULL, 0) != -1);
|
2016-09-09 23:51:40 +01:00
|
|
|
}
|
|
|
|
|
2015-09-27 18:02:21 -04:00
|
|
|
AudioCDManager *OSystem_POSIX::createAudioCDManager() {
|
2016-03-13 14:20:20 +01:00
|
|
|
#ifdef USE_LINUXCD
|
2015-09-27 18:02:21 -04:00
|
|
|
return createLinuxAudioCDManager();
|
2016-03-13 14:20:20 +01:00
|
|
|
#else
|
|
|
|
return OSystem_SDL::createAudioCDManager();
|
2015-09-27 18:02:21 -04:00
|
|
|
#endif
|
2016-03-13 14:20:20 +01:00
|
|
|
}
|
2011-06-04 15:07:12 +02:00
|
|
|
|
2010-06-23 21:07:03 +00:00
|
|
|
#endif
|