Rewrite the OS X bundle utils in Obj-C++ and return std::strings rather than malloced char *

Originally committed to SVN as r6896.
This commit is contained in:
Thomas Goyne 2012-06-12 03:13:49 +00:00
parent 4b78e05695
commit 0f071d978a
7 changed files with 119 additions and 213 deletions

View file

@ -46,8 +46,8 @@ SRC += \
unix/path.cpp unix/path.cpp
ifeq (yes, $(BUILD_DARWIN)) ifeq (yes, $(BUILD_DARWIN))
SRC += \ SRC += osx/util.mm
osx/util.cpp osx/util.o: OBJCXXFLAGS += -fobjc-arc
endif endif
HEADER += \ HEADER += \
@ -57,8 +57,7 @@ HEADER += \
include/libaegisub/charsets.def \ include/libaegisub/charsets.def \
include/libaegisub/cajun/*.h include/libaegisub/cajun/*.h
EXTRA_DIST += osx/util.cpp EXTRA_DIST += osx/util.mm
include ../Makefile.target include ../Makefile.target
-include */*.d -include */*.d

View file

@ -29,44 +29,38 @@
/// ///
/// When linking with this library, be sure to add '-framework CoreFoundation' /// When linking with this library, be sure to add '-framework CoreFoundation'
/// to the GCC commandline. /// to the GCC commandline.
///
/// @note All strings returned by these functions are allocated by strdup(), it is
/// the responsibility of the caller to free() them.
/// All of the functions may return NULL on error.
#ifndef LAGI_PRE
#include <string>
#endif
namespace agi { namespace agi {
namespace util { namespace util {
/// @brief Get the full name of bundle. /// @brief Get the full name of bundle.
/// @return Full name of bundle. /// @return Full name of bundle.
/// Get the full name of the bundle itself. /// Get the full name of the bundle itself.
/// ///
/// @warning May return NULL if the current executable is not inside a bundle. /// @warning May return "" if the current executable is not inside a bundle.
char * OSX_GetBundlePath(); std::string OSX_GetBundlePath();
/// @brief Get the esources directory. /// @brief Get the esources directory.
/// @return Resources directory. /// @return Resources directory.
/// ///
/// Mainly for user interface elements such as graphics and strings /// Mainly for user interface elements such as graphics and strings
char * OSX_GetBundleResourcesDirectory(); std::string OSX_GetBundleResourcesDirectory();
/// @brief Get the built-in plugins directory. /// @brief Get the built-in plugins directory.
/// @return Built-in plugins directory. /// @return Built-in plugins directory.
/// ///
/// This is generaly only used by native Carbon and Cocoa applications. It is /// This is generaly only used by native Carbon and Cocoa applications. It is
/// not for general shared libraries. /// not for general shared libraries.
char * OSX_GetBundleBuiltInPlugInsDirectory(); std::string OSX_GetBundleBuiltInPlugInsDirectory();
/// @brief Get the private Frameworks directory. /// @brief Get the private Frameworks directory.
/// @return Private Framework directory. /// @return Private Framework directory.
/// ///
/// These are suitable locations for shared libraries. /// These are suitable locations for shared libraries.
char * OSX_GetBundlePrivateFrameworksDirectory(); std::string OSX_GetBundlePrivateFrameworksDirectory();
/// @brief Get the shared Frameworks directory. /// @brief Get the shared Frameworks directory.
/// @return Shared Framework directory. /// @return Shared Framework directory.
@ -74,44 +68,30 @@ char * OSX_GetBundlePrivateFrameworksDirectory();
/// @see OSX_GetBundlePrivateFrameworksDirectory() /// @see OSX_GetBundlePrivateFrameworksDirectory()
/// @note Does anyone know the difference between private and shared frameworks /// @note Does anyone know the difference between private and shared frameworks
/// inside a bundle? /// inside a bundle?
char * OSX_GetBundleSharedFrameworksDirectory(); std::string OSX_GetBundleSharedFrameworksDirectory();
/// @brief Get the shared support directory /// @brief Get the shared support directory
/// @return Shared support directory /// @return Shared support directory
/// ///
/// This is a suitable location for static configuration files. (Remember, /// This is a suitable location for static configuration files. (Remember,
/// bundle is considered read-only.) /// bundle is considered read-only.)
char * OSX_GetBundleSharedSupportDirectory(); std::string OSX_GetBundleSharedSupportDirectory();
/// @brief Get the support directory
/// @return Support directory
/// @see OSX_GetBundleSharedSupportDirectory()
/// @note Again, what is the difference between Support and SharedSupport?
char * OSX_GetBundleSupportFilesDirectory();
/// @brief Get the main executable path. /// @brief Get the main executable path.
/// @return Main executable path. /// @return Main executable path.
/// ///
/// The binary run when the user launches the bundle from Finder. /// The binary run when the user launches the bundle from Finder.
char * OSX_GetBundleExecutablePath(); std::string OSX_GetBundleExecutablePath();
/// @brief Get the auxillary executable path. /// @brief Get the auxillary executable path.
/// @return Auxillary executable path. /// @return Auxillary executable path.
/// ///
/// Pass the basename of the executable to get the path. /// Pass the basename of the executable to get the path.
char * OSX_GetBundleAuxillaryExecutablePath(const char *executableName); std::string OSX_GetBundleAuxillaryExecutablePath(std::string const& executableName);
/// @brief Open a URI using the Launcher. /// @brief Open a URI using the Launcher.
/// @param location URI of file /// @param location URI of file
/// @note If this is a FILE or DIRECTORY the path must be ABSOLUTE no 'file://' /// @note If this is a FILE or DIRECTORY the path must be ABSOLUTE no 'file://'
/// @return Error code. void OSX_OpenLocation(std::string const& location);
void OSX_OpenLocation(const char *location);
} // namespace io } // namespace io
} // namespace agi } // namespace agi

View file

@ -1,156 +0,0 @@
// Copyright (c) 2008-2009 Niels Martin Hansen
// Copyright (c) 2010 Amar Takhar
//
// Permission to use, copy, modify, and distribute this software for any
// purpose with or without fee is hereby granted, provided that the above
// copyright notice and this permission notice appear in all copies.
//
// THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
// WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
// MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
// ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
// WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
// ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
// OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
//
// $Id$
/// @file util.cpp
/// @brief OSX Utilities
/// @ingroup libosxutil osx
#include <string.h>
#include <sys/param.h>
#include <CoreFoundation/CFBundle.h>
#include <CoreFoundation/CFURL.h>
#include <CoreFoundation/CFString.h>
#include <ApplicationServices/ApplicationServices.h>
#include "libaegisub/util_osx.h"
namespace agi {
namespace util {
/// @brief Type of functions that return a URL from a bundle.
/// @internal
typedef CFURLRef (*GetURLFunc)(CFBundleRef);
/// @brief Generic implementation to retrieve pathnames inside a bundle.
///
/// @internal Provide a generic implementation for most of the logic
/// in path-retrieval, since what differs for the various functions is
/// only the call used to retrieve the actual path inside the bundle.
static char * GetDir(GetURLFunc GetURL)
{
CFBundleRef bundle;
CFURLRef res_dir_url;
char res_dir_str[MAXPATHLEN];
Boolean res;
bundle = CFBundleGetMainBundle();
if (!bundle) return NULL;
res_dir_url = (*GetURL)(bundle);
/* we do not own 'bundle' so don't release it */
if (!res_dir_url) return NULL;
res = CFURLGetFileSystemRepresentation(res_dir_url, true, (UInt8*)res_dir_str, MAXPATHLEN);
CFRelease(res_dir_url);
if (res == false)
return NULL;
else
return strdup(res_dir_str);
}
char * OSX_GetBundlePath()
{
return GetDir(CFBundleCopyBundleURL);
}
char * OSX_GetBundleResourcesDirectory()
{
return GetDir(CFBundleCopyResourcesDirectoryURL);
}
char * OSX_GetBundleExecutablePath()
{
return GetDir(CFBundleCopyExecutableURL);
}
char * OSX_GetBundleBuiltInPlugInsDirectory()
{
return GetDir(CFBundleCopyBuiltInPlugInsURL);
}
char * OSX_GetBundlePrivateFrameworksDirectory()
{
return GetDir(CFBundleCopyPrivateFrameworksURL);
}
char * OSX_GetBundleSharedFrameworksDirectory()
{
return GetDir(CFBundleCopySharedFrameworksURL);
}
char * OSX_GetBundleSharedSupportDirectory()
{
return GetDir(CFBundleCopySharedSupportURL);
}
char * OSX_GetBundleSupportFilesDirectory()
{
return GetDir(CFBundleCopySupportFilesDirectoryURL);
}
char * OSX_GetBundleAuxillaryExecutablePath(const char *executableName)
{
CFStringRef exename_str;
CFBundleRef bundle;
CFURLRef res_dir_url;
char res_dir_str[MAXPATHLEN];
Boolean res;
exename_str = CFStringCreateWithCString(NULL, executableName, kCFStringEncodingUTF8);
if (!exename_str) return NULL;
bundle = CFBundleGetMainBundle();
if (!bundle) return NULL;
res_dir_url = CFBundleCopyAuxiliaryExecutableURL(bundle, exename_str);
CFRelease(exename_str);
if (!res_dir_url) return NULL;
res = CFURLGetFileSystemRepresentation(res_dir_url, true, (UInt8*)res_dir_str, MAXPATHLEN);
CFRelease(res_dir_url);
if (res == false)
return NULL;
else
return strdup(res_dir_str);
}
void OSX_OpenLocation (const char *location) {
CFStringRef CFSlocation = CFStringCreateWithCString(NULL, location, kCFStringEncodingUTF8);
CFURLRef url = CFURLCreateWithFileSystemPath(NULL, CFSlocation , kCFURLPOSIXPathStyle, false);
OSStatus stat = LSOpenCFURLRef(url, NULL);
printf("libosxutil::OSX_OpenLocation: %s\n", GetMacOSStatusCommentString(stat));
}
} // namespace io
} // namespace agi

