Swift Media Player
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 

657 lines
22 KiB

//
// Created by Marco Schmickler on 24.05.15.
// Copyright (c) 2015 Marco Schmickler. All rights reserved.
//
import Foundation
import Alamofire
class NetworkManager {
static let sharedInstance = NetworkManager()
let nodeurl = "http://linkstation:8081/"
let baseurl = "http://linkstation:8080/tomcat/media"
let vidurl = "http://linkstation:8089"
var authenticated = false
var offline = false
var favorites = MediaItem(name: "fav", path:"", root: "", type: ItemType.FAVROOT)
var currentDownloads = [String : MediaItem]()
lazy var operationQueue: OperationQueue = {
var queue = OperationQueue()
queue.name = "Backup queue"
queue.maxConcurrentOperationCount = 1
return queue
}()
internal typealias Weiter = ([MediaItem]) -> Void
func getDownloadJs() -> URL {
if offline {
let url = Bundle.main.url(forResource: "download.js", withExtension: nil)!
return url
}
return URL(string: "http://l inkstation:8089/ren/web/download.js")!
}
func saveFavDir(name: String, item: MediaItem) -> Void {
let json = item.toJSON()
let url = FileHelper.getDocumentsDirectory().appendingPathComponent(name)
do {
print (url)
try json.write(to: url, atomically: true, encoding: .utf8)
let input = try String(contentsOf: url)
print(input)
} catch {
print(json)
}
}
func loadFavDirs(_ rootParam: String, completionHandler: @escaping Weiter) -> Void {
var res = [MediaItem]()
var itemsMap = Dictionary<String, MediaItem>()
let fi = MediaItem(name: "images", path: "", root: "fav", type: ItemType.DETAILS)
fi.local = true
fi.loaded = true
res.append(fi)
let url = FileHelper.getDocumentsDirectory()
if let enumerator = FileManager.default.enumerator(at: url, includingPropertiesForKeys: [.isRegularFileKey], options: [.skipsHiddenFiles, .skipsPackageDescendants]) {
for case let fileURL as URL in enumerator {
do {
let fileAttributes = try fileURL.resourceValues(forKeys:[.isRegularFileKey])
if fileAttributes.isRegularFile! {
if (fileURL.pathExtension == "jpg" && fileURL.absoluteString.contains("/images/")) {
let p = fileURL.absoluteString.substringAfter("/Documents")
var path = p.substringBefore("/")
let fp = fileURL.absoluteString.substringAfter("/Documents/images/")
var fpath = fp.substringBefore("/")
var folder = itemsMap[fpath]
if folder == nil {
let f = MediaItem(name: fpath, path: "images", root: "fav", type: ItemType.PICS)
f.local = true
f.loaded = true
folder = f
itemsMap[fpath] = folder!
fi.children.append(f)
}
let m = MediaItem(name: fileURL.lastPathComponent, path: path, root: "fav", type: ItemType.PICS)
m.local = true
m.loaded = true
m.thumbUrl = fileURL.absoluteString
let jsonURL = fileURL.absoluteString.replacingOccurrences(of: ".jpg", with: ".json")
do {
let jsonData = try Data(contentsOf: URL(string: jsonURL)!)
let item = try JSONDecoder().decode(MediaModel.self, from: jsonData)
m.scale = item.scale
m.offset = item.offset
m.size = item.size
}
catch {
}
// var folder = itemsMap[path]
//
// if folder == nil {
// folder = MediaItem(name: item.path, path: item.path, root: item.root, type: ItemType.FOLDER)
// folder!.loaded = true
// folder!.local = item.local
// itemsMap[path] = folder!
// items.append(folder!)
// }
folder!.children.append(m)
print(fileURL.absoluteString)
}
if (fileURL.pathExtension == "mp4") {
print(fileURL.absoluteString)
let p = fileURL.absoluteString.substringAfter("/Documents")
var path = p.substringBefore("/")
let m = MediaItem(name: fileURL.lastPathComponent, path: path, root: "fav", type: ItemType.VIDEO)
m.local = true
m.thumbUrl = fileURL.appendingPathExtension("jpg").absoluteString
res.append(m)
}
}
} catch { print(error, fileURL) }
}
}
let m = MediaItem(name: "new", path: "new", root: "fav", type: ItemType.FOLDER)
m.local = true
res.append(m)
completionHandler(res)
}
func loadFav2Dirs(_ rootParam: String, completionHandler: @escaping Weiter) -> Void {
let files = FileHelper.listFiles(name: "1")
var res = [MediaItem]()
for f in files {
if f.pathExtension == "mp4" {
let m = MediaItem(name: f.lastPathComponent, path: "", root: "1", type: ItemType.VIDEO)
m.local = true
res.append(m)
}
}
completionHandler(res)
}
func loadFav1Dirs(_ rootParam: String, completionHandler: @escaping Weiter) -> Void {
var res = [MediaItem]()
do {
let jsonData = try FileHelper.getData(name: "fav.json")
let items = try JSONDecoder().decode(MediaModel.self, from: jsonData)
let loaded = MediaItem(model: items)
res = loaded.children
} catch {
print(error.localizedDescription)
}
// res.append(currentFav)
completionHandler(res)
}
func loadVideoDirs(_ rootParam: String, completionHandler: @escaping Weiter) -> Void {
var root = rootParam
if root.contains("*") {
root = String(rootParam[rootParam.startIndex..<rootParam.range(of: "*")!.lowerBound])
}
if root.endsWith("/") {
root = String(root[root.startIndex..<root.index(before: root.endIndex)])
}
let url1 = baseurl + "/service/listvideos" + rootParam
let len = root.count
var res = [MediaItem]()
let url = (url1 as NSString).replacingOccurrences(of: " ", with: "+")
print(url)
AF.request(url).responseJSON {
(response) in
if let json = response.value as? [String] {
print("Empfange \(json.count) Ergebnisse")
for s in json {
if s.hasSuffix(".mp4") || s.hasSuffix(".m4v") {
let l = s.count
let name = NSURL(fileURLWithPath: s).lastPathComponent!
var pathlen = l - len - name.count
if (pathlen < 2) {
pathlen = 2
}
let path = (s as NSString).substring(with: NSMakeRange(len + 1, pathlen - 2))
let i = MediaItem(name: name, path: path, root: root, type: ItemType.VIDEO)
if !name.hasPrefix(".") {
res.append(i)
}
}
}
}
completionHandler(res)
}
}
func loadPicDirs(_ rootParam: String, completionHandler: @escaping Weiter) -> Void {
var root = rootParam
if root.contains("*") {
root = String(rootParam[rootParam.startIndex..<rootParam.range(of: "*")!.lowerBound])
}
if root.endsWith("/") {
root = String(root[root.startIndex..<root.index(before: root.endIndex)])
}
let url1 = baseurl + "/service/listpicdirs" + rootParam
let len = root.count
var res = [MediaItem]()
let url = (url1 as NSString).replacingOccurrences(of: " ", with: "+")
print(url)
AF.request(url).responseJSON {
(response) in
if let json = response.value {
var items = Dictionary<String, MediaItem>()
let result = json as! [String]
print("Empfange \(result.count) Ergebnisse")
for s in result {
if s.lowercased().hasSuffix(".jpg") {
let l = s.count
let name = (s as NSString).lastPathComponent
var pathlen = l - len - name.count
if (pathlen < 2) {
pathlen = 2
}
let path = (s as NSString).substring(with: NSMakeRange(len + 1, pathlen - 2))
let folderName = NSURL(fileURLWithPath: path).lastPathComponent!
let fl = path.count
let pfl = fl - folderName.count
let fpath = (path as NSString).substring(with: NSMakeRange(0, pfl))
let i = MediaItem(name: folderName, path: fpath, root: root, type: ItemType.PICS)
i.thumbUrl = "\(s)?preview=true"
i.loaded = true
if !name.hasPrefix(".") {
if let picfolder = items[path] {
picfolder.children.append(i)
} else {
let iff = MediaItem(name: folderName, path: fpath, root: root, type: ItemType.PICS)
iff.thumbUrl = i.thumbUrl
items[path] = iff
res.append(iff)
iff.children.append(i)
}
}
}
}
}
completionHandler(res)
}
}
func deleteLocal(selectedItem: MediaItem) {
if (selectedItem.local) {
print(selectedItem.playerURL?.absoluteString)
do {
try FileManager.default.removeItem(at: selectedItem.playerURL!)
} catch {
print(error)
}
}
}
func listDirs(_ root: String, completionHandler: @escaping ([MediaItem], Bool) -> Void) -> Void {
let len = root.count
let url = (root as NSString).replacingOccurrences(of: " ", with: "+")
let ux = nodeurl + "listdirs" + url
print(ux)
AF.request(ux).responseJSON {
(response) in
if let json = response.value {
var res = [MediaItem]()
var leaf = false
var hasPics = false
let result = json as! [[String]]
print("Empfange \(result.count) Ergebnisse")
for s in result {
var name = s[0]
var type = s[1]
var t = ItemType.FOLDER
if (type == "video") {
t = ItemType.VIDEO
}
if (type == "pictures") {
t = ItemType.DETAILS
}
if (type == "web") {
t = ItemType.WEB
}
let i = MediaItem(name: name, path: name, root: root, type: t)
res.append(i)
}
completionHandler(res, leaf)
}
}
}
func loadItems(_ item: MediaItem) {
if (offline) {
return
}
if item.local {
if item.name == "download" {
var nodes = [MediaItem]()
for c in item.children {
if c.type != ItemType.DOWNLOAD {
nodes.append(c)
}
}
for d in NetworkManager.sharedInstance.currentDownloads {
nodes.append(d.value)
}
item.children = nodes
}
return
}
if (item.type == ItemType.WEB) {
let url = URL(string: vidurl)!.appendingPathComponent(item.root.substringStartingFrom(10)).appendingPathComponent(item.path).appendingPathComponent("links.html")
let parser = HtmlParser(url: url)
parser.parse()
item.children = parser.items
NotificationCenter.default.post(name: Notification.Name(rawValue: "loadedItems"), object: nil)
return
}
if (item.type != ItemType.VIDEO && item.type != ItemType.DETAILS) {
return
}
var j = 0
for i in item.children {
loadItem(i, index: j)
j+=1
}
NotificationCenter.default.post(name: Notification.Name(rawValue: "loadedItems"), object: nil)
}
func loadItem(_ item: MediaItem, index: Int) {
if (item.type != ItemType.VIDEO) {
var j = 0
for i in item.children {
loadItem(i, index: j)
j+=1
}
return
}
if item.loaded {
return
}
if !item.children.isEmpty {
return
}
let url = baseurl + "/service/listfiles" + item.snapshotDirPathForVideo
print(url)
AF.request(url).responseJSON {
(response) in
if let json = response.value {
var hashes = Dictionary<String, String>()
for b in json as! [String] {
let p = NSURL(fileURLWithPath: b).lastPathComponent!
if p.contains("_thumb.jpg") {
let ts = p.substringWithoutLast(10)
hashes[ts] = b
} else {
let ts = p.substringWithoutLast(4)
if hashes[ts] == nil {
hashes[ts] = b
}
}
}
item.children.removeAll(keepingCapacity: true)
for (ts, p) in hashes {
let t = (ts as NSString).doubleValue / 1000
let snap = MediaItem(name: item.name, path: item.path, root: item.root, type: .SNAPSHOT)
snap.time = t
snap.thumbUrl = p
snap.parent = item
snap.loaded = true
item.children.append(snap)
}
item.loaded = true
NotificationCenter.default.post(name: Notification.Name(rawValue: "loadedItems"), object: item)
}
}
}
func deleteThumb(_ path: String) {
let p = self.nodeurl + "deleteThumb\(path)"
print("Delete \(path)")
AF.request(p).responseString { response in
print(response)
}
}
func alive() {
let p = self.nodeurl + "alive"
print("alive")
AF.request(p).responseString { response in
self.offline = response.value == nil
print(response.result)
}
}
func favItem(_ item: MediaItem) {
let url = baseurl + "/service/linkfav" + item.fullPath
AF.request(url)
}
func saveItem(_ item: MediaItem) {
print(item.children)
if (item.local) {
return
}
if (item.type != ItemType.VIDEO) {
return
}
let url = baseurl + "/service/listfiles" + item.snapshotDirPathForVideo
print(url)
AF.request(url).responseJSON {
(response) in
var hashes = Set<String>()
if let json = response.value {
for b in json as! [String] {
hashes.insert(b)
print(b)
}
}
for c in item.children {
if let t = c.time {
let ms = Int(t * 1000)
let p = c.snapshotDirPathForVideo + "\(ms).jpg"
let pt = c.snapshotDirPathForVideo + "\(ms)_thumb.jpg"
print(p)
if hashes.contains(pt) {
print("contained")
} else {
if let id = c.image, let imageData = id.jpegData(compressionQuality: 1.0) {
let op = UploadOperation(baseUrl: self.nodeurl + "upload", data: imageData, path: p)
self.operationQueue.addOperation(op)
let thumb = id.scaleToSize(15 * 16, height: 15 * 9)
if let imageDataT = thumb.jpegData(compressionQuality: 1.0) {
c.image = thumb
let opT = UploadOperation(baseUrl: self.nodeurl + "upload", data: imageDataT, path: pt)
self.operationQueue.addOperation(opT)
}
c.loaded = true
}
}
}
}
}
}
func loadPicDetails(items: MediaItem, result: @escaping ([MediaItem]) -> () ) {
let len = items.root.count
let url = NetworkManager.sharedInstance.baseurl + "/service/listfiles" + items.fullPath
print(items)
print(url)
AF.request(url).responseJSON {
(response) in
if let json = response.value {
var im = [MediaItem]()
for s in json as! [String] {
if s.lowercased().hasSuffix(".jpg") {
let l = s.count
let name = NSURL(fileURLWithPath: s).lastPathComponent!
var pathlen = l - len - name.count
print(pathlen)
print(name)
print(s)
if (pathlen < 2) {
pathlen = 2
}
let path = (s as NSString).substring(with: NSMakeRange(len + 1, pathlen - 2))
let folderName = NSURL(fileURLWithPath: path).lastPathComponent!
let fl = path.count
let pfl = fl - folderName.count
print("\(folderName) \(pfl)")
let fpath = s.substringLeft(pfl)
let i = MediaItem(name: folderName, path: fpath, root: items.root, type: ItemType.PICS)
i.thumbUrl = "\(s)?preview=true"
if !name.hasPrefix(".") {
im.append(i)
}
}
}
result(im)
}
}
}
func downloadToServer(path: String, url: URL) {
let name = path + "/" + url.lastPathComponent
let queryItems = [URLQueryItem(name: "url", value: url.absoluteString), URLQueryItem(name: "name", value: name)]
let cmd: String
if url.pathExtension == "m3u8" {
cmd = "ffmpeg"
}
else {
cmd = "webdl"
}
var urlComps = URLComponents(string: nodeurl + cmd)!
urlComps.queryItems = queryItems
let p = urlComps.url!
print("ffmpeg \(url.lastPathComponent)")
AF.request(p).responseString { response in
print(response)
}
}
func download(url: URL, path: String, result: @escaping (URL) -> () ) {
UIApplication.shared.isIdleTimerDisabled = true
let destination: DownloadRequest.Destination = {temporaryURL, response in
if let suggestedFileName = response.suggestedFilename {
do {
let directory = try FileHelper.createDir(name: path)
let downloadedFilePath = directory.appendingPathComponent(suggestedFileName)
// if downloadedFilePath.exists { try self.downloadedFilePath?.deleteFile() }
return (downloadedFilePath, [.removePreviousFile, .createIntermediateDirectories])
} catch let e {
print("Failed to get temporary directory - \(e)")
}
}
let (downloadedFileURL, _) = DownloadRequest.suggestedDownloadDestination()(temporaryURL, response)
return (downloadedFileURL, [.removePreviousFile, .createIntermediateDirectories])
}
let request = AF.download(url, to: destination)
request.downloadProgress(queue: .main, closure: { (progress) in
let name = url.lastPathComponent
var dl = NetworkManager.sharedInstance.currentDownloads[name]
if dl == nil && !request.isCancelled {
dl = MediaItem(name: name, path: name, root: "", type: ItemType.DOWNLOAD)
NetworkManager.sharedInstance.currentDownloads[name] = dl
}
if (dl!.cancelled) {
request.cancel()
NetworkManager.sharedInstance.currentDownloads.removeValue(forKey: name)
}
dl!.length = progress.fractionCompleted
//progress closure
print(progress.fractionCompleted)
}).responseData { response in
if let destinationUrl = response.fileURL {
print(destinationUrl)
if let statusCode = (response as? HTTPURLResponse)?.statusCode {
NetworkManager.sharedInstance.currentDownloads.removeValue(forKey: url.lastPathComponent)
print("Success: \(statusCode)")
}
result(destinationUrl)
}
}
}
}