gphoto / libgphoto2

The libgphoto2 camera access and control library.
GNU Lesser General Public License v2.1
991 stars 317 forks source link

Android support #918

Closed artyom-beilis closed 8 months ago

artyom-beilis commented 10 months ago

I'm starting it since I was looking to be able to use it on Android. Basic difference that must be handled:

  1. You need to be able to open camera given file descriptor that was open for you.

    Android permission model does not allow device discovery or opening device directly. I can only receive a file descriptor of an opened device and work with it.

    I added it as drop in replacement of search function when fd is provided

  2. Android requires having all libraries/shared object being on one flat directory.

    So I changed naming of camera and io libraries, to libgphoto_port_iolibs_XXX for example libgphoto_port_iolibs_libusb1 and libgphoto_camlibs_ptp2 and I filter them by pattern during load like this

Finally I unfortunately failed to build the library using autotools - libtool is failing to build shared object for some reason. I tested with some small autotools based projects and they worked but not libgphoto. Currently I created CMake files to build the project... I hope I'll be able to resolve the issue with auto-tools but actually CMake may help me using libgphoto on Windows... so this is something probably temporary.

Now big open question:

I need to pass the file descriptor to libusb1 io library. I first I thought to use GPPortInfo... setting path to something like usb:fd=NNN. But I need to specify ALL parameters including path to library. Currently gp_port_set_library_path isn't even implemented. From what I have seen so far user can receive a list of "Infos" and select one. In my case I must provide something that library does not know.

I currently implemented an external function for libusb1. I link directly to it and I set file descriptor than I start libgphoto initialization.

I really don't like this method and I'd like to pass this file descriptor via library interface. What is recommended way of doing it?

Bottom like: this is work in progress but I want to consult with libgphoto developers to make sure my changes will be accepted back at some point

artyom-beilis commented 10 months ago

I managed to make autotools work for Android so I did some changes, also I modified API for sysdevice access:

/** 
 * \brief Allow using file descriptor of USB device without auto-discovery
 *
 * This is required for access of USB on android since applications don't have direct
 * access to USB device
 * 
 * It must be called prior to library initialization
 */
int gp_port_usb_set_sys_device(int fd);

/** 
 * \brief Get externally set file descriptor of USB device, return -1 if not set
 */
int gp_port_usb_get_sys_device(void);

So you can set fd via libgphoto2_port library

laheller commented 10 months ago

@artyom-beilis Nice!

Finally I unfortunately failed to build the library using autotools - libtool is failing to build shared object for some reason.

Here is how I built libtool for Android: https://github.com/gphoto/libgphoto2/issues/335#issuecomment-881946081

BR,

Ladislav

artyom-beilis commented 10 months ago

Here is how I built libtool for Android:

Actually I finally managed to do it using autotools. The problem with libtool and actually automake of libgphoto2 was incorrect build command in generated libtool file. I'll get to my dev machine and I'll put it there.

So now I can build everything using standard autotools. I'll remove CMakes from this pull since they aren't complete in general.

laheller commented 10 months ago

@msmeissn This is an old story, maybe now it's the time also for Android...

laheller commented 8 months ago

@hfiguiere @ndim @msmeissn

Hi!

Any chance to make this happen?

BR,

Ladislav

msmeissn commented 8 months ago

can you rebase the patch to remove the conflicts?

laheller commented 8 months ago

@artyom-beilis

ndim commented 8 months ago

How much sense does it still make these days to have all the camlibs and iolibs dynamically loaded? The flat layout thing would be entirely unnecessary if we were to just link all the camlibs into libgphoto2 and all iolibs into libgphoto2_port.

I have seen two patches doing that, even though I have tested neither yet at this time.

artyom-beilis commented 8 months ago

@msmeissn Rebase you mean lineup with latest version?

2nd question where should I write Android specific notes - because it requires some preparation to run on Android

artyom-beilis commented 8 months ago

Here the current status/notes for Android use

Under android you can't discover UBS devices - you don't have permissions. Only you can receive a file descriptor for the UBS device after user gave permission. So it is needed to pass this file descriptor to the gphoto2 as if it is discovery.

Second issue is file layout. Android has very specific naming and does not allow nested directories for libraries. So every camera and port lib should be renamed

lib/libgphoto2/2.5.31.1/canon.so to lib/libgphoto2_camlib_canon.so lib/libgphoto2_port/0.12.2/usb1.so to lib/libgphoto2_port_iolib_usb1.so

Here is the code for renaming where PRFX in installation prefix

for f in $PRFX/lib/libgphoto2/*/*.so
do
    mv -v $f $PRFX/lib/libgphoto2_camlib_$(basename $f)
done
for f in $PRFX/lib/libgphoto2_port/*/*.so
do
    mv -v $f $PRFX/lib/libgphoto2_port_iolib_$(basename $f)
done

To load cameras and port libraries you need to setup environment variables:

    setenv("CAMLIBS",libdir,1);
    setenv("IOLIBS", libdir,1);
    setenv("CAMLIBS_PREFIX","libgphoto2_camlib_",1);
    setenv("IOLIBS_PREFIX","libgphoto2_port_iolib_",1);

Where libdir is actual directory the files are installed in. You can get it via getApplicationInfo().nativeLibraryDir. Note make sure to set in manifest android:extractNativeLibs="true"

And once you receive file descriptor of USB device configure it before you call the open camera API gp_port_usb_set_sys_device(fd); It would simulate "search" and will find only the device with provided file descriptor.

Note you need to have latest libubs1 library that supports libusb_wrap_sys_device API

msmeissn commented 8 months ago

How much sense does it still make these days to have all the camlibs and iolibs dynamically loaded? The flat layout thing would be entirely unnecessary if we were to just link all the camlibs into libgphoto2 and all iolibs into libgphoto2_port.

