Code Monkey home page Code Monkey logo

gphoto2-rs's People

Contributors

gkodes avatar hfiguiere avatar maxicarlos08 avatar rreverser avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar

gphoto2-rs's Issues

CameraFile::get_data is probably leaking memory

From comment docs on gp_file_get_data_and_size:

 * For regular CameraFiles, the pointer to data that is returned is
 * still owned by libgphoto2 and its lifetime is the same as the #file.
 *
 * For filedescriptor or handler based CameraFile types, the returned
 * data pointer is owned by the caller and needs to be free()d to avoid
 * memory leaks.
 *
 **/

Consistent filesystem access?

All of the gp_camera_file_* and gp_camera_folder_* functions are thin wrappers around the corresponding gp_filesystem_get_*.

I wonder if it would be better to avoid exposing those bindings on Camera and instead focus only on CameraFS.

While libgphoto2 itself has to maintain both at least for backward compatibility, there's no need to bind both categories for us. On the other hand, exposing a single, consistent, interface for all file manipulation could be better from ergonomics perspective.

WDYT?

Task future is not multithreading-friendly

Looks like right now Context, Camera and Task is Send but not Sync, which makes it hard to use in many APIs that expect being able to check the future status from an arbitrary thread.

For example, trying to use such future inside a tokio::spawn API:

  tokio::task::spawn(async move {
    let camera = Context::new()?.autodetect_camera().await?;
    // TODO
    Ok(())
  });

will fail with something like:

error: future cannot be sent between threads safely
   --> examples/drop_camera.rs:8:22
    |
8   |     tokio::task::spawn(async move {
    |  ______________________^
9   | |     let camera = Context::new()?.autodetect_camera().await?;
10  | |     // TODO
11  | |     Ok(())
12  | |   });
    | |___^ future created by async block is not `Send`
    |
    = help: the trait `std::marker::Sync` is not implemented for `(dyn gphoto2::context::ProgressHandler + std::marker::Send + 'static)`
note: future is not `Send` as this value is used across an await
   --> examples/drop_camera.rs:9:53
    |
9   |     let camera = Context::new()?.autodetect_camera().await?;
    |                  ---------------                    ^^^^^^ await occurs here, with `Context::new()?` maybe used later
    |                  |
    |                  has type `&gphoto2::Context` which is not `Send`
note: `Context::new()?` is later dropped here
   --> examples/drop_camera.rs:9:60
    |
9   |     let camera = Context::new()?.autodetect_camera().await?;
    |                                                            ^
help: consider moving this into a `let` binding to create a shorter lived borrow
   --> examples/drop_camera.rs:9:18
    |
9   |     let camera = Context::new()?.autodetect_camera().await?;
    |                  ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
note: required by a bound in `tokio::spawn`
   --> /home/rreverser/.cargo/registry/src/github.com-1ecc6299db9ec823/tokio-1.25.0/src/task/spawn.rs:163:21
    |
163 |         T: Future + Send + 'static,
    |                     ^^^^ required by this bound in `tokio::spawn`

Seems the only reason those APIs are not Sync is because of progress handlers, which are only constrained by Send. It makes sense, since progress handlers are usually mutating the environment, but I wonder if it would make sense to turn them into channels similarly to waker field and other operations, so that background gphoto2 thread sends progress updates via Sender, and receivers on any thread handle them.

Hook up gp_log_add_func

As a follow-up to #26, it's also worth hooking up the global logging function gp_log_add_func to the log crate too as it provides even more info.

Add ability to set context progress functions

libgphoto2 allows you to set progress functions to a context.

These cannot be used to eg. track the download progress of a specific file being downloaded from the camera (you only get a display message). But you can use them to show some progress bars on your frontend (if you are building one) whenever libgphoto2 wants to report it

Investigate encodings and localisation

