From ea40e136eb44d33752de0236bd1dfc5ef9d6e2df Mon Sep 17 00:00:00 2001 From: Dimitris C Date: Mon, 3 Aug 2020 13:15:40 +0300 Subject: [PATCH] Adds Logger class --- AudioStreaming.xcodeproj/project.pbxproj | 16 ++++-- AudioStreaming/Core/Logger.swift | 56 +++++++++++++++++++ .../Core/Network/NetworkDataStream.swift | 6 +- .../Streaming/AudioPlayer/AudioPlayer.swift | 17 +++--- .../AudioSource/RemoteAudioSource.swift | 2 +- 5 files changed, 80 insertions(+), 17 deletions(-) create mode 100644 AudioStreaming/Core/Logger.swift diff --git a/AudioStreaming.xcodeproj/project.pbxproj b/AudioStreaming.xcodeproj/project.pbxproj index 2f07020..b538d37 100644 --- a/AudioStreaming.xcodeproj/project.pbxproj +++ b/AudioStreaming.xcodeproj/project.pbxproj @@ -7,6 +7,7 @@ objects = { /* Begin PBXBuildFile section */ + B500732024D00BAC00BB4475 /* Logger.swift in Sources */ = {isa = PBXBuildFile; fileRef = B500731F24D00BAC00BB4475 /* Logger.swift */; }; B514657F248E3884005C03F7 /* DispatchReadSource.swift in Sources */ = {isa = PBXBuildFile; fileRef = B514657E248E3884005C03F7 /* DispatchReadSource.swift */; }; B51FE0C02488F67C00F2A4D2 /* Queue.swift in Sources */ = {isa = PBXBuildFile; fileRef = B51FE0BF2488F67C00F2A4D2 /* Queue.swift */; }; B51FE0C22488F96A00F2A4D2 /* QueueTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = B51FE0C12488F96A00F2A4D2 /* QueueTests.swift */; }; @@ -71,6 +72,7 @@ /* End PBXCopyFilesBuildPhase section */ /* Begin PBXFileReference section */ + B500731F24D00BAC00BB4475 /* Logger.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Logger.swift; sourceTree = ""; }; B514657E248E3884005C03F7 /* DispatchReadSource.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = DispatchReadSource.swift; sourceTree = ""; }; B51FE0BF2488F67C00F2A4D2 /* Queue.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Queue.swift; sourceTree = ""; }; B51FE0C12488F96A00F2A4D2 /* QueueTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = QueueTests.swift; sourceTree = ""; }; @@ -321,6 +323,7 @@ B51FE0BF2488F67C00F2A4D2 /* Queue.swift */, B514657E248E3884005C03F7 /* DispatchReadSource.swift */, B59DF1A22493E90C0043C498 /* AudioFileStream+Helpers.swift */, + B500731F24D00BAC00BB4475 /* Logger.swift */, ); path = Core; sourceTree = ""; @@ -509,6 +512,7 @@ B5A5FA8B24AE371C00870E2F /* Data+Bytes.swift in Sources */, B55A736C247FCB420050C53D /* HTTPHeaderParser.swift in Sources */, B55CE96E248058B60001C498 /* MetadataParser.swift in Sources */, + B500732024D00BAC00BB4475 /* Logger.swift in Sources */, B5276B72247D4D5B00D2F56A /* NetworkTasksMap.swift in Sources */, B5276B74247D4D9F00D2F56A /* NetworkSessionDelegate.swift in Sources */, B55CE97824813BCA0001C498 /* UnsafeMutablePointer+Helpers.swift in Sources */, @@ -680,7 +684,7 @@ DYLIB_INSTALL_NAME_BASE = "@rpath"; INFOPLIST_FILE = AudioStreaming/Info.plist; INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks"; - IPHONEOS_DEPLOYMENT_TARGET = 12.0; + IPHONEOS_DEPLOYMENT_TARGET = 11.0; LD_RUNPATH_SEARCH_PATHS = ( "$(inherited)", "@executable_path/Frameworks", @@ -690,7 +694,7 @@ PRODUCT_BUNDLE_IDENTIFIER = com.decimal.AudioStreaming; PRODUCT_NAME = "$(TARGET_NAME:c99extidentifier)"; SKIP_INSTALL = YES; - SUPPORTS_MACCATALYST = YES; + SUPPORTS_MACCATALYST = NO; SWIFT_OBJC_BRIDGING_HEADER = ""; SWIFT_OPTIMIZATION_LEVEL = "-Onone"; SWIFT_VERSION = 5.0; @@ -709,7 +713,7 @@ DYLIB_INSTALL_NAME_BASE = "@rpath"; INFOPLIST_FILE = AudioStreaming/Info.plist; INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks"; - IPHONEOS_DEPLOYMENT_TARGET = 12.0; + IPHONEOS_DEPLOYMENT_TARGET = 11.0; LD_RUNPATH_SEARCH_PATHS = ( "$(inherited)", "@executable_path/Frameworks", @@ -719,7 +723,7 @@ PRODUCT_BUNDLE_IDENTIFIER = com.decimal.AudioStreaming; PRODUCT_NAME = "$(TARGET_NAME:c99extidentifier)"; SKIP_INSTALL = YES; - SUPPORTS_MACCATALYST = YES; + SUPPORTS_MACCATALYST = NO; SWIFT_OBJC_BRIDGING_HEADER = ""; SWIFT_VERSION = 5.0; TARGETED_DEVICE_FAMILY = "1,2"; @@ -781,7 +785,7 @@ "@executable_path/../Frameworks", "@loader_path/Frameworks", ); - MACOSX_DEPLOYMENT_TARGET = 10.14; + MACOSX_DEPLOYMENT_TARGET = 10.12; PRODUCT_BUNDLE_IDENTIFIER = com.decimal.AudioStreamingMac; PRODUCT_NAME = "$(TARGET_NAME:c99extidentifier)"; SDKROOT = macosx; @@ -806,7 +810,7 @@ "@executable_path/../Frameworks", "@loader_path/Frameworks", ); - MACOSX_DEPLOYMENT_TARGET = 10.14; + MACOSX_DEPLOYMENT_TARGET = 10.12; PRODUCT_BUNDLE_IDENTIFIER = com.decimal.AudioStreamingMac; PRODUCT_NAME = "$(TARGET_NAME:c99extidentifier)"; SDKROOT = macosx; diff --git a/AudioStreaming/Core/Logger.swift b/AudioStreaming/Core/Logger.swift new file mode 100644 index 0000000..4341386 --- /dev/null +++ b/AudioStreaming/Core/Logger.swift @@ -0,0 +1,56 @@ +// +// Created by Dimitrios Chatzieleftheriou on 28/07/2020. +// Copyright © 2020 Decimal. All rights reserved. +// + +import Foundation +import os + + +private let loggingSubsystem = "audio.streaming.log" + + +final internal class Logger { + private static let audioRendering = OSLog(subsystem: loggingSubsystem, category: "audio.rendering") + private static let networking = OSLog(subsystem: loggingSubsystem, category: "audio.networking") + private static let generic = OSLog(subsystem: loggingSubsystem, category: "audio.streaming.generic") + + /// Defines is the the logger displays any logs + static var isEnabled = true + + enum Category: CaseIterable { + case audioRendering + case networking + case generic + + func toOSLog() -> OSLog { + switch self { + case .audioRendering: return Logger.audioRendering + case .networking: return Logger.networking + case .generic: return Logger.generic + } + } + } + + static func error(_ message: StaticString, category: Category, args: CVarArg...) { + proccess(message, category: category, type: .error, args: args) + } + + static func error(_ message: StaticString, category: Category) { + error(message, category: category, args: []) + } + + static func debug(_ message: StaticString, category: Category, args: CVarArg...) { + proccess(message, category: category, type: .debug, args: args) + } + + static func debug(_ message: StaticString, category: Category) { + debug(message, category: category, args: []) + } + + private static func proccess(_ message: StaticString, category: Category, type: OSLogType, args: CVarArg...) { + guard isEnabled else { return } + os_log(message, log: category.toOSLog(), type: type, args) + } +} + diff --git a/AudioStreaming/Core/Network/NetworkDataStream.swift b/AudioStreaming/Core/Network/NetworkDataStream.swift index 9175056..b3954a9 100644 --- a/AudioStreaming/Core/Network/NetworkDataStream.swift +++ b/AudioStreaming/Core/Network/NetworkDataStream.swift @@ -150,13 +150,13 @@ extension NetworkDataStream: StreamDelegate { guard let stream = streamState.outputStream, aStream == stream else { return } switch eventCode { case .openCompleted: - print("output stream open completed") + Logger.debug("output stream open completed", category: .networking) case .hasSpaceAvailable: writeData(on: stream) case .endEncountered: - print("end encountered") + Logger.debug("output stream end encountered", category: .networking) case .errorOccurred: - print("handle error! stop everything right?") + Logger.debug("handle error! stop everything right?", category: .networking) default: break } diff --git a/AudioStreaming/Streaming/AudioPlayer/AudioPlayer.swift b/AudioStreaming/Streaming/AudioPlayer/AudioPlayer.swift index 7960f38..491b74f 100644 --- a/AudioStreaming/Streaming/AudioPlayer/AudioPlayer.swift +++ b/AudioStreaming/Streaming/AudioPlayer/AudioPlayer.swift @@ -312,11 +312,11 @@ public final class AudioPlayer { private func startEngineIfNeeded() throws { guard !isEngineRunning else { - print("engine already running") + Logger.debug("engine already running 🛵", category: .generic) return } try audioEngine.start() - print("engine started 🛵") + Logger.debug("engine started 🛵", category: .generic) } /// Pauses the audio engine and stops the player's hardware @@ -324,17 +324,17 @@ public final class AudioPlayer { guard isEngineRunning else { return } audioEngine.pause() player?.auAudioUnit.stopHardware() - print("engine paused ⏸") + Logger.debug("engine paused ⏸", category: .generic) } private func stopEngine() { guard isEngineRunning else { - print("already already stopped 🛑") + Logger.debug("already already stopped 🛑", category: .generic) return } audioEngine.stop() player?.auAudioUnit.stopHardware() - print("engine stopped 🛑") + Logger.debug("engine stopped 🛑", category: .generic) } private func startReadProcessFromSourceIfNeeded() { @@ -380,7 +380,7 @@ public final class AudioPlayer { private func setCurrentReading(entry: AudioEntry?, startPlaying: Bool, shouldClearQueue: Bool) { guard let entry = entry else { return } - print("Setting current reading entry to: \(entry)") + Logger.debug("Setting current reading entry to: %@", category: .generic, args: entry.debugDescription) if startPlaying { let count = Int(rendererContext.bufferTotalFrameCount * rendererContext.bufferFrameSizeInBytes) memset(rendererContext.audioBuffer.mData, 0, count) @@ -482,7 +482,10 @@ public final class AudioPlayer { private func raiseUnxpected(error: AudioPlayerError) { playerContext.internalState = .error // todo raise on main thread from playback thread - delegate?.audioPlayerUnexpectedError(player: self, error: error) + asyncOnMain { [weak self] in + guard let self = self else { return } + self.delegate?.audioPlayerUnexpectedError(player: self, error: error) + } Logger.error("Error: %@", category: .generic, args: error.localizedDescription) } diff --git a/AudioStreaming/Streaming/AudioSource/RemoteAudioSource.swift b/AudioStreaming/Streaming/AudioSource/RemoteAudioSource.swift index 40d4188..12a489e 100644 --- a/AudioStreaming/Streaming/AudioSource/RemoteAudioSource.swift +++ b/AudioStreaming/Streaming/AudioSource/RemoteAudioSource.swift @@ -229,7 +229,7 @@ extension RemoteAudioSource: StreamDelegate { public func stream(_ aStream: Stream, handle eventCode: Stream.Event) { switch eventCode { case .openCompleted: - print("input stream open completed") + Logger.debug("input stream open completed", category: .networking) case .hasBytesAvailable: if httpStatusCode == 0 { if self.parseResponseHeader(response: httpResponse) {