View file

@ -0,0 +1,92 @@
// Copyright (c) 2012 Thomas Goyne, <plorkyeran@aegisub.org>
//
// Permission to use, copy, modify, and distribute this software for any
// purpose with or without fee is hereby granted, provided that the above
// copyright notice and this permission notice appear in all copies.
//
// THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
// WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
// MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
// ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
// WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
// ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
// OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
//
// $Id$
/// @file util.mm
/// @brief OSX Utilities
/// @ingroup libosxutil osx
#include "config.h"
#include "libaegisub/util_osx.h"
#import <ApplicationServices/ApplicationServices.h>
#import <Foundation/Foundation.h>
static std::string EmptyIfNil(NSString *string) {
return string ? [string UTF8String] : "";
}
namespace agi {
namespace util {
std::string OSX_GetBundlePath() {
@autoreleasepool {
return EmptyIfNil([[NSBundle mainBundle] bundlePath]);
}
}
std::string OSX_GetBundleResourcesDirectory() {
@autoreleasepool {
return EmptyIfNil([[[NSBundle mainBundle] resourceURL] path]);
}
}
std::string OSX_GetBundleExecutablePath() {
@autoreleasepool {
return EmptyIfNil([[NSBundle mainBundle] executablePath]);
}
}
std::string OSX_GetBundleBuiltInPlugInsDirectory() {
@autoreleasepool {
return EmptyIfNil([[NSBundle mainBundle] builtInPlugInsPath]);
}
}
std::string OSX_GetBundlePrivateFrameworksDirectory() {
@autoreleasepool {
return EmptyIfNil([[NSBundle mainBundle] privateFrameworksPath]);
}
}
std::string OSX_GetBundleSharedFrameworksDirectory() {
@autoreleasepool {
return EmptyIfNil([[NSBundle mainBundle] sharedFrameworksPath]);
}
}
std::string OSX_GetBundleSharedSupportDirectory() {
@autoreleasepool {
return EmptyIfNil([[NSBundle mainBundle] sharedSupportPath]);
}
}
std::string OSX_GetBundleAuxillaryExecutablePath(std::string const& executableName) {
@autoreleasepool {
NSString *name = [NSString stringWithUTF8String:executableName.c_str()];
return EmptyIfNil([[NSBundle mainBundle]pathForAuxiliaryExecutable:name]);
}
}
void OSX_OpenLocation(std::string const& location) {
@autoreleasepool {
NSURL *url = [NSURL fileURLWithPath:[NSString stringWithUTF8String:location.c_str()]];
LSOpenCFURLRef((__bridge CFURLRef)url, NULL);
}
}
}
}

