Files
run/RunPlus/SessionMessage.swift

120 lines
4.5 KiB
Swift

import Foundation
struct SyncPlayPayload: Codable {
let trackID: String
let startUptime: TimeInterval
let startPosition: TimeInterval
}
struct TrackInfoPayload: Codable {
let trackID: String
let displayName: String
}
enum SessionMessage: Codable {
case hello
case libraryRequest
case trackInfo(TrackInfoPayload)
case trackRequest(String)
case play(SyncPlayPayload)
case pause
case seek(TimeInterval)
case syncRequest(TimeInterval)
case syncResponse(hostUptime: TimeInterval, peerUptime: TimeInterval)
case driftCorrection(position: TimeInterval, hostUptime: TimeInterval)
private enum CodingKeys: String, CodingKey {
case type
case payload
case position
case hostUptime
case peerUptime
case trackID
case displayName
}
private enum MessageType: String, Codable {
case hello
case libraryRequest
case trackInfo
case trackRequest
case play
case pause
case seek
case syncRequest
case syncResponse
case driftCorrection
}
init(from decoder: Decoder) throws {
let container = try decoder.container(keyedBy: CodingKeys.self)
let type = try container.decode(MessageType.self, forKey: .type)
switch type {
case .hello:
self = .hello
case .libraryRequest:
self = .libraryRequest
case .trackInfo:
let payload = try container.decode(TrackInfoPayload.self, forKey: .payload)
self = .trackInfo(payload)
case .trackRequest:
let trackID = try container.decode(String.self, forKey: .trackID)
self = .trackRequest(trackID)
case .play:
let payload = try container.decode(SyncPlayPayload.self, forKey: .payload)
self = .play(payload)
case .pause:
self = .pause
case .seek:
let position = try container.decode(TimeInterval.self, forKey: .position)
self = .seek(position)
case .syncRequest:
let hostUptime = try container.decode(TimeInterval.self, forKey: .hostUptime)
self = .syncRequest(hostUptime)
case .syncResponse:
let hostUptime = try container.decode(TimeInterval.self, forKey: .hostUptime)
let peerUptime = try container.decode(TimeInterval.self, forKey: .peerUptime)
self = .syncResponse(hostUptime: hostUptime, peerUptime: peerUptime)
case .driftCorrection:
let position = try container.decode(TimeInterval.self, forKey: .position)
let hostUptime = try container.decode(TimeInterval.self, forKey: .hostUptime)
self = .driftCorrection(position: position, hostUptime: hostUptime)
}
}
func encode(to encoder: Encoder) throws {
var container = encoder.container(keyedBy: CodingKeys.self)
switch self {
case .hello:
try container.encode(MessageType.hello, forKey: .type)
case .libraryRequest:
try container.encode(MessageType.libraryRequest, forKey: .type)
case .trackInfo(let payload):
try container.encode(MessageType.trackInfo, forKey: .type)
try container.encode(payload, forKey: .payload)
case .trackRequest(let trackID):
try container.encode(MessageType.trackRequest, forKey: .type)
try container.encode(trackID, forKey: .trackID)
case .play(let payload):
try container.encode(MessageType.play, forKey: .type)
try container.encode(payload, forKey: .payload)
case .pause:
try container.encode(MessageType.pause, forKey: .type)
case .seek(let position):
try container.encode(MessageType.seek, forKey: .type)
try container.encode(position, forKey: .position)
case .syncRequest(let hostUptime):
try container.encode(MessageType.syncRequest, forKey: .type)
try container.encode(hostUptime, forKey: .hostUptime)
case .syncResponse(let hostUptime, let peerUptime):
try container.encode(MessageType.syncResponse, forKey: .type)
try container.encode(hostUptime, forKey: .hostUptime)
try container.encode(peerUptime, forKey: .peerUptime)
case .driftCorrection(let position, let hostUptime):
try container.encode(MessageType.driftCorrection, forKey: .type)
try container.encode(position, forKey: .position)
try container.encode(hostUptime, forKey: .hostUptime)
}
}
}