From d7ea7d91a1fdf0890a736384d3243649b5e1ba7b Mon Sep 17 00:00:00 2001 From: Sam Bias Ferrar Date: Mon, 10 Dec 2018 13:58:18 +0000 Subject: [PATCH] Amz sig v4, subtitles, image frame --- README.md | 92 ++++++- TestVzaar.xcodeproj/project.pbxproj | 22 +- .../xcshareddata/IDEWorkspaceChecks.plist | 8 + TestVzaar/AppDelegate.swift | 11 +- .../AppIcon.appiconset/Contents.json | 5 + TestVzaar/Base.lproj/Main.storyboard | 190 +++++++++++++- TestVzaar/CreateSubtitleViewController.swift | 207 +++++++++++++++ TestVzaar/Info.plist | 9 +- TestVzaar/PosterViewController.swift | 168 ++++++++++++ TestVzaar/SubtitlesViewController.swift | 160 ++++++++++++ TestVzaar/VideoTableViewCell.swift | 22 ++ TestVzaar/VideoTableViewCell.xib | 44 +++- TestVzaar/VideosViewController.swift | 109 +++++++- Vzaar.xcodeproj/project.pbxproj | 44 ++++ Vzaar/AWS.swift | 105 ++++++-- Vzaar/Info.plist | 2 + Vzaar/Vzaar.swift | 239 ++++++++++++++++++ Vzaar/VzaarDeleteSubtitleParameters.swift | 35 +++ Vzaar/VzaarGetSubtitlesParameters.swift | 32 +++ ...aarMultiPartVideoSignatureParameters.swift | 2 +- Vzaar/VzaarParser.swift | 31 +++ Vzaar/VzaarPostSubtitlesParameters.swift | 63 +++++ Vzaar/VzaarRequestParameters.swift | 84 ++++++ Vzaar/VzaarSignature.swift | 21 +- ...arSinglePartVideoSignatureParameters.swift | 2 +- Vzaar/VzaarSubtitle.swift | 44 ++++ Vzaar/VzaarUpdateImageFrameParameters.swift | 42 +++ Vzaar/VzaarUpdateSubtitleParameters.swift | 65 +++++ Vzaar/VzaarUploadImageFrameParameters.swift | 48 ++++ Vzaar/VzaarVideo.swift | 18 +- file.srt | 7 + 31 files changed, 1869 insertions(+), 62 deletions(-) create mode 100644 TestVzaar.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist create mode 100644 TestVzaar/CreateSubtitleViewController.swift create mode 100644 TestVzaar/PosterViewController.swift create mode 100644 TestVzaar/SubtitlesViewController.swift create mode 100644 Vzaar/VzaarDeleteSubtitleParameters.swift create mode 100644 Vzaar/VzaarGetSubtitlesParameters.swift create mode 100644 Vzaar/VzaarPostSubtitlesParameters.swift create mode 100644 Vzaar/VzaarSubtitle.swift create mode 100644 Vzaar/VzaarUpdateImageFrameParameters.swift create mode 100644 Vzaar/VzaarUpdateSubtitleParameters.swift create mode 100644 Vzaar/VzaarUploadImageFrameParameters.swift create mode 100644 file.srt diff --git a/README.md b/README.md index 68e87f9..46cdd3f 100644 --- a/README.md +++ b/README.md @@ -6,7 +6,7 @@ Video Hosting For Business. * It allows your customers to upload their own videos via the vzaar API. * Pull information from vzaar databases and combine them with your app's own data. * For instance sync your product catalogue with your videos so that videos always appear on the right product page. -* Version 1.0.4 +* Version 1.1.0 ## Documentation ## @@ -62,6 +62,7 @@ vzaarGetVideosParameters.per_page = 50 Vzaar.sharedInstance().getVideos(vzaarGetVideosParameters: vzaarGetVideosParameters, success: { (vzaarVideos) in self.videos = vzaarVideos +//Handle UI response in Main Thread self.tableView.reloadData() }, failure: { (vzaarError) in @@ -512,6 +513,95 @@ print(vzaarError) print(error) } ``` +## IMAGE FRAME ## +### Set Image Frame ### + +``` +#!swift +let params = VzaarUpdateImageFrameParameters(id: Int32(videoId)) +Vzaar.sharedInstance().updateImageFrame(vzaarUpdateImageFrameParameters: params, success: { (vzaarVideo) in + +//Handle video from response + +}, failure: { (vzaarError) in +print(vzaarError) +}) { (error) in +print(error) +} +``` +### Upload Image Frame ### +``` +let params = VzaarUploadImageFrameParameters(id: Int32(self.videoId), image: image) +Vzaar.sharedInstance().uploadImageFrame(vzaarUploadImageFrameParameters: params, success: { (vzaarVideo) in + +//Handle video from response + +}, failure: { (vzaarError) in +print(vzaarError) +}) { (error) in +print(error) +} +``` + +## SUBTITLES ## +### Get Subtitles ### + +``` +let params = VzaarGetSubtitlesParameters(id: videoId) +Vzaar.sharedInstance().getSubtitles(vzaarGetSubtitlesParameters: params, success: { (vzaarSubtitles) in + +//Handle subtitles array + +}, failure: { (vzaarError) in +print(vzaarError) +}) { (error) in +print(error) +} +``` +### Create Subtitle ### +``` +let params = VzaarPostSubtitlesParameters(id: videoId) +params.code = languageCode //example: en , fr, de etc... +params.content = subtitlesContent //You can use either content or file parameter to create a Subtitle. File parameter is the fullPath to the subtitles file. +Vzaar.sharedInstance().createSubtitle(vzaarPostSubtitlesParameters: params, success: { (vzaarSubtitle) in + +//Handle subtitle from response + +}, failure: { (vzaarError) in +print(vzaarError) +}) { (error) in +print(error) +} +``` +### Update Subtitle ### +``` +let params = VzaarUpdateSubtitleParameters(id: videoId, subtitle: Int32(subtitleId)) +params.code = languageCode //example: en , fr, de etc... +params.content = subtitlesContent //You can use either content or file parameter to create a Subtitle. File parameter is the fullPath to the subtitles file. +Vzaar.sharedInstance().updateSubtitle(vzaarUpdateSubtitleParameters: params, success: { (vzaarSubtitle) in + +//Handle subtitle from response + +}, failure: { (vzaarError) in +print(vzaarError) +}) { (error) in +print(error) +} +``` +### Delete Subtitle ### +``` +let params = VzaarDeleteSubtitlesParameters(id: videoId, subtitle: Int32(subtitleId)) +Vzaar.sharedInstance().deleteSubtitle(vzaarDeleteSubtitlesParameters: params, success: { + +//Handle UI subtitle removal + +}, failure: { (vzaarError) in +print(vzaarError) +}) { (error) in +print(error) +} +``` + ### How do I get set up for an Objective-c project ### * If your project is in objective-c you have to use the specific version of the pod '1.0.1-objc' to access the classes and properties through the bridge headers. diff --git a/TestVzaar.xcodeproj/project.pbxproj b/TestVzaar.xcodeproj/project.pbxproj index 3f70e08..97190f8 100644 --- a/TestVzaar.xcodeproj/project.pbxproj +++ b/TestVzaar.xcodeproj/project.pbxproj @@ -20,6 +20,9 @@ 28254FD11ED87FDC00683656 /* PlaylistsViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 28254FD01ED87FDC00683656 /* PlaylistsViewController.swift */; }; 28254FD41ED8807D00683656 /* PlaylistTableViewCell.swift in Sources */ = {isa = PBXBuildFile; fileRef = 28254FD21ED8807D00683656 /* PlaylistTableViewCell.swift */; }; 28254FD51ED8807D00683656 /* PlaylistTableViewCell.xib in Resources */ = {isa = PBXBuildFile; fileRef = 28254FD31ED8807D00683656 /* PlaylistTableViewCell.xib */; }; + 283E942121B697E900F02E6F /* CreateSubtitleViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 283E942021B697E900F02E6F /* CreateSubtitleViewController.swift */; }; + 283E942A21B6D6F300F02E6F /* file.srt in Resources */ = {isa = PBXBuildFile; fileRef = 283E942921B6D6F200F02E6F /* file.srt */; }; + 286B000821B5484F00C34DBC /* PosterViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 286B000721B5484F00C34DBC /* PosterViewController.swift */; }; 287676C21E64810400E675BE /* AppDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = 287676C11E64810400E675BE /* AppDelegate.swift */; }; 287676C41E64810400E675BE /* VideosViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 287676C31E64810400E675BE /* VideosViewController.swift */; }; 287676C71E64810400E675BE /* Main.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 287676C51E64810400E675BE /* Main.storyboard */; }; @@ -30,6 +33,7 @@ 2882AD2E1ED589B60088F7E4 /* VideoTableViewCell.swift in Sources */ = {isa = PBXBuildFile; fileRef = 2882AD2C1ED589B60088F7E4 /* VideoTableViewCell.swift */; }; 2882AD2F1ED589B60088F7E4 /* VideoTableViewCell.xib in Resources */ = {isa = PBXBuildFile; fileRef = 2882AD2D1ED589B60088F7E4 /* VideoTableViewCell.xib */; }; 2882AD341ED5CF9A0088F7E4 /* LoadingView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 2882AD331ED5CF990088F7E4 /* LoadingView.swift */; }; + 28995CD921B58DDB0057EAD6 /* SubtitlesViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 28995CD821B58DDB0057EAD6 /* SubtitlesViewController.swift */; }; 28C2B4641E6978B400226606 /* Vzaar.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 28C2B4611E6977CC00226606 /* Vzaar.framework */; }; 28C2B4651E6978B400226606 /* Vzaar.framework in Embed Frameworks */ = {isa = PBXBuildFile; fileRef = 28C2B4611E6977CC00226606 /* Vzaar.framework */; settings = {ATTRIBUTES = (CodeSignOnCopy, RemoveHeadersOnCopy, ); }; }; 28CCE4761E78459800798834 /* Podfile in Resources */ = {isa = PBXBuildFile; fileRef = 28CCE4751E78459800798834 /* Podfile */; }; @@ -89,6 +93,9 @@ 28254FD01ED87FDC00683656 /* PlaylistsViewController.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = PlaylistsViewController.swift; sourceTree = ""; }; 28254FD21ED8807D00683656 /* PlaylistTableViewCell.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = PlaylistTableViewCell.swift; sourceTree = ""; }; 28254FD31ED8807D00683656 /* PlaylistTableViewCell.xib */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = file.xib; path = PlaylistTableViewCell.xib; sourceTree = ""; }; + 283E942021B697E900F02E6F /* CreateSubtitleViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CreateSubtitleViewController.swift; sourceTree = ""; }; + 283E942921B6D6F200F02E6F /* file.srt */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; path = file.srt; sourceTree = ""; }; + 286B000721B5484F00C34DBC /* PosterViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = PosterViewController.swift; sourceTree = ""; }; 287676BE1E64810400E675BE /* TestVzaar.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = TestVzaar.app; sourceTree = BUILT_PRODUCTS_DIR; }; 287676C11E64810400E675BE /* AppDelegate.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AppDelegate.swift; sourceTree = ""; }; 287676C31E64810400E675BE /* VideosViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = VideosViewController.swift; sourceTree = ""; }; @@ -101,6 +108,7 @@ 2882AD2C1ED589B60088F7E4 /* VideoTableViewCell.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = VideoTableViewCell.swift; sourceTree = ""; }; 2882AD2D1ED589B60088F7E4 /* VideoTableViewCell.xib */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = file.xib; path = VideoTableViewCell.xib; sourceTree = ""; }; 2882AD331ED5CF990088F7E4 /* LoadingView.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = LoadingView.swift; sourceTree = ""; }; + 28995CD821B58DDB0057EAD6 /* SubtitlesViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SubtitlesViewController.swift; sourceTree = ""; }; 28C2B4521E6977CC00226606 /* Vzaar.xcodeproj */ = {isa = PBXFileReference; lastKnownFileType = "wrapper.pb-project"; path = Vzaar.xcodeproj; sourceTree = ""; }; 28CCE4751E78459800798834 /* Podfile */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; path = Podfile; sourceTree = ""; xcLanguageSpecificationIdentifier = xcode.lang.ruby; }; 3CC36D2BAC1FD3C9ED57D320 /* Pods_TestVzaar.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = Pods_TestVzaar.framework; sourceTree = BUILT_PRODUCTS_DIR; }; @@ -157,6 +165,7 @@ 287676B51E64810400E675BE = { isa = PBXGroup; children = ( + 283E942921B6D6F200F02E6F /* file.srt */, 28CCE4751E78459800798834 /* Podfile */, 28C2B4521E6977CC00226606 /* Vzaar.xcodeproj */, 287676C01E64810400E675BE /* TestVzaar */, @@ -199,6 +208,9 @@ 28254FC11ED8637100683656 /* EncodingPresetsViewController.swift */, 28254FD01ED87FDC00683656 /* PlaylistsViewController.swift */, 287E42721EDD64AE0007765F /* AddPlaylistViewController.swift */, + 286B000721B5484F00C34DBC /* PosterViewController.swift */, + 28995CD821B58DDB0057EAD6 /* SubtitlesViewController.swift */, + 283E942021B697E900F02E6F /* CreateSubtitleViewController.swift */, ); name = Controllers; sourceTree = ""; @@ -258,7 +270,7 @@ TargetAttributes = { 287676BD1E64810400E675BE = { CreatedOnToolsVersion = 8.2.1; - DevelopmentTeam = 46QQZDC6KN; + DevelopmentTeam = CWGMHV7Z76; ProvisioningStyle = Automatic; }; }; @@ -316,6 +328,7 @@ 287676CC1E64810400E675BE /* Assets.xcassets in Resources */, 2882AD2F1ED589B60088F7E4 /* VideoTableViewCell.xib in Resources */, 28254FC61ED8643700683656 /* EncodingPresetTableViewCell.xib in Resources */, + 283E942A21B6D6F300F02E6F /* file.srt in Resources */, 287676C71E64810400E675BE /* Main.storyboard in Resources */, 28CCE4761E78459800798834 /* Podfile in Resources */, ); @@ -376,9 +389,12 @@ isa = PBXSourcesBuildPhase; buildActionMask = 2147483647; files = ( + 283E942121B697E900F02E6F /* CreateSubtitleViewController.swift in Sources */, 28254FC21ED8637100683656 /* EncodingPresetsViewController.swift in Sources */, + 286B000821B5484F00C34DBC /* PosterViewController.swift in Sources */, 28254FB71ED84F3000683656 /* IngestRecipesViewController.swift in Sources */, 287676C41E64810400E675BE /* VideosViewController.swift in Sources */, + 28995CD921B58DDB0057EAD6 /* SubtitlesViewController.swift in Sources */, 28254FBB1ED851E400683656 /* IngestRecipeTableViewCell.swift in Sources */, 287676CA1E64810400E675BE /* TestVzaar.xcdatamodeld in Sources */, 287E42731EDD64AE0007765F /* AddPlaylistViewController.swift in Sources */, @@ -525,7 +541,7 @@ buildSettings = { ALWAYS_EMBED_SWIFT_STANDARD_LIBRARIES = YES; ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; - DEVELOPMENT_TEAM = 46QQZDC6KN; + DEVELOPMENT_TEAM = CWGMHV7Z76; FRAMEWORK_SEARCH_PATHS = ( "$(inherited)", "$(PROJECT_DIR)/Vzaar", @@ -549,7 +565,7 @@ buildSettings = { ALWAYS_EMBED_SWIFT_STANDARD_LIBRARIES = YES; ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; - DEVELOPMENT_TEAM = 46QQZDC6KN; + DEVELOPMENT_TEAM = CWGMHV7Z76; FRAMEWORK_SEARCH_PATHS = ( "$(inherited)", "$(PROJECT_DIR)/Vzaar", diff --git a/TestVzaar.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist b/TestVzaar.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist new file mode 100644 index 0000000..18d9810 --- /dev/null +++ b/TestVzaar.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist @@ -0,0 +1,8 @@ + + + + + IDEDidComputeMac32BitWarning + + + diff --git a/TestVzaar/AppDelegate.swift b/TestVzaar/AppDelegate.swift index 73ddb49..8e62fba 100644 --- a/TestVzaar/AppDelegate.swift +++ b/TestVzaar/AppDelegate.swift @@ -8,6 +8,7 @@ import UIKit import CoreData +import Vzaar @UIApplicationMain class AppDelegate: UIResponder, UIApplicationDelegate { @@ -28,14 +29,22 @@ class AppDelegate: UIResponder, UIApplicationDelegate { func applicationDidEnterBackground(_ application: UIApplication) { // Use this method to release shared resources, save user data, invalidate timers, and store enough application state information to restore your application to its current state in case it is terminated later. // If your application supports background execution, this method is called instead of applicationWillTerminate: when the user quits. + + Vzaar.sharedInstance().suspendUploadTask() } func applicationWillEnterForeground(_ application: UIApplication) { // Called as part of the transition from the background to the active state; here you can undo many of the changes made on entering the background. + + + + } func applicationDidBecomeActive(_ application: UIApplication) { // Restart any tasks that were paused (or not yet started) while the application was inactive. If the application was previously in the background, optionally refresh the user interface. + + Vzaar.sharedInstance().resumeUploadTask() } func applicationWillTerminate(_ application: UIApplication) { @@ -43,7 +52,7 @@ class AppDelegate: UIResponder, UIApplicationDelegate { // Saves changes in the application's managed object context before the application terminates. self.saveContext() } - + // MARK: - Core Data stack lazy var persistentContainer: NSPersistentContainer = { diff --git a/TestVzaar/Assets.xcassets/AppIcon.appiconset/Contents.json b/TestVzaar/Assets.xcassets/AppIcon.appiconset/Contents.json index b8236c6..19882d5 100644 --- a/TestVzaar/Assets.xcassets/AppIcon.appiconset/Contents.json +++ b/TestVzaar/Assets.xcassets/AppIcon.appiconset/Contents.json @@ -39,6 +39,11 @@ "idiom" : "iphone", "size" : "60x60", "scale" : "3x" + }, + { + "idiom" : "ios-marketing", + "size" : "1024x1024", + "scale" : "1x" } ], "info" : { diff --git a/TestVzaar/Base.lproj/Main.storyboard b/TestVzaar/Base.lproj/Main.storyboard index 5a2afef..cad613c 100644 --- a/TestVzaar/Base.lproj/Main.storyboard +++ b/TestVzaar/Base.lproj/Main.storyboard @@ -1,11 +1,12 @@ - + - + + @@ -37,12 +38,187 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + @@ -105,7 +281,7 @@ - + @@ -124,7 +300,7 @@ - + @@ -177,7 +353,7 @@ - + @@ -349,7 +525,7 @@ - + @@ -368,7 +544,7 @@ - + diff --git a/TestVzaar/CreateSubtitleViewController.swift b/TestVzaar/CreateSubtitleViewController.swift new file mode 100644 index 0000000..8183578 --- /dev/null +++ b/TestVzaar/CreateSubtitleViewController.swift @@ -0,0 +1,207 @@ +// +// CreateSubtitleViewController.swift +// TestVzaar +// +// Created by Andreas Bagias on 04/12/2018. +// Copyright © 2018 Andreas Bagias. All rights reserved. +// + +import UIKit +import Vzaar + +class CreateSubtitleViewController: UIViewController { + + @IBOutlet weak var codeTextField: UITextField! + @IBOutlet weak var titleTextField: UITextField! + @IBOutlet weak var contentTextView: UITextView! + + var videoId: Int32! + var loadingView: LoadingView! + var subtitle: VzaarSubtitle? + + override func viewDidLoad() { + super.viewDidLoad() + + configureUI() + } + + func configureUI(){ + + if subtitle == nil{ + self.navigationItem.title = "Create Subtitle" + }else{ + self.navigationItem.title = "Update Subtitle" + } + + + contentTextView.layer.borderWidth = 1 + + codeTextField.delegate = self + titleTextField.delegate = self + contentTextView.delegate = self + + if let subtitle = subtitle{ + codeTextField.text = subtitle.code ?? "" + self.navigationItem.rightBarButtonItem = UIBarButtonItem(title: "Update", style: UIBarButtonItemStyle.plain, target: self, action: #selector(updateSubtitleAction)) + }else{ + self.navigationItem.rightBarButtonItem = UIBarButtonItem(title: "Create", style: UIBarButtonItemStyle.plain, target: self, action: #selector(createSubtitleAction)) + } + + + } + + @objc func updateSubtitleAction(){ + + let bundlePath = Bundle.main.path(forResource: "file", ofType: ".srt")! + + let destPath = NSSearchPathForDirectoriesInDomains(.documentDirectory, .userDomainMask, true).first! + + let fullPath = URL(fileURLWithPath: destPath).appendingPathComponent("file.srt") + let fullPathString = fullPath.path + + do{ + try FileManager.default.copyItem(atPath: bundlePath, toPath: fullPathString) + }catch{ + print(error) + } + + guard let subtitle = subtitle else{ return } + + codeTextField.resignFirstResponder() + titleTextField.resignFirstResponder() + contentTextView.resignFirstResponder() + + self.loadingView = LoadingView(frame: CGRect(x: 0, y: 0, width: UIScreen.main.bounds.size.width, height: UIScreen.main.bounds.size.height)) + let window: UIWindow = (UIApplication.shared.delegate?.window!)! + window.addSubview(self.loadingView) + + let params = VzaarUpdateSubtitleParameters(id: videoId, subtitle: Int32(subtitle.id!)) + params.code = codeTextField.text! + if let text = titleTextField.text, text != ""{ + params.title = text + } + if let text = contentTextView.text, text != ""{ + params.content = text + }else{ + params.file = fullPathString + } + + Vzaar.sharedInstance().updateSubtitle(vzaarUpdateSubtitleParameters: params, success: { (vzaarSubtitle) in + + DispatchQueue.main.async { + if self.loadingView != nil { self.loadingView.removeFromSuperview() } + + self.navigationController?.popViewController(animated: true) + + } + + }, failure: { (vzaarError) in + DispatchQueue.main.async { if self.loadingView != nil { self.loadingView.removeFromSuperview() } } + if let vzaarError = vzaarError{ + if let errors = vzaarError.errors{ + print(errors) + VZError.alert(viewController: self, errors: errors) + } + } + }) { (error) in + DispatchQueue.main.async { if self.loadingView != nil { self.loadingView.removeFromSuperview() } } + if let error = error{ + print(error) + } + } + + } + + @objc func createSubtitleAction(){ + + let bundlePath = Bundle.main.path(forResource: "file", ofType: ".srt")! + + let destPath = NSSearchPathForDirectoriesInDomains(.documentDirectory, .userDomainMask, true).first! + + let fullPath = URL(fileURLWithPath: destPath).appendingPathComponent("file.srt") + let fullPathString = fullPath.path + + do{ + try FileManager.default.copyItem(atPath: bundlePath, toPath: fullPathString) + }catch{ + print(error) + } + + + + + + codeTextField.resignFirstResponder() + titleTextField.resignFirstResponder() + contentTextView.resignFirstResponder() + + self.loadingView = LoadingView(frame: CGRect(x: 0, y: 0, width: UIScreen.main.bounds.size.width, height: UIScreen.main.bounds.size.height)) + let window: UIWindow = (UIApplication.shared.delegate?.window!)! + window.addSubview(self.loadingView) + + let params = VzaarPostSubtitlesParameters(id: videoId) + params.code = codeTextField.text! + if let text = titleTextField.text, text != ""{ + params.title = text + } + if let text = contentTextView.text, text != ""{ + params.content = text + }else{ + params.file = fullPathString + } + + + Vzaar.sharedInstance().createSubtitle(vzaarPostSubtitlesParameters: params, success: { (vzaarSubtitle) in + + DispatchQueue.main.async { + if self.loadingView != nil { self.loadingView.removeFromSuperview() } + + self.navigationController?.popViewController(animated: true) + + } + + }, failure: { (vzaarError) in + DispatchQueue.main.async { if self.loadingView != nil { self.loadingView.removeFromSuperview() } } + if let vzaarError = vzaarError{ + if let errors = vzaarError.errors{ + print(errors) + VZError.alert(viewController: self, errors: errors) + } + } + }) { (error) in + DispatchQueue.main.async { if self.loadingView != nil { self.loadingView.removeFromSuperview() } } + if let error = error{ + print(error) + } + } + + } + + override func didReceiveMemoryWarning() { + super.didReceiveMemoryWarning() + // Dispose of any resources that can be recreated. + } + + + /* + // MARK: - Navigation + + // In a storyboard-based application, you will often want to do a little preparation before navigation + override func prepare(for segue: UIStoryboardSegue, sender: Any?) { + // Get the new view controller using segue.destinationViewController. + // Pass the selected object to the new view controller. + } + */ + +} + +extension CreateSubtitleViewController: UITextFieldDelegate, UITextViewDelegate{ + + func textFieldShouldReturn(_ textField: UITextField) -> Bool { + textField.resignFirstResponder() + return true + } + + + +} diff --git a/TestVzaar/Info.plist b/TestVzaar/Info.plist index 9e04e7c..a846eac 100644 --- a/TestVzaar/Info.plist +++ b/TestVzaar/Info.plist @@ -20,21 +20,22 @@ 1 LSRequiresIPhoneOS + NSPhotoLibraryUsageDescription + Please approve to get access to videos UILaunchStoryboardName LaunchScreen UIMainStoryboardFile Main UIRequiredDeviceCapabilities + wifi armv7 - NSPhotoLibraryUsageDescription - Please approve to get access to videos + UIRequiresPersistentWifi + UISupportedInterfaceOrientations UIInterfaceOrientationPortrait - UIInterfaceOrientationLandscapeLeft - UIInterfaceOrientationLandscapeRight diff --git a/TestVzaar/PosterViewController.swift b/TestVzaar/PosterViewController.swift new file mode 100644 index 0000000..582a2bb --- /dev/null +++ b/TestVzaar/PosterViewController.swift @@ -0,0 +1,168 @@ +// +// PosterViewController.swift +// TestVzaar +// +// Created by Andreas Bagias on 03/12/2018. +// Copyright © 2018 Andreas Bagias. All rights reserved. +// + +import UIKit +import Vzaar + +class PosterViewController: UIViewController , UIImagePickerControllerDelegate, UINavigationControllerDelegate{ + + @IBOutlet weak var imageView: UIImageView! + @IBOutlet weak var updateImageFrameButton: UIButton! + @IBOutlet weak var addTimeImageFrameButton: UIButton! + + let imagePickerController = UIImagePickerController() + + var loadingView: LoadingView! + var video: VzaarVideo! + + override func viewDidLoad() { + super.viewDidLoad() + + configureUI() + } + + func configureUI(){ + + self.navigationItem.title = "Image Frame" + + updateImageFrameButton.addTarget(self, action: #selector(updateImageAction), for: UIControlEvents.touchUpInside) + addTimeImageFrameButton.addTarget(self, action: #selector(addTimeImageAction), for: UIControlEvents.touchUpInside) + + let imageGesture = UITapGestureRecognizer(target: self, action: #selector(imageTapped)) + imageView.isUserInteractionEnabled = true + imageView.addGestureRecognizer(imageGesture) + + imagePickerController.delegate = self + + } + + func imageTapped(){ + print("image Tapped") + self.present(imagePickerController, animated: true, completion: nil) + } + + func updateImageAction(sender: UIButton){ + + if let image = imageView.image{ + + let params = VzaarUploadImageFrameParameters(id: Int32(self.video.id!), image: image) + + self.loadingView = LoadingView(frame: CGRect(x: 0, y: 0, width: UIScreen.main.bounds.size.width, height: UIScreen.main.bounds.size.height)) + let window: UIWindow = (UIApplication.shared.delegate?.window!)! + window.addSubview(self.loadingView) + + Vzaar.sharedInstance().uploadImageFrame(vzaarUploadImageFrameParameters: params, success: { (vzaarVideo) in + DispatchQueue.main.async { + if self.loadingView != nil { self.loadingView.removeFromSuperview() } + print(vzaarVideo.asset_url) + print(vzaarVideo.poster_url) + self.navigationController?.popViewController(animated: true) + } + }, failure: { (vzaarError) in + DispatchQueue.main.async { if self.loadingView != nil { self.loadingView.removeFromSuperview() } } + if let vzaarError = vzaarError{ + if let errors = vzaarError.errors{ + print(errors) + VZError.alert(viewController: self, errors: errors) + } + } + }) { (error) in + DispatchQueue.main.async { if self.loadingView != nil { self.loadingView.removeFromSuperview() } } + if let error = error{ + print(error) + } + } + + }else{ + let alert = UIAlertController(title: "No Image", message: "You need to set image", preferredStyle: UIAlertControllerStyle.alert) + alert.addAction(UIAlertAction(title: "OK", style: UIAlertActionStyle.default, handler: nil)) + self.present(alert, animated: true, completion: nil) + } + + + } + + func addTimeImageAction(sender: UIButton){ + + let alertController = UIAlertController(title: "Set Poster Frame", message: "Input time in seconds", preferredStyle: UIAlertControllerStyle.alert) + alertController.addTextField { (textField) in + textField.autocapitalizationType = UITextAutocapitalizationType.words + textField.textAlignment = NSTextAlignment.center + textField.keyboardType = .decimalPad + textField.placeholder = "Time" + } + alertController.addAction(UIAlertAction(title: "OK", style: UIAlertActionStyle.default, handler: { (_) in + + guard let textField = alertController.textFields?.first else { return } + guard let time = Float(textField.text!) else { return } + + let params = VzaarUpdateImageFrameParameters(id: Int32(self.video.id!)) + params.time = time + + self.loadingView = LoadingView(frame: CGRect(x: 0, y: 0, width: UIScreen.main.bounds.size.width, height: UIScreen.main.bounds.size.height)) + let window: UIWindow = (UIApplication.shared.delegate?.window!)! + window.addSubview(self.loadingView) + + Vzaar.sharedInstance().updateImageFrame(vzaarUpdateImageFrameParameters: params, success: { (vzaarVideo) in + DispatchQueue.main.async { + if self.loadingView != nil { self.loadingView.removeFromSuperview() } + print(vzaarVideo.poster_url) + self.navigationController?.popViewController(animated: true) + } + }, failure: { (vzaarError) in + DispatchQueue.main.async { if self.loadingView != nil { self.loadingView.removeFromSuperview() } } + if let vzaarError = vzaarError{ + if let errors = vzaarError.errors{ + print(errors) + VZError.alert(viewController: self, errors: errors) + } + } + }) { (error) in + DispatchQueue.main.async { if self.loadingView != nil { self.loadingView.removeFromSuperview() } } + if let error = error{ + print(error) + } + } + + })) + alertController.addAction(UIAlertAction(title: "Cancel", style: UIAlertActionStyle.cancel, handler: nil)) + self.present(alertController, animated: true, completion: nil) + + } + + func imagePickerController(_ picker: UIImagePickerController, didFinishPickingMediaWithInfo info: [String : Any]) { + + print(info) + + if let image = info[UIImagePickerControllerOriginalImage] as? UIImage{ + + self.imageView.image = image + + } + + picker.dismiss(animated: true, completion: nil) + + } + + override func didReceiveMemoryWarning() { + super.didReceiveMemoryWarning() + // Dispose of any resources that can be recreated. + } + + + /* + // MARK: - Navigation + + // In a storyboard-based application, you will often want to do a little preparation before navigation + override func prepare(for segue: UIStoryboardSegue, sender: Any?) { + // Get the new view controller using segue.destinationViewController. + // Pass the selected object to the new view controller. + } + */ + +} diff --git a/TestVzaar/SubtitlesViewController.swift b/TestVzaar/SubtitlesViewController.swift new file mode 100644 index 0000000..d9aff7e --- /dev/null +++ b/TestVzaar/SubtitlesViewController.swift @@ -0,0 +1,160 @@ +// +// SubtitlesViewController.swift +// TestVzaar +// +// Created by Andreas Bagias on 03/12/2018. +// Copyright © 2018 Andreas Bagias. All rights reserved. +// + +import UIKit +import Vzaar + +class SubtitlesViewController: UIViewController { + + @IBOutlet weak var tableView: UITableView! + var loadingView: LoadingView! + var videoId: Int32! + + var subtitles:[VzaarSubtitle] = [VzaarSubtitle]() + + override func viewDidLoad() { + super.viewDidLoad() + + configureUI() + + getSubtitles() + } + + func configureUI(){ + + self.navigationItem.title = "Subtitles" + + tableView.dataSource = self + tableView.delegate = self + + let createSubtitleButton = UIBarButtonItem(title: "Add", style: UIBarButtonItemStyle.plain, target: self, action: #selector(createSubtitleAction)) + let refreshVideosButton = UIBarButtonItem(barButtonSystemItem: UIBarButtonSystemItem.refresh, target: self, action: #selector(refreshVideosAction)) + self.navigationItem.rightBarButtonItems = [createSubtitleButton, refreshVideosButton] + } + + @objc func refreshVideosAction(){ + getSubtitles() + } + + func getSubtitles(){ + + + + self.loadingView = LoadingView(frame: CGRect(x: 0, y: 0, width: UIScreen.main.bounds.size.width, height: UIScreen.main.bounds.size.height)) + let window: UIWindow = (UIApplication.shared.delegate?.window!)! + window.addSubview(self.loadingView) + + let params = VzaarGetSubtitlesParameters(id: videoId) + + Vzaar.sharedInstance().getSubtitles(vzaarGetSubtitlesParameters: params, success: { (vzaarSubtitles) in + + DispatchQueue.main.async { + if self.loadingView != nil { self.loadingView.removeFromSuperview() } + + self.subtitles = vzaarSubtitles + self.tableView.reloadData() + + } + + }, failure: { (vzaarError) in + DispatchQueue.main.async { if self.loadingView != nil { self.loadingView.removeFromSuperview() } } + if let vzaarError = vzaarError{ + if let errors = vzaarError.errors{ + print(errors) + VZError.alert(viewController: self, errors: errors) + } + } + }) { (error) in + DispatchQueue.main.async { if self.loadingView != nil { self.loadingView.removeFromSuperview() } } + if let error = error{ + print(error) + } + } + } + + @objc func createSubtitleAction(){ + + self.performSegue(withIdentifier: "createSubtitleSegue", sender: nil) + + } + + override func didReceiveMemoryWarning() { + super.didReceiveMemoryWarning() + // Dispose of any resources that can be recreated. + } + + + + // MARK: - Navigation + + // In a storyboard-based application, you will often want to do a little preparation before navigation + override func prepare(for segue: UIStoryboardSegue, sender: Any?) { + + if let destination = segue.destination as? CreateSubtitleViewController{ + destination.videoId = videoId + if let indexPathRow = sender as? Int{ + destination.subtitle = subtitles[indexPathRow] + } + } + } + + +} + +extension SubtitlesViewController: UITableViewDelegate, UITableViewDataSource{ + + func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int { + return subtitles.count + } + + func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell { + + let cell = UITableViewCell() + cell.selectionStyle = .none + cell.textLabel?.text = subtitles[indexPath.row].title + return cell + } + + func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) { + tableView.deselectRow(at: indexPath, animated: false) + + let alertController = UIAlertController(title: nil, message: nil, preferredStyle: UIAlertControllerStyle.actionSheet) + alertController.addAction(UIAlertAction(title: "Delete", style: UIAlertActionStyle.destructive, handler: { (_) in + + let params = VzaarDeleteSubtitlesParameters(id: self.videoId, subtitle: Int32(self.subtitles[indexPath.row].id!)) + + Vzaar.sharedInstance().deleteSubtitle(vzaarDeleteSubtitlesParameters: params, success: { + DispatchQueue.main.async { + self.getSubtitles() + } + }, failure: { (vzaarError) in + DispatchQueue.main.async { if self.loadingView != nil { self.loadingView.removeFromSuperview() } } + if let vzaarError = vzaarError{ + if let errors = vzaarError.errors{ + print(errors) + VZError.alert(viewController: self, errors: errors) + } + } + }) { (error) in + DispatchQueue.main.async { if self.loadingView != nil { self.loadingView.removeFromSuperview() } } + if let error = error{ + print(error) + } + } + + })) + alertController.addAction(UIAlertAction(title: "Update", style: UIAlertActionStyle.default, handler: { (_) in + + self.performSegue(withIdentifier: "createSubtitleSegue", sender: indexPath.row) + + })) + alertController.addAction(UIAlertAction(title: "Cancel", style: UIAlertActionStyle.cancel, handler: nil)) + self.present(alertController, animated: true, completion: nil) + } + +} diff --git a/TestVzaar/VideoTableViewCell.swift b/TestVzaar/VideoTableViewCell.swift index 41a43ce..2beb5d6 100644 --- a/TestVzaar/VideoTableViewCell.swift +++ b/TestVzaar/VideoTableViewCell.swift @@ -11,6 +11,8 @@ import UIKit protocol VideoTableViewCellDelegate { func deleteVideo(videoId: Int) func updateVideo(videoId: Int, currentTitleText: String) + func addPosterButtonAction(videoId: Int) + func subtitlesButtonAction(videoId: Int) } class VideoTableViewCell: UITableViewCell { @@ -20,6 +22,8 @@ class VideoTableViewCell: UITableViewCell { @IBOutlet weak var stateLabel: UILabel! @IBOutlet weak var deleteVideoButton: UIButton! @IBOutlet weak var updateVideoButton: UIButton! + @IBOutlet weak var addPosterButton: UIButton! + @IBOutlet weak var subtitlesButton: UIButton! var delegate: VideoTableViewCellDelegate? @@ -71,6 +75,24 @@ class VideoTableViewCell: UITableViewCell { delegate?.updateVideo(videoId: videoId, currentTitleText: text) } + func setPosterButton(){ + addPosterButton.addTarget(self, action: #selector(addPosterAction), for: UIControlEvents.touchUpInside) + } + + func addPosterAction(sender: UIButton){ + guard let videoId = videoId else { return } + delegate?.addPosterButtonAction(videoId: videoId) + } + + func setSubtitlesButton(){ + subtitlesButton.addTarget(self, action: #selector(subtitlesAction), for: UIControlEvents.touchUpInside) + } + + func subtitlesAction(sender: UIButton){ + guard let videoId = videoId else { return } + delegate?.subtitlesButtonAction(videoId: videoId) + } + override func awakeFromNib() { super.awakeFromNib() // Initialization code diff --git a/TestVzaar/VideoTableViewCell.xib b/TestVzaar/VideoTableViewCell.xib index 044305d..96fe238 100644 --- a/TestVzaar/VideoTableViewCell.xib +++ b/TestVzaar/VideoTableViewCell.xib @@ -1,22 +1,22 @@ - + - + - - + + - + @@ -27,19 +27,19 @@ + + + @@ -65,8 +82,11 @@ + + + + - @@ -74,13 +94,15 @@ + + - + diff --git a/TestVzaar/VideosViewController.swift b/TestVzaar/VideosViewController.swift index 50e7019..f7a4128 100644 --- a/TestVzaar/VideosViewController.swift +++ b/TestVzaar/VideosViewController.swift @@ -35,6 +35,7 @@ class VideosViewController: UIViewController , VzaarUploadProgressDelegate, UITa let refreshVideosButton = UIBarButtonItem(barButtonSystemItem: UIBarButtonSystemItem.refresh, target: self, action: #selector(refreshVideosAction)) self.navigationItem.rightBarButtonItems = [selectVideobutton, refreshVideosButton] + Vzaar.sharedInstance().config = VzaarConfig(clientId: "YOUR_CLIENT_ID", authToken: "YOUR_AUTH_TOKEN") getVideos() @@ -51,8 +52,25 @@ class VideosViewController: UIViewController , VzaarUploadProgressDelegate, UITa } func actionCancelUploadTask(){ - Vzaar.sharedInstance().cancelUploadTask() - if loadingView != nil{ loadingView.removeFromSuperview() } + + Vzaar.sharedInstance().suspendUploadTask() + if self.loadingView != nil{ self.loadingView.isHidden = true } + print("--------SUSPENDED-----------") + + let alertController = UIAlertController(title: "Suspended", message: "The video upload has been suspended. You can resume or cancel the video upload.", preferredStyle: UIAlertControllerStyle.alert) + alertController.addAction(UIAlertAction(title: "Resume", style: UIAlertActionStyle.default, handler: { (alertAction) in + print("--------RESUMED-----------") + Vzaar.sharedInstance().resumeUploadTask() + if self.loadingView != nil{ self.loadingView.isHidden = false } + })) + alertController.addAction(UIAlertAction(title: "Cancel", style: UIAlertActionStyle.destructive, handler: { (alertAction) in + print("--------CANCELED-----------") + Vzaar.sharedInstance().cancelUploadTask() + if self.loadingView != nil{ self.loadingView.removeFromSuperview() } + })) + self.present(alertController, animated: true, completion: nil) + + } func getVideos(state: VzaarGetVideosParametersState){ @@ -153,14 +171,65 @@ class VideosViewController: UIViewController , VzaarUploadProgressDelegate, UITa func uploadVideo(name: String, fileURLWithPath: URL){ - let singlePartVideoSignatureParameters = VzaarSinglePartVideoSignatureParameters() - singlePartVideoSignatureParameters.filename = name - let directory = NSTemporaryDirectory() let lastPathComponent = (fileURLWithPath.absoluteString as NSString).lastPathComponent let fullPath = directory + lastPathComponent let fileURLPath = URL(fileURLWithPath: fullPath) + do{ + + let data = try Data(contentsOf: fileURLPath) + + let filesize = data.count + print("filesize:\(filesize) bytes") + + if filesize > 16777216{ //16779030 + multiPartUpload(name: name, fileURLPath: fileURLPath, filesize: filesize) + }else{ + singlePartUpload(name: name, fileURLPath: fileURLPath) + } + + }catch let error{ + print(error) + } + + } + + private func multiPartUpload(name: String, fileURLPath: URL, filesize: Int){ + + let multipartVideoSignatureParameters = VzaarMultiPartVideoSignatureParameters(filename: name, filesize: Int64(filesize)) + + Vzaar.sharedInstance().uploadVideo(uploadProgressDelegate: self, + multiPartVideoSignatureParameters: multipartVideoSignatureParameters, + fileURLPath: fileURLPath, + success: { (vzaarVideo) in + + DispatchQueue.main.async { + if self.loadingView != nil { self.loadingView.removeFromSuperview() } + } + }, failure: { (vzaarError) in + DispatchQueue.main.async { if self.loadingView != nil { self.loadingView.removeFromSuperview() } } + if let vzaarError = vzaarError{ + if let errors = vzaarError.errors{ + print(errors) + VZError.alert(viewController: self, errors: errors) + } + } + }) { (error) in + DispatchQueue.main.async { if self.loadingView != nil { self.loadingView.removeFromSuperview() } } + if let error = error{ + print(error) + } + } + } + + private func singlePartUpload(name: String, fileURLPath: URL){ + + let singlePartVideoSignatureParameters = VzaarSinglePartVideoSignatureParameters() + singlePartVideoSignatureParameters.filename = name + + + Vzaar.sharedInstance().uploadVideo(uploadProgressDelegate: self, singlePartVideoSignatureParameters: singlePartVideoSignatureParameters, fileURLPath: fileURLPath, @@ -185,6 +254,7 @@ class VideosViewController: UIViewController , VzaarUploadProgressDelegate, UITa print(error) } } + } internal func deleteVideo(videoId: Int) { @@ -271,6 +341,24 @@ class VideosViewController: UIViewController , VzaarUploadProgressDelegate, UITa self.present(alertController, animated: true, completion: nil) } + + internal func addPosterButtonAction(videoId: Int) { + let vid = videosReady.filter { (video) -> Bool in + return video.id == videoId + } + if let video = vid.first{ + performSegue(withIdentifier: "posterSegue", sender: video) + } + } + + internal func subtitlesButtonAction(videoId: Int) { + let vid = videosReady.filter { (video) -> Bool in + return video.id == videoId + } + if let video = vid.first{ + performSegue(withIdentifier: "subtitlesSegue", sender: video) + } + } // MARK - TableView Datasource @@ -312,6 +400,8 @@ class VideosViewController: UIViewController , VzaarUploadProgressDelegate, UITa cell.delegate = self cell.setDeleteButton() cell.setUpdateButton() + cell.setPosterButton() + cell.setSubtitlesButton() return cell } @@ -322,6 +412,15 @@ class VideosViewController: UIViewController , VzaarUploadProgressDelegate, UITa // Dispose of any resources that can be recreated. } + override func prepare(for segue: UIStoryboardSegue, sender: Any?) { + + if let destination = segue.destination as? PosterViewController, let video = sender as? VzaarVideo{ + destination.video = video + }else if let destination = segue.destination as? SubtitlesViewController, let video = sender as? VzaarVideo{ + destination.videoId = Int32(video.id!) + } + + } } diff --git a/Vzaar.xcodeproj/project.pbxproj b/Vzaar.xcodeproj/project.pbxproj index 5ae0a41..35e45bf 100644 --- a/Vzaar.xcodeproj/project.pbxproj +++ b/Vzaar.xcodeproj/project.pbxproj @@ -29,6 +29,12 @@ 28254FD91ED8837400683656 /* VzaarGetPlaylistsParameters.swift in Sources */ = {isa = PBXBuildFile; fileRef = 28254FD81ED8837400683656 /* VzaarGetPlaylistsParameters.swift */; }; 28254FDB1ED8856C00683656 /* VzaarCreatePlaylistParameters.swift in Sources */ = {isa = PBXBuildFile; fileRef = 28254FDA1ED8856C00683656 /* VzaarCreatePlaylistParameters.swift */; }; 282C795A1E65D12900E5B3E1 /* VzaarRequestParameters.swift in Sources */ = {isa = PBXBuildFile; fileRef = 282C79591E65D12900E5B3E1 /* VzaarRequestParameters.swift */; }; + 283E941F21B68B1C00F02E6F /* VzaarGetSubtitlesParameters.swift in Sources */ = {isa = PBXBuildFile; fileRef = 283E941E21B68B1C00F02E6F /* VzaarGetSubtitlesParameters.swift */; }; + 283E942421B6A09400F02E6F /* VzaarPostSubtitlesParameters.swift in Sources */ = {isa = PBXBuildFile; fileRef = 283E942321B6A09400F02E6F /* VzaarPostSubtitlesParameters.swift */; }; + 283E942621B6B85C00F02E6F /* VzaarDeleteSubtitleParameters.swift in Sources */ = {isa = PBXBuildFile; fileRef = 283E942521B6B85C00F02E6F /* VzaarDeleteSubtitleParameters.swift */; }; + 283E942821B6C1C800F02E6F /* VzaarUpdateSubtitleParameters.swift in Sources */ = {isa = PBXBuildFile; fileRef = 283E942721B6C1C800F02E6F /* VzaarUpdateSubtitleParameters.swift */; }; + 286B000621B5403400C34DBC /* VzaarUpdateImageFrameParameters.swift in Sources */ = {isa = PBXBuildFile; fileRef = 286B000521B5403400C34DBC /* VzaarUpdateImageFrameParameters.swift */; }; + 286B000B21B5601900C34DBC /* VzaarUploadImageFrameParameters.swift in Sources */ = {isa = PBXBuildFile; fileRef = 286B000A21B5601900C34DBC /* VzaarUploadImageFrameParameters.swift */; }; 2876763E1E647F0600E675BE /* Vzaar.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 287676341E647F0600E675BE /* Vzaar.framework */; }; 287676451E647F0600E675BE /* Vzaar.h in Headers */ = {isa = PBXBuildFile; fileRef = 287676371E647F0600E675BE /* Vzaar.h */; settings = {ATTRIBUTES = (Public, ); }; }; 2876764F1E647F1400E675BE /* Vzaar.swift in Sources */ = {isa = PBXBuildFile; fileRef = 2876764E1E647F1400E675BE /* Vzaar.swift */; }; @@ -37,6 +43,7 @@ 287E42791EDD8C9F0007765F /* VzaarDeletePlaylistParameters.swift in Sources */ = {isa = PBXBuildFile; fileRef = 287E42781EDD8C9F0007765F /* VzaarDeletePlaylistParameters.swift */; }; 287E427B1EDD8D440007765F /* VzaarGetPlaylistParameters.swift in Sources */ = {isa = PBXBuildFile; fileRef = 287E427A1EDD8D440007765F /* VzaarGetPlaylistParameters.swift */; }; 2882AD321ED5C2880088F7E4 /* VzaarGetVideosParameters.swift in Sources */ = {isa = PBXBuildFile; fileRef = 2882AD311ED5C2870088F7E4 /* VzaarGetVideosParameters.swift */; }; + 28995CDC21B58EF70057EAD6 /* VzaarSubtitle.swift in Sources */ = {isa = PBXBuildFile; fileRef = 28995CDB21B58EF70057EAD6 /* VzaarSubtitle.swift */; }; 28C2B3CD1E68262100226606 /* VzaarSinglePartVideoSignatureParameters.swift in Sources */ = {isa = PBXBuildFile; fileRef = 28C2B3CC1E68262100226606 /* VzaarSinglePartVideoSignatureParameters.swift */; }; 28C2B3E51E68500400226606 /* VzaarSignature.swift in Sources */ = {isa = PBXBuildFile; fileRef = 28C2B3E41E68500400226606 /* VzaarSignature.swift */; }; 28C2B41D1E686E7300226606 /* VzaarError.swift in Sources */ = {isa = PBXBuildFile; fileRef = 28C2B41C1E686E7300226606 /* VzaarError.swift */; }; @@ -86,6 +93,12 @@ 28254FD81ED8837400683656 /* VzaarGetPlaylistsParameters.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = VzaarGetPlaylistsParameters.swift; sourceTree = ""; }; 28254FDA1ED8856C00683656 /* VzaarCreatePlaylistParameters.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = VzaarCreatePlaylistParameters.swift; sourceTree = ""; }; 282C79591E65D12900E5B3E1 /* VzaarRequestParameters.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = VzaarRequestParameters.swift; sourceTree = ""; }; + 283E941E21B68B1C00F02E6F /* VzaarGetSubtitlesParameters.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = VzaarGetSubtitlesParameters.swift; sourceTree = ""; }; + 283E942321B6A09400F02E6F /* VzaarPostSubtitlesParameters.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = VzaarPostSubtitlesParameters.swift; sourceTree = ""; }; + 283E942521B6B85C00F02E6F /* VzaarDeleteSubtitleParameters.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = VzaarDeleteSubtitleParameters.swift; sourceTree = ""; }; + 283E942721B6C1C800F02E6F /* VzaarUpdateSubtitleParameters.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = VzaarUpdateSubtitleParameters.swift; sourceTree = ""; }; + 286B000521B5403400C34DBC /* VzaarUpdateImageFrameParameters.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = VzaarUpdateImageFrameParameters.swift; sourceTree = ""; }; + 286B000A21B5601900C34DBC /* VzaarUploadImageFrameParameters.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = VzaarUploadImageFrameParameters.swift; sourceTree = ""; }; 287676341E647F0600E675BE /* Vzaar.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = Vzaar.framework; sourceTree = BUILT_PRODUCTS_DIR; }; 287676371E647F0600E675BE /* Vzaar.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = Vzaar.h; sourceTree = ""; }; 287676381E647F0600E675BE /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; @@ -96,6 +109,7 @@ 287E42781EDD8C9F0007765F /* VzaarDeletePlaylistParameters.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = VzaarDeletePlaylistParameters.swift; sourceTree = ""; }; 287E427A1EDD8D440007765F /* VzaarGetPlaylistParameters.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = VzaarGetPlaylistParameters.swift; sourceTree = ""; }; 2882AD311ED5C2870088F7E4 /* VzaarGetVideosParameters.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = VzaarGetVideosParameters.swift; sourceTree = ""; }; + 28995CDB21B58EF70057EAD6 /* VzaarSubtitle.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = VzaarSubtitle.swift; sourceTree = ""; }; 28C2B3CC1E68262100226606 /* VzaarSinglePartVideoSignatureParameters.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = VzaarSinglePartVideoSignatureParameters.swift; sourceTree = ""; }; 28C2B3E41E68500400226606 /* VzaarSignature.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = VzaarSignature.swift; sourceTree = ""; }; 28C2B41C1E686E7300226606 /* VzaarError.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = VzaarError.swift; sourceTree = ""; }; @@ -131,6 +145,26 @@ /* End PBXFrameworksBuildPhase section */ /* Begin PBXGroup section */ + 283E941D21B68AB300F02E6F /* Subtitles */ = { + isa = PBXGroup; + children = ( + 283E941E21B68B1C00F02E6F /* VzaarGetSubtitlesParameters.swift */, + 283E942321B6A09400F02E6F /* VzaarPostSubtitlesParameters.swift */, + 283E942521B6B85C00F02E6F /* VzaarDeleteSubtitleParameters.swift */, + 283E942721B6C1C800F02E6F /* VzaarUpdateSubtitleParameters.swift */, + ); + name = Subtitles; + sourceTree = ""; + }; + 286B000421B53FFB00C34DBC /* Image Frames */ = { + isa = PBXGroup; + children = ( + 286B000521B5403400C34DBC /* VzaarUpdateImageFrameParameters.swift */, + 286B000A21B5601900C34DBC /* VzaarUploadImageFrameParameters.swift */, + ); + name = "Image Frames"; + sourceTree = ""; + }; 2876762A1E647F0600E675BE = { isa = PBXGroup; children = ( @@ -250,6 +284,7 @@ 28C2B4721E69AC8800226606 /* VzaarLegacyRendition.swift */, 28C2B4A61E6DC8C100226606 /* VzaarIngestRecipe.swift */, 28C2B4A81E6DC9C200226606 /* VzaarEncodingPreset.swift */, + 28995CDB21B58EF70057EAD6 /* VzaarSubtitle.swift */, 28C2B46A1E6986A300226606 /* Meta.swift */, 28C2B46C1E69873F00226606 /* Links.swift */, ); @@ -267,6 +302,8 @@ 287E426D1EDD63340007765F /* Ingest Recipes */, 287E426E1EDD633D0007765F /* Encoding Presets */, 287E426F1EDD63480007765F /* Playlists */, + 286B000421B53FFB00C34DBC /* Image Frames */, + 283E941D21B68AB300F02E6F /* Subtitles */, ); name = Parameters; sourceTree = ""; @@ -385,16 +422,20 @@ buildActionMask = 2147483647; files = ( 28C2B41D1E686E7300226606 /* VzaarError.swift in Sources */, + 286B000621B5403400C34DBC /* VzaarUpdateImageFrameParameters.swift in Sources */, 287E42791EDD8C9F0007765F /* VzaarDeletePlaylistParameters.swift in Sources */, 28254FA81ED734EB00683656 /* VzaarCreateCategoryParameters.swift in Sources */, 28254FDB1ED8856C00683656 /* VzaarCreatePlaylistParameters.swift in Sources */, 28254F961ED6D99300683656 /* VzaarGetVideoParameters.swift in Sources */, + 28995CDC21B58EF70057EAD6 /* VzaarSubtitle.swift in Sources */, 28254FD71ED8812100683656 /* VzaarPlaylist.swift in Sources */, 287E42711EDD63D10007765F /* VzaarCreateLinkUploadParameters.swift in Sources */, + 283E942821B6C1C800F02E6F /* VzaarUpdateSubtitleParameters.swift in Sources */, 28C2B46F1E69A4E200226606 /* VzaarVideo.swift in Sources */, 28C2B4391E6976D100226606 /* VzaarMultiPartVideoSignatureParameters.swift in Sources */, 28254FCD1ED8713000683656 /* VzaarDeleteIngestRecipeParameters.swift in Sources */, 28254F9C1ED723E200683656 /* VzaarUpdateVideoParameters.swift in Sources */, + 283E942421B6A09400F02E6F /* VzaarPostSubtitlesParameters.swift in Sources */, 28254FB51ED84C6700683656 /* VzaarGetIngestRecipeParameters.swift in Sources */, 28C2B4AB1E6EB71D00226606 /* AWS.swift in Sources */, 28C2B3CD1E68262100226606 /* VzaarSinglePartVideoSignatureParameters.swift in Sources */, @@ -407,13 +448,16 @@ 28254FCF1ED87AAC00683656 /* VzaarUpdateIngestRecipeParameters.swift in Sources */, 28254FAB1ED8293C00683656 /* VzaarUpdateCategoryParameters.swift in Sources */, 28C2B4731E69AC8800226606 /* VzaarLegacyRendition.swift in Sources */, + 283E941F21B68B1C00F02E6F /* VzaarGetSubtitlesParameters.swift in Sources */, 28254FBE1ED855B800683656 /* VzaarCreateIngestRecipeParameters.swift in Sources */, 28C2B4711E69A79400226606 /* VzaarRendition.swift in Sources */, + 283E942621B6B85C00F02E6F /* VzaarDeleteSubtitleParameters.swift in Sources */, 28254FAF1ED8394500683656 /* VzaarGetCategoryParameters.swift in Sources */, 28C2B4A71E6DC8C100226606 /* VzaarIngestRecipe.swift in Sources */, 28254FC01ED861E100683656 /* VzaarGetEncodingPresetsParameters.swift in Sources */, 28C2B3E51E68500400226606 /* VzaarSignature.swift in Sources */, 2876764F1E647F1400E675BE /* Vzaar.swift in Sources */, + 286B000B21B5601900C34DBC /* VzaarUploadImageFrameParameters.swift in Sources */, 28C2B4A91E6DC9C200226606 /* VzaarEncodingPreset.swift in Sources */, 28C2B4691E69817A00226606 /* VzaarCategory.swift in Sources */, 28254FC81ED867B300683656 /* VzaarGetEncodingPresetParameters.swift in Sources */, diff --git a/Vzaar/AWS.swift b/Vzaar/AWS.swift index 52cfd22..718ea7c 100644 --- a/Vzaar/AWS.swift +++ b/Vzaar/AWS.swift @@ -17,14 +17,13 @@ class AWS: NSObject, URLSessionDelegate, URLSessionDataDelegate{ static var instance: AWS! var totalBytes:Int64! var bytes:Int64 = 0 + var totalBytesSent:Int64 = 0 var delegate: AWSUploadProgressDelegate! var uploadTask: URLSessionTask! class func sharedInstance()-> AWS { self.instance = (self.instance ?? AWS()) - self.instance.bytes = 0 - self.instance.totalBytes = nil return self.instance } @@ -38,20 +37,35 @@ class AWS: NSObject, URLSessionDelegate, URLSessionDataDelegate{ } } + func suspendUploadTask(){ + if uploadTask != nil { + uploadTask.suspend() + } + } + + func resumeUploadTask(){ + if uploadTask != nil { + uploadTask.resume() + } + } + public func urlSession(_ session: URLSession, task: URLSessionTask, didSendBodyData bytesSent: Int64, totalBytesSent: Int64, totalBytesExpectedToSend: Int64) { + print("bytesSent:\(bytesSent) totalBytesSent:\(totalBytesSent) totalBytesExpectedToSend:\(totalBytesExpectedToSend)") + var total: Int64 = totalBytesExpectedToSend if self.totalBytes != nil { total = self.totalBytes } self.bytes += bytesSent + self.totalBytesSent = totalBytesSent let x = Float(self.bytes)/Float(total) let percentage = Double(round(100*x)/100) if delegate != nil { delegate.awsUploadProgress(progress: percentage) } } - + func postFile(fileURLPath: URL, signature: VzaarSignature, singlePartVideoSignatureParameters: VzaarSinglePartVideoSignatureParameters, @@ -63,6 +77,8 @@ class AWS: NSObject, URLSessionDelegate, URLSessionDataDelegate{ filename = fn } + resetBytesCounters() + postPart(fileURLPath: fileURLPath, signature: signature, part: nil, filename: filename, success: { (data, response) in success(data, response) }) { (error) in @@ -77,6 +93,7 @@ class AWS: NSObject, URLSessionDelegate, URLSessionDataDelegate{ success: @escaping () -> Void, failure: @escaping (_ error:Error?) -> Void){ + resetBytesCounters() self.totalBytes = multiPartVideoSignatureParameters.filesize! postParts(fileURLPath: fileURLPath, signature: signature, multiPartVideoSignatureParameters: multiPartVideoSignatureParameters, success: { @@ -89,17 +106,31 @@ class AWS: NSObject, URLSessionDelegate, URLSessionDataDelegate{ } - func postPart(fileURLPath: URL, + private func resetBytesCounters(){ + self.bytes = 0 + self.totalBytes = nil + self.totalBytesSent = 0 + } + + private func postPart(fileURLPath: URL, signature: VzaarSignature, part: Int?, filename: String?, success: @escaping (_ data: Data?, _ response: URLResponse?) -> Void, failure: @escaping (_ error:Error?) -> Void){ - if let key = signature.key , let policy = signature.policy, let sign = signature.signature, let success_action_status = signature.success_action_status, let acl = signature.acl, let accessKeyId = signature.access_key_id, let upload_hostname = signature.upload_hostname, let bucket = signature.bucket{ + if let key = signature.key , + let policy = signature.policy, + let x_amz_signature = signature.x_amz_signature, + let x_amz_date = signature.x_amz_date, + let x_amz_algorithm = signature.x_amz_algorithm, + let x_amz_credential = signature.x_amz_credential, + let success_action_status = signature.success_action_status, + let acl = signature.acl, + let upload_hostname = signature.upload_hostname, + let bucket = signature.bucket{ let lastPathComponent = fileURLPath.lastPathComponent - let pathExtension = (lastPathComponent as NSString).pathExtension var name = "video_\(Int(Date().timeIntervalSince1970))" @@ -122,14 +153,16 @@ class AWS: NSObject, URLSessionDelegate, URLSessionDataDelegate{ } let videoDictionary = ["key":key.replacingOccurrences(of: "${filename}", with: "\(name)\(keySuffix)"), - "AWSAccessKeyId": accessKeyId, "acl": acl, "policy": policy, "success_action_status": success_action_status, - "signature": sign, + "X-Amz-Algorithm":x_amz_algorithm, + "X-Amz-Credential":x_amz_credential, + "X-Amz-Date":x_amz_date, + "X-Amz-Signature":x_amz_signature, "bucket": bucket, "x-amz-meta-uploader": "iOS-Swift"] - + do{ var data = try Data(contentsOf: fileURLPath) @@ -144,16 +177,11 @@ class AWS: NSObject, URLSessionDelegate, URLSessionDataDelegate{ let session = URLSession(configuration: URLSessionConfiguration.default, delegate: self, delegateQueue: OperationQueue.main) - self.uploadTask = session.uploadTask(with: request as URLRequest, from: nil, completionHandler: { (data, response, error) in - - if error != nil { - failure(error) - }else{ - success(data, response) - } - - }) - uploadTask.resume() + self.tryUploadTask(session: session, request: request, success: { (data, response) in + success(data, response) + }) { (error) in + failure(error) + } }catch let error{ print("Data error : \(error)") @@ -164,7 +192,36 @@ class AWS: NSObject, URLSessionDelegate, URLSessionDataDelegate{ } - func postParts(fileURLPath: URL, + private func tryUploadTask(session: URLSession, + request: NSMutableURLRequest, + success: @escaping (_ data: Data?, _ response: URLResponse?) -> Void, + failure: @escaping (_ error:Error?) -> Void){ + + self.uploadTask = session.uploadTask(with: request as URLRequest, from: nil, completionHandler: { (data, response, error) in + + if error != nil { + + if error.debugDescription.contains("The network connection was lost."){ + + //retry upload and remove the bytes sent in that part if multipart from the counter + self.bytes -= self.totalBytesSent + self.tryUploadTask(session: session, request: request, success: { (data, response) in + success(data, response) + }, failure: { (error) in + failure(error) + }) + }else{ + failure(error) + } + }else{ + success(data, response) + } + + }) + uploadTask.resume() + } + + private func postParts(fileURLPath: URL, signature: VzaarSignature, multiPartVideoSignatureParameters: VzaarMultiPartVideoSignatureParameters, success: @escaping () -> Void, @@ -183,7 +240,7 @@ class AWS: NSObject, URLSessionDelegate, URLSessionDataDelegate{ } - func postPartRecursion(fileURLPath: URL, + private func postPartRecursion(fileURLPath: URL, signature: VzaarSignature, filename: String, part: Int, @@ -216,7 +273,7 @@ class AWS: NSObject, URLSessionDelegate, URLSessionDataDelegate{ } - func partData(data: Data, part: Int, parts: Int, part_size_in_bytes: Int) -> Data{ + private func partData(data: Data, part: Int, parts: Int, part_size_in_bytes: Int) -> Data{ let count = data.count var dataParts = [Data]() @@ -237,11 +294,13 @@ class AWS: NSObject, URLSessionDelegate, URLSessionDataDelegate{ } + print("current part:\(part)") + return dataParts[part] } - func createBody(parameters: [String: String], + private func createBody(parameters: [String: String], boundary: String, data: Data, mimeType: String, diff --git a/Vzaar/Info.plist b/Vzaar/Info.plist index 33543cd..bd6df1e 100644 --- a/Vzaar/Info.plist +++ b/Vzaar/Info.plist @@ -2,6 +2,8 @@ + UIRequiresPersistentWifi + CFBundleDevelopmentRegion en CFBundleExecutable diff --git a/Vzaar/Vzaar.swift b/Vzaar/Vzaar.swift index 08e0cae..2bafb17 100644 --- a/Vzaar/Vzaar.swift +++ b/Vzaar/Vzaar.swift @@ -41,6 +41,20 @@ public class Vzaar: NSObject, AWSUploadProgressDelegate{ } } + public func suspendUploadTask(){ + AWS.sharedInstance().suspendUploadTask() + if sessionDataTask != nil { + sessionDataTask.suspend() + } + } + + public func resumeUploadTask(){ + AWS.sharedInstance().resumeUploadTask() + if sessionDataTask != nil { + sessionDataTask.resume() + } + } + /** * Function that gets one Video from vzaar * @@ -104,6 +118,7 @@ public class Vzaar: NSObject, AWSUploadProgressDelegate{ }else { noResponse(NSError(domain: "com.Vzaar.data.error", code: 405, userInfo: ["Data":"There was a problem with data"]) as Error) } + }, failure: { (vzaarError) in failure(vzaarError) }) { (error) in @@ -1032,6 +1047,230 @@ public class Vzaar: NSObject, AWSUploadProgressDelegate{ } } + /** + * Function that sets image frame + * + * @param vzaarUpdateImageFrameParameters The query parameters for the setting of image frame + * + */ + public func updateImageFrame(vzaarUpdateImageFrameParameters: VzaarUpdateImageFrameParameters, + success: @escaping (_ vzaarVideo:VzaarVideo) -> Void, + failure: @escaping (_ error:VzaarError?) -> Void, + noResponse: @escaping (_ error:Error?) -> Void){ + + guard let config = self.config else { + noResponse(NSError(domain: "com.Vzaar.RequestParameters.error", code: 405, userInfo: ["Request Parameters":"You need to set Vzaar Config Parameters"]) as Error) + return + } + + let request = vzaarUpdateImageFrameParameters.createRequest(withConfig: config) + + performSessionDataTask(withRequest: request, success: { (data, response) in + + if let data = data{ + VzaarParser.getVideo(withData: data, success: { (video) in + success(video) + }, failure: { (message) in + noResponse(NSError(domain: "com.Vzaar.json.error", code: 405, userInfo: ["Invalid Json": message]) as Error) + }) + }else{ + noResponse(NSError(domain: "com.Vzaar.data.error", code: 405, userInfo: ["Data":"There was a problem with data"]) as Error) + } + + }, failure: { (vzaarError) in + failure(vzaarError) + }) { (error) in + noResponse(error) + } + + } + + /** + * + * Function that uploads the image frame + * + * @param image The query parameters for the uploading of image frame + * + */ + public func uploadImageFrame(vzaarUploadImageFrameParameters: VzaarUploadImageFrameParameters, + success: @escaping (_ vzaarVideo:VzaarVideo) -> Void, + failure: @escaping (_ error:VzaarError?) -> Void, + noResponse: @escaping (_ error:Error?) -> Void){ + + guard let config = self.config else { + noResponse(NSError(domain: "com.Vzaar.RequestParameters.error", code: 405, userInfo: ["Request Parameters":"You need to set Vzaar Config Parameters"]) as Error) + return + } + + //let request = vzaarUploadImageFrameParameters.createRequest(withConfig: config) + let request = vzaarUploadImageFrameParameters.createImageRequest(withConfig: config) + + performSessionDataTask(withRequest: request, success: { (data, response) in + + if let data = data{ + VzaarParser.getVideo(withData: data, success: { (video) in + success(video) + }, failure: { (message) in + noResponse(NSError(domain: "com.Vzaar.json.error", code: 405, userInfo: ["Invalid Json": message]) as Error) + }) + }else{ + noResponse(NSError(domain: "com.Vzaar.data.error", code: 405, userInfo: ["Data":"There was a problem with data"]) as Error) + } + + }, failure: { (vzaarError) in + failure(vzaarError) + }) { (error) in + noResponse(error) + } + + } + + /** + * + * Function that get the list of subtitles + * + * @param vzaarUploadImageFrameParameters + * + **/ + public func getSubtitles(vzaarGetSubtitlesParameters: VzaarGetSubtitlesParameters, + success: @escaping (_ vzaarSubtitles:[VzaarSubtitle]) -> Void, + failure: @escaping (_ error:VzaarError?) -> Void, + noResponse: @escaping (_ error:Error?) -> Void){ + + guard let config = self.config else { + noResponse(NSError(domain: "com.Vzaar.RequestParameters.error", code: 405, userInfo: ["Request Parameters":"You need to set Vzaar Config Parameters"]) as Error) + return + } + + let request = vzaarGetSubtitlesParameters.createRequest(withConfig: config) + + performSessionDataTask(withRequest: request, success: { (data, response) in + + if let data = data{ + VzaarParser.getSubtitles(withData: data, success: { (subtitles) in + success(subtitles) + }, failure: { (message) in + noResponse(NSError(domain: "com.Vzaar.json.error", code: 405, userInfo: ["Invalid Json": message]) as Error) + }) + }else{ + noResponse(NSError(domain: "com.Vzaar.data.error", code: 405, userInfo: ["Data":"There was a problem with data"]) as Error) + } + + }, failure: { (vzaarError) in + failure(vzaarError) + }) { (error) in + noResponse(error) + } + + } + + /** + * + * Function to create subtitle + * + * @params vzaarPostSubtitlesParameters + * + */ + public func createSubtitle(vzaarPostSubtitlesParameters: VzaarPostSubtitlesParameters, + success: @escaping (_ vzaarSubtitle:VzaarSubtitle) -> Void, + failure: @escaping (_ error:VzaarError?) -> Void, + noResponse: @escaping (_ error:Error?) -> Void){ + + guard let config = self.config else { + noResponse(NSError(domain: "com.Vzaar.RequestParameters.error", code: 405, userInfo: ["Request Parameters":"You need to set Vzaar Config Parameters"]) as Error) + return + } + + let request = vzaarPostSubtitlesParameters.createRequest(withConfig: config) + + performSessionDataTask(withRequest: request, success: { (data, response) in + + if let data = data{ + VzaarParser.getSubtitle(withData: data, success: { (subtitle) in + success(subtitle) + }, failure: { (message) in + noResponse(NSError(domain: "com.Vzaar.json.error", code: 405, userInfo: ["Invalid Json": message]) as Error) + }) + }else{ + noResponse(NSError(domain: "com.Vzaar.data.error", code: 405, userInfo: ["Data":"There was a problem with data"]) as Error) + } + + }, failure: { (vzaarError) in + failure(vzaarError) + }) { (error) in + noResponse(error) + } + + } + + /** + * + * Function to update subtitle + * + * @params vzaarUpdateSubtitleParameters + * + */ + public func updateSubtitle(vzaarUpdateSubtitleParameters: VzaarUpdateSubtitleParameters, + success: @escaping (_ vzaarSubtitle:VzaarSubtitle) -> Void, + failure: @escaping (_ error:VzaarError?) -> Void, + noResponse: @escaping (_ error:Error?) -> Void){ + + guard let config = self.config else { + noResponse(NSError(domain: "com.Vzaar.RequestParameters.error", code: 405, userInfo: ["Request Parameters":"You need to set Vzaar Config Parameters"]) as Error) + return + } + + let request = vzaarUpdateSubtitleParameters.createRequest(withConfig: config) + + performSessionDataTask(withRequest: request, success: { (data, response) in + + if let data = data{ + VzaarParser.getSubtitle(withData: data, success: { (subtitle) in + success(subtitle) + }, failure: { (message) in + noResponse(NSError(domain: "com.Vzaar.json.error", code: 405, userInfo: ["Invalid Json": message]) as Error) + }) + }else{ + noResponse(NSError(domain: "com.Vzaar.data.error", code: 405, userInfo: ["Data":"There was a problem with data"]) as Error) + } + + }, failure: { (vzaarError) in + failure(vzaarError) + }) { (error) in + noResponse(error) + } + + } + + /** + * + * Function to delete subtitle + * + * @params vzaarDeleteSubtitlesParameters + * + */ + public func deleteSubtitle(vzaarDeleteSubtitlesParameters: VzaarDeleteSubtitlesParameters, + success: @escaping () -> Void, + failure: @escaping (_ error:VzaarError?) -> Void, + noResponse: @escaping (_ error:Error?) -> Void){ + + guard let config = self.config else { + noResponse(NSError(domain: "com.Vzaar.RequestParameters.error", code: 405, userInfo: ["Request Parameters":"You need to set Vzaar Config Parameters"]) as Error) + return + } + + let request = vzaarDeleteSubtitlesParameters.createRequest(withConfig: config) + + performSessionDataTask(withRequest: request, success: { (data, response) in + success() + }, failure: { (vzaarError) in + failure(vzaarError) + }) { (error) in + noResponse(error) + } + + } + func performSessionDataTask(withRequest request:NSMutableURLRequest, success: @escaping (_ data:Data?, _ response:URLResponse?) -> Void, failure: @escaping (_ error:VzaarError?) -> Void, diff --git a/Vzaar/VzaarDeleteSubtitleParameters.swift b/Vzaar/VzaarDeleteSubtitleParameters.swift new file mode 100644 index 0000000..cdb3cda --- /dev/null +++ b/Vzaar/VzaarDeleteSubtitleParameters.swift @@ -0,0 +1,35 @@ +// +// VzaarDeleteSubtitleParameters.swift +// Vzaar +// +// Created by Andreas Bagias on 04/12/2018. +// Copyright © 2018 Andreas Bagias. All rights reserved. +// + +import UIKit + +public class VzaarDeleteSubtitlesParameters: VzaarRequestParameters { + + //Video id - REQUIRED + public var id: Int32? + //Subtitle id - REQUIRED + public var subtitle: Int32? + + override init() { + super.init() + } + + public convenience init(id: Int32, subtitle: Int32) { + self.init() + + self.id = id + self.subtitle = subtitle + super.method = MethodType.delete + super.urlSuffix = "videos/\(id)/subtitles/\(subtitle)" + } + + override func createRequest(withConfig config: VzaarConfig) -> NSMutableURLRequest { + return super.createRequest(withConfig: config) + } + +} diff --git a/Vzaar/VzaarGetSubtitlesParameters.swift b/Vzaar/VzaarGetSubtitlesParameters.swift new file mode 100644 index 0000000..f7fe3f5 --- /dev/null +++ b/Vzaar/VzaarGetSubtitlesParameters.swift @@ -0,0 +1,32 @@ +// +// VzaarGetSubtitlesParameters.swift +// Vzaar +// +// Created by Andreas Bagias on 04/12/2018. +// Copyright © 2018 Andreas Bagias. All rights reserved. +// + +import UIKit + +public class VzaarGetSubtitlesParameters: VzaarRequestParameters { + + //Video id - REQUIRED + public var id: Int32? + + override init() { + super.init() + } + + public convenience init(id: Int32) { + self.init() + + self.id = id + super.method = MethodType.get + super.urlSuffix = "videos/\(id)/subtitles" + } + + override func createRequest(withConfig config: VzaarConfig) -> NSMutableURLRequest { + return super.createRequest(withConfig: config) + } + +} diff --git a/Vzaar/VzaarMultiPartVideoSignatureParameters.swift b/Vzaar/VzaarMultiPartVideoSignatureParameters.swift index 9087b8a..4bead12 100644 --- a/Vzaar/VzaarMultiPartVideoSignatureParameters.swift +++ b/Vzaar/VzaarMultiPartVideoSignatureParameters.swift @@ -33,7 +33,7 @@ public class VzaarMultiPartVideoSignatureParameters: VzaarRequestParameters { super.init() super.method = MethodType.post - super.urlSuffix = "signature/multipart" + super.urlSuffix = "signature/multipart/2" } public convenience init(filename: String, filesize: Int64){ diff --git a/Vzaar/VzaarParser.swift b/Vzaar/VzaarParser.swift index a148ce7..1d1993e 100644 --- a/Vzaar/VzaarParser.swift +++ b/Vzaar/VzaarParser.swift @@ -191,4 +191,35 @@ class VzaarParser: NSObject { failure(error.localizedDescription) } } + + // Subtitles data parser + static func getSubtitles(withData data: Data, success: @escaping (_ subtitles:[VzaarSubtitle]) -> Void, failure: @escaping (_ message: String) -> Void){ + do { + if let json = try JSONSerialization.jsonObject(with: data, options: JSONSerialization.ReadingOptions.allowFragments) as? [String: Any]{ + + if let subtitleArrayDict = json["data"] as? [NSDictionary]{ + var subtitles: [VzaarSubtitle] = [VzaarSubtitle]() + for subtitleDict in subtitleArrayDict{ + subtitles.append(VzaarSubtitle(withDict: subtitleDict)) + } + success(subtitles) + } + + } + } catch let error{ + failure(error.localizedDescription) + } + } + + // Subtitle data parser + static func getSubtitle(withData data: Data, success: @escaping (_ subtitle:VzaarSubtitle) -> Void, failure: @escaping (_ message: String) -> Void){ + do { + if let json = try JSONSerialization.jsonObject(with: data, options: JSONSerialization.ReadingOptions.allowFragments) as? [String: Any]{ + let subtitle: VzaarSubtitle = VzaarSubtitle(withDict: json["data"] as! NSDictionary) + success(subtitle) + } + } catch let error{ + failure(error.localizedDescription) + } + } } diff --git a/Vzaar/VzaarPostSubtitlesParameters.swift b/Vzaar/VzaarPostSubtitlesParameters.swift new file mode 100644 index 0000000..e208e88 --- /dev/null +++ b/Vzaar/VzaarPostSubtitlesParameters.swift @@ -0,0 +1,63 @@ +// +// VzaarPostSubtitlesParameters.swift +// Vzaar +// +// Created by Andreas Bagias on 04/12/2018. +// Copyright © 2018 Andreas Bagias. All rights reserved. +// + +import UIKit + +public class VzaarPostSubtitlesParameters: VzaarRequestParameters { + + //Video id - REQUIRED + public var id: Int32? + //Language code + public var code: String? + //Name for subtitle file + public var title: String? + //Subtitle content + public var content: String? + //Subtitle file path + public var file: String? + + override init() { + super.init() + } + + public convenience init(id: Int32) { + self.init() + + self.id = id + super.method = MethodType.post + super.urlSuffix = "videos/\(id)/subtitles" + } + + func createBodyParameters(){ + var params: [String: Any] = [String: Any]() + + if let code = code{ params["code"] = code } + if let title = title{ params["title"] = title } + if let content = content{ params["content"] = content } + if let file = file{ + + params["file"] = file + + } + + bodyParameters = params + } + + override func createRequest(withConfig config: VzaarConfig) -> NSMutableURLRequest { + createBodyParameters() + + if file == nil{ + return super.createRequest(withConfig: config) + }else{ + return super.createFileRequest(withConfig: config) + } + + } + +} + diff --git a/Vzaar/VzaarRequestParameters.swift b/Vzaar/VzaarRequestParameters.swift index 46700d3..64a0125 100644 --- a/Vzaar/VzaarRequestParameters.swift +++ b/Vzaar/VzaarRequestParameters.swift @@ -65,6 +65,90 @@ public class VzaarRequestParameters: NSObject{ } } + func createFileRequest(withConfig config: VzaarConfig) -> NSMutableURLRequest{ + + let request: NSMutableURLRequest = NSMutableURLRequest() + + request.httpMethod = (method?.rawValue)! + let boundary = "Boundary-\(UUID().uuidString)" + request.setValue("multipart/form-data; boundary=\(boundary)", forHTTPHeaderField: "Content-Type") + request.addValue(config.clientId, forHTTPHeaderField: "X-Client-Id") + request.addValue(config.authToken, forHTTPHeaderField: "X-Auth-Token") + request.url = getURL() + + if let bodyparameters = bodyParameters, let file = bodyparameters["file"] as? String{ + + let url = URL(fileURLWithPath: file) + let fileData = try! Data(contentsOf: url) + + let filename = url.lastPathComponent + + var dictionary: [String: String] = [String: String]() + + if let code = bodyparameters["code"] as? String{ + dictionary["code"] = code + } + if let title = bodyparameters["title"] as? String{ + dictionary["title"] = title + } + + request.httpBody = createBody(parameters: dictionary, boundary: boundary, data: fileData, name: "file", mimeType: "text/plain", filename: filename) + } + + return request + } + + func createImageRequest(withConfig config: VzaarConfig) -> NSMutableURLRequest{ + + let request: NSMutableURLRequest = NSMutableURLRequest() + + request.httpMethod = (method?.rawValue)! + let boundary = "Boundary-\(UUID().uuidString)" + request.setValue("multipart/form-data; boundary=\(boundary)", forHTTPHeaderField: "Content-Type") + request.addValue(config.clientId, forHTTPHeaderField: "X-Client-Id") + request.addValue(config.authToken, forHTTPHeaderField: "X-Auth-Token") + request.url = getURL() + + if let bodyparameters = bodyParameters, let imageData = bodyparameters["image"] as? Data{ + request.httpBody = createBody(parameters: [:], boundary: boundary, data: imageData, name: "image", mimeType: "application/octet-stream", filename: "image.jpg") + } + + return request + } + + private func createBody(parameters: [String: String], + boundary: String, + data: Data, + name: String, + mimeType: String, + filename: String) -> Data { + let body = NSMutableData() + + let boundaryPrefix = "--\(boundary)\r\n" + + for (key, value) in parameters { + body.appendString(boundaryPrefix) + body.appendString("Content-Disposition: form-data; name=\"\(key)\"\r\n") + let valueData = value.data(using: String.Encoding.utf8, allowLossyConversion: false) + if let valueData = valueData{ + body.appendString("Content-Length: \(valueData.count)\r\n\r\n") + + } + body.appendString("\(value)\r\n") + } + + body.appendString(boundaryPrefix) + body.appendString("Content-Disposition: form-data; name=\"\(name)\"; filename=\"\(filename)\"\r\n") + body.appendString("Content-Length: \(data.count)\r\n") + body.appendString("Content-Type: \(mimeType)\r\n\r\n") + body.append(data) + body.appendString("\r\n") + body.appendString("--".appending(boundary.appending("--"))) + + return body as Data + } + + } enum MethodType: String{ diff --git a/Vzaar/VzaarSignature.swift b/Vzaar/VzaarSignature.swift index 71d731f..436d992 100644 --- a/Vzaar/VzaarSignature.swift +++ b/Vzaar/VzaarSignature.swift @@ -14,7 +14,6 @@ public class VzaarSignature: NSObject{ public var key: String? public var acl: String? public var policy: String? - public var signature: String? public var success_action_status: String? public var content_type: String? public var guid: String? @@ -24,6 +23,11 @@ public class VzaarSignature: NSObject{ public var part_size_in_bytes: Int? public var parts: Int? + public var x_amz_credential: String? + public var x_amz_algorithm: String? + public var x_amz_date: String? + public var x_amz_signature: String? + init(withDictionary dict: NSDictionary){ @@ -39,9 +43,6 @@ public class VzaarSignature: NSObject{ if let policy = dict["policy"] as? String{ self.policy = policy } - if let signature = dict["signature"] as? String{ - self.signature = signature - } if let success_action_status = dict["success_action_status"] as? String{ self.success_action_status = success_action_status } @@ -67,6 +68,18 @@ public class VzaarSignature: NSObject{ self.parts = parts } + if let x_amz_credential = dict["x-amz-credential"] as? String{ + self.x_amz_credential = x_amz_credential + } + if let x_amz_algorithm = dict["x-amz-algorithm"] as? String{ + self.x_amz_algorithm = x_amz_algorithm + } + if let x_amz_date = dict["x-amz-date"] as? String{ + self.x_amz_date = x_amz_date + } + if let x_amz_signature = dict["x-amz-signature"] as? String{ + self.x_amz_signature = x_amz_signature + } } diff --git a/Vzaar/VzaarSinglePartVideoSignatureParameters.swift b/Vzaar/VzaarSinglePartVideoSignatureParameters.swift index 15e889a..cba3693 100644 --- a/Vzaar/VzaarSinglePartVideoSignatureParameters.swift +++ b/Vzaar/VzaarSinglePartVideoSignatureParameters.swift @@ -21,7 +21,7 @@ public class VzaarSinglePartVideoSignatureParameters: VzaarRequestParameters { super.init() super.method = MethodType.post - super.urlSuffix = "signature/single" + super.urlSuffix = "signature/single/2" } public convenience init(filename: String, filesize: Int64){ diff --git a/Vzaar/VzaarSubtitle.swift b/Vzaar/VzaarSubtitle.swift new file mode 100644 index 0000000..0e2af7c --- /dev/null +++ b/Vzaar/VzaarSubtitle.swift @@ -0,0 +1,44 @@ +// +// VzaarSubtitle.swift +// Vzaar +// +// Created by Andreas Bagias on 03/12/2018. +// Copyright © 2018 Andreas Bagias. All rights reserved. +// + +import UIKit + +public class VzaarSubtitle: NSObject { + + public var id: Int? + public var code: String? + public var title: String? + public var language: String? + public var created_at: String? + public var updated_at: String? + public var url: String? + + public init(withDict dict: NSDictionary){ + + if let id = dict["id"] as? Int{ + self.id = id + } + if let code = dict["code"] as? String{ + self.code = code + } + if let title = dict["title"] as? String{ + self.title = title + } + if let language = dict["language"] as? String{ + self.language = language + } + if let created_at = dict["created_at"] as? String{ + self.created_at = created_at + } + if let updated_at = dict["updated_at"] as? String{ + self.updated_at = updated_at + } + + } + +} diff --git a/Vzaar/VzaarUpdateImageFrameParameters.swift b/Vzaar/VzaarUpdateImageFrameParameters.swift new file mode 100644 index 0000000..7f277ff --- /dev/null +++ b/Vzaar/VzaarUpdateImageFrameParameters.swift @@ -0,0 +1,42 @@ +// +// VzaarUpdateImageFrameParameters.swift +// Vzaar +// +// Created by Andreas Bagias on 03/12/2018. +// Copyright © 2018 Andreas Bagias. All rights reserved. +// + +import Foundation + +public class VzaarUpdateImageFrameParameters: VzaarRequestParameters { + + //Video id - REQUIRED + public var id: Int32? + //Seconds into video to generate poster frame from + public var time: Float? + + override init() { + super.init() + } + + public convenience init(id: Int32) { + self.init() + + self.id = id + super.method = MethodType.patch + super.urlSuffix = "videos/\(id)/image" + } + + func createBodyParameters(){ + var params: [String: Any] = [String: Any]() + + if let time = time{ params["time"] = time } + + bodyParameters = params + } + + override func createRequest(withConfig config: VzaarConfig) -> NSMutableURLRequest { + createBodyParameters() + return super.createRequest(withConfig: config) + } +} diff --git a/Vzaar/VzaarUpdateSubtitleParameters.swift b/Vzaar/VzaarUpdateSubtitleParameters.swift new file mode 100644 index 0000000..068bcac --- /dev/null +++ b/Vzaar/VzaarUpdateSubtitleParameters.swift @@ -0,0 +1,65 @@ +// +// VzaarUpdateSubtitleParameters.swift +// Vzaar +// +// Created by Andreas Bagias on 04/12/2018. +// Copyright © 2018 Andreas Bagias. All rights reserved. +// + +import UIKit + +public class VzaarUpdateSubtitleParameters: VzaarRequestParameters { + + //Video id - REQUIRED + public var id: Int32? + //Subtitle id - REQUIRED + public var subtitle: Int32? + //Language code + public var code: String? + //Name for subtitle file + public var title: String? + //Subtitle content + public var content: String? + //Subtitle file path + public var file: String? + + override init() { + super.init() + } + + public convenience init(id: Int32, subtitle: Int32) { + self.init() + + self.id = id + self.subtitle = subtitle + super.method = MethodType.patch + super.urlSuffix = "videos/\(id)/subtitles/\(subtitle)" + } + + func createBodyParameters(){ + var params: [String: Any] = [String: Any]() + + if let code = code{ params["code"] = code } + if let title = title{ params["title"] = title } + if let content = content{ params["content"] = content } + if let file = file{ + + params["file"] = file + + } + + bodyParameters = params + } + + override func createRequest(withConfig config: VzaarConfig) -> NSMutableURLRequest { + createBodyParameters() + + if file == nil{ + return super.createRequest(withConfig: config) + }else{ + return super.createFileRequest(withConfig: config) + } + + } + +} diff --git a/Vzaar/VzaarUploadImageFrameParameters.swift b/Vzaar/VzaarUploadImageFrameParameters.swift new file mode 100644 index 0000000..a88e811 --- /dev/null +++ b/Vzaar/VzaarUploadImageFrameParameters.swift @@ -0,0 +1,48 @@ +// +// VzaarUploadImageFrameParameters.swift +// Vzaar +// +// Created by Andreas Bagias on 03/12/2018. +// Copyright © 2018 Andreas Bagias. All rights reserved. +// + +import Foundation + +public class VzaarUploadImageFrameParameters: VzaarRequestParameters { + + //Video id - REQUIRED + public var id: Int32? + //Seconds into video to generate poster frame from + public var image: UIImage? + + override init() { + super.init() + } + + public convenience init(id: Int32, image: UIImage) { + self.init() + + self.id = id + self.image = image + super.method = MethodType.post + super.urlSuffix = "videos/\(id)/image" + } + + func createBodyParameters(){ + var params: [String: Any] = [String: Any]() + + if let image = image{ + if let imageData = UIImageJPEGRepresentation(image, 1){ + params["image"] = imageData + } + } + + + bodyParameters = params + } + + override func createImageRequest(withConfig config: VzaarConfig) -> NSMutableURLRequest { + createBodyParameters() + return super.createImageRequest(withConfig: config) + } +} diff --git a/Vzaar/VzaarVideo.swift b/Vzaar/VzaarVideo.swift index d97e55e..5b11c52 100644 --- a/Vzaar/VzaarVideo.swift +++ b/Vzaar/VzaarVideo.swift @@ -27,6 +27,10 @@ public class VzaarVideo: NSObject{ public var categories: [VzaarCategory]? public var renditions: [VzaarRendition]? public var legacy_renditions: [VzaarLegacyRendition]? + public var account_name: String? //NEW + public var user_login: String? //NEW + public var poster_url: String? //NEW + public var asset_url: String? //NEW public init(withDict dict: NSDictionary){ @@ -94,6 +98,18 @@ public class VzaarVideo: NSObject{ self.legacy_renditions?.append(legacy_rendition) } } - + if let account_name = dict["account_name"] as? String{ + self.account_name = account_name + } + if let user_login = dict["user_login"] as? String{ + self.user_login = user_login + } + if let poster_url = dict["poster_url"] as? String{ + self.poster_url = poster_url + } + if let asset_url = dict["asset_url"] as? String{ + self.asset_url = asset_url + } + } } diff --git a/file.srt b/file.srt new file mode 100644 index 0000000..0c966d9 --- /dev/null +++ b/file.srt @@ -0,0 +1,7 @@ +1 +00:00:00,150 --> 00:00:02,234 +These are subtitles + +2 +00:00:03,234 --> 00:00:04.123 +More subtitles \ No newline at end of file