I have seen two patches doing that, even though I have tested neither yet at this time.

@ndim I think these days we can have just a single library, which would make things easier. people dont seem to provide pluggable drivers or so, they all rebuilds anyway.

artyom-beilis commented 8 months ago

I lined it all up to master.

So far it had been tested by multiple users of OpenLiveStacker and seems to be Ok

laheller commented 8 months ago

@msmeissn Rebase you mean lineup with latest version?

2nd question where should I write Android specific notes - because it requires some preparation to run on Android

@artyom-beilis @msmeissn I would add a new README.Android file, because it's really Android specific.

Anyway thanks for effort, I plan to use this in my own project!

BR,

Ladislav

jamie-ward commented 7 months ago

Great work! This is incredible... I'm trying to implement this into my own android project and I'm a bit of a n00b when it comes to this. Are you able to give any advice on how to get this running in my own project? Currently maintaining my own ptp library in kotlin and would be amazed if I could this into my project.

artyom-beilis commented 7 months ago

Great work! This is incredible... I'm trying to implement this into my own android project and I'm a bit of a n00b when it comes to this. Are you able to give any advice on how to get this running in my own project? Currently maintaining my own ptp library in kotlin and would be amazed if I could this into my project.

My project mostly uses C++, and only tiny Java wrapper around C++ project. So you need to create some binding code between C or C++ and Java/Kotlin for libgphoto

jamie-ward commented 7 months ago

Great work! This is incredible... I'm trying to implement this into my own android project and I'm a bit of a n00b when it comes to this. Are you able to give any advice on how to get this running in my own project? Currently maintaining my own ptp library in kotlin and would be amazed if I could this into my project.

My project mostly uses C++, and only tiny Java wrapper around C++ project. So you need to create some binding code between C or C++ and Java/Kotlin for libgphoto

That's great! Have a bit of experience binding code for rust and kotlin so I'll give this a try.

Thanks again.

jamie-ward commented 7 months ago

Here is how I built libtool for Android:

Actually I finally managed to do it using autotools. The problem with libtool and actually automake of libgphoto2 was incorrect build command in generated libtool file. I'll get to my dev machine and I'll put it there.

So now I can build everything using standard autotools. I'll remove CMakes from this pull since they aren't complete in general.

Out of interest, what was the fix? Currently falling into a similar issue with libtool and autoconf not auto detecting it

artyom-beilis commented 7 months ago

Here is how I built libtool for Android:

Actually I finally managed to do it using autotools. The problem with libtool and actually automake of libgphoto2 was incorrect build command in generated libtool file. I'll get to my dev machine and I'll put it there. So now I can build everything using standard autotools. I'll remove CMakes from this pull since they aren't complete in general.

Out of interest, what was the fix? Currently falling into a similar issue with libtool and autoconf not auto detecting it

The generated libtool file has incorrect value of archive_cmds="" it should be

archive_cmds="\$CC -shared -nostdlib \$predep_objects \$libobjs \$deplibs \$postdep_objects \$compiler_flags -o \$lib

Once it fixed the build succeeds. Below the script that I use to build the library for all 4 architechtures - of course some paths are local but it can be easily adapted.

Of course you also need libltdl library as well (it fails with same error)

android_bash.txt

jamie-ward commented 7 months ago

Here is how I built libtool for Android:

Actually I finally managed to do it using autotools. The problem with libtool and actually automake of libgphoto2 was incorrect build command in generated libtool file. I'll get to my dev machine and I'll put it there. So now I can build everything using standard autotools. I'll remove CMakes from this pull since they aren't complete in general.

Out of interest, what was the fix? Currently falling into a similar issue with libtool and autoconf not auto detecting it

The generated libtool file has incorrect value of archive_cmds="" it should be

archive_cmds="\$CC -shared -nostdlib \$predep_objects \$libobjs \$deplibs \$postdep_objects \$compiler_flags -o \$lib

Once it fixed the build succeeds. Below the script that I use to build the library for all 4 architechtures - of course some paths are local but it can be easily adapted.

Of course you also need libltdl library as well (it fails with same error)

android_bash.txt

Great stuff, thanks. Got it all compiled and working in my project perfectly.

zoe-zywang commented 4 months ago

Here is how I built libtool for Android:

Actually I finally managed to do it using autotools. The problem with libtool and actually automake of libgphoto2 was incorrect build command in generated libtool file. I'll get to my dev machine and I'll put it there. So now I can build everything using standard autotools. I'll remove CMakes from this pull since they aren't complete in general.

Out of interest, what was the fix? Currently falling into a similar issue with libtool and autoconf not auto detecting it

The generated libtool file has incorrect value of archive_cmds="" it should be

archive_cmds="\$CC -shared -nostdlib \$predep_objects \$libobjs \$deplibs \$postdep_objects \$compiler_flags -o \$lib

Once it fixed the build succeeds. Below the script that I use to build the library for all 4 architechtures - of course some paths are local but it can be easily adapted.

Of course you also need libltdl library as well (it fails with same error)

android_bash.txt

What is the meaning of the "AROOT=/home/artik/Packages/Android/$arch"? Android SDK? If it means SDK, what is the version of it?

artyom-beilis commented 4 months ago

What is the meaning of the "AROOT=/home/artik/Packages/Android/$arch"? Android SDK? If it means SDK, what is the version of it?

AROOT is a location of the packages I build for Android (outside SDK) for example libtool, libusb

zoe-zywang commented 4 months ago

What is the meaning of the "AROOT=/home/artik/Packages/Android/$arch"? Android SDK? If it means SDK, what is the version of it?

AROOT is a location of the packages I build for Android (outside SDK) for example libtool, libusb

Thanks a lot, I think that it belongs in an output folder. ^^