Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
12 changes: 12 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,17 @@
# Sony Camera Plugin

## 1.0.0.6 — corrective community preview

Follow-up to the 1.0.0.5 audit, retaining all previously integrated contributions and Doug Henderson's original authorship. Install manually using [INSTALLATION.md](INSTALLATION.md).

- Preserve aborts received during capture-start preflight. An aborted pending start cannot launch an exposure after its status check returns; a rejected busy start preserves cancellation of the preceding capture.
- Verify the specific nearest learnt shutter step using the native driver's float rounding and absolute-distance selection, replacing the broad ratio that accepted a stalled adjacent speed.
- Retry a valid previous Bulb readback when switching to a short numeric exposure. Malformed readbacks still fail, and a persistent mismatch cannot start capture.
- Restore the repeated-failure camera-loss protection adapted from Robert Hasson's upstream #13: three consecutive qualifying native errors mark the camera disconnected and block all further native access until NINA restarts. Never-working properties, explicit unsupported results, lock contention and shutter-verification mismatches do not count. A successful camera operation resets the count. No native close, retry or automatic reconnection is attempted after the guard trips.
- Add regression coverage using the production capture controller and managed native wrappers, replacing only native delegates and NINA logging/notifications for portable tests.

See [the corrective review](docs/RELEASE-REVIEW-1.0.0.6.md). Physical camera/USB operation remains unverified; this is a prerelease for manual testing and is not distributed through NINA's plugin manager.

## 1.0.0.5 — community preview

