mirror of
https://github.com/libsdl-org/SDL.git
synced 2026-06-04 19:55:19 +00:00
filesystem: Implement SDL_GetExeName() for all platforms.
This commit is contained in:
parent
6b780c5ff9
commit
d7ba3efe6b
11 changed files with 141 additions and 30 deletions
|
|
@ -267,7 +267,9 @@ extern "C" {
|
|||
anything calling it without an extremely good reason. */
|
||||
extern SDL_NORETURN void SDL_ExitProcess(int exitcode);
|
||||
|
||||
// Get just the process's binary name, no path. Calculates and caches the string on first call. String lives until SDL_Quit(). This is not a public API right now!
|
||||
// Get just the process's binary name, no path. NULL if it doesn't make sense for a platform.
|
||||
// Can be something not a file, like a package ID on Android. Meant to be human-readable, not appended to a path, etc.
|
||||
// Calculates and caches the string on first call. String lives until SDL_Quit(). This is not a public API right now!
|
||||
extern const char *SDL_GetExeName(void);
|
||||
|
||||
#ifdef HAVE_LIBC
|
||||
|
|
|
|||
|
|
@ -2886,6 +2886,43 @@ int SDL_GetAndroidSDKVersion(void)
|
|||
return sdk_version;
|
||||
}
|
||||
|
||||
char *SDL_GetAndroidPackageName(void)
|
||||
{
|
||||
// this doesn't currently cache this, because it's only used by SDL_GetExeName, which _does_ cache it.
|
||||
struct LocalReferenceHolder refs = LocalReferenceHolder_Setup(SDL_FUNCTION);
|
||||
|
||||
JNIEnv *env = Android_JNI_GetEnv();
|
||||
if (!LocalReferenceHolder_Init(&refs, env)) {
|
||||
LocalReferenceHolder_Cleanup(&refs);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
// context = SDLActivity.getContext();
|
||||
jobject context = (*env)->CallStaticObjectMethod(env, mActivityClass, midGetContext);
|
||||
if (!context) {
|
||||
SDL_SetError("Couldn't get Android context!");
|
||||
LocalReferenceHolder_Cleanup(&refs);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
// fileObj = context.getFilesDir();
|
||||
jmethodID mid = (*env)->GetMethodID(env, (*env)->GetObjectClass(env, context), "getPackageName", "()Ljava/lang/String;");
|
||||
jstring jstr = (jstring)(*env)->CallObjectMethod(env, context, mid);
|
||||
if (Android_JNI_ExceptionOccurred(false)) {
|
||||
LocalReferenceHolder_Cleanup(&refs);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
const char *cstr = (*env)->GetStringUTFChars(env, jstr, NULL);
|
||||
char *retval = cstr ? SDL_strdup(cstr) : NULL;
|
||||
(*env)->ReleaseStringUTFChars(env, jstr, cstr);
|
||||
|
||||
LocalReferenceHolder_Cleanup(&refs);
|
||||
|
||||
return retval;
|
||||
}
|
||||
|
||||
|
||||
bool SDL_IsAndroidTablet(void)
|
||||
{
|
||||
JNIEnv *env = Android_JNI_GetEnv();
|
||||
|
|
|
|||
|
|
@ -153,6 +153,8 @@ int SDL_GetAndroidSDKVersion(void);
|
|||
bool SDL_IsAndroidTablet(void);
|
||||
bool SDL_IsAndroidTV(void);
|
||||
|
||||
char *SDL_GetAndroidPackageName(void); // this is a SDL_malloc'd string the caller will own.
|
||||
|
||||
// File Dialogs
|
||||
bool Android_JNI_ShowFileDialog(SDL_DialogFileCallback callback, void *userdata,
|
||||
const SDL_DialogFileFilter *filters, int nfilters, SDL_FileDialogType type,
|
||||
|
|
|
|||
|
|
@ -26,8 +26,7 @@
|
|||
// System dependent filesystem routines
|
||||
|
||||
#include "../SDL_sysfilesystem.h"
|
||||
|
||||
#include <unistd.h>
|
||||
#include "../../core/android/SDL_android.h"
|
||||
|
||||
char *SDL_SYS_GetBasePath(void)
|
||||
{
|
||||
|
|
@ -36,7 +35,7 @@ char *SDL_SYS_GetBasePath(void)
|
|||
|
||||
char *SDL_SYS_GetExeName(void)
|
||||
{
|
||||
return NULL; // !!! FIXME: probably just use the Linux path?
|
||||
return SDL_GetAndroidPackageName();
|
||||
}
|
||||
|
||||
char *SDL_SYS_GetPrefPath(const char *org, const char *app)
|
||||
|
|
|
|||
|
|
@ -47,7 +47,7 @@ char *SDL_SYS_GetBasePath(void)
|
|||
} else if (SDL_strcasecmp(baseType, "parent") == 0) {
|
||||
base = [[[bundle bundlePath] stringByDeletingLastPathComponent] fileSystemRepresentation];
|
||||
} else {
|
||||
// this returns the exedir for non-bundled and the resourceDir for bundled apps
|
||||
// this returns the exedir for non-bundled and the resourceDir for bundled apps
|
||||
base = [[bundle resourcePath] fileSystemRepresentation];
|
||||
}
|
||||
|
||||
|
|
@ -65,8 +65,24 @@ char *SDL_SYS_GetBasePath(void)
|
|||
|
||||
char *SDL_SYS_GetExeName(void)
|
||||
{
|
||||
SDL_Unsupported(); // !!! FIXME
|
||||
return NULL;
|
||||
@autoreleasepool {
|
||||
NSBundle *bundle = [NSBundle mainBundle];
|
||||
const char *name = [[[bundle infoDictionary] objectForKey:@"CFBundleIdentifier"] UTF8String];
|
||||
if (!name) {
|
||||
name = [[[bundle infoDictionary] objectForKey:@"CFBundleDisplayName"] UTF8String];
|
||||
if (!name) {
|
||||
name = [[[bundle infoDictionary] objectForKey:@"CFBundleName"] UTF8String];
|
||||
if (!name) {
|
||||
name = [[[bundle infoDictionary] objectForKey:@"CFBundleExecutable"] UTF8String];
|
||||
if (!name) {
|
||||
name = [[[NSProcessInfo processInfo] processName] UTF8String]; // oh well.
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return name ? SDL_strdup(name) : NULL;
|
||||
}
|
||||
}
|
||||
|
||||
char *SDL_SYS_GetPrefPath(const char *org, const char *app)
|
||||
|
|
|
|||
|
|
@ -31,7 +31,7 @@
|
|||
|
||||
#include "../SDL_sysfilesystem.h"
|
||||
|
||||
char *SDL_SYS_GetBasePath(void)
|
||||
static char *GetExePath(void)
|
||||
{
|
||||
/* As of MS-DOS 3.0, you can get the full path to the EXE from the very end of the
|
||||
environment table, which is discovered through the PSP:
|
||||
|
|
@ -80,34 +80,45 @@ char *SDL_SYS_GetBasePath(void)
|
|||
|
||||
slen++; /* count the null terminator. */
|
||||
|
||||
char *lastbackslash = NULL;
|
||||
char *retval = (char *) SDL_malloc(slen);
|
||||
if (retval) {
|
||||
for (int i = 0; i < slen; i++) {
|
||||
const char ch = (char) _farpeekb(envsel, offset + i);
|
||||
if (ch == '\\') {
|
||||
retval[i] = '/'; // I don't know if this is a good idea. Drop DOS path separators, use Unix style instead.
|
||||
lastbackslash = &retval[i];
|
||||
} else {
|
||||
retval[i] = ch;
|
||||
}
|
||||
retval[i] = (ch == '\\') ? '/' : ch; // I don't know if this is a good idea. Drop DOS path separators, use Unix style instead.
|
||||
}
|
||||
}
|
||||
|
||||
if (lastbackslash) {
|
||||
lastbackslash[1] = '\0'; /* chop off exe name, just leave path */
|
||||
} else { // uh...should have been a full path...?!
|
||||
SDL_free(retval);
|
||||
retval = NULL;
|
||||
}
|
||||
|
||||
return retval;
|
||||
}
|
||||
|
||||
char *SDL_SYS_GetBasePath(void)
|
||||
{
|
||||
char *path = GetExePath(); // look up full path of the current process's EXE file.
|
||||
if (!path) {
|
||||
return NULL; // error message was already set.
|
||||
}
|
||||
|
||||
char *ptr = SDL_strrchr(path, '/');
|
||||
SDL_assert(ptr != NULL); // Should have been an absolute path.
|
||||
|
||||
ptr[1] = '\0'; // chop off filename, leave '/'.
|
||||
|
||||
ptr = (char *) SDL_realloc(path, ((size_t) (ptr - path)) + 2); // try to shrink this allocation down a little.
|
||||
return ptr ? ptr : path; // return shrunk buffer if shrink worked out, unchanged original buffer if not.
|
||||
}
|
||||
|
||||
char *SDL_SYS_GetExeName(void)
|
||||
{
|
||||
SDL_Unsupported(); // !!! FIXME: Move most of SDL_SYS_GetBasePath to a separate function and reuse it here.
|
||||
return NULL;
|
||||
char *path = GetExePath(); // look up full path of the current process's EXE file.
|
||||
if (!path) {
|
||||
return NULL; // error message was already set.
|
||||
}
|
||||
|
||||
char *ptr = SDL_strrchr(path, '/');
|
||||
const size_t slen = SDL_strlen(ptr); // counts null terminator because we're still sitting on path separator.
|
||||
SDL_memmove(path, ptr + 1, slen); // move filename string to start of SDL_realloc'd region.
|
||||
ptr = (char *) SDL_realloc(path, slen); // try to shrink this allocation down a little.
|
||||
return ptr ? ptr : path; // return shrunk buffer if shrink worked out, unchanged original buffer if not.
|
||||
}
|
||||
|
||||
char *SDL_SYS_GetPrefPath(const char *org, const char *app)
|
||||
|
|
|
|||
|
|
@ -44,6 +44,7 @@ char *SDL_SYS_GetBasePath(void)
|
|||
return NULL;
|
||||
}
|
||||
|
||||
// !!! FIXME: if find_path promises an absolute path, can we dump this and just do SDL_strrchr(name, '/')?
|
||||
BEntry entry(name, true);
|
||||
BPath path;
|
||||
status_t rc = entry.GetPath(&path); // (path) now has binary's path.
|
||||
|
|
@ -66,8 +67,12 @@ char *SDL_SYS_GetBasePath(void)
|
|||
|
||||
char *SDL_SYS_GetExeName(void)
|
||||
{
|
||||
SDL_Unsupported(); // !!! FIXME: Move most of SDL_SYS_GetBasePath to a separate function and reuse it here.
|
||||
return NULL;
|
||||
char name[MAXPATHLEN];
|
||||
if (find_path(B_APP_IMAGE_SYMBOL, B_FIND_PATH_IMAGE_PATH, NULL, name, sizeof(name)) != B_OK) {
|
||||
return NULL;
|
||||
}
|
||||
char *ptr = SDL_strrchr(name, '/');
|
||||
return SDL_strdup(ptr ? ptr + 1 : name);
|
||||
}
|
||||
|
||||
char *SDL_SYS_GetPrefPath(const char *org, const char *app)
|
||||
|
|
|
|||
|
|
@ -21,6 +21,7 @@
|
|||
#include "SDL_internal.h"
|
||||
|
||||
extern void NGAGE_GetAppPath(char *path);
|
||||
extern void NGAGE_GetExeName(char *path);
|
||||
|
||||
char *SDL_SYS_GetBasePath(void)
|
||||
{
|
||||
|
|
@ -32,8 +33,9 @@ char *SDL_SYS_GetBasePath(void)
|
|||
|
||||
char *SDL_SYS_GetExeName(void)
|
||||
{
|
||||
SDL_Unsupported(); // !!! FIXME: see code in NGAGE_GetAppPath
|
||||
return NULL;
|
||||
char exe_name[512];
|
||||
NGAGE_GetExeName(exe_name);
|
||||
return SDL_strdup(exe_name);
|
||||
}
|
||||
|
||||
char *SDL_SYS_GetPrefPath(const char *org, const char *app)
|
||||
|
|
|
|||
|
|
@ -63,6 +63,23 @@ void NGAGE_GetAppPath(char *path)
|
|||
}
|
||||
}
|
||||
|
||||
void NGAGE_GetExeName(char *path)
|
||||
{
|
||||
TBuf<512> aPath;
|
||||
|
||||
TFileName fullExePath = RProcess().FileName();
|
||||
|
||||
TParsePtrC parser(fullExePath);
|
||||
aPath.Copy(parser.NameAndExt());
|
||||
|
||||
TBuf8<512> utf8Path; // Temporary buffer for UTF-8 data.
|
||||
CnvUtfConverter::ConvertFromUnicodeToUtf8(utf8Path, aPath);
|
||||
|
||||
// Copy UTF-8 data to the provided char* buffer.
|
||||
strncpy(path, (const char *)utf8Path.Ptr(), utf8Path.Length());
|
||||
path[utf8Path.Length()] = '\0';
|
||||
}
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
|
|
|||
|
|
@ -154,8 +154,25 @@ char *SDL_SYS_GetBasePath(void)
|
|||
|
||||
char *SDL_SYS_GetExeName(void)
|
||||
{
|
||||
SDL_Unsupported(); // !!! FIXME: see code in SDL_SYS_GetBasePath.
|
||||
return NULL;
|
||||
_kernel_swi_regs regs;
|
||||
_kernel_oserror *error;
|
||||
char *canon, *ptr, *retval;
|
||||
|
||||
error = _kernel_swi(OS_GetEnv, ®s, ®s);
|
||||
if (error) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
canon = canonicalisePath((const char *)regs.r[0], "Run$Path");
|
||||
if (!canon) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
// find filename.
|
||||
ptr = SDL_strrchr(canon, '.');
|
||||
retval = SDL_strdup(ptr ? ptr + 1 : canon);
|
||||
SDL_free(canon);
|
||||
return retval;
|
||||
}
|
||||
|
||||
char *SDL_SYS_GetPrefPath(const char *org, const char *app)
|
||||
|
|
|
|||
|
|
@ -94,6 +94,9 @@ int main(int argc, char *argv[])
|
|||
char *curdir;
|
||||
const char *base_path;
|
||||
|
||||
/* this will be SDL's best guess at the human-readable exe name (or bundle id, or whatever) by default. */
|
||||
SDL_Log("Default app name: '%s'", SDL_GetAppMetadataProperty(SDL_PROP_APP_METADATA_NAME_STRING));
|
||||
|
||||
/* Initialize test framework */
|
||||
state = SDLTest_CommonCreateState(argv, 0);
|
||||
if (!state) {
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue