/***************************************************************************** * VLCMediaThumbnailerCache.swift * VLC for iOS ***************************************************************************** * Copyright (c) 2019 VideoLAN. All rights reserved. * $Id$ * * Authors: Pierre Sagaspe * * Refer to the COPYING file of the official project for license. *****************************************************************************/ import UIKit @objc class VLCMediaThumbnailerCache: NSObject, VLCMediaThumbnailerDelegate { @objc func getVideoThumbnail(_ videoURL: NSString) { if getThumbnailURL(videoURL) != nil { return } let media = VLCMedia(url: URL(fileURLWithPath: videoURL.removingPercentEncoding!)) let thumbnailer = VLCMediaThumbnailer(media: media, andDelegate: self) let thumbSize = CGSize(width: 800, height: 600) thumbnailer?.thumbnailWidth = thumbSize.width thumbnailer?.thumbnailHeight = thumbSize.height thumbnailer?.fetchThumbnail() } // MARK: - VLCMediaThumbnailer data source func mediaThumbnailer(_ mediaThumbnailer: VLCMediaThumbnailer!, didFinishThumbnail thumbnail: CGImage!) { if thumbnail != nil { let thumbnailImage: UIImage? = UIImage.init(cgImage: thumbnail) if thumbnailImage != nil { saveThumbnail(thumbnailImage!, mediaURL: mediaThumbnailer.media.url) NotificationCenter.default.post(name: Notification.Name("thumbnailIComplete"), object: nil) } } } func mediaThumbnailerDidTimeOut(_ mediaThumbnailer: VLCMediaThumbnailer!) { print("Time out : \(mediaThumbnailer.media.url)") } // MARK: - private func getThumbnailDirectory() -> NSString { let paths = NSSearchPathForDirectoriesInDomains(.cachesDirectory, .userDomainMask, true)[0] as NSString let thumbnailDirectory = paths.appendingPathComponent("thumbnail") return thumbnailDirectory.removingPercentEncoding! as NSString } @objc func getThumbnailURL(_ mediaPath: NSString) -> URL? { let thumbnailDir = getThumbnailDirectory() let thumbnailPath = String(format: "%@/%@.%@", thumbnailDir, (mediaPath.lastPathComponent as NSString).deletingPathExtension.removingPercentEncoding!, "png") let fileManager = FileManager.default if fileManager.fileExists(atPath: thumbnailPath) { return URL.init(fileURLWithPath: thumbnailPath) } return nil } @objc func removeThumbnail(_ mediaPath: NSString? = nil) { var thumbnailPath = getThumbnailDirectory() if mediaPath != nil { thumbnailPath = NSString(format: "%@/%@.%@", thumbnailPath, (mediaPath!.lastPathComponent as NSString ).deletingPathExtension.removingPercentEncoding!, "png") } let fileManager = FileManager.default var isDir = ObjCBool(false) if fileManager.fileExists(atPath: thumbnailPath as String, isDirectory: &isDir) { do { try fileManager.removeItem(atPath: thumbnailPath as String) //print("removed : \(String(describing: thumbnailPath))") } catch let error as NSError { print("error remove : \(error)") } } } func saveThumbnail(_ thumbnail: UIImage, mediaURL: URL) { let imageData = thumbnail.pngData() let pngSize: Int = imageData?.count ?? 0 if pngSize > getFreeDiskSpace() ?? 0 { return } let thumbnailDir = getThumbnailDirectory() let thumbnailPath = NSString(format: "%@/%@.%@", thumbnailDir, ((mediaURL.relativePath.removingPercentEncoding! as NSString).lastPathComponent as NSString).deletingPathExtension, "png") let fileManager = FileManager.default if !fileManager.fileExists(atPath: thumbnailDir as String) { do { try fileManager.createDirectory(atPath: thumbnailDir as String, withIntermediateDirectories: true, attributes: nil) } catch let error as NSError { print("error creating directory: \(error)") } } if !fileManager.fileExists(atPath: thumbnailPath as String) { do { try imageData?.write(to: URL(fileURLWithPath: thumbnailPath.standardizingPath, relativeTo: nil)) } catch let error as NSError { print("error writing thumbnail : \(error)") } } } func getFreeDiskSpace() -> Int? { let fileURL = URL(fileURLWithPath:"/") do { let values = try fileURL.resourceValues(forKeys: [.volumeAvailableCapacityKey]) if let capacity = values.volumeAvailableCapacity { //print("Available capacity for important usage: \(capacity)") return capacity } else { print("Capacity is unavailable") } } catch { print("Error retrieving capacity") } return nil } }