I've been looking a bit into how libgphoto2 deals with encodings, and found that it actually respects system localisation + some undocumented APIs for overriding localisation/encodings. What worries me there is that I'm not certain that non-English strings are guaranteed to be encoded in UTF-8 by libgphoto2, in which case perhaps we don't have a right to return them as String, or perhaps we at least have to customize encoding upon startup to enforce UTF-8 or something... As I said, I only started looking at this and there's a bit of uncertainty here. Now that I added test framework, I think it would be helpful to try and verify those assumptions and check what happens with non-ASCII characters.

Originally posted by @RReverser in #27 (comment)

Interaction between Context::set_progress_handlers and Task::set_progress_handler

If I'm reading code correctly, it seems that right now these two methods would conflict with each other - Task::set_progress_handler sets its own set of handlers on the context and unsets them at the end of the task, so it would always override any global handlers set by Context::set_progress_handlers.

If so... maybe it's better to make Context::set_progress_handlers private rather than part of the public API as it seems pretty easy to misuse?

Memory unsoundness in port_info (and maybe others)

In the process of writing tests, I've noticed that the internal pointer of camera.port_info() seems to be tied to the Camera's own lifetime, and is freed when the camera is.

As a result, it's very easy to run into memory corruption issues in safe code. Example:

let camera = Context::new()?.autodetect_camera()?;
let port_info = camera.port_info()?;
println!("1) {:?}", port_info);
drop(camera);
println!("2) {:?}", port_info);
1) PortInfo { name: "Universal Serial Bus", path: "usb:001,001", port_type: Some(Usb) }
2) PortInfo { name: "pG�m�U", path: "��m�U", port_type: Some(Usb) }

