mirror of
https://github.com/love2d/love.git
synced 2026-08-19 20:19:42 +02:00
Android: Cleanup and remove usage of love:// custom protocol.
Let SDL3 handle content:// URI support instead.
This commit is contained in:
+79
-141
@@ -434,7 +434,7 @@ struct AssetInfo: public love::filesystem::physfs::PhysfsIo<AssetInfo>
|
|||||||
return AAsset_getLength64(asset);
|
return AAsset_getLength64(asset);
|
||||||
}
|
}
|
||||||
|
|
||||||
int64_t flush() const
|
int flush() const
|
||||||
{
|
{
|
||||||
// Do nothing
|
// Do nothing
|
||||||
PHYSFS_setErrorCode(PHYSFS_ERR_OK);
|
PHYSFS_setErrorCode(PHYSFS_ERR_OK);
|
||||||
@@ -450,7 +450,7 @@ struct AssetInfo: public love::filesystem::physfs::PhysfsIo<AssetInfo>
|
|||||||
if (asset == nullptr)
|
if (asset == nullptr)
|
||||||
{
|
{
|
||||||
PHYSFS_setErrorCode(PHYSFS_ERR_OS_ERROR);
|
PHYSFS_setErrorCode(PHYSFS_ERR_OS_ERROR);
|
||||||
throw new love::Exception("Unable to duplicate AssetInfo");
|
throw love::Exception("Unable to duplicate AssetInfo");
|
||||||
}
|
}
|
||||||
|
|
||||||
filename = new (std::nothrow) char[size];
|
filename = new (std::nothrow) char[size];
|
||||||
@@ -697,7 +697,80 @@ static PHYSFS_Io *getDummyIO(PHYSFS_Io *io)
|
|||||||
return &dummyIo;
|
return &dummyIo;
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
} // aasset
|
||||||
|
|
||||||
|
struct SDLIO: public love::filesystem::physfs::PhysfsIo<SDLIO>
|
||||||
|
{
|
||||||
|
static const uint32_t version = 0;
|
||||||
|
|
||||||
|
SDLIO(const std::string &filename)
|
||||||
|
: filename(filename)
|
||||||
|
, io(nullptr)
|
||||||
|
{
|
||||||
|
io = SDL_IOFromFile(filename.c_str(), "rb");
|
||||||
|
if (!io)
|
||||||
|
throw love::Exception("Cannot open %s: %s", filename.c_str(), SDL_GetError());
|
||||||
|
}
|
||||||
|
|
||||||
|
SDLIO(const SDLIO &other)
|
||||||
|
: filename(other.filename)
|
||||||
|
, io(nullptr)
|
||||||
|
{
|
||||||
|
io = SDL_IOFromFile(filename.c_str(), "rb");
|
||||||
|
if (!io)
|
||||||
|
throw love::Exception("Cannot open %s: %s", filename.c_str(), SDL_GetError());
|
||||||
|
}
|
||||||
|
|
||||||
|
int64_t read(void* buf, uint64_t len) const
|
||||||
|
{
|
||||||
|
size_t readed = SDL_ReadIO(io, buf, (size_t) len);
|
||||||
|
return (int64_t) readed;
|
||||||
|
}
|
||||||
|
|
||||||
|
int64_t write(const void* buf, uint64_t len) const
|
||||||
|
{
|
||||||
|
size_t written = SDL_WriteIO(io, buf, (size_t) len);
|
||||||
|
return (int64_t) written;
|
||||||
|
}
|
||||||
|
|
||||||
|
int seek(uint64_t offset) const
|
||||||
|
{
|
||||||
|
int64_t newpos = SDL_SeekIO(io, (Sint64) offset, SDL_IO_SEEK_SET);
|
||||||
|
|
||||||
|
PHYSFS_setErrorCode(newpos >= 0 ? PHYSFS_ERR_OK : PHYSFS_ERR_OS_ERROR);
|
||||||
|
return newpos >= 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
int64_t tell() const
|
||||||
|
{
|
||||||
|
int64_t pos = SDL_TellIO(io);
|
||||||
|
PHYSFS_setErrorCode(pos >= 0 ? PHYSFS_ERR_OK : PHYSFS_ERR_OS_ERROR);
|
||||||
|
return pos;
|
||||||
|
}
|
||||||
|
|
||||||
|
int64_t length() const
|
||||||
|
{
|
||||||
|
int64_t size = SDL_GetIOSize(io);
|
||||||
|
PHYSFS_setErrorCode(size >= 0 ? PHYSFS_ERR_OK : PHYSFS_ERR_OS_ERROR);
|
||||||
|
return size;
|
||||||
|
}
|
||||||
|
|
||||||
|
int flush() const
|
||||||
|
{
|
||||||
|
bool success = SDL_FlushIO(io);
|
||||||
|
PHYSFS_setErrorCode(success ? PHYSFS_ERR_OK : PHYSFS_ERR_OS_ERROR);
|
||||||
|
return success;
|
||||||
|
}
|
||||||
|
|
||||||
|
~SDLIO() override
|
||||||
|
{
|
||||||
|
SDL_CloseIO(io);
|
||||||
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
std::string filename;
|
||||||
|
SDL_IOStream *io;
|
||||||
|
};
|
||||||
|
|
||||||
static bool isVirtualArchiveInitialized = false;
|
static bool isVirtualArchiveInitialized = false;
|
||||||
|
|
||||||
@@ -782,145 +855,10 @@ const char *getCRequirePath()
|
|||||||
return path.c_str();
|
return path.c_str();
|
||||||
}
|
}
|
||||||
|
|
||||||
int getFDFromContentProtocol(const char *path)
|
void *getIOFromContentProtocol(const char *uri)
|
||||||
{
|
{
|
||||||
int fd = -1;
|
// Note: The static_cast is necessary, otherwise the pointer is shifted.
|
||||||
|
return static_cast<PHYSFS_Io*>(new SDLIO(uri));
|
||||||
if (strstr(path, "content://") == path)
|
|
||||||
{
|
|
||||||
JNIEnv *env = (JNIEnv*) SDL_GetAndroidJNIEnv();
|
|
||||||
jobject activity = (jobject) SDL_GetAndroidActivity();
|
|
||||||
jclass clazz = env->GetObjectClass(activity);
|
|
||||||
|
|
||||||
static jmethodID converter = env->GetMethodID(clazz, "convertToFileDescriptor", "(Ljava/lang/String;)I");
|
|
||||||
|
|
||||||
jstring uri = env->NewStringUTF(path);
|
|
||||||
fd = (int) env->CallIntMethod(activity, converter, uri);
|
|
||||||
|
|
||||||
env->DeleteLocalRef(uri);
|
|
||||||
env->DeleteLocalRef(clazz);
|
|
||||||
env->DeleteLocalRef(activity);
|
|
||||||
}
|
|
||||||
|
|
||||||
return fd;
|
|
||||||
}
|
|
||||||
|
|
||||||
int getFDFromLoveProtocol(const char *path)
|
|
||||||
{
|
|
||||||
constexpr const char PROTOCOL[] = "love2d://fd/";
|
|
||||||
constexpr size_t PROTOCOL_LEN = sizeof(PROTOCOL) - 1;
|
|
||||||
|
|
||||||
if (*path == '/')
|
|
||||||
path++;
|
|
||||||
|
|
||||||
if (memcmp(path, PROTOCOL, PROTOCOL_LEN) == 0)
|
|
||||||
{
|
|
||||||
try
|
|
||||||
{
|
|
||||||
return std::stoi(path + PROTOCOL_LEN, nullptr, 10);
|
|
||||||
}
|
|
||||||
catch (std::logic_error &)
|
|
||||||
{ }
|
|
||||||
}
|
|
||||||
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
class FileDescriptorTracker: public love::Object
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
explicit FileDescriptorTracker(int fd): Object(), fd(fd) {}
|
|
||||||
~FileDescriptorTracker() override { close(fd); }
|
|
||||||
int getFd() const { return fd; }
|
|
||||||
private:
|
|
||||||
int fd;
|
|
||||||
};
|
|
||||||
|
|
||||||
struct FileDescriptorIO
|
|
||||||
{
|
|
||||||
FileDescriptorTracker *fd;
|
|
||||||
off64_t size;
|
|
||||||
off64_t offset;
|
|
||||||
};
|
|
||||||
|
|
||||||
void *getIOFromFD(int fd)
|
|
||||||
{
|
|
||||||
if (fd == -1)
|
|
||||||
return nullptr;
|
|
||||||
|
|
||||||
// Create file descriptor IO structure
|
|
||||||
FileDescriptorIO *fdio = new FileDescriptorIO();
|
|
||||||
fdio->size = lseek64(fd, 0, SEEK_END);
|
|
||||||
fdio->offset = 0;
|
|
||||||
lseek64(fd, 0, SEEK_SET);
|
|
||||||
|
|
||||||
if (fdio->size == -1)
|
|
||||||
{
|
|
||||||
// Cannot get size
|
|
||||||
delete fdio;
|
|
||||||
return nullptr;
|
|
||||||
}
|
|
||||||
|
|
||||||
fdio->fd = new FileDescriptorTracker(fd);
|
|
||||||
|
|
||||||
PHYSFS_Io *io = new PHYSFS_Io();
|
|
||||||
io->version = 0;
|
|
||||||
io->opaque = fdio;
|
|
||||||
io->read = [](PHYSFS_Io *io, void *buf, PHYSFS_uint64 size)
|
|
||||||
{
|
|
||||||
FileDescriptorIO *fdio = (FileDescriptorIO *) io->opaque;
|
|
||||||
ssize_t ret = pread64(fdio->fd->getFd(), buf, (size_t) size, fdio->offset);
|
|
||||||
|
|
||||||
if (ret == -1)
|
|
||||||
PHYSFS_setErrorCode(PHYSFS_ERR_OTHER_ERROR);
|
|
||||||
else
|
|
||||||
fdio->offset = std::min(fdio->offset + (off64_t) ret, fdio->size);
|
|
||||||
|
|
||||||
return (PHYSFS_sint64) ret;
|
|
||||||
};
|
|
||||||
io->write = nullptr;
|
|
||||||
io->seek = [](PHYSFS_Io *io, PHYSFS_uint64 offset)
|
|
||||||
{
|
|
||||||
FileDescriptorIO *fdio = (FileDescriptorIO *) io->opaque;
|
|
||||||
fdio->offset = std::min(std::max<off64_t>((off64_t) offset, 0), fdio->size);
|
|
||||||
// Always success
|
|
||||||
return 1;
|
|
||||||
};
|
|
||||||
io->tell = [](PHYSFS_Io *io)
|
|
||||||
{
|
|
||||||
FileDescriptorIO *fdio = (FileDescriptorIO *) io->opaque;
|
|
||||||
return (PHYSFS_sint64) fdio->offset;
|
|
||||||
};
|
|
||||||
io->length = [](PHYSFS_Io *io)
|
|
||||||
{
|
|
||||||
FileDescriptorIO *fdio = (FileDescriptorIO *) io->opaque;
|
|
||||||
return (PHYSFS_sint64) fdio->size;
|
|
||||||
};
|
|
||||||
io->duplicate = [](PHYSFS_Io *io)
|
|
||||||
{
|
|
||||||
FileDescriptorIO *fdio = (FileDescriptorIO *) io->opaque;
|
|
||||||
FileDescriptorIO *fdio2 = new FileDescriptorIO();
|
|
||||||
PHYSFS_Io *io2 = new PHYSFS_Io();
|
|
||||||
|
|
||||||
fdio->fd->retain();
|
|
||||||
|
|
||||||
// Copy data
|
|
||||||
*fdio2 = *fdio;
|
|
||||||
*io2 = *io;
|
|
||||||
io2->opaque = fdio2;
|
|
||||||
|
|
||||||
return io2;
|
|
||||||
};
|
|
||||||
io->flush = nullptr;
|
|
||||||
io->destroy = [](PHYSFS_Io *io)
|
|
||||||
{
|
|
||||||
FileDescriptorIO *fdio = (FileDescriptorIO *) io->opaque;
|
|
||||||
fdio->fd->release();
|
|
||||||
delete fdio;
|
|
||||||
delete io;
|
|
||||||
};
|
|
||||||
|
|
||||||
return io;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
const char *getArg0()
|
const char *getArg0()
|
||||||
|
|||||||
+2
-21
@@ -54,11 +54,6 @@ bool openURL(const std::string &url);
|
|||||||
|
|
||||||
void vibrate(double seconds);
|
void vibrate(double seconds);
|
||||||
|
|
||||||
/*
|
|
||||||
* Helper functions for the filesystem module
|
|
||||||
*/
|
|
||||||
void freeGameArchiveMemory(void *ptr);
|
|
||||||
|
|
||||||
bool directoryExists(const char *path);
|
bool directoryExists(const char *path);
|
||||||
|
|
||||||
bool mkdir(const char *path);
|
bool mkdir(const char *path);
|
||||||
@@ -101,25 +96,11 @@ bool checkFusedGame(void **physfsIO_Out);
|
|||||||
const char *getCRequirePath();
|
const char *getCRequirePath();
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Convert "content://" to file descriptor.
|
* Convert "content://" to PHYSFS_Io using SDL_IOStream.
|
||||||
* @param path Path with content:// URI
|
* @param path Path with content:// URI
|
||||||
* @return File descriptor if successful, -1 on failure.
|
|
||||||
*/
|
|
||||||
int getFDFromContentProtocol(const char *path);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Attempt to parse "(/)love2d://fd/<fd>" from path.
|
|
||||||
* @param path Potentially special path.
|
|
||||||
* @return File descriptor passed if successful, -1 if path is not valid.
|
|
||||||
*/
|
|
||||||
int getFDFromLoveProtocol(const char *path);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Create PHYSFS_Io from file descriptor.
|
|
||||||
* @param fd File descriptor
|
|
||||||
* @return PHYSFS_Io casted to void*.
|
* @return PHYSFS_Io casted to void*.
|
||||||
*/
|
*/
|
||||||
void *getIOFromFD(int fd);
|
void *getIOFromContentProtocol(const char *path);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Retrieve PHYSFS_AndroidInit structure.
|
* Retrieve PHYSFS_AndroidInit structure.
|
||||||
|
|||||||
@@ -279,20 +279,16 @@ bool Filesystem::setSource(const char *source)
|
|||||||
|
|
||||||
if (!isAAssetMounted)
|
if (!isAAssetMounted)
|
||||||
{
|
{
|
||||||
// Is this love2d://fd/ URIs?
|
// Is this content:// URIs?
|
||||||
int fd = love::android::getFDFromLoveProtocol(source);
|
auto io = (PHYSFS_Io *) love::android::getIOFromContentProtocol(source);
|
||||||
if (fd != -1)
|
|
||||||
|
if (PHYSFS_mountIo(io, "LOVE.FD", nullptr, 0))
|
||||||
{
|
{
|
||||||
PHYSFS_Io *io = (PHYSFS_Io *) love::android::getIOFromFD(fd);
|
gameSource = source;
|
||||||
|
return true;
|
||||||
if (PHYSFS_mountIo(io, "LOVE.FD", nullptr, 0))
|
|
||||||
{
|
|
||||||
gameSource = source;
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
io->destroy(io);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
io->destroy(io);
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user