GoogleChromeLabs / web-gphoto2

Running gPhoto2 to control DSLR cameras over USB on the Web
https://web-gphoto2.rreverser.com/
GNU Lesser General Public License v2.1
101 stars 16 forks source link

Cannot stop live-view after starting it #13

Open icheered opened 10 months ago

icheered commented 10 months ago

Camera: Nikon D5300

When starting the viewfinder (live-view) the camera raises the mirror and you can capturePreviewAsBlob at high speed. When trying to disable the viewfinder it will error:

Error: libapi.mjs?v=263350c0:9 Uncaught (in promise) Error: I/O in progress

My first guess is that it has something to do with the scheduling of events like @RReverser mentions in his blog.

Notes

  1. I can still change other settings like ISO while in liveview.
  2. Using the gphoto2 CLI I can enable and disable liveview as normal
  3. Updating libgphoto2 to the latest version does not fix the issue
irvandikky commented 10 months ago

I'm also always got

Could not refresh preview: Error: Unspecified error
    at throw_msg (libapi.mjs?v=54d10e0e:9:16162)
    at libapi.wasm:0xe8f33
    at ret.<computed> (libapi.mjs?v=54d10e0e:9:125562)
    at invoke_vi (libapi.mjs?v=54d10e0e:9:191780)
    at libapi.wasm:0xe28c0
    at libapi.wasm:0xc70ff
    at libapi.wasm:0xe8cfc
    at ret.<computed> (libapi.mjs?v=54d10e0e:9:125562)
    at Object.doRewind (libapi.mjs?v=54d10e0e:9:126851)
    at libapi.mjs?v=54d10e0e:9:127444

Is there any reference?

RReverser commented 10 months ago

When trying to disable the viewfinder it will error:

What do you mean by disabling the viewfinder? Manually on the camera? Or somehow via the API?

icheered commented 10 months ago

Via the API. I call camera.setConfigValue() with name='viewfinder' and value='1' which raises the mirror (audible), but when calling the function again but with value='0' to lower the mirror again it will give the previously mentioned "I/O in progress" error.

This is the settings object that I retrieve from the camera:

    "name": "viewfinder",
    "info": "",
    "label": "Nikon Viewfinder",
    "readonly": false,
    "type": "toggle",
    "value": "0",
    "category": "actions"
}
RReverser commented 10 months ago

Just to be sure, are you awaiting the promise from setConfigValue before continuing?

RReverser commented 10 months ago

Basically yeah, this sounds like typical scheduling problem. That #schedule wrapper in the API should take care of it and make sure that you're not trying to lower the mirror in the middle of a frame capture. If it doesn't, then either the uiTimeout needs to be increased or there is some other ordering bug.

RReverser commented 10 months ago

not trying to lower the mirror in the middle of a frame capture

FWIW this doesn't happen in official CLI because they are not thread-safe, run in single-threaded mode and from their PoV all USB operations are blocking so can't execute concurrently in principle.

In our case it's async APIs under the hood which is why the promise queue is needed - if kinda acts like a mutex, ensuring that no operations overlap, otherwise you get the mentioned "device busy" issue.