PortInfo should probably hold reference to Camera (either as a Rust reference, or via libgphoto2's reference counting), but also, where is one there might be others.

It's worth walking through other data structures that have pointers and are returned from camera / context / filesystem / etc. and making sure they are not tied similarly to their parents.

Example code in README.md does not work

The example code to take a picture in the README.md gives an error message: Error: Path not absolute.
The file and folder arguments in camera_fs.download_to are reversed.

camera_fs.download_to(&file_path.name(), &file_path.folder(), Path::new(&file_path.name().to_string())).wait()?;

Should be:

camera_fs.download_to(&file.folder(), &file.name(), Path::new(&file.name().to_string())).wait()?;

The code in the examples/capture.rs runs fine.

[Solved] Compilation error on Linux Mint: 'stdarg.h' file not found

hi there! when compiling a rust project using gphoto2-rs under linux mint i get the following error:

          $ cargo run
           Compiling libgphoto2_sys v1.2.0
          error: failed to run custom build command for `libgphoto2_sys v1.2.0`
          
          Caused by:
            process didn't exit successfully: `/home/<project-folder>/target/debug/build/libgphoto2_sys-7987dc01ee9af43d/build-script-build` (exit status: 101)
            --- stdout
            cargo:rerun-if-env-changed=LIBGPHOTO2_NO_PKG_CONFIG
            cargo:rerun-if-env-changed=PKG_CONFIG_x86_64-unknown-linux-gnu
            cargo:rerun-if-env-changed=PKG_CONFIG_x86_64_unknown_linux_gnu
            cargo:rerun-if-env-changed=HOST_PKG_CONFIG
            cargo:rerun-if-env-changed=PKG_CONFIG
            cargo:rerun-if-env-changed=LIBGPHOTO2_STATIC
            cargo:rerun-if-env-changed=LIBGPHOTO2_DYNAMIC
            cargo:rerun-if-env-changed=PKG_CONFIG_ALL_STATIC
            cargo:rerun-if-env-changed=PKG_CONFIG_ALL_DYNAMIC
            cargo:rerun-if-env-changed=PKG_CONFIG_PATH_x86_64-unknown-linux-gnu
            cargo:rerun-if-env-changed=PKG_CONFIG_PATH_x86_64_unknown_linux_gnu
            cargo:rerun-if-env-changed=HOST_PKG_CONFIG_PATH
            cargo:rerun-if-env-changed=PKG_CONFIG_PATH
            cargo:rerun-if-env-changed=PKG_CONFIG_LIBDIR_x86_64-unknown-linux-gnu
            cargo:rerun-if-env-changed=PKG_CONFIG_LIBDIR_x86_64_unknown_linux_gnu
            cargo:rerun-if-env-changed=HOST_PKG_CONFIG_LIBDIR
            cargo:rerun-if-env-changed=PKG_CONFIG_LIBDIR
            cargo:rerun-if-env-changed=PKG_CONFIG_SYSROOT_DIR_x86_64-unknown-linux-gnu
            cargo:rerun-if-env-changed=PKG_CONFIG_SYSROOT_DIR_x86_64_unknown_linux_gnu
            cargo:rerun-if-env-changed=HOST_PKG_CONFIG_SYSROOT_DIR
            cargo:rerun-if-env-changed=PKG_CONFIG_SYSROOT_DIR
            cargo:rerun-if-env-changed=PKG_CONFIG_SYSROOT_DIR
            cargo:rerun-if-env-changed=SYSROOT
            cargo:rerun-if-env-changed=LIBGPHOTO2_STATIC
            cargo:rerun-if-env-changed=LIBGPHOTO2_DYNAMIC
            cargo:rerun-if-env-changed=PKG_CONFIG_ALL_STATIC
            cargo:rerun-if-env-changed=PKG_CONFIG_ALL_DYNAMIC
            cargo:rustc-link-search=native=/usr/lib/x86_64-linux-gnu
            cargo:rustc-link-lib=gphoto2
            cargo:rustc-link-lib=m
            cargo:rustc-link-lib=gphoto2_port
            cargo:rustc-link-lib=m
            cargo:rerun-if-env-changed=PKG_CONFIG_x86_64-unknown-linux-gnu
            cargo:rerun-if-env-changed=PKG_CONFIG_x86_64_unknown_linux_gnu
            cargo:rerun-if-env-changed=HOST_PKG_CONFIG
            cargo:rerun-if-env-changed=PKG_CONFIG
            cargo:rerun-if-env-changed=LIBGPHOTO2_STATIC
            cargo:rerun-if-env-changed=LIBGPHOTO2_DYNAMIC
            cargo:rerun-if-env-changed=PKG_CONFIG_ALL_STATIC
            cargo:rerun-if-env-changed=PKG_CONFIG_ALL_DYNAMIC
            cargo:rerun-if-env-changed=PKG_CONFIG_PATH_x86_64-unknown-linux-gnu
            cargo:rerun-if-env-changed=PKG_CONFIG_PATH_x86_64_unknown_linux_gnu
            cargo:rerun-if-env-changed=HOST_PKG_CONFIG_PATH
            cargo:rerun-if-env-changed=PKG_CONFIG_PATH
            cargo:rerun-if-env-changed=PKG_CONFIG_LIBDIR_x86_64-unknown-linux-gnu
            cargo:rerun-if-env-changed=PKG_CONFIG_LIBDIR_x86_64_unknown_linux_gnu
            cargo:rerun-if-env-changed=HOST_PKG_CONFIG_LIBDIR
            cargo:rerun-if-env-changed=PKG_CONFIG_LIBDIR
            cargo:rerun-if-env-changed=PKG_CONFIG_SYSROOT_DIR_x86_64-unknown-linux-gnu
            cargo:rerun-if-env-changed=PKG_CONFIG_SYSROOT_DIR_x86_64_unknown_linux_gnu
            cargo:rerun-if-env-changed=HOST_PKG_CONFIG_SYSROOT_DIR
            cargo:rerun-if-env-changed=PKG_CONFIG_SYSROOT_DIR
          
            --- stderr
            /usr/include/gphoto2/gphoto2-port-log.h:24:10: fatal error: 'stdarg.h' file not found
            thread 'main' panicked at 'Unable to generate bindings: ClangDiagnostic("/usr/include/gphoto2/gphoto2-port-log.h:24:10: fatal error: 'stdarg.h' file not found\n")', /home/<user>/.cargo/registry/src/github.com-1ecc6299db9ec823/libgphoto2_sys-1.2.0/src/build.rs:35:6
            stack backtrace:
               0:     0x55a4fc4b1a5a - std::backtrace_rs::backtrace::libunwind::trace::hba70c054c9cdbd74
                                           at /rustc/8460ca823e8367a30dda430efda790588b8c84d3/library/std/src/../../backtrace/src/backtrace/libunwind.rs:93:5
               1:     0x55a4fc4b1a5a - std::backtrace_rs::backtrace::trace_unsynchronized::hfff24a4d77b00fef
                                           at /rustc/8460ca823e8367a30dda430efda790588b8c84d3/library/std/src/../../backtrace/src/backtrace/mod.rs:66:5
               2:     0x55a4fc4b1a5a - std::sys_common::backtrace::_print_fmt::h6fb3e9652d3b4f4e
                                           at /rustc/8460ca823e8367a30dda430efda790588b8c84d3/library/std/src/sys_common/backtrace.rs:65:5
               3:     0x55a4fc4b1a5a - <std::sys_common::backtrace::_print::DisplayBacktrace as core::fmt::Display>::fmt::h254ba81a1e20fed0
                                           at /rustc/8460ca823e8367a30dda430efda790588b8c84d3/library/std/src/sys_common/backtrace.rs:44:22
               4:     0x55a4fc4d6ffe - core::fmt::write::h232ccd94259bfe24
                                           at /rustc/8460ca823e8367a30dda430efda790588b8c84d3/library/core/src/fmt/mod.rs:1213:17
               5:     0x55a4fc4aebe5 - std::io::Write::write_fmt::h963cfaecfdd596f7
                                           at /rustc/8460ca823e8367a30dda430efda790588b8c84d3/library/std/src/io/mod.rs:1682:15
               6:     0x55a4fc4b1825 - std::sys_common::backtrace::_print::h6fbc4343523214ce
                                           at /rustc/8460ca823e8367a30dda430efda790588b8c84d3/library/std/src/sys_common/backtrace.rs:47:5
               7:     0x55a4fc4b1825 - std::sys_common::backtrace::print::h55ab07cec21aacd5
                                           at /rustc/8460ca823e8367a30dda430efda790588b8c84d3/library/std/src/sys_common/backtrace.rs:34:9
               8:     0x55a4fc4b322f - std::panicking::default_hook::{{closure}}::hc10df65206eee69e
                                           at /rustc/8460ca823e8367a30dda430efda790588b8c84d3/library/std/src/panicking.rs:267:22
               9:     0x55a4fc4b2f6b - std::panicking::default_hook::hdd684731d8d78925
                                           at /rustc/8460ca823e8367a30dda430efda790588b8c84d3/library/std/src/panicking.rs:286:9
              10:     0x55a4fc4b3939 - std::panicking::rust_panic_with_hook::h58681788b2d08dc0
                                           at /rustc/8460ca823e8367a30dda430efda790588b8c84d3/library/std/src/panicking.rs:688:13
              11:     0x55a4fc4b36d9 - std::panicking::begin_panic_handler::{{closure}}::he6d9da406579493c
                                           at /rustc/8460ca823e8367a30dda430efda790588b8c84d3/library/std/src/panicking.rs:579:13
              12:     0x55a4fc4b1f0c - std::sys_common::backtrace::__rust_end_short_backtrace::h5b1f3b233c047d47
                                           at /rustc/8460ca823e8367a30dda430efda790588b8c84d3/library/std/src/sys_common/backtrace.rs:137:18
              13:     0x55a4fc4b33e2 - rust_begin_unwind
                                           at /rustc/8460ca823e8367a30dda430efda790588b8c84d3/library/std/src/panicking.rs:575:5
              14:     0x55a4fbfb5c13 - core::panicking::panic_fmt::hea602a2467b5109d
                                           at /rustc/8460ca823e8367a30dda430efda790588b8c84d3/library/core/src/panicking.rs:64:14
              15:     0x55a4fbfb60c3 - core::result::unwrap_failed::he3f6a4db4030a3f8
                                           at /rustc/8460ca823e8367a30dda430efda790588b8c84d3/library/core/src/result.rs:1790:5
              16:     0x55a4fbfb9d67 - core::result::Result<T,E>::expect::hbaab93758227f04c
                                           at /rustc/8460ca823e8367a30dda430efda790588b8c84d3/library/core/src/result.rs:1069:23
              17:     0x55a4fbfb9815 - build_script_build::main::h4895ba51fb0920c7
                                           at /home/js/.cargo/registry/src/github.com-1ecc6299db9ec823/libgphoto2_sys-1.2.0/src/build.rs:24:18
              18:     0x55a4fbfb72bb - core::ops::function::FnOnce::call_once::h37466a4baa549378
                                           at /rustc/8460ca823e8367a30dda430efda790588b8c84d3/library/core/src/ops/function.rs:250:5
              19:     0x55a4fbfb752e - std::sys_common::backtrace::__rust_begin_short_backtrace::h8d2f616e44d46b44
                                           at /rustc/8460ca823e8367a30dda430efda790588b8c84d3/library/std/src/sys_common/backtrace.rs:121:18
              20:     0x55a4fbfb6f91 - std::rt::lang_start::{{closure}}::hf44732de27ff8381
                                           at /rustc/8460ca823e8367a30dda430efda790588b8c84d3/library/std/src/rt.rs:166:18
              21:     0x55a4fc4aaebc - core::ops::function::impls::<impl core::ops::function::FnOnce<A> for &F>::call_once::h2dd1a24ae3e0569f
                                           at /rustc/8460ca823e8367a30dda430efda790588b8c84d3/library/core/src/ops/function.rs:287:13
              22:     0x55a4fc4aaebc - std::panicking::try::do_call::h71e38d3ed05d0919
                                           at /rustc/8460ca823e8367a30dda430efda790588b8c84d3/library/std/src/panicking.rs:483:40
              23:     0x55a4fc4aaebc - std::panicking::try::h9dd8fea17c119511
                                           at /rustc/8460ca823e8367a30dda430efda790588b8c84d3/library/std/src/panicking.rs:447:19
              24:     0x55a4fc4aaebc - std::panic::catch_unwind::h073a10d358958706
                                           at /rustc/8460ca823e8367a30dda430efda790588b8c84d3/library/std/src/panic.rs:140:14
              25:     0x55a4fc4aaebc - std::rt::lang_start_internal::{{closure}}::h0cf5d9b5652f6b98
                                           at /rustc/8460ca823e8367a30dda430efda790588b8c84d3/library/std/src/rt.rs:148:48
              26:     0x55a4fc4aaebc - std::panicking::try::do_call::hc59ab1d339fa21e7
                                           at /rustc/8460ca823e8367a30dda430efda790588b8c84d3/library/std/src/panicking.rs:483:40
              27:     0x55a4fc4aaebc - std::panicking::try::h40dd3124b394a6da
                                           at /rustc/8460ca823e8367a30dda430efda790588b8c84d3/library/std/src/panicking.rs:447:19
              28:     0x55a4fc4aaebc - std::panic::catch_unwind::hff10c6c48e0fc17d
                                           at /rustc/8460ca823e8367a30dda430efda790588b8c84d3/library/std/src/panic.rs:140:14
              29:     0x55a4fc4aaebc - std::rt::lang_start_internal::h7868f0ffe3ad1ec2
                                           at /rustc/8460ca823e8367a30dda430efda790588b8c84d3/library/std/src/rt.rs:148:20
              30:     0x55a4fbfb6f6a - std::rt::lang_start::h22ae034c20e50bce
                                           at /rustc/8460ca823e8367a30dda430efda790588b8c84d3/library/std/src/rt.rs:165:17
              31:     0x55a4fbfb9aae - main
              32:     0x7f70e08be083 - __libc_start_main
                                           at /build/glibc-SzIz7B/glibc-2.31/csu/../csu/libc-start.c:308:16
              33:     0x55a4fbfb62ae - _start
              34:                0x0 - <unknown>

rust ist up to date, it is installed via rustup. maybe i'm missing a linux package or there is a file linking issue. libgphoto2-dev is installed.
my system:

    System:    Kernel: 5.15.0-67-generic x86_64 bits: 64 Desktop: Cinnamon 5.2.7 
               Distro: Linux Mint 20.3 Una 
    Machine:   Type: Laptop System: Dell product: Latitude 3520 v: N/A serial: <filter> 
               Mobo: Dell model: 03VVMC v: A00 serial: <filter> UEFI: Dell v: 1.23.2 
               date: 10/27/2022 
    Battery:   ID-1: BAT0 charge: 54.0 Wh condition: 54.0/54.0 Wh (100%) 
    CPU:       Topology: Quad Core model: 11th Gen Intel Core i5-1135G7 bits: 64 type: MT MCP 
               L2 cache: 8192 KiB 
               Speed: 1041 MHz min/max: 400/4200 MHz Core speeds (MHz): 1: 937 2: 888 3: 633 4: 941 
               5: 1004 6: 1007 7: 900 8: 1090 
    Graphics:  Device-1: Intel driver: i915 v: kernel 
               Display: server: X.Org 1.20.13 driver: modesetting unloaded: fbdev,vesa 
               resolution: 1920x1080~60Hz 
               OpenGL: renderer: Mesa Intel Xe Graphics (TGL GT2) v: 4.6 Mesa 21.2.6 
    Audio:     Device-1: Intel driver: sof-audio-pci-intel-tgl 
               Device-2: Logitech HD Pro Webcam C920 type: USB driver: snd-usb-audio,uvcvideo 
               Sound Server: ALSA v: k5.15.0-67-generic 
    Network:   Device-1: Intel driver: iwlwifi 
               IF: wlp0s20f3 state: down mac: <filter> 
               Device-2: Realtek RTL8111/8168/8411 PCI Express Gigabit Ethernet driver: r8169 
               IF: enp43s0 state: up speed: 1000 Mbps duplex: full mac: <filter> 
    Drives:    Local Storage: total: 238.47 GiB used: 300.88 GiB (126.2%) 
               ID-1: /dev/nvme0n1 model: KBG40ZNS256G NVMe KIOXIA 256GB size: 238.47 GiB 
    RAID:      Hardware-1: Intel Volume Management Device NVMe RAID Controller driver: vmd 
    Partition: ID-1: / size: 159.84 GiB used: 150.40 GiB (94.1%) fs: ext4 dev: /dev/nvme0n1p6 
    Sensors:   System Temperatures: cpu: 37.0 C mobo: N/A 
               Fan Speeds (RPM): N/A 
    Info:      Processes: 283 Uptime: 3h 55m Memory: 7.51 GiB used: 4.76 GiB (63.3%) Shell: bash 
               inxi: 3.0.38

Possibility of merging extra features?

Hi! The creation of this repo / crate is very well timed. I actually forked gphoto2 myself a month or two to add extra functionality as @dcuddeback's repos are dead. Are we able to go over the code I wrote / possibly clean it up and get it merged??

Edit It looks like you have added most features! Great work! I have two requests below Edit
.
.

Below is a summary of my features:

Added in-memory file downloads: add-in-memory-filemedia

  • Added means to save a FileMedia into a memory buffer instead of a file. Code was taken from various forks of the original @dcuddeback.
  • ********* Looks like you added this in (More idiomatic I might add - using new's):
    pub(crate) fn new() -> Result<Self> {
    please ignore *********

Added ability to query and update widgets: add-camera-widget

Added ability to stream video out of device: add-camera-video

Post edit: Since It looks like you have implemented most features I had (and your code better written than mine), there is no point integrating any of my code mentioned above. The only two potential requests I have are to implement the video streaming (video.rs), and the Widget::set_value_string function. That would make this crate 100% usable for my needs, and I can archive my github fork :)

Thanks!

libgphoto2 has thread safety issues

Looks like libgphoto2 is not thread-safe (gphoto/libgphoto2#166) even in the sense that you can't instantiate separate Contexts in different threads, because it uses libltdl for loading iolibs & camlibs, which is not thread safe.

Given how common multithreading is in Rust, and how it can only protect against explicit access to the same resource, but knows nothing about implicit C statics, it would be good to walk over all the libgphoto2 methods from the patch linked in that issue (or just over all libgphoto2 functions that use lt_* APIs) and add internal mutex on Rust side and lock it wherever we use those functions.

In theory, that should only include loading/destroying/managing abilities list and port list, but there might be other transitive dependencies.

@maxicarlos08

0 byte file left behind

If the download fail (it seems that I often lose the USB connection on my camera) using CameraFs::download_file, it leave behind a 0 bytes file. IMHO it should clean it up at least if it is zero size, since no download occured.

Mixed Widget types in error message.

I tried to use lib, however i spent long period of time on this error:

thread 'main' panicked at 'called Result::unwrap()on anErr value: Unspecified error [Expected GroupWidget but got RadioWidget { id: 2, name: "shutterspeed", label: "Shutter Speed", readonly: false, choices: [_; 53], choice: "1/250" }]'

however changing the type to GroupWidget:
let mut shutterspeed = camera.config_key::<gphoto2::widget::GroupWidget>("shutterspeed").wait().unwrap();
is not helping, however if i will change it to:
let mut shutterspeed = camera.config_key::<gphoto2::widget::RadioWidget>("shutterspeed").wait().unwrap();

Error is gone. It seems that in error message GroupWidget and RadioWidget are mixed.
Here is simple example that will help you to figure out:

use gphoto2::{Camera, Context, Result};
use gphoto2::widget::{RadioWidget, Widget};

fn get_iso(camera: Camera) {
    let mut shutterspeed = camera
        .config_key::<gphoto2::widget::GroupWidget>("shutterspeed")
        .wait()
        .unwrap();
    let mut camera_model = camera
        .config_key::<gphoto2::widget::TextWidget>("cameramodel")
        .wait()
        .unwrap();
}

fn main() -> Result<()> {
    env_logger::init();
    let camera = Context::new()?.autodetect_camera().wait()?;
    get_iso(camera);
    Ok(())
}

Relicensing to LGPL

libgphoto2 itself is licensed under LGPL-v2.1, which allows it to be used in many more contexts than GPL does.

Currently, the Rust wrapper is licensed under GPL-v3.0, which makes it unnecessarily more restrictive than the library itself.

Would it be possible to change license of the Rust wrapper to make it at least as permissive as the underlying library?

Windows help: runs great in mingw64 & ucrt64, gets Error loading a library output when trying to run outside of msys2 env.

Hey there, pretty stumped and don't know how else to try to move forward.

I have a basic application that uses these bindings and it successfully compiles and runs when executed from within mingw64 and ucrt64, however running ntldd -Rand copying over the dll's for my application (just libgphoto2-6.dll, libgphoto2_port-12.dll and their non-system dependencies) to the target/debug directory where the executable sits, and running through cmd, I get the error: Error loading a library. It is not more descriptive than that and I'm not sure how to get a more verbose output. I've tried increased logging, backtraces, etc, Windows & Visual Studio debugging tools to no avail.

I believe it has to do with libgphoto2 as it happens when trying to initialize the camera handler in my application, but i'd love to have some additional input as to what to try next.

The full list of DLL's I have in the same directory as the compiled executable:

libexif-12.dll
libgphoto2_port-12.dll
libgphoto2-6.dll
libintl-8.dll
libiconv-2.dll
libsystre-0.dll
libtre-5.dll
libwinpthread-1.dll

Happy to provide any other information that might be useful to help get to the bottom of this.

Downloading previews

It seems the API to download previews is missing.

FileInfo doesn't have the data.

In C, you use gp_camera_file_get() with GP_FILE_TYPE_PREVIEW.

Switch from log to tracing?

Looks like ecosystem is increasingly moving towards tracing for logging. log is still supported via backward compatibility, but tracing provides even more features including structural logging of individual values in addition to the message, compatibility with more backends, nested spans for grouping messages and neat attribute that allows to get all of that by simply instrumenting functions.

While not a high priority, I think for debugging it would be useful to integrate with tracing although it might require some care in the Task struct to make sure that it works correctly in asynchronous contexts like tracing's own Instrumented helper.

String helpers have stack-use-after-return issues

After lifetime cleanup in #6, I've decided to take a look at other potential instances of unbounded lifetimes now that there's not much to look at.

I've noticed that string helpers have such unbounded lifetimes, but, unlike with heap pointers in #6, those can actually be harmful. For example:

pub fn camera_text_to_str<'a>(text: libgphoto2_sys::CameraText) -> Cow<'a, str> {
  unsafe { String::from_utf8_lossy(ffi::CStr::from_ptr(text.text.as_ptr()).to_bytes()) }
}

Here, CameraText contains on-stack array of chars. The helper takes a pointer to that stack array, passes via CStr & String conversions, and potentially gets a Cow back with that same pointer. Then, it claims that the returned pointer is valid and borrowed (from unbounded lifetime 'a), and returns upwards, even though the actual data is no longer reachable once the function returns.

Same applies to usages of chars_to_cow whenever input pointer points to temporary on-stack data.

It's pretty hard to trigger this to show that strings might contain garbage once overridden by other stack data, but, as far as I can tell, it works only by accident.

Those unbounded lifetimes should be eliminated, and instead there should probably be a couple of helpers:

  1. Takes &'a [c_char] and returns Cow<'a, str> - this would be most popular (there's lots of [c_char; 123] data in the codebase, including in CameraText) and safe as the lifetime would be clearly bound to the input.
  2. Something like the current chars_to_cow, but marked unsafe so that it's clear it should be used only if you can pass explicit lifetime (e.g. strings returned from Widget::name etc. that are constructed from *const c_char that is valid as long as Widget itself).
  3. chars_to_string for the rest of the cases, to immediately convert into String and not expect the input pointer to live after the function call.

Context & the rest shouldn't have a lifetime

Right now, Context creates an unbounded lifetime (see Unbounded Lifetimes tied to whatever scope it was created in via Context::new. This is not very useful and doesn't provide any extra guarantees, since the pointers returned from libgphoto2 are heap-allocated anyway. As such, the lifetime from Context and most of other data structures that inherit the same lifetime, can be safely removed.

@maxicarlos08 do you want to take this one?

Missing Feature: Liveview

The gphoto2 feature live view might be missing in this rust binding.
With this feature of gphoto2 you can capture a live preview video stream from a supported camera.
To approach feature completeness of this binding with the original gphoto2, I think this feature should be added, if possible.

As there is no std video stream API in rust I know of, my suggestion would be to provide some interface that could, for example, be connected to the official rust binding for gstreamer (maybe as a video-source for gst-pipelines) or other popular media framework.

CameraFile shouldn't keep ownership of the original File

When creating from an existing File, we use gp_file_new_from_fd, which says:

 * This function takes ownership of the filedescriptor and will close it when closing the CameraFile.

That is, we actually shouldn't keep the original File around as its ownership has already been transferred, so it must not be closed on drop by Rust.

libgphoto2 is actually not thread-safe at all :(

Continuation of the multithreading shenanigans, and I found out that libgphoto2 is actually non-reentrant - not safe to use from multiple threads even if you create separate Contexts. We'll need to wrap around this unsafety somehow (see my suggestion at the end of the quote).

Now that I'm looking a bit deeper, I'm actually not sure that libgphoto2 is thread-safe at all, so fixing ltdl codepaths won't help much... There seems to be a lot of global mutable variables throughout the codebase, which are not protected by mutexes or atomics, and as such are inherently prone to corruption via race conditions.

So even if one takes care and creates separate gphoto2 contexts per-thread, all those internal data structures can be still corrupted by racing calls.

I guess the only safe way to use gphoto2 in multithreaded environment is to actually pin it to a single thread and make sure all work, for all devices, is done there. (at least until it's refactored in some future to avoid global variables, or to have mutex around all of them)

Originally posted by @RReverser in gphoto/libgphoto2#848 (comment)

Problem with tauri

I try to use this wrapper on tauri, but face the following issue, is this a problem with gphoto2 or tauri?
image

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.