View file

@ -98,10 +98,7 @@ struct help_files : public Command {
STR_HELP("Resource files") STR_HELP("Resource files")
void operator()(agi::Context *) { void operator()(agi::Context *) {
char *shared_path = agi::util::OSX_GetBundleSharedSupportDirectory(); agi::util::OSX_OpenLocation((agi::util::OSX_GetBundleSharedSupportDirectory() + "/doc").c_str());
wxString help_path = wxString::Format("%s/doc", wxString(shared_path, wxConvUTF8));
agi::util::OSX_OpenLocation(help_path.c_str());
free(shared_path);
} }
}; };
#endif #endif

View file

@ -83,15 +83,10 @@ class FontConfigCacheThread : public wxThread {
ASS_Renderer *ass_renderer; ASS_Renderer *ass_renderer;
FontConfigCacheThread** thisPtr; FontConfigCacheThread** thisPtr;
ExitCode Entry() { ExitCode Entry() {
#ifdef __APPLE__
char config_path[MAXPATHLEN];
char *config_dir;
config_dir = agi::util::OSX_GetBundleResourcesDirectory();
snprintf(config_path, MAXPATHLEN, "%s/etc/fonts/fonts.conf", config_dir);
free(config_dir);
#else
const char *config_path = NULL; const char *config_path = NULL;
#ifdef __APPLE__
std::string conf_path = agi::util::OSX_GetBundleResourcesDirectory() + "/etc/fonts/fonts.conf";
config_path = conf_path.c_str();
#endif #endif
if (ass_library) ass_renderer = ass_renderer_init(ass_library); if (ass_library) ass_renderer = ass_renderer_init(ass_library);

View file

@ -282,14 +282,13 @@ void RestartAegisub() {
wxStandardPaths stand; wxStandardPaths stand;
wxExecute("\"" + stand.GetExecutablePath() + "\""); wxExecute("\"" + stand.GetExecutablePath() + "\"");
#elif defined(__WXMAC__) #elif defined(__WXMAC__)
char *bundle_path = agi::util::OSX_GetBundlePath(); std::string bundle_path = agi::util::OSX_GetBundlePath();
char *support_path = agi::util::OSX_GetBundleSupportFilesDirectory(); std::string helper_path = agi::util::OSX_GetBundleAuxillaryExecutablePath("restart-helper");
if (!bundle_path || !support_path) return; // oops if (bundle_path.empty() || helper_path.empty()) return;
wxString exec = wxString::Format("\"%s/MacOS/restart-helper\" /usr/bin/open -n \"%s\"'", wxString(support_path, wxConvUTF8), wxString(bundle_path, wxConvUTF8));
wxString exec = wxString::Format("\"%s\" /usr/bin/open -n \"%s\"'", lagi_wxString(helper_path), lagi_wxString(bundle_path));
LOG_I("util/restart/exec") << exec; LOG_I("util/restart/exec") << exec;
wxExecute(exec); wxExecute(exec);
free(bundle_path);
free(support_path);
#else #else
wxStandardPaths stand; wxStandardPaths stand;
wxExecute(stand.GetExecutablePath()); wxExecute(stand.GetExecutablePath());