MediaModel.swift 5.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157
  1. /*****************************************************************************
  2. * MediaModel.swift
  3. *
  4. * Copyright © 2018 VLC authors and VideoLAN
  5. * Copyright © 2018 Videolabs
  6. *
  7. * Authors: Soomin Lee <bubu@mikan.io>
  8. *
  9. * Refer to the COPYING file of the official project for license.
  10. *****************************************************************************/
  11. protocol MediaModel: MLBaseModel where MLType == VLCMLMedia { }
  12. extension MediaModel {
  13. func append(_ item: VLCMLMedia) {
  14. if !files.contains { $0 == item } {
  15. files.append(item)
  16. }
  17. }
  18. func delete(_ items: [VLCMLObject]) {
  19. do {
  20. for case let media as VLCMLMedia in items {
  21. if let mainFile = media.mainFile() {
  22. try FileManager.default.removeItem(atPath: mainFile.mrl.path)
  23. }
  24. }
  25. medialibrary.reload()
  26. }
  27. catch let error as NSError {
  28. assertionFailure("MediaModel: Delete failed: \(error.localizedDescription)")
  29. }
  30. }
  31. }
  32. // MARK: - Helpers
  33. extension VLCMLMedia {
  34. static func == (lhs: VLCMLMedia, rhs: VLCMLMedia) -> Bool {
  35. return lhs.identifier() == rhs.identifier()
  36. }
  37. }
  38. extension VLCMLMedia {
  39. @objc func mediaDuration() -> String {
  40. return String(format: "%@", VLCTime(int: Int32(duration())))
  41. }
  42. @objc func formatSize() -> String {
  43. return ByteCountFormatter.string(fromByteCount: Int64(mainFile()?.size() ?? 0),
  44. countStyle: .file)
  45. }
  46. func mediaProgress() -> Float {
  47. guard let string = metadata(of: .progress).str as NSString? else {
  48. return 0.0
  49. }
  50. return string.floatValue
  51. }
  52. func isNew() -> Bool {
  53. let integer = metadata(of: .seen).integer()
  54. return integer == 0
  55. }
  56. }
  57. // MARK: - CoreSpotlight
  58. extension VLCMLMedia {
  59. func coreSpotlightAttributeSet() -> CSSearchableItemAttributeSet {
  60. let attributeSet = CSSearchableItemAttributeSet(itemContentType: "public.audiovisual-content")
  61. attributeSet.title = title
  62. attributeSet.metadataModificationDate = Date()
  63. attributeSet.addedDate = Date()
  64. attributeSet.duration = NSNumber(value: duration() / 1000)
  65. attributeSet.streamable = 0
  66. attributeSet.deliveryType = 0
  67. attributeSet.local = 1
  68. attributeSet.playCount = NSNumber(value: playCount())
  69. if isThumbnailGenerated() {
  70. attributeSet.thumbnailData = UIImage(contentsOfFile: thumbnail.path)?.jpegData(compressionQuality: 0.9)
  71. }
  72. attributeSet.codecs = codecs()
  73. attributeSet.languages = languages()
  74. if let audioTracks = audioTracks {
  75. for track in audioTracks {
  76. attributeSet.audioBitRate = NSNumber(value: track.bitrate())
  77. attributeSet.audioChannelCount = NSNumber(value: track.nbChannels())
  78. attributeSet.audioSampleRate = NSNumber(value: track.sampleRate())
  79. }
  80. }
  81. if let albumTrack = albumTrack {
  82. if let genre = albumTrack.genre {
  83. attributeSet.genre = genre.name
  84. }
  85. if let artist = albumTrack.artist {
  86. attributeSet.artist = artist.name
  87. }
  88. attributeSet.audioTrackNumber = NSNumber(value:albumTrack.trackNumber())
  89. if let album = albumTrack.album {
  90. attributeSet.artist = album.title
  91. }
  92. }
  93. return attributeSet
  94. }
  95. func codecs() -> [String] {
  96. var codecs = [String]()
  97. if let videoTracks = videoTracks {
  98. for track in videoTracks {
  99. codecs.append(track.codec)
  100. }
  101. }
  102. if let audioTracks = audioTracks {
  103. for track in audioTracks {
  104. codecs.append(track.codec)
  105. }
  106. }
  107. if let subtitleTracks = subtitleTracks {
  108. for track in subtitleTracks {
  109. codecs.append(track.codec)
  110. }
  111. }
  112. return codecs
  113. }
  114. func languages() -> [String] {
  115. var languages = [String]()
  116. if let videoTracks = videoTracks {
  117. for track in videoTracks where track.language != "" {
  118. languages.append(track.language)
  119. }
  120. }
  121. if let audioTracks = audioTracks {
  122. for track in audioTracks where track.language != "" {
  123. languages.append(track.language)
  124. }
  125. }
  126. if let subtitleTracks = subtitleTracks {
  127. for track in subtitleTracks where track.language != "" {
  128. languages.append(track.language)
  129. }
  130. }
  131. return languages
  132. }
  133. func updateCoreSpotlightEntry() {
  134. if !KeychainCoordinator.passcodeLockEnabled {
  135. let groupIdentifier = ProcessInfo.processInfo.environment["GROUP_IDENTIFIER"]
  136. let item = CSSearchableItem(uniqueIdentifier: "\(identifier())", domainIdentifier: groupIdentifier, attributeSet: coreSpotlightAttributeSet())
  137. CSSearchableIndex.default().indexSearchableItems([item], completionHandler: nil)
  138. }
  139. }
  140. }