First maintained release from [Lucas Lepski’s fork](https://github.com/shurkanTwo/NINASonyCameraPlugin), preserving Doug Henderson’s original authorship and MPL-2.0. Install manually using [INSTALLATION.md](INSTALLATION.md). This preview is not distributed through NINA’s plugin manager.
Expand Down
46 changes: 33 additions & 13 deletions Drivers/CaptureController.cs
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ internal sealed class CaptureController {
internal enum AbortResult { AlreadyRequested, NativeCancelRequested, SoftCancelRequested }

private readonly object captureLock = new object();
private readonly object requestLock = new object();
private readonly Func<uint> getStatus;
private readonly Action<float> startCapture;
private readonly Func<bool> cancelCapture;
Expand All @@ -27,6 +28,7 @@ private sealed class CaptureRequest {
internal int CancelRequested;
}
private CaptureRequest currentRequest = new CaptureRequest();
private CaptureRequest pendingRequest;

internal CaptureController(Func<uint> getStatus, Action<float> startCapture,
Func<bool> cancelCapture, Func<bool> nativeCancelEnabled, int cancelLockTimeoutMs = 1000) {
Expand All @@ -39,26 +41,44 @@ internal CaptureController(Func<uint> getStatus, Action<float> startCapture,

internal void Start(float exposureTime) {
lock (captureLock) {
uint status = getStatus();
if (IsBusy(status)) {
throw new InvalidOperationException("Cannot start exposure: camera is still busy with a previous exposure.");
}
if (status != Created && status != Cancelled && status != Complete && status != Failed) {
throw new InvalidOperationException($"Cannot start exposure: capture status unavailable or unexpected ({status}).");
var request = new CaptureRequest();
lock (requestLock) {
pendingRequest = request;
}
try {
uint status = getStatus();
if (IsBusy(status)) {
throw new InvalidOperationException("Cannot start exposure: camera is still busy with a previous exposure.");
}
if (status != Created && status != Cancelled && status != Complete && status != Failed) {
throw new InvalidOperationException($"Cannot start exposure: capture status unavailable or unexpected ({status}).");
}

// A rejected start must not clear cancellation of the preceding exposure.
Volatile.Write(ref currentRequest, new CaptureRequest());
// Serialize the native start itself: it can replace the native capture object.
startCapture(exposureTime);
lock (requestLock) {
Volatile.Write(ref currentRequest, request);
pendingRequest = null;
}
ThrowIfCancelled(request);
// Serialize the native start itself: it can replace the native capture object.
startCapture(exposureTime);
} finally {
lock (requestLock) {
pendingRequest = null;
}
}
}
}

internal AbortResult Abort() {
// Record cancellation before waiting for the lock, including while StartCapture is blocked.
var request = Volatile.Read(ref currentRequest);
if (Interlocked.Exchange(ref request.CancelRequested, 1) != 0) {
return AbortResult.AlreadyRequested;
CaptureRequest request;
lock (requestLock) {
request = pendingRequest ?? currentRequest;
int alreadyRequested = Interlocked.Exchange(ref request.CancelRequested, 1);
// If preflight rejects the new request, the previous capture must
// still retain this abort. No native call runs under requestLock.
Interlocked.Exchange(ref currentRequest.CancelRequested, 1);
if (alreadyRequested != 0) return AbortResult.AlreadyRequested;
}
if (!nativeCancelEnabled() || !Monitor.TryEnter(captureLock, cancelLockTimeoutMs)) {
return AbortResult.SoftCancelRequested;
Expand Down
9 changes: 5 additions & 4 deletions INSTALLATION.md
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ These instructions install the community-maintained build from
The original plugin was developed by **Doug Henderson**. This fork is maintained
by **Lucas Lepski and contributors** while shared upstream maintenance is being discussed.

The first community release, **1.0.0.5**, is a preview for manual testing. Windows
The current community release, **1.0.0.6**, is a preview for manual testing. Windows
builds and automated tests are checked; physical Sony camera/USB operation has
not been verified for this combined release. See the release notes for scope.

Expand All @@ -17,7 +17,7 @@ not been verified for this combined release. See the release notes for scope.

## Install or replace an existing version

1. Download **`SonyCameraPlugin-1.0.0.5.zip`** from the [1.0.0.5 release](https://github.com/shurkanTwo/NINASonyCameraPlugin/releases/tag/1.0.0.5). Choose the release asset, rather than GitHub's automatic “Source code” archives. Extract it to a temporary folder. The plugin is `NINA.RetroKiwi.Plugin.SonyCamera.dll`.
1. Download **`SonyCameraPlugin-1.0.0.6.zip`** from the [1.0.0.6 release](https://github.com/shurkanTwo/NINASonyCameraPlugin/releases/tag/1.0.0.6). Choose the release asset, rather than GitHub's automatic “Source code” archives. Extract it to a temporary folder. The plugin is `NINA.RetroKiwi.Plugin.SonyCamera.dll`.
2. Disconnect the camera and focuser in NINA, then **close every NINA window** before changing plugin files.
3. Press **Win+R**, enter `%LOCALAPPDATA%\NINA\Plugins`, and open the plugin-version folder used by your NINA installation. NINA 3.x installations commonly use **`3.0.0`**: this folder tracks plugin compatibility, so it need not match the NINA version in About. If several version folders exist, use the one in NINA's startup log (`%LOCALAPPDATA%\NINA\Logs`); look for the path from which the Sony plugin was loaded.
4. If Sony Camera Plugin is already installed, locate its existing `NINA.RetroKiwi.Plugin.SonyCamera.dll` and copy the entire containing plugin folder **outside `%LOCALAPPDATA%\NINA\Plugins`** as a backup. Replace the DLL **in that existing folder**, even if the folder name differs from the example. Do not create another plugin folder containing a second copy. Keep the rest of the existing folder's files.
Expand All @@ -29,7 +29,7 @@ not been verified for this combined release. See the release notes for scope.

6. Copy the extracted DLL into the existing or newly created folder. The ZIP also contains the license, source reference, and these instructions; you can keep those files alongside it. It contains no replacement NINA runtime libraries or native Sony driver.
7. If Windows shows an **Unblock** checkbox in the downloaded ZIP or DLL's Properties, unblock the file. Alternatively run `Unblock-File` in PowerShell on that downloaded ZIP/DLL before copying/extracting it.
8. Restart NINA. In its plugin manager, confirm **Sony Camera Plugin 1.0.0.5** is loaded; the description identifies the community-maintained build. Select the Sony camera in Equipment and connect it.
8. Restart NINA. In its plugin manager, confirm **Sony Camera Plugin 1.0.0.6** is loaded; the description identifies the community-maintained build. Select the Sony camera in Equipment and connect it.
9. Leave **Enable native cancel** disabled initially. Try one short exposure and check the downloaded image, ISO and exposure before using the build for a sequence. Temperature appears only after downloading an ARW that contains a supported Sony temperature reading.

This is a replacement for the upstream plugin, with the same identifier so existing
Expand All @@ -45,7 +45,7 @@ The release includes **`SHA256SUMS.txt`** for its ZIP and standalone DLL. In
PowerShell, calculate a downloaded file's hash and compare it to the matching entry:

```powershell
Get-FileHash "$env:USERPROFILE\Downloads\SonyCameraPlugin-1.0.0.5.zip" -Algorithm SHA256
Get-FileHash "$env:USERPROFILE\Downloads\SonyCameraPlugin-1.0.0.6.zip" -Algorithm SHA256
```

## Roll back
Expand All @@ -62,6 +62,7 @@ version. The separate Sony driver installation and your images do not need chang
- **Missing ISO choices:** use the native driver's `SonyCameraInfo64.exe /s` learning/scanning procedure. This release offers manual ISO choices; AUTO and Multi Frame NR modes are excluded.
- **Cannot set the requested exposure:** the shutter change is retried before capture. If it cannot be verified, the exposure fails rather than being silently captured at the previous shutter speed. A camera without learnt shutter settings still uses its manually selected speed; learn its settings before using automatic flats.
- **Abort appears to leave the camera busy:** soft cancellation stops NINA's wait while the camera finishes its current exposure. Wait for it to finish before starting another. Reading/processing is always soft-cancelled.
- **Camera marked disconnected after repeated failures:** three consecutive qualifying native errors stop further native access. A property that has never worked and explicit unsupported-property results are excluded. Restart NINA and power-cycle the camera before reconnecting; the plugin does not attempt recovery against the failed handle.
- **Driver stopped responding:** close NINA, power-cycle the camera, and restart NINA before reconnecting. The plugin deliberately blocks further native calls after an execution timeout. USB unplugging and power-off while connected can still cause native crashes; disconnect in NINA first.

Report problems with this build in [this fork's issue tracker](https://github.com/shurkanTwo/NINASonyCameraPlugin/issues).
Expand Down
4 changes: 2 additions & 2 deletions Properties/AssemblyInfo.cs
Original file line number Diff line number Diff line change
Expand Up @@ -8,8 +8,8 @@

// [MANDATORY] The assembly versioning
//Should be incremented for each new release build of a plugin
[assembly: AssemblyVersion("1.0.0.5")]
[assembly: AssemblyFileVersion("1.0.0.5")]
[assembly: AssemblyVersion("1.0.0.6")]
[assembly: AssemblyFileVersion("1.0.0.6")]

// [MANDATORY] The name of your plugin
[assembly: AssemblyTitle("Sony Camera Plugin")]
Expand Down
6 changes: 3 additions & 3 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@ Native NINA plugin for Sony mirrorless/DSLR bodies over the Sony MTP interface,

## Installation

Download a maintained build from [this fork’s releases](https://github.com/shurkanTwo/NINASonyCameraPlugin/releases) and follow the **[manual installation instructions](INSTALLATION.md)**. The first community release is a preview for manual testing. It replaces the upstream plugin; install one copy only.
Download a maintained build from [this fork’s releases](https://github.com/shurkanTwo/NINASonyCameraPlugin/releases) and follow the **[manual installation instructions](INSTALLATION.md)**. Community releases are previews for manual testing. It replaces the upstream plugin; install one copy only.

The N.I.N.A. plugin manager currently distributes the upstream release. This fork has not been submitted as its update source.

Expand All @@ -37,8 +37,8 @@ The N.I.N.A. plugin manager currently distributes the upstream release. This for
- The driver chooses the nearest learnt built-in shutter speed; durations beyond the longest numeric speed use Bulb. The requested mode is verified before capture.
- To keep a copy on the camera's memory card as well as sending it to NINA, use the camera's **PC Remote Settings → Still Img. Save Dest. → PC+Camera** setting (see below).
- Powering off/unplugging the camera while connected can crash NINA via Windows' MTP stack (PortableDeviceApi.dll access violation); disconnect in NINA first to avoid it.
- Native driver calls are serialized across camera and lens operations. If a native call stops responding, restart NINA and power-cycle the camera before reconnecting. Automatic USB reconnection is not included.
- Shutter changes are read back and retried before capture. If a readable shutter remains outside supported-step rounding after the retry budget, capture fails instead of silently using the old exposure. Cameras without a learnt shutter list retain their manually selected shutter setting; learn that list before using automatic flats. Sky Flat behavior is not claimed to be resolved.
- Native driver calls are serialized across camera and lens operations. If a native call stops responding, restart NINA and power-cycle the camera before reconnecting. After three consecutive qualifying native errors, the camera is marked disconnected and further native access is also blocked until NINA restarts. Never-working properties and explicit unsupported-property results do not trigger this guard. Automatic USB reconnection is not included.
- Shutter changes are read back and retried before capture. If the camera does not reach the nearest learnt shutter step after the retry budget, capture fails instead of silently using the old exposure. Cameras without a learnt shutter list retain their manually selected shutter setting; learn that list before using automatic flats. Sky Flat behavior is not claimed to be resolved.
- “Enable native cancel” is off by default and saved per NINA profile. With it off, abort cancels the wait and discards the exposure, while the camera finishes capturing; another exposure can start once the camera finishes. Enabling it allows native cancellation during aborts before image readout/processing, which may crash NINA on some camera models and Windows drivers. New exposure requests never cancel an existing capture.

## Simulator development
Expand Down
Loading