From 0f071d978a20fcd8273b8d3dacf64e497da80c7f Mon Sep 17 00:00:00 2001 From: Thomas Goyne Date: Tue, 12 Jun 2012 03:13:49 +0000 Subject: [PATCH] Rewrite the OS X bundle utils in Obj-C++ and return std::strings rather than malloced char * Originally committed to SVN as r6896. --- aegisub/libaegisub/Makefile | 7 +- .../libaegisub/include/libaegisub/util_osx.h | 50 ++---- aegisub/libaegisub/osx/util.cpp | 156 ------------------ aegisub/libaegisub/osx/util.mm | 92 +++++++++++ aegisub/src/command/help.cpp | 5 +- aegisub/src/subtitles_provider_libass.cpp | 11 +- aegisub/src/utils.cpp | 11 +- 7 files changed, 119 insertions(+), 213 deletions(-) delete mode 100644 aegisub/libaegisub/osx/util.cpp create mode 100644 aegisub/libaegisub/osx/util.mm diff --git a/aegisub/libaegisub/Makefile b/aegisub/libaegisub/Makefile index b321b9e02..ac2648871 100644 --- a/aegisub/libaegisub/Makefile +++ b/aegisub/libaegisub/Makefile @@ -46,8 +46,8 @@ SRC += \ unix/path.cpp ifeq (yes, $(BUILD_DARWIN)) -SRC += \ - osx/util.cpp +SRC += osx/util.mm +osx/util.o: OBJCXXFLAGS += -fobjc-arc endif HEADER += \ @@ -57,8 +57,7 @@ HEADER += \ include/libaegisub/charsets.def \ include/libaegisub/cajun/*.h -EXTRA_DIST += osx/util.cpp - +EXTRA_DIST += osx/util.mm include ../Makefile.target -include */*.d diff --git a/aegisub/libaegisub/include/libaegisub/util_osx.h b/aegisub/libaegisub/include/libaegisub/util_osx.h index fe308e229..ed7eac4c1 100644 --- a/aegisub/libaegisub/include/libaegisub/util_osx.h +++ b/aegisub/libaegisub/include/libaegisub/util_osx.h @@ -16,8 +16,8 @@ /// @file util_osx.h -/// @brief OSX Utilities -/// @ingroup libaegisub osx +/// @brief OSX Utilities +/// @ingroup libaegisub osx /// /// Utility functions for running regular *NIX libraries inside application /// bundles on Apple Macintosh OS X. @@ -29,44 +29,38 @@ /// /// When linking with this library, be sure to add '-framework CoreFoundation' /// 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 +#endif namespace agi { namespace util { - /// @brief Get the full name of bundle. /// @return Full name of bundle. /// Get the full name of the bundle itself. /// -/// @warning May return NULL if the current executable is not inside a bundle. -char * OSX_GetBundlePath(); - +/// @warning May return "" if the current executable is not inside a bundle. +std::string OSX_GetBundlePath(); /// @brief Get the esources directory. /// @return Resources directory. /// /// Mainly for user interface elements such as graphics and strings -char * OSX_GetBundleResourcesDirectory(); - +std::string OSX_GetBundleResourcesDirectory(); /// @brief Get the built-in plugins directory. /// @return Built-in plugins directory. /// /// This is generaly only used by native Carbon and Cocoa applications. It is /// not for general shared libraries. -char * OSX_GetBundleBuiltInPlugInsDirectory(); - +std::string OSX_GetBundleBuiltInPlugInsDirectory(); /// @brief Get the private Frameworks directory. /// @return Private Framework directory. /// /// These are suitable locations for shared libraries. -char * OSX_GetBundlePrivateFrameworksDirectory(); - +std::string OSX_GetBundlePrivateFrameworksDirectory(); /// @brief Get the shared Frameworks directory. /// @return Shared Framework directory. @@ -74,44 +68,30 @@ char * OSX_GetBundlePrivateFrameworksDirectory(); /// @see OSX_GetBundlePrivateFrameworksDirectory() /// @note Does anyone know the difference between private and shared frameworks /// inside a bundle? -char * OSX_GetBundleSharedFrameworksDirectory(); - +std::string OSX_GetBundleSharedFrameworksDirectory(); /// @brief Get the shared support directory /// @return Shared support directory /// /// This is a suitable location for static configuration files. (Remember, /// bundle is considered read-only.) -char * 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(); - +std::string OSX_GetBundleSharedSupportDirectory(); /// @brief Get the main executable path. /// @return Main executable path. /// /// The binary run when the user launches the bundle from Finder. -char * OSX_GetBundleExecutablePath(); - +std::string OSX_GetBundleExecutablePath(); /// @brief Get the auxillary executable path. /// @return Auxillary executable 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. /// @param location URI of file /// @note If this is a FILE or DIRECTORY the path must be ABSOLUTE no 'file://' -/// @return Error code. -void OSX_OpenLocation(const char *location); - - +void OSX_OpenLocation(std::string const& location); } // namespace io } // namespace agi diff --git a/aegisub/libaegisub/osx/util.cpp b/aegisub/libaegisub/osx/util.cpp deleted file mode 100644 index 70481ca03..000000000 --- a/aegisub/libaegisub/osx/util.cpp +++ /dev/null @@ -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 -#include -#include -#include -#include -#include - -#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 - diff --git a/aegisub/libaegisub/osx/util.mm b/aegisub/libaegisub/osx/util.mm new file mode 100644 index 000000000..41297ccbb --- /dev/null +++ b/aegisub/libaegisub/osx/util.mm @@ -0,0 +1,92 @@ +// Copyright (c) 2012 Thomas Goyne, +// +// 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 +#import + +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); + } +} + + } +} diff --git a/aegisub/src/command/help.cpp b/aegisub/src/command/help.cpp index 3a809f985..6f6c88b2c 100644 --- a/aegisub/src/command/help.cpp +++ b/aegisub/src/command/help.cpp @@ -98,10 +98,7 @@ struct help_files : public Command { STR_HELP("Resource files") void operator()(agi::Context *) { - char *shared_path = agi::util::OSX_GetBundleSharedSupportDirectory(); - wxString help_path = wxString::Format("%s/doc", wxString(shared_path, wxConvUTF8)); - agi::util::OSX_OpenLocation(help_path.c_str()); - free(shared_path); + agi::util::OSX_OpenLocation((agi::util::OSX_GetBundleSharedSupportDirectory() + "/doc").c_str()); } }; #endif diff --git a/aegisub/src/subtitles_provider_libass.cpp b/aegisub/src/subtitles_provider_libass.cpp index 37711ff4b..a396bd7c3 100644 --- a/aegisub/src/subtitles_provider_libass.cpp +++ b/aegisub/src/subtitles_provider_libass.cpp @@ -83,15 +83,10 @@ class FontConfigCacheThread : public wxThread { ASS_Renderer *ass_renderer; FontConfigCacheThread** thisPtr; 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; +#ifdef __APPLE__ + std::string conf_path = agi::util::OSX_GetBundleResourcesDirectory() + "/etc/fonts/fonts.conf"; + config_path = conf_path.c_str(); #endif if (ass_library) ass_renderer = ass_renderer_init(ass_library); diff --git a/aegisub/src/utils.cpp b/aegisub/src/utils.cpp index ec15c10a8..a36d084ea 100644 --- a/aegisub/src/utils.cpp +++ b/aegisub/src/utils.cpp @@ -282,14 +282,13 @@ void RestartAegisub() { wxStandardPaths stand; wxExecute("\"" + stand.GetExecutablePath() + "\""); #elif defined(__WXMAC__) - char *bundle_path = agi::util::OSX_GetBundlePath(); - char *support_path = agi::util::OSX_GetBundleSupportFilesDirectory(); - if (!bundle_path || !support_path) return; // oops - wxString exec = wxString::Format("\"%s/MacOS/restart-helper\" /usr/bin/open -n \"%s\"'", wxString(support_path, wxConvUTF8), wxString(bundle_path, wxConvUTF8)); + std::string bundle_path = agi::util::OSX_GetBundlePath(); + std::string helper_path = agi::util::OSX_GetBundleAuxillaryExecutablePath("restart-helper"); + if (bundle_path.empty() || helper_path.empty()) return; + + wxString exec = wxString::Format("\"%s\" /usr/bin/open -n \"%s\"'", lagi_wxString(helper_path), lagi_wxString(bundle_path)); LOG_I("util/restart/exec") << exec; wxExecute(exec); - free(bundle_path); - free(support_path); #else wxStandardPaths stand; wxExecute(stand.GetExecutablePath());