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.
 
 
 

479 lines
17 KiB

//
// Created by Marco Schmickler on 04.06.15.
// Copyright (c) 2015 Marco Schmickler. All rights reserved.
//
import Foundation
import Nimbus
import Alamofire
class MediaPhotoController: NIToolbarPhotoViewController, NIPhotoAlbumScrollViewDataSource, NIPhotoScrubberViewDataSource, NSURLSessionDelegate {
var items = [MediaItem]()
var completionHandler: ((Void) -> Void)?
var requests = Array<ImageLoadOperation>()
var imageCache = NSCache()
var total = 0
var slide = 0
var timer: NSTimer?
var currentIndex = 100
var urlSession: NSURLSession?
var sessionOwner = false
let dateFormatter = NSDateFormatter()
lazy var operationQueue: NSOperationQueue = {
var queue = NSOperationQueue()
queue.name = "Photo queue"
queue.maxConcurrentOperationCount = 3
return queue
}()
override func viewDidDisappear(animated: Bool) {
operationQueue.cancelAllOperations()
}
public func URLSession(session: NSURLSession, didBecomeInvalidWithError error: NSError?) {
print(error)
}
override func viewDidLoad() {
super.viewDidLoad()
if urlSession == nil {
sessionOwner = true
let configuration = NSURLSessionConfiguration.ephemeralSessionConfiguration(); // backgroundSessionConfigurationWithIdentifier("imageLoad");
configuration.HTTPMaximumConnectionsPerHost = 10;
configuration.timeoutIntervalForRequest = 100;
configuration.timeoutIntervalForResource = 200;
urlSession = NSURLSession(configuration: configuration, delegate: self, delegateQueue: nil);
}
imageCache.totalCostLimit = 1024 * 1024 * 1024
let backButton = UIBarButtonItem(barButtonSystemItem: .Cancel, target: self, action: Selector("back"))
let slideButton = UIBarButtonItem(barButtonSystemItem: .FastForward, target: self, action: Selector("slideShow"))
navigationItem.leftBarButtonItems = [backButton, slideButton]
let playButton = UIBarButtonItem(barButtonSystemItem: .Play, target: self, action: Selector("play"))
let shotButton = UIBarButtonItem(barButtonSystemItem: .Camera, target: self, action: Selector("shot"))
navigationItem.rightBarButtonItems = [playButton, shotButton]
setChromeVisibility(true, animated: true)
self.photoAlbumView.reloadData();
preload(0, count: 50)
preload(50, count: 50)
}
func loadData(d: NSData, start: Int, end: Int) {
let bytes = Array(UnsafeBufferPointer(start: UnsafePointer<UInt8>(d.bytes), count: d.length))
let string1 = NSString(data: d, encoding: NSUTF8StringEncoding)
print(string1)
var index = 0
let fHi = (Int(bytes[index++]) << 24) + (Int(bytes[index++]) << 16)
let f = fHi + (Int(bytes[index++]) << 8) + Int(bytes[index++])
// let f = (bytes[index++] << 24)+(bytes[index++] << 16)+(bytes[index++] << 8) + bytes[index++]
let time = dateFormatter.stringFromDate(NSDate())
print("\(time) start \(start) count \(f) size \(d.length)")
var rest = self.items.count - self.currentIndex
if rest > 50 {
rest = 50
}
if rest > 0 {
self.preload(self.currentIndex, count: rest)
self.currentIndex += rest
} else {
dispatch_async(dispatch_get_main_queue(), {
() -> Void in
self.photoScrubberView.reloadData();
})
}
for var bild = start; bild < end; bild++ {
let sizeHi = (Int(bytes[index++]) << 24) + (Int(bytes[index++]) << 16)
let size = (Int(bytes[index++]) << 8) + Int(bytes[index++]) + sizeHi
if size > 0 {
// var buf = //UnsafeMutablePointer<UInt8>(&bytes[index])
let part = d.subdataWithRange(NSMakeRange(index, size))
if let img = UIImage(data: part) {
let imageRef = img.CGImage;
let bytesPerPixel = CGImageGetBitsPerPixel(imageRef) / 8;
let cost = CGImageGetWidth(imageRef) * CGImageGetHeight(imageRef) * bytesPerPixel;
self.total += d.length
let i = self.items[bild]
// print("\(time) preload combi image loaded \(i.name) cost \(cost) total\(self.total)")
self.imageCache.setObject(img, forKey: i.thumbUrlAbsolute, cost: size)
}
}
index += size
}
}
func preload(start: Int, count: Int) {
dateFormatter.dateFormat = "HH:mm:ss.SSSZ"
var preview = ""
var end = start + count
if end > items.count {
end = items.count
}
for var k = start; k < end; k++ {
let tu = items[k].thumbUrl!.stringByReplacingOccurrencesOfString("?preview=true", withString: "")
preview += "\(tu);"
}
preview = preview.stringByAddingPercentEscapesUsingEncoding(NSISOLatin1StringEncoding)!
let u2 = "\(NetworkManager.sharedInstance.baseurl)/service/preload?preview=\(preview)"
let u3 = NSURL(string: u2)
if let URL = u3 {
let time = dateFormatter.stringFromDate(NSDate())
print("\(time) preload image \(u2)")
urlSession!.dataTaskWithURL(URL) {
(da, response, error) in
if let d = da {
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_HIGH, 0)) {
() -> Void in
self.loadData(d, start: start, end: end)
}
}
}.resume()
// op1.qualityOfService = NSQualityOfService.Background
// backgroundOperationQueue.addOperation(op1)
} else {
print("## Invalid URL: \(u2)")
}
}
override func didReceiveMemoryWarning() {
print("warning")
imageCache.removeAllObjects()
super.didReceiveMemoryWarning()
}
func shot() {
let currentItem = items[photoAlbumView.centerPageIndex]
var imageUrl = currentItem.thumbUrl!.stringByReplacingOccurrencesOfString("_thumb.jpg", withString: ".jpg")
imageUrl = imageUrl.stringByReplacingOccurrencesOfString("?preview=true", withString: "")
let url = NetworkManager.sharedInstance.baseurl + "/service/linkfavpic" + imageUrl
print(url)
Alamofire.request(.GET, url).responseString {
(_, _, string) in
print("ok")
}
}
func back() {
imageCache.removeAllObjects()
operationQueue.cancelAllOperations()
if sessionOwner {
urlSession!.invalidateAndCancel()
}
completionHandler!()
}
func slideShow() {
if (++slide > 2) {
slide = 0
}
if timer == nil {
showItem()
}
}
func showItem() {
var nextItem = photoAlbumView.centerPageIndex + 1
if (nextItem >= (items).count) {
nextItem = 0
}
photoAlbumView.moveToPageAtIndex(nextItem, animated: false);
photoScrubberView.setSelectedPhotoIndex(nextItem, animated: true)
if (slide > 0) {
timer = NSTimer.scheduledTimerWithTimeInterval(Double(slide) / 2.0, target: self, selector: Selector("showItem"), userInfo: nil, repeats: false)
} else {
timer = nil
}
}
func play() {
let currentItem = items[photoAlbumView.centerPageIndex]
if (currentItem.type == ItemType.PICS) {
let items = currentItem
let len = items.root.characters.count
let url = NetworkManager.sharedInstance.baseurl + "/service/listfiles" + items.root + "/" + items.path + "/" + items.name
print(items)
print(url)
Alamofire.request(.GET, url).responseJSON {
(request, response, result) in
var im = [MediaItem]()
if let json = result.value {
for s in json as! [String] {
if s.hasSuffix(".jpg") {
let l = s.length
let name = NSURL(fileURLWithPath: s).lastPathComponent!
var pathlen = l - len - name.length
// if (pathlen > 1000) {
print(pathlen)
print(name)
print(s)
// }
if (pathlen < 2) {
pathlen = 2
}
let path = (s as NSString).substringWithRange(NSMakeRange(len + 1, pathlen - 2))
let folderName = NSURL(fileURLWithPath: path).lastPathComponent!
let fl = path.length
let pfl = fl - folderName.length
print("\(folderName) \(pfl)")
let fpath = (s as NSString).substringWithRange(NSMakeRange(0, 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)
}
}
}
let pc = MediaPhotoController()
pc.urlSession = self.urlSession!
pc.items = im
pc.completionHandler = {
self.dismissViewControllerAnimated(true, completion: nil);
}
let navController = UINavigationController(rootViewController: pc) // Creating a navigation controller with pc at the root of the navigation stack.
self.presentViewController(navController, animated: false, completion: nil)
}
}
return
}
let controller = VideoPlayerController()
controller.edit = false
controller.allowEdit = false
controller.currentItem = currentItem
controller.navigationItem.leftItemsSupplementBackButton = true
navigationController!.navigationBar.barTintColor = UIColor.blackColor()
navigationController!.pushViewController(controller, animated: true)
controller.completionHandler = {
() in
// NetworkManager.sharedInstance.saveItem(self.currentItem!)
self.dismissViewControllerAnimated(true, completion: nil);
}
}
override func loadView() {
super.loadView()
photoAlbumView.dataSource = self
photoScrubberView.dataSource = self
toolbarIsTranslucent = true
hidesChromeWhenScrolling = true
chromeCanBeHidden = true
scrubberIsEnabled = true
// Toolbar Setup
let bounds = self.view.bounds;
let toolbarHeight = CGFloat(120.0)
toolbar.frame = CGRectMake(0, bounds.size.height - toolbarHeight, bounds.size.width, toolbarHeight);
photoAlbumView.zoomingAboveOriginalSizeIsEnabled = true;
// This title will be displayed until we get the results back for the album information.
self.title = "loading"
// self.photoAlbumView.loadingImage = UIImage(named: "Kirschkeks-256x256.png")
print("\(items.count)")
}
func photoAlbumScrollView(photoAlbumScrollView: NIPhotoAlbumScrollView!, photoAtIndex: Int, photoSize: UnsafeMutablePointer<NIPhotoScrollViewPhotoSize>,
isLoading: UnsafeMutablePointer<ObjCBool>, originalPhotoDimensions: UnsafeMutablePointer<CGSize>) -> UIImage! {
let newItem = items[photoAtIndex]
let u1 = NSURL(string: newItem.imageUrlAbsolute)
let u2 = NSURL(string: newItem.thumbUrlAbsolute)
if let hqURL = u1, URL = u2 {
var image: UIImage? = nil
var size = NIPhotoScrollViewPhotoSizeUnknown
for r in requests {
let pages = self.photoAlbumView.visiblePages() as NSMutableSet!
var ok = false
for page in pages.allObjects {
if (page.pageIndex == r.index) {
ok = true
break
}
}
if !ok {
r.cancel()
requests.removeAtIndex(requests.indexOf(r)!)
}
}
image = imageCache.objectForKey(URL.absoluteString) as? UIImage
if image != nil {
size = NIPhotoScrollViewPhotoSizeThumbnail
isLoading[0] = false
} else {
let URL = NSURL(string: newItem.thumbUrlAbsolute)!
let op3 = DataLoadOperation(imageURL: URL, succeeder: {
d in
if d.length > 0 {
if let i = UIImage(data: d) {
// println("thumb preload image loaded \(newItem.imageUrlAbsolute)")
let imageRef = i.CGImage;
let bytesPerPixel = CGImageGetBitsPerPixel(imageRef) / 8;
let cost = CGImageGetWidth(imageRef) * CGImageGetHeight(imageRef) * bytesPerPixel;
self.imageCache.setObject(d, forKey: newItem.thumbUrlAbsolute, cost: d.length)
size = NIPhotoScrollViewPhotoSizeThumbnail
self.photoAlbumView.didLoadPhoto(i, atIndex: photoAtIndex, photoSize: size)
self.photoScrubberView.didLoadThumbnail(i, atIndex: photoAtIndex);
}
}
}, index: photoAtIndex, session: urlSession!)
op3.qualityOfService = NSQualityOfService.UserInteractive
operationQueue.addOperation(op3)
}
let op2 = ImageLoadOperation(imageURL: hqURL, succeeder: {
i in
// println("image loaded \(newItem.imageUrlAbsolute) at \(photoAtIndex)")
size = NIPhotoScrollViewPhotoSizeOriginal
self.photoAlbumView.didLoadPhoto(i, atIndex: photoAtIndex, photoSize: size)
photoSize[0] = size
}, index: photoAtIndex)
op2.qualityOfService = NSQualityOfService.UserInitiated
requests.append(op2)
operationQueue.addOperation(op2)
if (image == nil) {
isLoading[0] = true
}
photoSize[0] = size
return image
} else {
print("## Invalid URL: \(newItem.imageUrlAbsolute)")
return nil
}
}
func numberOfPagesInPagingScrollView(pagingScrollView: NIPagingScrollView) -> Int {
let c = items.count
return c
}
/**
* Fetches a page that will be displayed at the given page index.
*
* You should always try to reuse pages by calling dequeueReusablePageWithIdentifier: on the
* paging scroll view before allocating a new page.
*/
func pagingScrollView(pagingScrollView: NIPagingScrollView, pageViewForIndex: Int) -> UIView {
let view = photoAlbumView.pagingScrollView(pagingScrollView, pageViewForIndex: pageViewForIndex) as! NIPhotoScrollView
view.maximumScale = 3;
return view;
}
func numberOfPhotosInScrubberView(photoScrubberView: NIPhotoScrubberView!) -> Int {
let c = items.count
return c
}
/**
* Fetch the thumbnail image for the given photo index.
*
* Please read and understand the performance considerations for this data source.
*/
func photoScrubberView(photoScrubberView: NIPhotoScrubberView!, thumbnailAtIndex thumbnailIndex: Int) -> UIImage! {
if thumbnailIndex < 0 {
return nil
}
var image: UIImage?
let newItem = items[thumbnailIndex]
let u1 = NSURL(string: newItem.thumbUrlAbsolute)
if let URL = u1 {
image = imageCache.objectForKey(URL.absoluteString) as? UIImage
if (image == nil) {
urlSession!.dataTaskWithURL(URL) {
(da, response, error) in
if let d = da {
if let i = UIImage(data: d) {
// println("thumb image loaded \(newItem.thumbUrlAbsolute)")
let imageRef = i.CGImage;
let bytesPerPixel = CGImageGetBitsPerPixel(imageRef) / 8;
let cost = CGImageGetWidth(imageRef) * CGImageGetHeight(imageRef) * bytesPerPixel;
self.imageCache.setObject(i, forKey: newItem.thumbUrlAbsolute, cost: d.length)
self.photoScrubberView.didLoadThumbnail(i, atIndex: thumbnailIndex);
}
}
}
}
}
else {
print("## Invalid URL: \(newItem.thumbUrlAbsolute)")
}
return image
}
}