From e8cbd26e9f036754a2d50c994ede63bb25bfe370 Mon Sep 17 00:00:00 2001 From: rti Date: Wed, 3 Nov 2010 16:32:06 +0100 Subject: [PATCH] Fixed: #1153 Make ryzom_client run completely in an .app bundle --- code/nel/src/misc/path.cpp | 2 +- code/ryzom/client/src/app_bundle_utils.cpp | 65 ++++++++++++++++++++++ code/ryzom/client/src/app_bundle_utils.h | 32 +++++++++++ code/ryzom/client/src/client.cpp | 46 ++------------- code/ryzom/client/src/client_cfg.cpp | 13 ++++- code/ryzom/client/src/init.cpp | 10 +++- 6 files changed, 123 insertions(+), 45 deletions(-) create mode 100644 code/ryzom/client/src/app_bundle_utils.cpp create mode 100644 code/ryzom/client/src/app_bundle_utils.h diff --git a/code/nel/src/misc/path.cpp b/code/nel/src/misc/path.cpp index 0abc4ba8c..ba69da3af 100644 --- a/code/nel/src/misc/path.cpp +++ b/code/nel/src/misc/path.cpp @@ -1702,7 +1702,7 @@ std::string CFileContainer::getApplicationDirectory(const std::string &appName) appPath = CPath::standardizePath(ucstring((ucchar*)buffer).toUtf8()); #elif defined(NL_OS_MAC) appPath = CPath::standardizePath(getenv("HOME")); - appPath += "/Library/Preferences/"; + appPath += "/Library/Application Support/"; #else appPath = CPath::standardizePath(getenv("HOME")); #endif diff --git a/code/ryzom/client/src/app_bundle_utils.cpp b/code/ryzom/client/src/app_bundle_utils.cpp new file mode 100644 index 000000000..ebd1960d3 --- /dev/null +++ b/code/ryzom/client/src/app_bundle_utils.cpp @@ -0,0 +1,65 @@ +// Ryzom - MMORPG Framework +// Copyright (C) 2010 Winch Gate Property Limited +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU Affero General Public License as +// published by the Free Software Foundation, either version 3 of the +// License, or (at your option) any later version. +// +// 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 Affero General Public License for more details. +// +// You should have received a copy of the GNU Affero General Public License +// along with this program. If not, see . + +#include "app_bundle_utils.h" + +#if defined(NL_OS_MAC) +#include + +std::string getAppBundlePath() +{ + static std::string cachedPathToBundle; + + if(cachedPathToBundle.size()) + return cachedPathToBundle; + + // get the bundle + CFBundleRef bundle = CFBundleGetMainBundle(); + + if(bundle) + { + // get the url to the bundles root + CFURLRef url = CFBundleCopyBundleURL(bundle); + + if(url) + { + // get the file system path + CFStringRef str; + str = CFURLCopyFileSystemPath( + CFURLCopyAbsoluteURL(url), kCFURLPOSIXPathStyle); + CFRelease(url); + + if(str) + { + cachedPathToBundle = CFStringGetCStringPtr( + str, CFStringGetSmallestEncoding(str)); + CFRelease(str); + + return cachedPathToBundle; + } + else + nlerror("CFStringGetCStringPtr"); + } + else + nlerror("CFBundleCopyBundleURL"); + } + else + nlerror("CFBundleGetMainBundle"); + + return std::string(); +} + +#endif // defined(NL_OS_MAC) diff --git a/code/ryzom/client/src/app_bundle_utils.h b/code/ryzom/client/src/app_bundle_utils.h new file mode 100644 index 000000000..f2adad6db --- /dev/null +++ b/code/ryzom/client/src/app_bundle_utils.h @@ -0,0 +1,32 @@ +// Ryzom - MMORPG Framework +// Copyright (C) 2010 Winch Gate Property Limited +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU Affero General Public License as +// published by the Free Software Foundation, either version 3 of the +// License, or (at your option) any later version. +// +// 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 Affero General Public License for more details. +// +// You should have received a copy of the GNU Affero General Public License +// along with this program. If not, see . + +#ifndef CL_APP_BUNDLE_UTILS_H +#define CL_APP_BUNDLE_UTILS_H 1 + +#include "nel/misc/types_nl.h" + +#if defined(NL_OS_MAC) +#include + +/** + * Returns the current path to the .app bundle on Mac OS X. + * @note This path will have "Contents" as sub directory. + */ +std::string getAppBundlePath(); + +#endif // defined(NL_OS_MAC) +#endif // CL_APP_BUNDLE_UTILS_H diff --git a/code/ryzom/client/src/client.cpp b/code/ryzom/client/src/client.cpp index 427439519..43ea4408a 100644 --- a/code/ryzom/client/src/client.cpp +++ b/code/ryzom/client/src/client.cpp @@ -33,8 +33,8 @@ #ifdef NL_OS_MAC #include #include -#include #include "nel/misc/dynloadlib.h" +#include "app_bundle_utils.h" #endif #include "nel/misc/debug.h" @@ -352,47 +352,6 @@ int main(int argc, char **argv) // init the Nel context CApplicationContext *appContext = new CApplicationContext; -#if defined(NL_OS_MAC) - // get the bundle - CFBundleRef bundle = CFBundleGetMainBundle(); - if(bundle) - { - // get the url to the bundles root - CFURLRef url = CFBundleCopyBundleURL(bundle); - if(url) - { - // get the file system path - CFStringRef str; - str = CFURLCopyFileSystemPath( - CFURLCopyAbsoluteURL(url), kCFURLPOSIXPathStyle); - CFRelease(url); - - if(str) - { - std::string pathToBundle = CFStringGetCStringPtr( - str, CFStringGetSmallestEncoding(str)); - CFRelease(str); - - // change the working directory - nldebug("Bundle Path is %s", pathToBundle.c_str()); - nldebug("setCurrentPath %s", (pathToBundle + "/Contents/Resources/").c_str()); - CPath::setCurrentPath(pathToBundle + "/Contents/Resources/"); - - // add the search path for plugins (nel drivers) - nldebug("addLibPath %s", (pathToBundle + "/Contents/PlugIns/nel/").c_str()); - CLibrary::addLibPath(pathToBundle + "/Contents/PlugIns/nel/"); - } - else - nlerror("CFStringGetCStringPtr"); - - } - else - nlerror("CFBundleCopyBundleURL"); - } - else - nlerror("CFBundleGetMainBundle"); -#endif - createDebug(); #ifndef NL_DEBUG @@ -426,6 +385,9 @@ int main(int argc, char **argv) getrlimit(RLIMIT_NOFILE, &rlp3); nlinfo("rlimit before %d %d\n", rlp.rlim_cur, rlp.rlim_max); nlinfo("rlimit after %d %d\n", rlp3.rlim_cur, rlp3.rlim_max); + + // add the bundle's plugins path as library search path (for nel drivers) + CLibrary::addLibPath(getAppBundlePath() + "/Contents/PlugIns/nel/"); #endif #if defined(NL_OS_WINDOWS) diff --git a/code/ryzom/client/src/client_cfg.cpp b/code/ryzom/client/src/client_cfg.cpp index 96054e19c..b8d2bbcb9 100644 --- a/code/ryzom/client/src/client_cfg.cpp +++ b/code/ryzom/client/src/client_cfg.cpp @@ -45,6 +45,10 @@ # include "config.h" #endif // HAVE_CONFIG_H +#ifdef NL_OS_MAC +#include "app_bundle_utils.h" +#endif // NL_OS_MAC + #include /////////// @@ -1888,7 +1892,14 @@ void CClientConfig::init(const string &configFileName) if (CFile::isExists(defaultConfigFileName)) found = true; -#ifdef RYZOM_ETC_PREFIX +#ifdef NL_OS_MAC + if (!found) + { + defaultConfigFileName = + getAppBundlePath() + "/Contents/Resources/" + defaultConfigFileName; + if(CFile::isExists(defaultConfigFileName)) found = true; + } +#elif defined(RYZOM_ETC_PREFIX) if (!found) { defaultConfigFileName = CPath::standardizePath(RYZOM_ETC_PREFIX) + defaultConfigFileName; diff --git a/code/ryzom/client/src/init.cpp b/code/ryzom/client/src/init.cpp index ff581b12b..b6cda77b1 100644 --- a/code/ryzom/client/src/init.cpp +++ b/code/ryzom/client/src/init.cpp @@ -105,6 +105,10 @@ extern HINSTANCE HInstance; extern HWND SlashScreen; #endif // NL_OS_WINDOWS +#ifdef NL_OS_MAC +#include "app_bundle_utils.h" +#endif // NL_OS_MAC + #include /////////// @@ -617,7 +621,11 @@ void addPreDataPaths(NLMISC::IProgressCallback &progress) progress.progress ((float)i/(float)ClientCfg.PreDataPath.size()); progress.pushCropedValues ((float)i/(float)ClientCfg.PreDataPath.size(), (float)(i+1)/(float)ClientCfg.PreDataPath.size()); - CPath::addSearchPath(ClientCfg.PreDataPath[i], true, false, &progress); + std::string preDataPath = ClientCfg.PreDataPath[i]; +#if defined(NL_OS_MAC) + preDataPath = getAppBundlePath() + "/Contents/Resources/" + preDataPath; +#endif // defined(NL_OS_MAC) + CPath::addSearchPath(preDataPath, true, false, &progress); progress.popCropedValues (); }