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
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
|
|
}
|
|
}
|
|
|