Repository navigation
Conversation
Add a SwiftSMBAVFoundation product that streams media files from an SMB share into AVFoundation. SMB.Connection gains makeAsset(at:contentType:options:) and makePlayerItem(at:contentType:), backed by an AVAssetResourceLoaderDelegate that serves AVFoundation's byte-range requests from one shared read-only handle. The content type is inferred from the path extension, falling back to .movie. The module builds empty on watchOS, Linux, and Android. Expose SMB.File.read(upTo:atOffset:transferChunkSize:), a positional read over smb2_pread that leaves the handle's current offset untouched, so concurrent tasks can read different ranges of one handle. Co-Authored-By: Claude Opus 5.5 <[email protected]>
Build the "leave unchanged" basic-info timestamp sentinel with truncatingIfNeeded so it compiles where time_t is 32-bit and still matches libsmb2's 0xffffffff comparison in both widths. Stop conversions that trap where Int is 32-bit: asUInt32's Int(UInt32.max) bound, and server-supplied notify entry lengths, maximum read/write sizes, and copy-chunk counts. Co-Authored-By: Claude Opus 5.5 <[email protected]>
The asset's resource loader keeps a read handle open until AVFoundation releases it, and the server refuses to delete an open file with STATUS_SHARING_VIOLATION. The reader and player item tests therefore left their movie_*.mp4 behind on the test share. Retry the removal for up to three seconds instead of ignoring the failure. Co-Authored-By: Claude Sonnet 5.5 <[email protected]>
SampleApp/SMB+AV connects to a share and plays an audio or video file with AVPlayer through SwiftSMBAVFoundation's makePlayerItem(at:). It links the local package, enables outgoing network connections in the macOS sandbox, and adds the iOS local network usage description. Document the sample app in the video playback guide, note that the asset keeps the file open on the server while it is alive, and ignore the sample project's generated xcworkspace. Co-Authored-By: Claude Sonnet 5.5 <[email protected]>
Report the POSIX error code that matches an SMB.Error. POSIX errors keep their own code, and SMB status errors use the code libsmb2's nterror_to_errno maps their status to, such as ENOENT for STATUS_OBJECT_NAME_NOT_FOUND and EACCES for STATUS_ACCESS_DENIED. A closed connection, an invalid argument, and a failed context creation report ENOTCONN, EINVAL, and ENOMEM. Co-Authored-By: Claude Opus 5.5 <[email protected]>
UTType(filenameExtension:) returns a dynamic type, not nil, for an extension it doesn't know, so makeAsset(at:) reported types such as dyn.ah62d4rv4ge81a2pwsu for .part or .bak files instead of the documented .movie fallback. Ignore dynamic types when inferring the content type. Make the asset's loader and its content type internal, so the integration tests can check the inferred type. Co-Authored-By: Claude Opus 5.5 <[email protected]>
AVFoundation keeps only the code of the error a loading request finishes
with and reads it as a POSIX errno. An SMB.Error bridges with its enum
case index as its code, so a missing file surfaced as ESRCH ("No such
process") and a closed connection as E2BIG ("Argument list too long").
Finish failed requests with an NSPOSIXErrorDomain error built from
SMB.Error.posixCode instead. A missing file now reports ENOENT, which
AVFoundation turns into NSURLErrorFileDoesNotExist, and a closed
connection ENOTCONN.
Correct the video playback guide, which promised the SMB error in the
player item's error, and show how to read the POSIX code.
Co-Authored-By: Claude Opus 5.5 <[email protected]>
AVFoundation never cancels the loading requests of an asset it releases, not even after replaceCurrentItem(with: nil). Each serving task retained the resource loader until it had read its whole range, which for AVPlayer is often the rest of the file, so closing a player kept downloading the movie in the background, with the file open on the server and the connection busy. The loader's deinit, meant to cancel those tasks, could never run while one was serving. Serve requests from a RequestServer value that the tasks capture instead of the loader, so releasing the asset releases the loader and its deinit cancels the tasks. The new integration test stalls the media connection behind a blocking byte-range lock, seeks so that a request waits on it, releases the player item, and checks that the loader goes away. TestMovie remuxes long copies of its movie for it without re-encoding. Co-Authored-By: Claude Opus 5.5 <[email protected]>
Open another connection to the same server and share, with the credentials and configuration of the connection it is called on, so callers can run operations in parallel without passing the credentials around again. The connection keeps its credentials in a private property for this; libsmb2 already keeps the password in the context for the connection's lifetime. The fork follows what is in effect on the original rather than what was configured: its transferBlockSize is the larger of the accepted read and write block sizes, so it transfers in the same blocks, and its timeout is the current command timeout, including changes made with setTimeout. The dialect and the other negotiation options are negotiated again from the configured preferences. When no accepted block size can be determined, the configured one is kept. Document fork in the README, suggest it for playback connections in the video playback guide, and correct the container name in AGENTS.md's docker ps filter, which never matched the test server. Co-Authored-By: Claude Opus 5.5 <[email protected]>
…icit Android support
Write through smb2_pwrite, the counterpart of read(upTo:atOffset:): the handle's current offset is neither used nor moved, so concurrent tasks can write different ranges of one handle without coordinating seeks. Writing past the end extends the file, the append option does not apply, and a write that would end past UInt64.max throws EFBIG. Co-Authored-By: Claude Opus 5.5 <[email protected]>
The new SwiftSMBEXIFKit product mirrors SwiftSFTPEXIFKit and re-exports EXIFKit (from 0.3.0), which supports every platform SwiftSMB does. - Read metadata with EXIFKit.read(file:), SMB.File.imageMetadata() and SMB.Connection.imageMetadata(at:). The connection variant reads the thumbnail with loadingThumbnail() and closes the file before returning. - Edit and remove metadata with EXIFKit.write/strip, writeImageMetadata and removeImageMetadata on SMB.File and SMB.Connection. The connection variants write a temporary file next to the destination and rename it over it. SMB renames never replace a file, so an existing destination moves to a backup first, which is restored if the rename fails. - The internal SMBFileHandleForEXIFKit adapts an SMB.File to EXIFKit's AbstractFileHandle with positional reads and writes, so EXIFKit's concurrent reads share one handle without a serial queue. - Integration and cookbook tests, a guide in docs/image-metadata.md, and a README example that shows a thumbnail in a UIImage. Co-Authored-By: Claude Opus 5.5 <[email protected]>
The positional write added in d7fa89a throws EFBIG through POSIXErrorCode, which Foundation does not provide on Android. Co-Authored-By: Claude Opus 5.5 <[email protected]>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
No description provided.