         outputs.filter({$0.portType == .headphones}).isNotEmpty
     }
 }
-
-// MARK: - AVAudioEngine
-
-extension AVAudioEngine {
-    func detachAll() {
-        attachedNodes.forEach {
-            detach($0)
-        }
-    }
-}

    
    internal func deinitAudioEngine() {
        engine.stop()
        engine.detachAll()
    }
        
    @discardableResult private func _play() -> Bool {

        tailPosition = file.length
                
        initAudioEngine()
        
        if wasPlaying {
            _play()
        }
    }
    
    ///This is a temporary? hack to release the avaudioengine which appears
    ///to have a retain cycle issue. This must be called after play has been called on the object or
    ///avaudioengine will retain this object indefinitetly.
    public func shutdown() {
        DispatchQueue.main.async {
            self.stop()
            self.deinitAudioEngine()
        }
    }
        
    ///Set outputs for the engine
    public func mapOutputs(to channels: [AVAudioOutputNode.OutputChannelMapping]) {
        engine.outputNode.mapRouteOutputs(to: channels)
