From 2186cd69e3309b279b95c9456f80bf3823111d17 Mon Sep 17 00:00:00 2001 From: Daniel Barber Date: Mon, 13 Jan 2020 22:00:47 -0500 Subject: [PATCH] Refactor connection logic The app would crash when connection settings were changed. This refactors the connection logic to be consistent with the rest of the mpdclient command structure. This ultimately fixes the bug. --- Persephone/AppDelegate.swift | 17 ++---- .../Shared/MPDServerController.swift | 27 ++++++++-- .../Extensions/MPDClient+Command.swift | 8 +++ .../Extensions/MPDClient+Connection.swift | 54 ++++++++++--------- Persephone/MPDClient/MPDClient.swift | 3 +- Persephone/MPDClient/Models/MPDCommand.swift | 3 ++ 6 files changed, 66 insertions(+), 46 deletions(-) diff --git a/Persephone/AppDelegate.swift b/Persephone/AppDelegate.swift index cf46953..95879b4 100644 --- a/Persephone/AppDelegate.swift +++ b/Persephone/AppDelegate.swift @@ -23,9 +23,6 @@ class AppDelegate: NSObject, @IBOutlet weak var addSelectedSongToQueueMenuItem: NSMenuItem! func applicationDidFinishLaunching(_ aNotification: Notification) { - connectToMPDServer() - instantiateControllers() - mediaKeyTap = MediaKeyTap(delegate: self) mediaKeyTap?.start() @@ -34,22 +31,16 @@ class AppDelegate: NSObject, $0.uiState } } + + instantiateControllers() + connectToMPDServer() } func connectToMPDServer() { - let mpdServer = App.store.state.preferencesState.mpdServer - - App.mpdClient = MPDClient( - host: mpdServer.hostOrDefault, - port: mpdServer.portOrDefault, - withDelegate: App.mpdServerDelegate - ) - - App.mpdClient.connect() + App.mpdServerController.connect() } func instantiateControllers() { - _ = App.mpdServerController _ = App.userNotificationsController } diff --git a/Persephone/Components/Shared/MPDServerController.swift b/Persephone/Components/Shared/MPDServerController.swift index a21e940..f4ae753 100644 --- a/Persephone/Components/Shared/MPDServerController.swift +++ b/Persephone/Components/Shared/MPDServerController.swift @@ -11,9 +11,24 @@ import ReSwift class MPDServerController { init() { -// App.store.subscribe(self) { -// $0.select { $0.preferencesState.mpdServer } -// } + App.mpdClient = MPDClient(withDelegate: App.mpdServerDelegate) + + App.store.subscribe(self) { + $0.select { $0.preferencesState.mpdServer } + } + } + + func connect() { + let mpdServer = App.store.state.preferencesState.mpdServer + + App.mpdClient.connect( + host: mpdServer.hostOrDefault, + port: mpdServer.portOrDefault + ) + } + + func disconnect() { + App.mpdClient.disconnect() } } @@ -21,7 +36,9 @@ extension MPDServerController: StoreSubscriber { typealias StoreSubscriberStateType = MPDServer func newState(state: MPDServer) { - App.mpdClient.disconnect() - App.mpdClient.connect() + guard App.mpdClient != nil else { return } + + disconnect() + connect() } } diff --git a/Persephone/MPDClient/Extensions/MPDClient+Command.swift b/Persephone/MPDClient/Extensions/MPDClient+Command.swift index 049d443..af1ff43 100644 --- a/Persephone/MPDClient/Extensions/MPDClient+Command.swift +++ b/Persephone/MPDClient/Extensions/MPDClient+Command.swift @@ -14,6 +14,14 @@ extension MPDClient { userData: Dictionary = [:] ) { switch command { + + case .connect: + guard let host = userData["host"] as? String, + let port = userData["port"] as? Int + else { return } + createConnection(host: host, port: port) + case .disconnect: + freeConnection() // Transport commands case .prevTrack: diff --git a/Persephone/MPDClient/Extensions/MPDClient+Connection.swift b/Persephone/MPDClient/Extensions/MPDClient+Connection.swift index d219fd0..b18295b 100644 --- a/Persephone/MPDClient/Extensions/MPDClient+Connection.swift +++ b/Persephone/MPDClient/Extensions/MPDClient+Connection.swift @@ -10,40 +10,42 @@ import Foundation import mpdclient extension MPDClient { - func makeConnectionOperation(host: String, port: Int) -> BlockOperation { - BlockOperation { [unowned self] in - guard let connection = mpd_connection_new(host, UInt32(port), 10000), - mpd_connection_get_error(connection) == MPD_ERROR_SUCCESS - else { return } + func createConnection(host: String, port: Int) { + guard let connection = mpd_connection_new(host, UInt32(port), 10000), + mpd_connection_get_error(connection) == MPD_ERROR_SUCCESS + else { return } - self.isConnected = true + self.isConnected = true - guard let status = mpd_run_status(connection) - else { return } + guard let status = mpd_run_status(connection) + else { return } - self.connection = connection - self.status = MPDStatus(status) + self.connection = connection + self.status = MPDStatus(status) - self.delegate?.didConnect(mpdClient: self) - self.delegate?.didUpdateStatus(mpdClient: self, status: self.status!) + self.delegate?.didConnect(mpdClient: self) + self.delegate?.didUpdateStatus(mpdClient: self, status: self.status!) + } + + func freeConnection() { + guard isConnected else { return } + + self.delegate?.willDisconnect(mpdClient: self) + + mpd_connection_free(self.connection) + self.isConnected = false + } + + func connect(host: String, port: Int) { + let commandOperation = BlockOperation() { [unowned self] in + self.sendCommand(command: .connect, userData: ["host": host, "port": port]) self.idle() } + commandQueue.addOperation(commandOperation) } - - func connect() { - commandQueue.addOperation(connectionOperation) - } - + func disconnect() { - guard isConnected else { return } - - noIdle() - commandQueue.addOperation { [unowned self] in - self.delegate?.willDisconnect(mpdClient: self) - - mpd_connection_free(self.connection) - self.isConnected = false - } + enqueueCommand(command: .disconnect) } } diff --git a/Persephone/MPDClient/MPDClient.swift b/Persephone/MPDClient/MPDClient.swift index 75c8d36..9decfd8 100644 --- a/Persephone/MPDClient/MPDClient.swift +++ b/Persephone/MPDClient/MPDClient.swift @@ -22,9 +22,8 @@ class MPDClient { let commandQueue = OperationQueue() - init(host: String, port: Int, withDelegate delegate: MPDClientDelegate?) { + init(withDelegate delegate: MPDClientDelegate?) { commandQueue.maxConcurrentOperationCount = 1 self.delegate = delegate - self.connectionOperation = makeConnectionOperation(host: host, port: port) } } diff --git a/Persephone/MPDClient/Models/MPDCommand.swift b/Persephone/MPDClient/Models/MPDCommand.swift index f3dee72..8c3d1ec 100644 --- a/Persephone/MPDClient/Models/MPDCommand.swift +++ b/Persephone/MPDClient/Models/MPDCommand.swift @@ -10,6 +10,9 @@ import Foundation extension MPDClient { enum MPDCommand { + case connect + case disconnect + // Transport commands case prevTrack case nextTrack