diff --git a/Example/SwiftUploadSDKExample/SwiftUploadSDKExample/Model/ThumbnailModel.swift b/Example/SwiftUploadSDKExample/SwiftUploadSDKExample/Model/ThumbnailModel.swift index c00d3c29..f349ff4c 100644 --- a/Example/SwiftUploadSDKExample/SwiftUploadSDKExample/Model/ThumbnailModel.swift +++ b/Example/SwiftUploadSDKExample/SwiftUploadSDKExample/Model/ThumbnailModel.swift @@ -48,13 +48,13 @@ class ThumbnailModel: ObservableObject { } private let asset: AVAsset - private let upload: MuxUpload + private let upload: DirectUpload private var thumbnailGenerator: AVAssetImageGenerator? @Published var thumbnail: CGImage? - @Published var uploadProgress: MuxUpload.TransportStatus? + @Published var uploadProgress: DirectUpload.TransportStatus? - init(asset: AVAsset, upload: MuxUpload) { + init(asset: AVAsset, upload: DirectUpload) { self.asset = asset self.upload = upload diff --git a/Example/SwiftUploadSDKExample/SwiftUploadSDKExample/Model/UploadCreationModel.swift b/Example/SwiftUploadSDKExample/SwiftUploadSDKExample/Model/UploadCreationModel.swift index 1c606b0e..c587a1b0 100644 --- a/Example/SwiftUploadSDKExample/SwiftUploadSDKExample/Model/UploadCreationModel.swift +++ b/Example/SwiftUploadSDKExample/SwiftUploadSDKExample/Model/UploadCreationModel.swift @@ -41,8 +41,8 @@ class UploadCreationModel : ObservableObject { } } - @discardableResult func startUpload(preparedMedia: PreparedUpload, forceRestart: Bool) -> MuxUpload { - let upload = MuxUpload( + @discardableResult func startUpload(preparedMedia: PreparedUpload, forceRestart: Bool) -> DirectUpload { + let upload = DirectUpload( uploadURL: preparedMedia.remoteURL, videoFileURL: preparedMedia.localVideoFile ) diff --git a/Example/SwiftUploadSDKExample/SwiftUploadSDKExample/Model/UploadListModel.swift b/Example/SwiftUploadSDKExample/SwiftUploadSDKExample/Model/UploadListModel.swift index 2fe3bd03..b068dda8 100644 --- a/Example/SwiftUploadSDKExample/SwiftUploadSDKExample/Model/UploadListModel.swift +++ b/Example/SwiftUploadSDKExample/SwiftUploadSDKExample/Model/UploadListModel.swift @@ -12,7 +12,7 @@ import MuxUploadSDK class UploadListModel : ObservableObject { init() { - UploadManager.shared.addUploadsUpdatedDelegate( + DirectUploadManager.shared.addDelegate( Delegate( handler: { uploads in @@ -40,17 +40,17 @@ class UploadListModel : ObservableObject { ) } - @Published var lastKnownUploads: [MuxUpload] = Array() + @Published var lastKnownUploads: [DirectUpload] = Array() } -fileprivate class Delegate: UploadsUpdatedDelegate { - let handler: ([MuxUpload]) -> Void - - func uploadListUpdated(with list: [MuxUpload]) { - handler(list) +fileprivate class Delegate: DirectUploadManagerDelegate { + let handler: ([DirectUpload]) -> Void + + func didUpdate(managedDirectUploads: [DirectUpload]) { + handler(managedDirectUploads) } - init(handler: @escaping ([MuxUpload]) -> Void) { + init(handler: @escaping ([DirectUpload]) -> Void) { self.handler = handler } } diff --git a/Example/SwiftUploadSDKExample/SwiftUploadSDKExample/Screens/UploadListView.swift b/Example/SwiftUploadSDKExample/SwiftUploadSDKExample/Screens/UploadListView.swift index 766149eb..cb8a2d12 100644 --- a/Example/SwiftUploadSDKExample/SwiftUploadSDKExample/Screens/UploadListView.swift +++ b/Example/SwiftUploadSDKExample/SwiftUploadSDKExample/Screens/UploadListView.swift @@ -23,7 +23,7 @@ struct UploadListScreen: View { } } -extension MuxUpload { +extension DirectUpload { var objectIdentifier: ObjectIdentifier { ObjectIdentifier(self) } @@ -51,7 +51,7 @@ fileprivate struct ListContainerView: View { fileprivate struct ListItem: View { @StateObject var thumbnailModel: ThumbnailModel - let upload: MuxUpload + let upload: DirectUpload var body: some View { ZStack(alignment: .bottom) { @@ -130,7 +130,7 @@ fileprivate struct ListItem: View { } } - private func statusLine(status: MuxUpload.TransportStatus?) -> String { + private func statusLine(status: DirectUpload.TransportStatus?) -> String { guard let status = status, let progress = status.progress, let startTime = status.startTime, startTime > 0 else { return "missing status" } @@ -152,14 +152,14 @@ fileprivate struct ListItem: View { return "\(formattedMBytes) MB in \(formattedTime)s (\(formattedDataRate) KB/s)" } - private func elapsedBytesOfTotal(status: MuxUpload.TransportStatus) -> String { + private func elapsedBytesOfTotal(status: DirectUpload.TransportStatus) -> String { guard let progress = status.progress else { return "unknown" } return "\(progress.completedUnitCount / 1000)KB" } - init(upload: MuxUpload) { + init(upload: DirectUpload) { self.upload = upload _thumbnailModel = StateObject( wrappedValue: { @@ -214,7 +214,7 @@ struct UploadListItem_Previews: PreviewProvider { static var previews: some View { ZStack { WindowBackground - let upload = MuxUpload(uploadURL: URL(string: "file:///")!, videoFileURL: URL(string: "file:///")!) + let upload = DirectUpload(uploadURL: URL(string: "file:///")!, videoFileURL: URL(string: "file:///")!) ListItem(upload: upload) } } diff --git a/Example/SwiftUploadSDKExample/SwiftUploadSDKExample/Widgets/UploadProgressView.swift b/Example/SwiftUploadSDKExample/SwiftUploadSDKExample/Widgets/UploadProgressView.swift index 311dfa45..5327f078 100644 --- a/Example/SwiftUploadSDKExample/SwiftUploadSDKExample/Widgets/UploadProgressView.swift +++ b/Example/SwiftUploadSDKExample/SwiftUploadSDKExample/Widgets/UploadProgressView.swift @@ -40,7 +40,7 @@ struct UploadProgressView: View { } } - private func uploadStatus(uploadState: AppUploadState) -> MuxUpload.Status? { + private func uploadStatus(uploadState: AppUploadState) -> DirectUpload.Status? { switch uploadState { case .done(let success): return success.finalState case .uploading(let status): return status @@ -48,7 +48,7 @@ struct UploadProgressView: View { } } - private func dataRateTxt(status: MuxUpload.Status?) -> String { + private func dataRateTxt(status: DirectUpload.Status?) -> String { guard let status = status, let progress = status.progress else { return "" } @@ -69,7 +69,7 @@ struct UploadProgressView: View { } } - private func elapsedBytesOfTotal(status: MuxUpload.Status) -> String { + private func elapsedBytesOfTotal(status: DirectUpload.Status) -> String { guard let progress = status.progress else { return "unknown" } diff --git a/README.md b/README.md index 3a7adca1..609c3b15 100644 --- a/README.md +++ b/README.md @@ -38,7 +38,7 @@ import MuxUploadSDK let directUploadURL: URL = /* Fetch the direct upload URL created before */ let videoInputURL: URL = /* File URL to your video file. See Test App for how to retrieve a video from PhotosKit */ -let upload = MuxUpload( +let upload = DirectUpload( uploadURL: directUploadURL, inputFileURL: videoInputURL, ) diff --git a/Sources/MuxUploadSDK/InputStandardization/UploadInputStandardizationWorker.swift b/Sources/MuxUploadSDK/InputStandardization/UploadInputStandardizationWorker.swift index 7cd1a328..d9ecbc07 100644 --- a/Sources/MuxUploadSDK/InputStandardization/UploadInputStandardizationWorker.swift +++ b/Sources/MuxUploadSDK/InputStandardization/UploadInputStandardizationWorker.swift @@ -43,7 +43,7 @@ class UploadInputStandardizationWorker { func standardize( sourceAsset: AVAsset, - maximumResolution: UploadOptions.InputStandardization.MaximumResolution, + maximumResolution: DirectUploadOptions.InputStandardization.MaximumResolution, outputURL: URL, completion: @escaping (AVAsset, AVAsset?, Error?) -> () ) { diff --git a/Sources/MuxUploadSDK/InputStandardization/UploadInputStandardizer.swift b/Sources/MuxUploadSDK/InputStandardization/UploadInputStandardizer.swift index 7dcdc9d1..c2505d5e 100644 --- a/Sources/MuxUploadSDK/InputStandardization/UploadInputStandardizer.swift +++ b/Sources/MuxUploadSDK/InputStandardization/UploadInputStandardizer.swift @@ -11,7 +11,7 @@ class UploadInputStandardizer { func standardize( id: String, sourceAsset: AVAsset, - maximumResolution: UploadOptions.InputStandardization.MaximumResolution, + maximumResolution: DirectUploadOptions.InputStandardization.MaximumResolution, outputURL: URL, completion: @escaping (AVAsset, AVAsset?, Error?) -> () ) { diff --git a/Sources/MuxUploadSDK/InternalUtilities/ChunkedFile.swift b/Sources/MuxUploadSDK/InternalUtilities/ChunkedFile.swift index 36795b00..97980504 100644 --- a/Sources/MuxUploadSDK/InternalUtilities/ChunkedFile.swift +++ b/Sources/MuxUploadSDK/InternalUtilities/ChunkedFile.swift @@ -39,7 +39,7 @@ class ChunkedFile { /// Reads the next chunk from the file, advancing the file for the next read /// This method does synchronous I/O, so call it in the background func readNextChunk() -> Result { - MuxUploadSDK.logger?.info("--readNextChunk(): called") + SDKLogger.logger?.info("--readNextChunk(): called") do { guard fileHandle != nil else { return Result.failure(ChunkedFileError.invalidState("readNextChunk() called but the file was not open")) @@ -62,7 +62,7 @@ class ChunkedFile { fileHandle: fileHandle, fileURL: fileURL ) - MuxUploadSDK.logger?.info("Opened file with len \(String(describing: fileSize)) at path \(fileURL.path)") + SDKLogger.logger?.info("Opened file with len \(String(describing: fileSize)) at path \(fileURL.path)") } catch { throw ChunkedFileError.fileHandle(error) } @@ -75,7 +75,7 @@ class ChunkedFile { do { try fileHandle?.close() } catch { - MuxUploadSDK.logger?.warning("Swallowed error closing file: \(error.localizedDescription)") + SDKLogger.logger?.warning("Swallowed error closing file: \(error.localizedDescription)") } state = nil } @@ -87,7 +87,7 @@ class ChunkedFile { } private func doReadNextChunk() throws -> FileChunk { - MuxUploadSDK.logger?.info("--doReadNextChunk") + SDKLogger.logger?.info("--doReadNextChunk") guard let fileHandle = fileHandle, let fileURL = fileURL else { throw ChunkedFileError.invalidState("doReadNextChunk called without file handle. Did you call open()?") } diff --git a/Sources/MuxUploadSDK/InternalUtilities/Reporting/Reporter.swift b/Sources/MuxUploadSDK/InternalUtilities/Reporting/Reporter.swift index 389c9ef2..99697543 100644 --- a/Sources/MuxUploadSDK/InternalUtilities/Reporting/Reporter.swift +++ b/Sources/MuxUploadSDK/InternalUtilities/Reporting/Reporter.swift @@ -92,7 +92,7 @@ extension Reporter { func reportUploadSuccess( inputDuration: Double, inputSize: UInt64, - options: UploadOptions, + options: DirectUploadOptions, uploadEndTime: Date, uploadStartTime: Date, uploadURL: URL @@ -133,7 +133,7 @@ extension Reporter { errorDescription: String, inputDuration: Double, inputSize: UInt64, - options: UploadOptions, + options: DirectUploadOptions, uploadEndTime: Date, uploadStartTime: Date, uploadURL: URL @@ -173,7 +173,7 @@ extension Reporter { func reportUploadInputStandardizationSuccess( inputDuration: Double, inputSize: UInt64, - options: UploadOptions, + options: DirectUploadOptions, nonStandardInputReasons: [UploadInputFormatInspectionResult.NonstandardInputReason], standardizationEndTime: Date, standardizationStartTime: Date, @@ -216,7 +216,7 @@ extension Reporter { inputDuration: Double, inputSize: UInt64, nonStandardInputReasons: [UploadInputFormatInspectionResult.NonstandardInputReason], - options: UploadOptions, + options: DirectUploadOptions, standardizationEndTime: Date, standardizationStartTime: Date, uploadCanceled: Bool, diff --git a/Sources/MuxUploadSDK/InternalUtilities/UploadInput.swift b/Sources/MuxUploadSDK/InternalUtilities/UploadInput.swift index 9f7cf90b..97100c1a 100644 --- a/Sources/MuxUploadSDK/InternalUtilities/UploadInput.swift +++ b/Sources/MuxUploadSDK/InternalUtilities/UploadInput.swift @@ -21,10 +21,10 @@ struct UploadInput { ) case standardizationFailed(AVAsset, UploadInfo) case awaitingUploadConfirmation(UploadInfo) - case uploadInProgress(UploadInfo, MuxUpload.TransportStatus) - case uploadPaused(UploadInfo, MuxUpload.TransportStatus) - case uploadSucceeded(UploadInfo, MuxUpload.Success) - case uploadFailed(UploadInfo, MuxUpload.UploadError) + case uploadInProgress(UploadInfo, DirectUpload.TransportStatus) + case uploadPaused(UploadInfo, DirectUpload.TransportStatus) + case uploadSucceeded(UploadInfo, DirectUpload.SuccessDetails) + case uploadFailed(UploadInfo, DirectUploadError) } var status: Status @@ -83,7 +83,7 @@ struct UploadInput { } } - var transportStatus: MuxUpload.TransportStatus? { + var transportStatus: DirectUpload.TransportStatus? { switch status { case .ready: return nil @@ -122,7 +122,7 @@ extension UploadInput { } mutating func processStartNetworkTransport( - startingTransportStatus: MuxUpload.TransportStatus + startingTransportStatus: DirectUpload.TransportStatus ) { if case UploadInput.Status.underInspection = status { status = .uploadInProgress(uploadInfo, startingTransportStatus) @@ -132,16 +132,16 @@ extension UploadInput { } mutating func processUploadSuccess( - transportStatus: MuxUpload.TransportStatus + transportStatus: DirectUpload.TransportStatus ) { if case UploadInput.Status.uploadInProgress(let info, _) = status { - status = .uploadSucceeded(info, MuxUpload.Success(finalState: transportStatus)) + status = .uploadSucceeded(info, DirectUpload.SuccessDetails(finalState: transportStatus)) } else { return } } - mutating func processUploadFailure(error: MuxUpload.UploadError) { + mutating func processUploadFailure(error: DirectUploadError) { status = .uploadFailed(uploadInfo, error) } diff --git a/Sources/MuxUploadSDK/PublicAPI/AVFoundation+MuxUpload/MuxUpload+AVFoundation.swift b/Sources/MuxUploadSDK/PublicAPI/AVFoundation+DirectUpload/DirectUpload+AVFoundation.swift similarity index 85% rename from Sources/MuxUploadSDK/PublicAPI/AVFoundation+MuxUpload/MuxUpload+AVFoundation.swift rename to Sources/MuxUploadSDK/PublicAPI/AVFoundation+DirectUpload/DirectUpload+AVFoundation.swift index cd0fb434..12ff1b41 100644 --- a/Sources/MuxUploadSDK/PublicAPI/AVFoundation+MuxUpload/MuxUpload+AVFoundation.swift +++ b/Sources/MuxUploadSDK/PublicAPI/AVFoundation+DirectUpload/DirectUpload+AVFoundation.swift @@ -1,13 +1,13 @@ // -// MuxUpload+AVFoundation.swift +// DirectUpload+AVFoundation.swift // import AVFoundation import Foundation -extension MuxUpload { +extension DirectUpload { - /// Initializes a MuxUpload from an ``AVAsset`` + /// Initializes a DirectUpload from an ``AVAsset`` /// /// - Parameters: /// - uploadURL: the URL of your direct upload, see @@ -20,7 +20,7 @@ extension MuxUpload { public convenience init( uploadURL: URL, inputAsset: AVAsset, - options: UploadOptions + options: DirectUploadOptions ) { self.init( input: UploadInput( diff --git a/Sources/MuxUploadSDK/PublicAPI/MuxUpload.swift b/Sources/MuxUploadSDK/PublicAPI/DirectUpload.swift similarity index 84% rename from Sources/MuxUploadSDK/PublicAPI/MuxUpload.swift rename to Sources/MuxUploadSDK/PublicAPI/DirectUpload.swift index 3704806f..22064448 100644 --- a/Sources/MuxUploadSDK/PublicAPI/MuxUpload.swift +++ b/Sources/MuxUploadSDK/PublicAPI/DirectUpload.swift @@ -1,5 +1,5 @@ // -// MuxUpload.swift +// DirectUpload.swift // Mux Upload SDK // // Created by Emily Dixon on 2/7/23. @@ -8,7 +8,7 @@ import AVFoundation import Foundation -public typealias UploadResult = Result +public typealias DirectUploadResult = Result /// /// Uploads a media asset to Mux using a previously-created @@ -20,8 +20,8 @@ public typealias UploadResult = Result /// /// For example: /// ```swift -/// let upload = MuxUpload( -/// uploadURL: myMuxUploadURL, +/// let upload = DirectUpload( +/// uploadURL: myDirectUploadURL, /// videoFileURL: myVideoFileURL, /// ) /// @@ -48,7 +48,7 @@ public typealias UploadResult = Result /// Uploads created by this SDK are globally managed by default, and can be resumed after failures or even after process death. For more information on /// this topic, see ``UploadManager`` /// -public final class MuxUpload { +public final class DirectUpload { var input: UploadInput { didSet { @@ -74,7 +74,7 @@ public final class MuxUpload { public enum InputStatus { /// Upload initialized and not yet started case ready(AVAsset) - /// Upload started by a call to ``MuxUpload.start(forceRestart:)`` + /// Upload started by a call to ``DirectUpload.start(forceRestart:)`` case started(AVAsset) /// Upload is being prepared for transport to the /// server. If input standardization was requested, @@ -83,15 +83,14 @@ public final class MuxUpload { case preparing(AVAsset) /// SDK is waiting for confirmation to continue the /// upload despite being unable to standardize input - case awaitingUploadConfirmation(AVAsset) + case awaitingConfirmation(AVAsset) /// Transport of upload inputs is in progress - case uploadInProgress(AVAsset, TransportStatus) + case transportInProgress(AVAsset, TransportStatus) /// Upload has been paused - case uploadPaused(AVAsset, TransportStatus) - /// Upload has succeeded - case uploadSucceeded(AVAsset, MuxUpload.Success) - /// Upload has failed - case uploadFailed(AVAsset, MuxUpload.UploadError) + case paused(AVAsset, TransportStatus) + /// Direct upload has succeeded and all inputs + /// transported or upload failed with a fatal error + case finished(AVAsset, DirectUploadResult) } /// Current status of the upload input as it goes through @@ -111,28 +110,28 @@ public final class MuxUpload { case .standardizationFailed(let sourceAsset, _): return InputStatus.preparing(sourceAsset) case .awaitingUploadConfirmation(let uploadInfo): - return InputStatus.awaitingUploadConfirmation( + return InputStatus.awaitingConfirmation( uploadInfo.sourceAsset() ) case .uploadInProgress(let uploadInfo, let transportStatus): - return InputStatus.uploadInProgress( + return InputStatus.transportInProgress( uploadInfo.sourceAsset(), transportStatus ) case .uploadPaused(let uploadInfo, let transportStatus): - return InputStatus.uploadPaused( + return InputStatus.paused( uploadInfo.sourceAsset(), transportStatus ) case .uploadSucceeded(let uploadInfo, let success): - return InputStatus.uploadSucceeded( + return InputStatus.finished( uploadInfo.sourceAsset(), - success + .success(success) ) case .uploadFailed(let uploadInfo, let error): - return InputStatus.uploadFailed( + return InputStatus.finished( uploadInfo.sourceAsset(), - error + .failure(error) ) } } @@ -163,7 +162,7 @@ public final class MuxUpload { var id: String { uploadInfo.id } - private let uploadManager: UploadManager + private let uploadManager: DirectUploadManager private let inputInspector: UploadInputInspector private let inputStandardizer: UploadInputStandardizer = UploadInputStandardizer() @@ -193,24 +192,7 @@ public final class MuxUpload { public let isPaused: Bool } - /** - An fatal error that ocurred during the upload process. The last-known state of the upload is available, as well as the Error that stopped the upload - */ - public struct UploadError : Error { - public let lastStatus: TransportStatus? - public let code: MuxErrorCase - public let message: String - public let reason: Error? - - var localizedDescription: String { - get { - return "Error \(code): \(message). Caused by:\n\t\(String(describing: reason))" - } - } - - } - - /// Initializes a MuxUpload from a local file URL with + /// Initializes a DirectUpload from a local file URL with /// the given configuration /// - Parameters: /// - uploadURL: the URL of your direct upload, see @@ -220,7 +202,7 @@ public final class MuxUpload { /// - chunkSize: the size of chunks when uploading, /// at least 8M is recommended /// - retriesPerChunk: number of retry attempts for - /// a failed chunk upload request + /// a failed chunk request /// - inputStandardization: enable or disable input /// standardization by the SDK locally /// - eventTracking: options to opt out of event @@ -231,8 +213,8 @@ public final class MuxUpload { videoFileURL: URL, chunkSize: Int = 8 * 1024 * 1024, // Google recommends at least 8M retriesPerChunk: Int = 3, - inputStandardization: UploadOptions.InputStandardization = .default, - eventTracking: UploadOptions.EventTracking = .default + inputStandardization: DirectUploadOptions.InputStandardization = .default, + eventTracking: DirectUploadOptions.EventTracking = .default ) { let asset = AVAsset(url: videoFileURL) self.init( @@ -241,9 +223,9 @@ public final class MuxUpload { info: UploadInfo( id: UUID().uuidString, uploadURL: uploadURL, - options: UploadOptions( + options: DirectUploadOptions( inputStandardization: inputStandardization, - transport: UploadOptions.Transport( + transport: DirectUploadOptions.Transport( chunkSizeInBytes: chunkSize, retryLimitPerChunk: retriesPerChunk ), @@ -256,7 +238,7 @@ public final class MuxUpload { ) } - /// Initializes a MuxUpload from a local file URL + /// Initializes a DirectUpload from a local file URL /// /// - Parameters: /// - uploadURL: the URL of your direct upload, see @@ -269,7 +251,7 @@ public final class MuxUpload { public convenience init( uploadURL: URL, inputFileURL: URL, - options: UploadOptions = .default + options: DirectUploadOptions = .default ) { let asset = AVAsset( url: inputFileURL @@ -291,7 +273,7 @@ public final class MuxUpload { init( input: UploadInput, manage: Bool = true, - uploadManager: UploadManager, + uploadManager: DirectUploadManager, inputInspector: AVFoundationUploadInputInspector = .shared ) { self.input = input @@ -304,7 +286,7 @@ public final class MuxUpload { init( input: UploadInput, manage: Bool = true, - uploadManager: UploadManager, + uploadManager: DirectUploadManager, inputInspector: UploadInputInspector ) { self.input = input @@ -316,7 +298,7 @@ public final class MuxUpload { internal convenience init( wrapping uploader: ChunkedFileUploader, - uploadManager: UploadManager + uploadManager: DirectUploadManager ) { self.init( input: UploadInput( @@ -359,7 +341,7 @@ public final class MuxUpload { */ public var progressHandler: StateHandler? - public struct Success : Sendable, Hashable { + public struct SuccessDetails : Sendable, Hashable { public let finalState: TransportStatus } @@ -373,7 +355,7 @@ public final class MuxUpload { /** Handles the final result of this upload in your app */ - public typealias ResultHandler = (Result) -> Void + public typealias ResultHandler = (DirectUploadResult) -> Void /** If set will be notified when this upload is successfully @@ -385,7 +367,7 @@ public final class MuxUpload { True if this upload is currently in progress and not paused */ public var inProgress: Bool { - if case InputStatus.uploadInProgress = inputStatus { + if case InputStatus.transportInProgress = inputStatus { return true } else { return false @@ -396,9 +378,7 @@ public final class MuxUpload { True if this upload was completed */ public var complete: Bool { - if case InputStatus.uploadSucceeded = inputStatus { - return true - } else if case InputStatus.uploadFailed = inputStatus { + if case InputStatus.finished = inputStatus { return true } else { return false @@ -435,7 +415,7 @@ public final class MuxUpload { ) } if fileWorker != nil && !forceRestart { - MuxUploadSDK.logger?.warning("start() called but upload is already in progress") + SDKLogger.logger?.warning("start() called but upload is already in progress") fileWorker?.addDelegate( withToken: id, InternalUploaderDelegate { @@ -687,27 +667,28 @@ public final class MuxUpload { startTime: result.startTime, isPaused: false ) - let successDetails = MuxUpload.Success(finalState: transportStatus) + let successDetails = DirectUpload.SuccessDetails(finalState: transportStatus) input.processUploadSuccess(transportStatus: transportStatus) - resultHandler?(Result.success(successDetails)) + resultHandler?(Result.success(successDetails)) fileWorker?.removeDelegate(withToken: id) fileWorker = nil } case .failure(let error): do { - let parsedError = error.parseAsUploadError( + let parsedError = parseAsUploadError( lastSeenUploadStatus: input.transportStatus ?? TransportStatus( progress: nil, updatedTime: Date().timeIntervalSince1970, startTime: 0, isPaused: false - ) + ), + error: error ) input.processUploadFailure(error: parsedError) - if case .cancelled = parsedError.code { - // This differs from what MuxUpload does + if case .cancelled = parsedError.kind { + // This differs from what DirectUpload does // when cancelled with an external API call - MuxUploadSDK.logger?.info("task canceled") - let canceledStatus = MuxUpload.TransportStatus( + SDKLogger.logger?.info("task canceled") + let canceledStatus = DirectUpload.TransportStatus( progress: input.transportStatus?.progress, updatedTime: input.transportStatus?.updatedTime ?? Date().timeIntervalSince1970, startTime: input.transportStatus?.startTime ?? Date().timeIntervalSince1970, @@ -744,12 +725,12 @@ public final class MuxUpload { } } -extension MuxUpload.UploadError { +extension DirectUploadError { internal init( - lastStatus: MuxUpload.TransportStatus + lastStatus: DirectUpload.TransportStatus ) { self.lastStatus = lastStatus - self.code = MuxErrorCase.unknown + self.kind = .unknown self.message = "" self.reason = nil } @@ -769,70 +750,103 @@ fileprivate class InternalUploaderDelegate : ChunkedFileUploaderDelegate { } } -extension MuxUpload.UploadError: Equatable { - public static func == (lhs: MuxUpload.UploadError, rhs: MuxUpload.UploadError) -> Bool { +extension DirectUploadError: Equatable { + public static func == (lhs: DirectUploadError, rhs: DirectUploadError) -> Bool { return lhs.message == rhs.message && lhs.lastStatus == rhs.lastStatus && - lhs.code == rhs.code && + lhs.kind == rhs.kind && lhs.reason?.localizedDescription == rhs.reason?.localizedDescription } } -public extension Error { - func asMuxUploadError() -> MuxUpload.UploadError? { - return self as? MuxUpload.UploadError - } -} - -extension Error { +extension DirectUpload { /// Parses Errors thrown by this SDK, wrapping the internal error types in a public error - func parseAsUploadError(lastSeenUploadStatus: MuxUpload.TransportStatus) -> MuxUpload.UploadError { - let error = self + func parseAsUploadError( + lastSeenUploadStatus: DirectUpload.TransportStatus, + error: Error + ) -> DirectUploadError { if (error.asCancellationError()) != nil { - return MuxUpload.UploadError( + return DirectUploadError( lastStatus: lastSeenUploadStatus, - code: MuxErrorCase.cancelled, + kind: .cancelled, message: "Cancelled by user", - reason: self + reason: error ) } else if (error.asChunkWorkerError()) != nil { if let realCause = error.asHttpError() { - return MuxUpload.UploadError( + return DirectUploadError( lastStatus: lastSeenUploadStatus, - code: MuxErrorCase.http, + kind: .http, message: "Http Failed: \(realCause.statusCode): \(realCause.statusMsg)", - reason: self + reason: error ) } else { - return MuxUpload.UploadError( + return DirectUploadError( lastStatus: lastSeenUploadStatus, - code: MuxErrorCase.connection, + kind: .connection, message: "Connection error", - reason: self + reason: error ) } } else if let realError = error.asInternalUploaderError() { - // All UploaderError does is wrap ChunkedFile and ChunkWorker errors - return realError.reason.parseAsUploadError(lastSeenUploadStatus: lastSeenUploadStatus) + // All DirectUploadError does is wrap ChunkedFile + // and ChunkWorker errors + return DirectUploadError( + lastStatus: lastSeenUploadStatus, + kind: .unknown, + message: "Unknown Internal Error", + reason: realError + ) } else if let realError = error.asChunkedFileError() { switch realError { - case .fileHandle(_): return MuxUpload.UploadError( + case .fileHandle(_): return DirectUploadError( lastStatus: lastSeenUploadStatus, - code: MuxErrorCase.file, + kind: .file, message: "Couldn't read file for upload", - reason: self + reason: error ) - case .invalidState(let msg): return MuxUpload.UploadError( + case .invalidState(let msg): return DirectUploadError( lastStatus: lastSeenUploadStatus, - code: MuxErrorCase.unknown, + kind: .unknown, message: "Internal error: \(msg)", reason: nil ) } } else { - return MuxUpload.UploadError( + return DirectUploadError( lastStatus: lastSeenUploadStatus ) } } } + +/** + An fatal error that ocurred during the upload process. The last-known state of the upload is available, as well as the Error that stopped the upload + */ +public struct DirectUploadError : Error { + /// Represents the possible error cases from a ``DirectUpload`` + public enum Kind : Int { + /// The cause of the error is not known + case unknown = -1 + /// The direct upload was cancelled + case cancelled = 0 + /// The input file could not be read or processed + case file = 1 + /// The direct upload could not be completed due to an HTTP error + case http = 2 + /// The direct upload could not be completed due to a connection error + case connection = 3 + } + + public let lastStatus: DirectUpload.TransportStatus? + public let kind: Kind + public let message: String + public let reason: Error? + + var localizedDescription: String { + get { + return "Error \(kind): \(message). Caused by:\n\t\(String(describing: reason))" + } + } + +} diff --git a/Sources/MuxUploadSDK/PublicAPI/UploadManager.swift b/Sources/MuxUploadSDK/PublicAPI/DirectUploadManager.swift similarity index 79% rename from Sources/MuxUploadSDK/PublicAPI/UploadManager.swift rename to Sources/MuxUploadSDK/PublicAPI/DirectUploadManager.swift index a71f43da..76edfaa5 100644 --- a/Sources/MuxUploadSDK/PublicAPI/UploadManager.swift +++ b/Sources/MuxUploadSDK/PublicAPI/DirectUploadManager.swift @@ -1,5 +1,5 @@ // -// UploadManager.swift +// DirectUploadManager.swift // Manages large file uploads in a global context for access by many UI elements // // Created by Emily Dixon on 3/8/23. @@ -10,9 +10,9 @@ import Foundation /// Manages uploads in-progress by the Mux Upload SDK. Uploads are managed globally by default and can be started, paused, /// or cancelled from anywhere in your app. /// -/// This class is used to find and resume uploads previously-created via ``MuxUpload``. Upload tasks created by ``MuxUpload`` -/// are, by defauly globally managed. If your ``MuxUpload`` is managed, you can get a new handle to it anywhere by using -/// ``findStartedUpload(ofFile:)`` or ``allManagedUploads()`` +/// This class is used to find and resume uploads previously-created via ``DirectUpload``. Upload tasks created by ``DirectUpload`` +/// are, by defauly globally managed. If your ``DirectUpload`` is managed, you can get a new handle to it anywhere by using +/// ``startedDirectUpload(ofFile:)`` or ``allManagedDirectUploads()`` /// /// ## Handling failure, backgrounding, and process death /// Managed uploads can be resumed where they left off after process death, and can be accessed anywhere in your @@ -21,17 +21,17 @@ import Foundation /// /// ```swift /// // Call during app init -/// UploadManager.resumeAllUploads() -/// let restartedUploads = UploadManager.allManagedUploads() +/// DirectUploadManager.shared.resumeAllDirectUploads() +/// let restartedUploads = DirectUploadManager.shared.allManagedDirectUploads() /// // ... do something with the restrted uploads, like subscribing to progress updates for instance /// ``` /// -public final class UploadManager { +public final class DirectUploadManager { private struct UploadStorage: Equatable, Hashable { - let upload: MuxUpload + let upload: DirectUpload - static func == (lhs: UploadManager.UploadStorage, rhs: UploadManager.UploadStorage) -> Bool { + static func == (lhs: DirectUploadManager.UploadStorage, rhs: DirectUploadManager.UploadStorage) -> Bool { ObjectIdentifier( lhs.upload ) == ObjectIdentifier( @@ -45,14 +45,14 @@ public final class UploadManager { } private var uploadsByID: [String : UploadStorage] = [:] - private var uploadsUpdateDelegatesByToken: [ObjectIdentifier : any UploadsUpdatedDelegate] = [:] + private var uploadsUpdateDelegatesByToken: [ObjectIdentifier : any DirectUploadManagerDelegate] = [:] private let uploadActor = UploadCacheActor() private lazy var uploaderDelegate: FileUploaderDelegate = FileUploaderDelegate(manager: self) - /// Finds an upload already in-progress and returns a new ``MuxUpload`` that can be observed + /// Finds an upload already in-progress and returns a new ``DirectUpload`` that can be observed /// to track and control its state /// Returns nil if there was no uplod in progress for thr given file - public func findStartedUpload(ofFile url: URL) -> MuxUpload? { + public func startedDirectUpload(ofFile url: URL) -> DirectUpload? { for upload in uploadsByID.values.map(\.upload) { if upload.videoFile == url { return upload @@ -65,18 +65,18 @@ public final class UploadManager { /// Returns all uploads currently-managed uploads. /// Uploads are managed while in-progress or compelted. /// Uploads become un-managed when canceled, or if the process dies after they complete - public func allManagedUploads() -> [MuxUpload] { + public func allManagedDirectUploads() -> [DirectUpload] { // Sort upload list for consistent ordering return Array(uploadsByID.values.map(\.upload)) } /// Attempts to resume an upload that was previously paused or interrupted by process death /// If no upload was found in the cache, this method returns null without taking any action - public func resumeUpload(ofFile: URL) async -> MuxUpload? { - let fileUploader = await uploadActor.getUpload(ofFileAt: ofFile) + public func resumeDirectUpload(ofFile url: URL) async -> DirectUpload? { + let fileUploader = await uploadActor.getUpload(ofFileAt: url) if let nonNilUploader = fileUploader { nonNilUploader.addDelegate(withToken: UUID().uuidString, uploaderDelegate) - return MuxUpload(wrapping: nonNilUploader, uploadManager: self) + return DirectUpload(wrapping: nonNilUploader, uploadManager: self) } else { return nil } @@ -84,9 +84,9 @@ public final class UploadManager { /// Attempts to resume an upload that was previously paused or interrupted by process death /// If no upload was found in the cache, this method returns null without taking any action - public func resumeUpload(ofFile: URL, completion: @escaping (MuxUpload) -> Void) { + public func resumeDirectUpload(ofFile url: URL, completion: @escaping (DirectUpload) -> Void) { Task.detached { - let upload = await self.resumeUpload(ofFile: ofFile) + let upload = await self.resumeDirectUpload(ofFile: url) if let nonNilUpload = upload { await MainActor.run { completion(nonNilUpload) } } @@ -95,7 +95,7 @@ public final class UploadManager { /// Resumes all upload that were paused or interrupted /// It can be useful to call this during app initialization to resume uploads that have been killed by the process dying - public func resumeAllUploads() { + public func resumeAllDirectUploads() { Task.detached { [self] in for upload in await uploadActor.getAllUploads() { upload.addDelegate(withToken: UUID().uuidString, uploaderDelegate) @@ -103,13 +103,13 @@ public final class UploadManager { } } - /// Adds an ``UploadsUpdatedDelegate`` You can add as many of these as you like - public func addUploadsUpdatedDelegate(_ delegate: Delegate) { + /// Adds an ``DirectUploadManagerDelegate`` You can add as many of these as you like + public func addDelegate(_ delegate: Delegate) { uploadsUpdateDelegatesByToken[ObjectIdentifier(delegate)] = delegate } - /// Removes an ``UploadsUpdatedDelegate`` - public func removeUploadsUpdatedDelegate(_ delegate: Delegate) { + /// Removes an ``DirectUploadManagerDelegate`` + public func removeDelegate(_ delegate: Delegate) { uploadsUpdateDelegatesByToken.removeValue(forKey: ObjectIdentifier(delegate)) } @@ -127,18 +127,18 @@ public final class UploadManager { internal func findChunkedFileUploader( inputFileURL: URL ) -> ChunkedFileUploader? { - findStartedUpload( + startedDirectUpload( ofFile: inputFileURL )?.fileWorker } - internal func registerUpload(_ upload: MuxUpload) { + internal func registerUpload(_ upload: DirectUpload) { guard let fileWorker = upload.fileWorker else { // Only started uploads, aka uploads with a file // worker can be registered. // TODO: Should this throw? - MuxUploadSDK.logger?.debug("registerUpload() called for an unstarted upload") + SDKLogger.logger?.debug("registerUpload() called for an unstarted upload") return } @@ -158,21 +158,21 @@ public final class UploadManager { Task.detached { await MainActor.run { let delegates = self.uploadsUpdateDelegatesByToken.values - let allManagedUploads = self.allManagedUploads() + let allManagedUploads = self.allManagedDirectUploads() for delegate in delegates { - delegate.uploadListUpdated(with: allManagedUploads) + delegate.didUpdate(managedDirectUploads: allManagedUploads) } } } } /// The shared instance of this object that should be used - public static let shared = UploadManager() + public static let shared = DirectUploadManager() internal init() { } private struct FileUploaderDelegate : ChunkedFileUploaderDelegate { - let manager: UploadManager + let manager: DirectUploadManager func chunkedFileUploader(_ uploader: ChunkedFileUploader, stateUpdated state: ChunkedFileUploader.InternalUploadState) { Task.detached { @@ -192,9 +192,9 @@ public final class UploadManager { } /// A delegate that handles changes to the list of active uploads -public protocol UploadsUpdatedDelegate: AnyObject { +public protocol DirectUploadManagerDelegate: AnyObject { /// Called when the global list of uploads changes. This happens whenever a new upload is started, or an existing one completes or fails - func uploadListUpdated(with list: [MuxUpload]) + func didUpdate(managedDirectUploads: [DirectUpload]) } diff --git a/Sources/MuxUploadSDK/PublicAPI/MuxErrorCase.swift b/Sources/MuxUploadSDK/PublicAPI/MuxErrorCase.swift deleted file mode 100644 index dceda3ad..00000000 --- a/Sources/MuxUploadSDK/PublicAPI/MuxErrorCase.swift +++ /dev/null @@ -1,22 +0,0 @@ -// -// MuxErrorCode.swift -// -// -// Created by Emily Dixon on 2/27/23. -// - -import Foundation - -/// Represents the possible error cases from a ``MuxUpload`` -public enum MuxErrorCase : Int { - /// The cause of the error is not known - case unknown = -1 - /// The upload was cancelled - case cancelled = 0 - /// The input file could not be read or processed - case file = 1 - /// The upload could not be completed due to an HTTP error - case http = 2 - /// The upload could not be completed due to a connection error - case connection = 3 -} diff --git a/Sources/MuxUploadSDK/PublicAPI/Options/UploadOptions.swift b/Sources/MuxUploadSDK/PublicAPI/Options/DirectUploadOptions.swift similarity index 78% rename from Sources/MuxUploadSDK/PublicAPI/Options/UploadOptions.swift rename to Sources/MuxUploadSDK/PublicAPI/Options/DirectUploadOptions.swift index 5f8f5d40..e152c805 100644 --- a/Sources/MuxUploadSDK/PublicAPI/Options/UploadOptions.swift +++ b/Sources/MuxUploadSDK/PublicAPI/Options/DirectUploadOptions.swift @@ -1,11 +1,11 @@ // -// UploadOptions.swift +// DirectUploadOptions.swift // import Foundation /// Options for the direct upload -public struct UploadOptions { +public struct DirectUploadOptions { // MARK: - Transport Options @@ -64,24 +64,24 @@ public struct UploadOptions { /// Preset to control the resolution of the standard /// input. /// - /// See ``UploadOptions.InputStandardization.maximumResolution`` + /// See ``DirectUploadOptions.InputStandardization.maximumResolution`` /// for more details. public enum MaximumResolution { - /// Preset standardized upload input to the SDK + /// Preset standardized direct upload input to the SDK /// default standard resolution of 1920x1080 (1080p). case `default` - /// Limit standardized upload input resolution to + /// Limit standardized direct upload input resolution to /// 1280x720 (720p). case preset1280x720 // 720p - /// Limit standardized upload input resolution to + /// Limit standardized direct upload input resolution to /// 1920x1080 (1080p). case preset1920x1080 // 1080p } - /// The maximum resolution of the standardized upload - /// input. If the input video provided to the upload - /// has a resolution below this value, the resolution - /// will remain unchanged after input standardization. + /// The maximum resolution of the standardized direct + /// upload input. If the input has a video resolution + /// below this value, the resolution will remain + /// unchanged after input standardization. /// /// Example 1: a direct upload input with 1440 x 1080 /// resolution encoded using Apple ProRes and with @@ -113,13 +113,12 @@ public struct UploadOptions { /// Skip all local input standardization by the SDK. /// - /// Initializing an upload with input standardization - /// skipped will prevent the SDK from making any - /// changes before commencing the upload. All input - /// will be uploaded to Mux as-is. - /// - /// Note: non-standard input will still be converted - /// to a standardized format upon ingestion. + /// Initializing a ``DirectUpload`` with input + /// standardization skipped will result in SDK + /// uploading all inputs as they are with no format + /// changes performed on the client. Mux Video will + /// still convert your input to a standard format + /// on the server when it is ingested. public static let skipped: InputStandardization = InputStandardization( isRequested: false, maximumResolution: .default @@ -135,13 +134,13 @@ public struct UploadOptions { self.maximumResolution = maximumResolution } - /// Used to initialize ``UploadOptions.InputStandardization`` + /// Used to initialize ``DirectUploadOptions.InputStandardization`` /// with that enables input standardization with /// a maximum resolution /// /// - Parameters: /// - maximumResolution: the maximum resolution - /// of the standardized upload input + /// of the standardized input public init( maximumResolution: MaximumResolution ) { @@ -179,20 +178,20 @@ public struct UploadOptions { /// Event tracking options for the direct upload public var eventTracking: EventTracking - // MARK: Default Upload Options + // MARK: Default Direct Upload Options - public static var `default`: UploadOptions { - UploadOptions() + public static var `default`: DirectUploadOptions { + DirectUploadOptions() } - // MARK: Upload Options Initializers + // MARK: Direct Upload Options Initializers /// - Parameters: /// - inputStandardization: options to enable or /// disable standardizing the format of the direct /// upload inputs, it is requested by default. To /// prevent the SDK from making any changes to the - /// format of the input use ``UploadOptions.InputStandardization.skipped`` + /// format of the input use ``DirectUploadOptions.InputStandardization.skipped`` /// - transport: options for transporting the /// direct upload input to Mux /// - eventTracking: event tracking options for the @@ -214,7 +213,7 @@ public struct UploadOptions { /// disable standardizing the format of the direct /// upload inputs, it is requested by default. To /// prevent the SDK from making any changes to the - /// format of the input use ``UploadOptions.InputStandardization.skipped`` + /// format of the input use ``DirectUploadOptions.InputStandardization.skipped`` /// - chunkSize: the size of each file chunk in /// bytes the SDK sends when uploading, default /// value is 8MB @@ -238,7 +237,7 @@ public struct UploadOptions { // MARK: - Extensions -extension UploadOptions.InputStandardization.MaximumResolution: CustomStringConvertible { +extension DirectUploadOptions.InputStandardization.MaximumResolution: CustomStringConvertible { public var description: String { switch self { case .preset1280x720: @@ -251,22 +250,22 @@ extension UploadOptions.InputStandardization.MaximumResolution: CustomStringConv } } -extension UploadOptions: Codable { } +extension DirectUploadOptions: Codable { } -extension UploadOptions.EventTracking: Codable { } +extension DirectUploadOptions.EventTracking: Codable { } -extension UploadOptions.InputStandardization: Codable { } +extension DirectUploadOptions.InputStandardization: Codable { } -extension UploadOptions.InputStandardization.MaximumResolution: Codable { } +extension DirectUploadOptions.InputStandardization.MaximumResolution: Codable { } -extension UploadOptions.Transport: Codable { } +extension DirectUploadOptions.Transport: Codable { } -extension UploadOptions: Equatable { } +extension DirectUploadOptions: Equatable { } -extension UploadOptions.EventTracking: Equatable { } +extension DirectUploadOptions.EventTracking: Equatable { } -extension UploadOptions.InputStandardization: Equatable { } +extension DirectUploadOptions.InputStandardization: Equatable { } -extension UploadOptions.InputStandardization.MaximumResolution: Equatable { } +extension DirectUploadOptions.InputStandardization.MaximumResolution: Equatable { } -extension UploadOptions.Transport: Equatable { } +extension DirectUploadOptions.Transport: Equatable { } diff --git a/Sources/MuxUploadSDK/PublicAPI/PhotosKit+MuxUpload/PHAsset+MuxUpload.swift b/Sources/MuxUploadSDK/PublicAPI/PhotosKit+DirectUpload/PHAsset+DirectUpload.swift similarity index 79% rename from Sources/MuxUploadSDK/PublicAPI/PhotosKit+MuxUpload/PHAsset+MuxUpload.swift rename to Sources/MuxUploadSDK/PublicAPI/PhotosKit+DirectUpload/PHAsset+DirectUpload.swift index 48442c12..2402cd4e 100644 --- a/Sources/MuxUploadSDK/PublicAPI/PhotosKit+MuxUpload/PHAsset+MuxUpload.swift +++ b/Sources/MuxUploadSDK/PublicAPI/PhotosKit+DirectUpload/PHAsset+DirectUpload.swift @@ -1,5 +1,5 @@ // -// MuxUpload+PhotosKit.swift +// PHAsset+DirectUpload.swift // import Foundation @@ -9,11 +9,11 @@ extension PHAsset { /// Convenience method that requests an ``AVAsset`` /// containing audiovisual media associated with the callee - /// ``PHAsset``. If the request succeeds ``MuxUpload`` + /// ``PHAsset``. If the request succeeds ``DirectUpload`` /// is initialized with the received ``AVAsset``. This method /// enables network access when performing its request. /// - /// A ``MuxUpload`` can only be initialized from a ``PHAsset`` + /// A ``DirectUpload`` can only be initialized from a ``PHAsset`` /// whose ``PHAsset.mediaType`` is ``PHAssetMediaType.video``. /// /// - Parameters: @@ -23,14 +23,14 @@ extension PHAsset { /// upload of the input to Mux /// - uploadURL: the URL of your direct upload, see /// the [direct upload guide](https://docs.mux.com/api-reference#video/operation/create-direct-upload) - /// - completion: called when initialized ``MuxUpload`` + /// - completion: called when initialized ``DirectUpload`` /// is ready, receives nil if the asset data request /// failed or if the ``PHAsset`` callee is not a video func prepareForDirectUpload( from imageManager: PHImageManager = .default(), - options: UploadOptions = .default, + options: DirectUploadOptions = .default, uploadURL: URL, - completion: @escaping (MuxUpload?) -> () + completion: @escaping (DirectUpload?) -> () ) { if mediaType != .video { completion(nil) @@ -46,8 +46,8 @@ extension PHAsset { forVideo: self, options: requestOptions ) { asset, audioMix, params in - let upload: MuxUpload? = asset.map { unwrappedAsset in - MuxUpload( + let upload: DirectUpload? = asset.map { unwrappedAsset in + DirectUpload( uploadURL: uploadURL, inputAsset: unwrappedAsset, options: options diff --git a/Sources/MuxUploadSDK/PublicAPI/MuxUploadSDK.swift b/Sources/MuxUploadSDK/PublicAPI/SDKLogger.swift similarity index 66% rename from Sources/MuxUploadSDK/PublicAPI/MuxUploadSDK.swift rename to Sources/MuxUploadSDK/PublicAPI/SDKLogger.swift index 87e6b560..f84c07d7 100644 --- a/Sources/MuxUploadSDK/PublicAPI/MuxUploadSDK.swift +++ b/Sources/MuxUploadSDK/PublicAPI/SDKLogger.swift @@ -1,5 +1,5 @@ // -// MuxUploadSDK.swift +// SDKLogger.swift // // // Created by AJ Barinov on 4/8/22. @@ -11,21 +11,21 @@ import OSLog /// /// Metadata and logging for this SDK /// -public enum MuxUploadSDK { +public enum SDKLogger { } -public extension MuxUploadSDK { +public extension SDKLogger { /// The `Logger` being used to log events from this SDK - static var logger: Logger? = nil + static var logger: os.Logger? = nil /// Enables logging by adding a `Logger` with `subsystem: "Mux"` and `category: "Upload"` static func enableDefaultLogging() { - logger = Logger(subsystem: "Mux", category: "MuxUpload") + logger = os.Logger(subsystem: "Mux", category: "MuxUpload") } /// Uses the specified `Logger` to log events from this SDK - static func useLogger(logger: Logger) { + static func useLogger(logger: os.Logger) { self.logger = logger } diff --git a/Sources/MuxUploadSDK/Upload/ChunkWorker.swift b/Sources/MuxUploadSDK/Upload/ChunkWorker.swift index a7943b81..4f6b4e0e 100644 --- a/Sources/MuxUploadSDK/Upload/ChunkWorker.swift +++ b/Sources/MuxUploadSDK/Upload/ChunkWorker.swift @@ -69,7 +69,7 @@ class ChunkWorker { let resp = try await chunkActor.upload() let httpResponse = resp as! HTTPURLResponse - MuxUploadSDK.logger?.info("ChunkWorker: Upload chunk with response: \(String(describing: httpResponse.statusCode))") + SDKLogger.logger?.info("ChunkWorker: Upload chunk with response: \(String(describing: httpResponse.statusCode))") switch repsonseValidator.validate(statusCode: httpResponse.statusCode) { case .error: do { // Throw and break out if the request can't be retried @@ -92,7 +92,7 @@ class ChunkWorker { } } // switch responseValidator.validate() } catch { - MuxUploadSDK.logger?.error("Failed to upload a chunk with error: \(error.localizedDescription)") + SDKLogger.logger?.error("Failed to upload a chunk with error: \(error.localizedDescription)") retries += 1 requestError = error } diff --git a/Sources/MuxUploadSDK/Upload/ChunkedFileUploader.swift b/Sources/MuxUploadSDK/Upload/ChunkedFileUploader.swift index 31214e06..418a7894 100644 --- a/Sources/MuxUploadSDK/Upload/ChunkedFileUploader.swift +++ b/Sources/MuxUploadSDK/Upload/ChunkedFileUploader.swift @@ -64,7 +64,7 @@ class ChunkedFileUploader { case .paused(_): beginUpload() default: - MuxUploadSDK.logger?.info("start() ignored in state \(String(describing: self.currentState))") + SDKLogger.logger?.info("start() ignored in state \(String(describing: self.currentState))") } } @@ -74,7 +74,7 @@ class ChunkedFileUploader { case .paused(_): beginUpload(duration: duration) default: - MuxUploadSDK.logger?.info("start() ignored in state \(String(describing: self.currentState))") + SDKLogger.logger?.info("start() ignored in state \(String(describing: self.currentState))") } } @@ -154,12 +154,12 @@ class ChunkedFileUploader { ) { file.close() if error is CancellationError { - MuxUploadSDK.logger?.debug("Task finished due to cancellation in state \(String(describing: self.currentState))") + SDKLogger.logger?.debug("Task finished due to cancellation in state \(String(describing: self.currentState))") if case let .uploading(update) = self.currentState { self.currentState = .paused(update) } } else { - MuxUploadSDK.logger?.debug("Task finished due to error in state \(String(describing: self.currentState))") + SDKLogger.logger?.debug("Task finished due to error in state \(String(describing: self.currentState))") let uploadError = InternalUploaderError(reason: error, lastByte: lastReadCount) let lastUpdate: Update? @@ -231,12 +231,12 @@ class ChunkedFileUploader { } catch { file.close() if error is CancellationError { - MuxUploadSDK.logger?.debug("Task finished due to cancellation in state \(String(describing: self.currentState))") + SDKLogger.logger?.debug("Task finished due to cancellation in state \(String(describing: self.currentState))") if case let .uploading(update) = self.currentState { self.currentState = .paused(update) } } else { - MuxUploadSDK.logger?.debug("Task finished due to error in state \(String(describing: self.currentState))") + SDKLogger.logger?.debug("Task finished due to error in state \(String(describing: self.currentState))") let uploadError = InternalUploaderError(reason: error, lastByte: lastReadCount) let lastUpdate: Update? @@ -456,10 +456,10 @@ fileprivate actor Worker { } let chunkResult = try await chunkWorker.getTask().value - MuxUploadSDK.logger?.info("Completed Chunk:\n \(String(describing: chunkResult))") + SDKLogger.logger?.info("Completed Chunk:\n \(String(describing: chunkResult))") } while (readBytes == uploadInfo.options.transport.chunkSizeInBytes) - MuxUploadSDK.logger?.info("Finished uploading file: \(self.inputFileURL.relativeString)") + SDKLogger.logger?.info("Finished uploading file: \(self.inputFileURL.relativeString)") let finalState = ChunkedFileUploader.Update( progress: overallProgress, diff --git a/Sources/MuxUploadSDK/Upload/UploadInfo.swift b/Sources/MuxUploadSDK/Upload/UploadInfo.swift index 1a91498b..8c7661dc 100644 --- a/Sources/MuxUploadSDK/Upload/UploadInfo.swift +++ b/Sources/MuxUploadSDK/Upload/UploadInfo.swift @@ -25,7 +25,7 @@ struct UploadInfo : Codable { /** Options selected for the upload */ - var options: UploadOptions + var options: DirectUploadOptions } extension UploadInfo: Equatable { } diff --git a/Tests/MuxUploadSDKTests/PublicAPITests/MuxUploadTests.swift b/Tests/MuxUploadSDKTests/PublicAPITests/DirectUploadTests.swift similarity index 79% rename from Tests/MuxUploadSDKTests/PublicAPITests/MuxUploadTests.swift rename to Tests/MuxUploadSDKTests/PublicAPITests/DirectUploadTests.swift index 1fe23abe..8133e0fa 100644 --- a/Tests/MuxUploadSDKTests/PublicAPITests/MuxUploadTests.swift +++ b/Tests/MuxUploadSDKTests/PublicAPITests/DirectUploadTests.swift @@ -1,5 +1,5 @@ // -// MuxUploadTests.swift +// DirectUploadTests.swift // import AVFoundation @@ -7,22 +7,22 @@ import Foundation import XCTest @testable import MuxUploadSDK -class MuxUploadTest: XCTestCase { +class DirectUploadTests: XCTestCase { func testInitializationInputStatus() throws { - let upload = MuxUpload( + let upload = DirectUpload( uploadURL: URL(string: "https://www.example.com/upload")!, inputFileURL: URL(string: "file://var/mobile/Containers/Data/Application/Documents/myvideo.mp4")! ) - guard case MuxUpload.InputStatus.ready(_) = upload.inputStatus else { + guard case DirectUpload.InputStatus.ready(_) = upload.inputStatus else { XCTFail("Expected initial input status to be ready") return } } func testStartStatusUpdate() throws { - let upload = MuxUpload( + let upload = DirectUpload( uploadURL: URL(string: "https://www.example.com/upload")!, inputFileURL: URL(string: "file://var/mobile/Containers/Data/Application/Documents/myvideo.mp4")! ) @@ -32,7 +32,7 @@ class MuxUploadTest: XCTestCase { ) upload.inputStatusHandler = { inputStatus in - if case MuxUpload.InputStatus.started = inputStatus { + if case DirectUpload.InputStatus.started = inputStatus { ex.fulfill() } } @@ -48,9 +48,9 @@ class MuxUploadTest: XCTestCase { func testInputInspectionSuccess() throws { let input = try UploadInput.mockReadyInput() - let upload = MuxUpload( + let upload = DirectUpload( input: input, - uploadManager: UploadManager(), + uploadManager: DirectUploadManager(), inputInspector: MockUploadInputInspector.alwaysStandard ) @@ -63,11 +63,11 @@ class MuxUploadTest: XCTestCase { ) upload.inputStatusHandler = { inputStatus in - if case MuxUpload.InputStatus.preparing = inputStatus { + if case DirectUpload.InputStatus.preparing = inputStatus { preparingStatusExpectation.fulfill() } - if case MuxUpload.InputStatus.uploadInProgress = inputStatus { + if case DirectUpload.InputStatus.transportInProgress = inputStatus { uploadInProgressExpecation.fulfill() } } @@ -84,9 +84,9 @@ class MuxUploadTest: XCTestCase { func testInputInspectionFailure() throws { let input = try UploadInput.mockReadyInput() - let upload = MuxUpload( + let upload = DirectUpload( input: input, - uploadManager: UploadManager(), + uploadManager: DirectUploadManager(), inputInspector: MockUploadInputInspector.alwaysFailing ) @@ -99,11 +99,11 @@ class MuxUploadTest: XCTestCase { ) upload.inputStatusHandler = { inputStatus in - if case MuxUpload.InputStatus.preparing = inputStatus { + if case DirectUpload.InputStatus.preparing = inputStatus { preparingStatusExpectation.fulfill() } - if case MuxUpload.InputStatus.uploadInProgress = inputStatus { + if case DirectUpload.InputStatus.transportInProgress = inputStatus { uploadInProgressExpecation.fulfill() } } diff --git a/Tests/MuxUploadSDKTests/UploadManagerTests/UploadManagerTests.swift b/Tests/MuxUploadSDKTests/UploadManagerTests/UploadManagerTests.swift index 1b3e5c4b..01b4eea3 100644 --- a/Tests/MuxUploadSDKTests/UploadManagerTests/UploadManagerTests.swift +++ b/Tests/MuxUploadSDKTests/UploadManagerTests/UploadManagerTests.swift @@ -8,10 +8,10 @@ import XCTest @testable import MuxUploadSDK -extension UploadOptions { +extension DirectUploadOptions { - static var inputStandardizationSkipped: UploadOptions { - UploadOptions( + static var inputStandardizationSkipped: DirectUploadOptions { + DirectUploadOptions( inputStandardization: .skipped ) } @@ -22,7 +22,7 @@ class UploadManagerTests: XCTestCase { func testUploadManagerURLDeduplication() throws { - let uploadManager = UploadManager() + let uploadManager = DirectUploadManager() let uploadURL = try XCTUnwrap( URL(string: "https://www.example.com/upload") @@ -32,7 +32,7 @@ class UploadManagerTests: XCTestCase { URL(string: "file://path/to/dummy/file/") ) - let upload = MuxUpload( + let upload = DirectUpload( input: UploadInput( asset: AVAsset(url: videoInputURL), info: UploadInfo( @@ -43,7 +43,7 @@ class UploadManagerTests: XCTestCase { uploadManager: uploadManager ) - let duplicateUpload = MuxUpload( + let duplicateUpload = DirectUpload( input: UploadInput( asset: AVAsset(url: videoInputURL), info: UploadInfo( @@ -58,7 +58,7 @@ class UploadManagerTests: XCTestCase { duplicateUpload.start(forceRestart: false) XCTAssertEqual( - uploadManager.allManagedUploads().count, + uploadManager.allManagedDirectUploads().count, 1, "There should only be one active upload for a given URL" )