Stuff…
This commit is contained in:
286
TagTunes/TagTunesTrack.swift
Executable file
286
TagTunes/TagTunesTrack.swift
Executable file
@@ -0,0 +1,286 @@
|
||||
//
|
||||
// Track.swift
|
||||
// TagTunes
|
||||
//
|
||||
// Created by Kim Wittenburg on 17.03.16.
|
||||
// Copyright © 2016 Kim Wittenburg. All rights reserved.
|
||||
//
|
||||
|
||||
import SearchAPI
|
||||
|
||||
// TODO: Documentation
|
||||
public enum TagTunesTrackErrors: ErrorType {
|
||||
|
||||
case FileNotFound
|
||||
case FileNotReadable
|
||||
case NoIDFound
|
||||
|
||||
}
|
||||
|
||||
/// Represents a track in TagTunes. A track is directly related to a file. There
|
||||
/// may be different subclasses of this class representing different kinds of
|
||||
/// tracks (for example mp3, aac, ...).
|
||||
///
|
||||
/// `TagTunesTrack` should be regarded as a protocol. Due to Swift's limitation
|
||||
/// with associated types this is currently not possible. Nevertheless every the
|
||||
/// class `TagTunesTrack` can not be used by itself.
|
||||
public class TagTunesTrack: NSObject, NSSecureCoding {
|
||||
|
||||
/// The entity containing the track.
|
||||
public internal(set) weak var entity: TagTunesEntityItem?
|
||||
|
||||
/// The track's lookup state. By default the state is `Unprocessed`. The
|
||||
/// state is changed by the lookup controller and may be changed on any
|
||||
/// thread.
|
||||
public internal(set) var lookupState = LookupState.Unprocessed
|
||||
|
||||
// TODO: Change DOcumentation
|
||||
/// Returns the `id` of the track. The id can be used to query the track on
|
||||
/// the iTunes Store. If no such id exists, `nil` is returned.
|
||||
///
|
||||
/// This property may block the main thread until the id could be fetched.
|
||||
/// Subclasses may choose to use the `NSProgress` mechanism to report the
|
||||
/// progress of the fetching of the id. If possible the id should be cached
|
||||
/// to minimize waiting time for the user.
|
||||
///
|
||||
/// This property must be overridden by subclasses.
|
||||
public private(set) var id: SearchAPIID?
|
||||
|
||||
// TODO: Documentation
|
||||
public func updateTrackID() {
|
||||
do {
|
||||
try id = readTrackID()
|
||||
} catch {
|
||||
lookupState = LookupState.Unqualified(error)
|
||||
}
|
||||
}
|
||||
|
||||
// TODO: Documentation
|
||||
public func readTrackID() throws -> SearchAPIID {
|
||||
fatalError("Must override readTrackID()")
|
||||
}
|
||||
|
||||
/// Initializes the track. This is the designated initializer of
|
||||
/// `TagTunesTrack`. Also it is the only initializer that does not crash the
|
||||
/// programm.
|
||||
public override init() {
|
||||
super.init()
|
||||
}
|
||||
|
||||
/// Decodes the track. This method must be implemented by subclasses.
|
||||
/// Subclasses must not call this method on `super` in their implementation.
|
||||
/// Instead subclasses should use `super.init()`.
|
||||
@objc public required init?(coder aDecoder: NSCoder) {
|
||||
fatalError("Must override init(coder:)")
|
||||
}
|
||||
|
||||
/// Encoded the track. This method must be implemented by subclasses.
|
||||
@objc public func encodeWithCoder(aCoder: NSCoder) {
|
||||
fatalError("Must override encodeWithCoder(_:)")
|
||||
}
|
||||
|
||||
@objc public static func supportsSecureCoding() -> Bool {
|
||||
return true
|
||||
}
|
||||
|
||||
/// Per-tag querying. This method must be implemented by subclasses. It is
|
||||
/// generally not a good idea to return `nil` from this method.
|
||||
public func valueForTag(tag: Tag) -> AnyObject! {
|
||||
fatalError("Must override valueForTag(_:)")
|
||||
}
|
||||
|
||||
/// Reveals the track. Normally this launches another application in which to
|
||||
/// reveal the track. Which application is launched depends on the actual
|
||||
/// track.
|
||||
///
|
||||
/// This method must be implemented by subclasses.
|
||||
public func reveal() {
|
||||
fatalError("Must override reveal()")
|
||||
}
|
||||
|
||||
// TODO: Documentation
|
||||
public var supportsBatchSaving: Bool {
|
||||
fatalError("Must override property supportsBatchSaving")
|
||||
}
|
||||
|
||||
// TODO: Remove
|
||||
/// Saves the track using the data from the specified `entity`. Subclasses
|
||||
/// may use the `NSProgress` mechanism to report the saving process.
|
||||
///
|
||||
/// This method may be overridden by subclasses. It should respect the user's
|
||||
/// preferences. The default implementation invokes `saveTag(_:value:)` for
|
||||
/// each tag to be saved.
|
||||
///
|
||||
/// - returns: `true` if the `tags` could be saved successfully, `false`
|
||||
/// otherwise. If `false` is returned the `saveErrors` property
|
||||
/// should contain information about the errors that occured. If
|
||||
/// `true` is returned `saveErrors` should be empty.
|
||||
// public func save(entity: TagTunesEntityItem) -> Bool {
|
||||
// var success = true
|
||||
// saveErrors = []
|
||||
// let progress = NSProgress(totalUnitCount: Int64(Tag.allTags.count))
|
||||
// for tag in Tag.allTags {
|
||||
// do {
|
||||
// switch Preferences.sharedPreferences.tagSavingBehaviors[tag]! {
|
||||
// case .Save: try success = success && saveTag(tag, value: entity.valueForTag(tag))
|
||||
// case .Clear: success = success && saveTag(tag, value: nil)
|
||||
// case .Ignore: break
|
||||
// }
|
||||
// } catch let error {
|
||||
// saveErrors.append(error)
|
||||
// }
|
||||
// dispatch_sync(dispatch_get_main_queue()) {
|
||||
// progress.completedUnitCount += 1
|
||||
// }
|
||||
// }
|
||||
// return success
|
||||
// }
|
||||
|
||||
// TODO: Documentation
|
||||
public func saveTags(tags: [Tag: AnyObject?]) throws {
|
||||
fatalError("Must override saveTags(_:)")
|
||||
}
|
||||
|
||||
// TODO: throws documentation
|
||||
/// Saves the specified `value` for the specified `tag`. This method should
|
||||
/// not act depending on the user's `Preferences`.
|
||||
///
|
||||
/// This method must be overridden by subclasses.
|
||||
///
|
||||
/// - parameters:
|
||||
/// - value: The value to be saved. If this value is `nil` the value for
|
||||
/// the specified `tag` should be removed from the track.
|
||||
/// - tag: The `Tag` to be saved.
|
||||
public func saveValue(value: AnyObject?, forTag tag: Tag) throws {
|
||||
fatalError("Must override saveTag(_:value:)")
|
||||
}
|
||||
|
||||
public override var hashValue: Int {
|
||||
fatalError("Must override property hashValue.")
|
||||
}
|
||||
|
||||
public override func isEqual(object: AnyObject?) -> Bool {
|
||||
if let other = object as? TagTunesTrack {
|
||||
return self == other
|
||||
}
|
||||
return super.isEqual(object)
|
||||
}
|
||||
|
||||
public override var hash: Int {
|
||||
return hashValue
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
public func ==(lhs: TagTunesTrack, rhs: TagTunesTrack) -> Bool {
|
||||
if let leftTrack = lhs as? ImportedTrack, rightTrack = rhs as? ImportedTrack {
|
||||
return leftTrack == rightTrack
|
||||
}
|
||||
return lhs === rhs
|
||||
}
|
||||
|
||||
public extension TagTunesTrack {
|
||||
|
||||
/// The track's name.
|
||||
public var name: String? {
|
||||
return valueForTag(.Name) as? String
|
||||
}
|
||||
|
||||
/// The track's artist.
|
||||
public var artist: String? {
|
||||
return valueForTag(.Artist) as? String
|
||||
}
|
||||
|
||||
/// The track's year.
|
||||
public var year: Int? {
|
||||
return valueForTag(.Year) as? Int
|
||||
}
|
||||
|
||||
/// The track's track number.
|
||||
public var trackNumber: Int? {
|
||||
return valueForTag(.TrackNumber) as? Int
|
||||
}
|
||||
|
||||
/// The track's track count. The track count is respective to the track's
|
||||
/// `discNumber`.
|
||||
public var trackCount: Int? {
|
||||
return valueForTag(.TrackCount) as? Int
|
||||
}
|
||||
|
||||
/// The track's disc number.
|
||||
public var discNumber: Int? {
|
||||
return valueForTag(.DiscNumber) as? Int
|
||||
}
|
||||
|
||||
/// The track's disc count.
|
||||
public var discCount: Int? {
|
||||
return valueForTag(.DiscCount) as? Int
|
||||
}
|
||||
|
||||
/// The track's genre.
|
||||
public var genre: String? {
|
||||
return valueForTag(.Genre) as? String
|
||||
}
|
||||
|
||||
/// The track's album.
|
||||
public var album: String? {
|
||||
return valueForTag(.AlbumName) as? String
|
||||
}
|
||||
|
||||
/// The track's album artist.
|
||||
public var albumArtist: String? {
|
||||
return valueForTag(.AlbumArtist) as? String
|
||||
}
|
||||
|
||||
/// The track's release date.
|
||||
public var releaseDate: NSDate? {
|
||||
return valueForTag(.ReleaseDate) as? NSDate
|
||||
}
|
||||
|
||||
/// A boolean value indicating whether the track belongs to a compilation
|
||||
/// album.
|
||||
public var compilation: Bool? {
|
||||
return valueForTag(.Compilation) as? Bool
|
||||
}
|
||||
|
||||
/// The track's artwork.
|
||||
public var artwork: NSImage? {
|
||||
return valueForTag(.Artwork) as? NSImage
|
||||
}
|
||||
|
||||
/// The track's sort name.
|
||||
public var sortName: String? {
|
||||
return valueForTag(.SortName) as? String
|
||||
}
|
||||
|
||||
/// The track's sort artist.
|
||||
public var sortArtist: String? {
|
||||
return valueForTag(.SortArtist) as? String
|
||||
}
|
||||
|
||||
/// The track's sort album.
|
||||
public var sortAlbum: String? {
|
||||
return valueForTag(.SortAlbumName) as? String
|
||||
}
|
||||
|
||||
/// The track's sort album artist.
|
||||
public var sortAlbumArtist: String? {
|
||||
return valueForTag(.SortAlbumArtist) as? String
|
||||
}
|
||||
|
||||
/// The track's composer.
|
||||
public var composer: String? {
|
||||
return valueForTag(.Composer) as? String
|
||||
}
|
||||
|
||||
/// The track's sort composer.
|
||||
public var sortComposer: String? {
|
||||
return valueForTag(.SortComposer) as? String
|
||||
}
|
||||
|
||||
/// The track's comment.
|
||||
public var comment: String? {
|
||||
return valueForTag(.Comment) as? String
|
||||
}
|
||||
|
||||
}
|
||||
Reference in New Issue
Block a user