diff --git a/Assets/Vimeo/Scripts/Config/PlayerSettings.cs b/Assets/Vimeo/Scripts/Config/PlayerSettings.cs index a03ba321..334bc6eb 100644 --- a/Assets/Vimeo/Scripts/Config/PlayerSettings.cs +++ b/Assets/Vimeo/Scripts/Config/PlayerSettings.cs @@ -34,7 +34,6 @@ public class PlayerSettings : VimeoSettings public Depthkit.Depthkit_Clip depthKitClip; #endif public StreamingResolution selectedResolution = StreamingResolution.x2160p_4K; - public string vimeoVideoId; public bool muteAudio = false; public bool autoPlay = true; public int startTime = 0; diff --git a/Assets/Vimeo/Scripts/Config/RecorderSettings.cs b/Assets/Vimeo/Scripts/Config/RecorderSettings.cs index 959b1c64..54cfcd06 100644 --- a/Assets/Vimeo/Scripts/Config/RecorderSettings.cs +++ b/Assets/Vimeo/Scripts/Config/RecorderSettings.cs @@ -82,6 +82,10 @@ public class RecorderSettings : VimeoSettings public RenderTexture renderTextureTarget; + [TextArea(2, 5)] + public string description; + + public bool replaceExisting = false; public VimeoApi.PrivacyModeDisplay privacyMode = VimeoApi.PrivacyModeDisplay.Anyone; public VimeoApi.CommentMode commentMode = VimeoApi.CommentMode.Anyone; public bool enableDownloads = true; @@ -127,6 +131,48 @@ public string ReplaceSpecialChars(string input) return input; } + + public void SetVimeoIdFromName() + { + if (!string.IsNullOrEmpty(videoName)) + { + for (int i = 0; i < vimeoVideos.Count; i++) + { + var video = vimeoVideos[i]; + if (video.GetVideoName() == videoName) + { + currentVideo = video; + vimeoVideoId = video.id.ToString(); + description = video.description; + break; + } + } + } + } + + public void SetVimeoVideoFromId() + { + if (!string.IsNullOrEmpty(vimeoVideoId)) + { + for (int i = 0; i < vimeoVideos.Count; i++) + { + var video = vimeoVideos[i]; + if (video.id.ToString() == vimeoVideoId) + { + currentVideo = video; + if (string.IsNullOrEmpty(videoName)) + { + videoName = video.GetVideoName(); + } + if (string.IsNullOrEmpty(description)) + { + description = video.description; + } + break; + } + } + } + } } public class AspectRatioHelper diff --git a/Assets/Vimeo/Scripts/Config/VimeoSettings.cs b/Assets/Vimeo/Scripts/Config/VimeoSettings.cs index e91dc924..9c82a5ea 100644 --- a/Assets/Vimeo/Scripts/Config/VimeoSettings.cs +++ b/Assets/Vimeo/Scripts/Config/VimeoSettings.cs @@ -25,6 +25,9 @@ public class VimeoSettings : MonoBehaviour public bool signInError = false; private const string VIMEO_TOKEN_PREFIX = "vimeo-token-"; + // Played or Overwritten video + public string vimeoVideoId; + public int GetCurrentFolderIndex() { if (currentFolder != null) { diff --git a/Assets/Vimeo/Scripts/Config/VimeoVideo.cs b/Assets/Vimeo/Scripts/Config/VimeoVideo.cs index c55b8f60..0fee4e63 100644 --- a/Assets/Vimeo/Scripts/Config/VimeoVideo.cs +++ b/Assets/Vimeo/Scripts/Config/VimeoVideo.cs @@ -33,7 +33,7 @@ public VimeoVideo(string _name, string _uri = null) name = _name; uri = _uri; if (_uri != null) { - string[] matches = Regex.Split(_uri, "/([0-9]+)$"); + string[] matches = Regex.Split(_uri, "/([0-9]+)"); if (matches.Length > 1) { id = int.Parse(matches[1]); } @@ -42,38 +42,38 @@ public VimeoVideo(string _name, string _uri = null) public VimeoVideo(JSONNode video) { - if (video["name"] != null) { + if (!JSONNode.IsNullNode(video["name"])) { name = video["name"].Value; } - - if (video["uri"] != null) { + + if (!JSONNode.IsNullNode(video["uri"])) { uri = video["uri"].Value; } - - if (video["description"] != null) { - description = video["description"].Value; + + if (!JSONNode.IsNullNode(video["description"])) { + description = UnescapeNewLines(video["description"].Value); } - - if (video["duration"] != null) { + + if (!JSONNode.IsNullNode(video["duration"])) { duration = int.Parse(video["duration"].Value); } - if (video["width"] != null) { + if (!JSONNode.IsNullNode(video["width"])) { width = int.Parse(video["width"].Value); } - if (video["height"] != null) { + if (!JSONNode.IsNullNode(video["height"])) { height = int.Parse(video["height"].Value); } - if (video["spatial"] != null && !video["spatial"].IsNull) { + if (!JSONNode.IsNullNode(video["spatial"])) { is3D = true; projection = video["spatial"]["projection"].Value; stereoFormat = video["spatial"]["stereo_format"].Value; } if (uri != null) { - string[] matches = Regex.Split(uri, "/([0-9]+)$"); + string[] matches = Regex.Split(uri, "/([0-9]+)"); if (matches.Length > 1) { id = int.Parse(matches[1]); name = name + " (" + id + ")"; @@ -111,6 +111,20 @@ public VimeoVideo(JSONNode video) } } + private static string UnescapeNewLines(string text) + { + return text.Replace("\\n", "\n"); + } + + public string GetVideoName() + { + string videoIdParenthesisSuffix = " (" + id + ")"; + if (name.EndsWith(videoIdParenthesisSuffix)) { + return name.Substring(0, name.Length - videoIdParenthesisSuffix.Length); + } + return name; + } + public int CompareTo(VimeoVideo other) { if (other == null) { diff --git a/Assets/Vimeo/Scripts/Editor/BaseEditor.cs b/Assets/Vimeo/Scripts/Editor/BaseEditor.cs index dfe9d840..b96da913 100644 --- a/Assets/Vimeo/Scripts/Editor/BaseEditor.cs +++ b/Assets/Vimeo/Scripts/Editor/BaseEditor.cs @@ -2,156 +2,64 @@ using UnityEngine; using UnityEditor; -using Vimeo.Player; -using Vimeo.Recorder; -using Vimeo.SimpleJSON; using System.Linq; +using Vimeo.Recorder; +using Vimeo.Player; +using System; namespace Vimeo { public class BaseEditor : Editor { - VimeoApi api; + VimeoFetcher fetcher; - private void InitAPI() + private void InitFetcher() { var settings = target as VimeoSettings; - if (api == null) { - if (settings.gameObject.GetComponent()) { - api = settings.gameObject.GetComponent(); - } else { - api = settings.gameObject.AddComponent(); + if (fetcher == null) { + if (settings.gameObject.GetComponent()) { + fetcher = settings.gameObject.GetComponent(); + } + else { + fetcher = settings.gameObject.AddComponent(); } } - api.token = settings.GetVimeoToken(); + fetcher.OnFetchComplete += DestroyFetcher; + fetcher.OnFetchError += DestroyFetcher; + fetcher.Init(settings); } - protected void GetRecentVideos() + private void DestroyFetcher(string response) { - var settings = target as VimeoSettings; - if (!settings.Authenticated()) return; - InitAPI(); - - settings.vimeoVideos.Clear(); - settings.vimeoVideos.Add( - new VimeoVideo("Loading...", null) - ); + fetcher.OnFetchComplete -= DestroyFetcher; + fetcher.OnFetchError -= DestroyFetcher; - api.OnRequestComplete += GetVideosComplete; - api.OnError += OnRequestError; - - api.GetRecentUserVideos(); - } - - protected void GetVideosInFolder(VimeoFolder folder) - { var settings = target as VimeoSettings; - if (!settings.Authenticated()) return; - InitAPI(); - - settings.vimeoVideos.Clear(); - settings.vimeoVideos.Add( - new VimeoVideo("Loading...", null) - ); - - api.OnRequestComplete += GetVideosComplete; - api.OnError += OnRequestError; - - api.GetVideosInFolder(folder); - } - - private void GetVideosComplete(string response) - { - var settings = target as VimeoPlayer; - settings.vimeoVideos.Clear(); - - api.OnRequestComplete -= GetVideosComplete; - api.OnError -= OnRequestError; - - if (!EditorApplication.isPlaying) { - DestroyImmediate(settings.gameObject.GetComponent()); - } - - var json = JSONNode.Parse(response); - JSONNode videoData = json["data"]; - - if (videoData.Count == 0) { - settings.vimeoVideos.Add(new VimeoVideo("(No videos found)")); - } else { - settings.vimeoVideos.Add(new VimeoVideo("---- Select a video ----", null)); - - for (int i = 0; i < videoData.Count; i++) { - settings.vimeoVideos.Add( - new VimeoVideo(videoData[i]) - ); - } +#if UNITY_EDITOR + if (!EditorApplication.isPlaying) +#endif + { + DestroyImmediate(settings.gameObject.GetComponent()); } } - protected void FetchFolders() + private void FetchFolders() { - var settings = target as VimeoSettings; - if (!settings.Authenticated()) return; - - InitAPI(); - settings.vimeoFolders.Clear(); - settings.vimeoFolders.Add( - new VimeoFolder("Loading...", null) - ); - - api.OnRequestComplete += GetFoldersComplete; - api.OnError += OnRequestError; - api.GetUserFolders(); + InitFetcher(); + fetcher.FetchFolders(); } - private void GetFoldersComplete(string response) + private void GetVideosInFolder(VimeoFolder currentFolder) { - var settings = target as VimeoSettings; - settings.vimeoFolders.Clear(); - - api.OnRequestComplete -= GetFoldersComplete; - - if (!EditorApplication.isPlaying) { - DestroyImmediate(settings.gameObject.GetComponent()); - } - - var json = JSONNode.Parse(response); - var folderData = json["data"]; - - string folder_prefix = ""; - - if (settings is VimeoPlayer) { - var player = target as VimeoPlayer; - player.vimeoFolders.Add(new VimeoFolder("---- Find a video ----", null)); - player.vimeoFolders.Add(new VimeoFolder("Get video by ID or URL", "custom")); - player.vimeoFolders.Add(new VimeoFolder("Most recent videos", "recent")); - - if (player.currentFolder == null || !player.currentFolder.IsValid()) { - if (player.vimeoVideoId != null && player.vimeoVideoId != "") { - player.currentFolder = player.vimeoFolders[1]; - } else { - player.currentFolder = player.vimeoFolders[0]; - } - } - folder_prefix = "Projects / "; - } else { - settings.vimeoFolders.Add(new VimeoFolder("No project", null)); - } - - for (int i = 0; i < folderData.Count; i++) { - VimeoFolder folder = new VimeoFolder(folder_prefix + folderData[i]["name"], folderData[i]["uri"]); - settings.vimeoFolders.Add(folder); - } + InitFetcher(); + fetcher.GetVideosInFolder(currentFolder); } - private void OnRequestError(string error) + private void GetRecentVideos() { - var settings = target as VimeoSettings; - if (!EditorApplication.isPlaying) { - DestroyImmediate(settings.gameObject.GetComponent()); - } - settings.signInError = true; + InitFetcher(); + fetcher.GetRecentVideos(); } protected void GUIManageVideosButton() @@ -172,7 +80,7 @@ protected bool GUISelectFolder() bool folderChanged = false; int cur_index = settings.GetCurrentFolderIndex(); - int new_index = EditorGUILayout.Popup(settings is VimeoPlayer ? "Vimeo Video" : "Add to Project", cur_index, settings.vimeoFolders.Select(folder => folder.name).ToArray()); + int new_index = EditorGUILayout.Popup("Project", cur_index, settings.vimeoFolders.Select(folder => folder.name).ToArray()); if (new_index != cur_index) { folderChanged = true; @@ -183,7 +91,7 @@ protected bool GUISelectFolder() Application.OpenURL("https://vimeo.com/manage/folders"); } - if (GUILayout.Button("↺", GUILayout.Width(25)) || (settings.vimeoFolders.Count == 0 && settings.GetComponent() == null)) { // Refresh folders + if (GUILayout.Button("↺", GUILayout.Width(25)) || (settings.vimeoFolders.Count == 0 && settings.GetComponent() == null)) { // Refresh folders FetchFolders(); } @@ -195,35 +103,50 @@ protected bool GUISelectFolder() protected void GUISelectVideo(bool refreshVideos = false) { var so = serializedObject; - var player = target as VimeoPlayer; + var settings = target as VimeoSettings; - if (player.currentFolder.uri == "custom") { + if (settings.currentFolder.uri == "custom") { EditorGUILayout.PropertyField(so.FindProperty("vimeoVideoId"), new GUIContent("Vimeo Video URL")); - } else if (player.currentFolder.uri != null && player.currentFolder.uri != "") { + } else if (settings.currentFolder.uri != null && settings.currentFolder.uri != "") { GUILayout.BeginHorizontal(); - int cur_video_index = player.GetCurrentVideoIndex(); - int new_video_index = EditorGUILayout.Popup(" ", cur_video_index, player.vimeoVideos.Select(v => v.name).ToArray()); + int cur_video_index = settings.GetCurrentVideoIndex(); + int new_video_index = EditorGUILayout.Popup("Selected Video", cur_video_index, settings.vimeoVideos.Select(v => v.name).ToArray()); if (new_video_index != cur_video_index) { - player.currentVideo = player.vimeoVideos[new_video_index]; - player.vimeoVideoId = player.currentVideo.id.ToString(); + settings.currentVideo = settings.vimeoVideos[new_video_index]; + settings.vimeoVideoId = new_video_index > 0 ? settings.currentVideo.id.ToString() : null; + if (settings is RecorderSettings) + { + var recorder = settings as RecorderSettings; + recorder.videoName = new_video_index > 0 ? settings.currentVideo.GetVideoName() : ""; + recorder.description = new_video_index > 0 ? settings.currentVideo.description : ""; + } } if (GUILayout.Button("↺", GUILayout.Width(25)) || refreshVideos || - (player.vimeoVideos.Count == 0 && player.GetComponent() == null)) { - - if (player.currentFolder.uri == "recent") { - GetRecentVideos(); - } else if (player.currentFolder.id > 0) { - GetVideosInFolder(player.currentFolder); - } + (settings.vimeoVideos.Count == 0 && settings.GetComponent() == null)) { + UpdateVideosList(); } GUILayout.EndHorizontal(); } } + protected void UpdateVideosList() + { + var settings = target as VimeoSettings; + + if (settings.currentFolder.uri == "recent") + { + GetRecentVideos(); + } + else if (settings.currentFolder.id > 0) + { + GetVideosInFolder(settings.currentFolder); + } + } + protected void GUISignOutButton() { var settings = target as VimeoSettings; diff --git a/Assets/Vimeo/Scripts/Editor/VimeoRecorderEditor.cs b/Assets/Vimeo/Scripts/Editor/VimeoRecorderEditor.cs index f4bdc48e..fea3b014 100644 --- a/Assets/Vimeo/Scripts/Editor/VimeoRecorderEditor.cs +++ b/Assets/Vimeo/Scripts/Editor/VimeoRecorderEditor.cs @@ -75,13 +75,23 @@ public void DrawConfig(VimeoRecorder recorder) EditorGUI.indentLevel++; EditorGUILayout.PropertyField(so.FindProperty("videoName")); - EditorGUILayout.PropertyField(so.FindProperty("privacyMode")); - if (VimeoApi.PrivacyModeDisplay.OnlyPeopleWithAPassword == recorder.privacyMode) { - EditorGUILayout.PropertyField(so.FindProperty("videoPassword"), new GUIContent("Password")); + EditorGUILayout.PropertyField(so.FindProperty("description")); + + bool updated = GUISelectFolder(); + + EditorGUILayout.PropertyField(so.FindProperty("replaceExisting")); + + if (recorder.replaceExisting) + { + GUISelectVideo(updated); } - GUISelectFolder(); + EditorGUILayout.PropertyField(so.FindProperty("privacyMode")); + if (VimeoApi.PrivacyModeDisplay.OnlyPeopleWithAPassword == recorder.privacyMode) + { + EditorGUILayout.PropertyField(so.FindProperty("videoPassword"), new GUIContent("Password")); + } EditorGUILayout.PropertyField(so.FindProperty("commentMode"), new GUIContent("Comments")); EditorGUILayout.PropertyField(so.FindProperty("enableDownloads")); @@ -122,12 +132,12 @@ public void DrawRecordingControls() GUI.backgroundColor = Color.red; if (GUILayout.Button("Cancel", GUILayout.Height(30))) { - recorder.CancelRecording(); + recorder.Cancel(); } } else if (recorder.isUploading) { GUI.backgroundColor = Color.red; if (GUILayout.Button("Cancel", GUILayout.Height(30))) { - recorder.CancelRecording(); + recorder.Cancel(); } } else { GUI.backgroundColor = Color.green; @@ -175,6 +185,12 @@ public void DrawRecordingControls() GUILayout.Box("", GUILayout.Height(20)); EditorGUI.ProgressBar(rect, recorder.uploadProgress, "Uploading to Vimeo..."); GUILayout.EndHorizontal(); + + if (recorder.uploadProgress == 1) + { + UpdateVideosList(); + } + } } diff --git a/Assets/Vimeo/Scripts/Recorder/VimeoPublisher.cs b/Assets/Vimeo/Scripts/Recorder/VimeoPublisher.cs index cc68ff94..56139070 100644 --- a/Assets/Vimeo/Scripts/Recorder/VimeoPublisher.cs +++ b/Assets/Vimeo/Scripts/Recorder/VimeoPublisher.cs @@ -13,7 +13,7 @@ public class VimeoPublisher : MonoBehaviour public event UploadAction OnUploadProgress; public delegate void RequestAction(string error_message); - public event RequestAction OnNetworkError; + public event RequestAction OnUploadError; [HideInInspector] public VimeoRecorder recorder; // recorder contains all the settings @@ -64,7 +64,15 @@ public void OnUploadInit(string response) } #endif - m_vimeoUploader.SetVideoDescription("Recorded and uploaded with the Vimeo Unity SDK: https://github.com/vimeo/vimeo-unity-sdk"); + if (string.IsNullOrEmpty(recorder.description)) + { + m_vimeoUploader.SetVideoDescription("Recorded and uploaded with the Vimeo Unity SDK: https://github.com/vimeo/vimeo-unity-sdk"); + } + else + { + m_vimeoUploader.SetVideoDescription(recorder.description); + } + if (recorder.enableDownloads == false) { m_vimeoUploader.SetVideoDownload(recorder.enableDownloads); } @@ -96,11 +104,11 @@ public string GetVimeoPermalink() return null; } - public void PublishVideo(string filename) + public void PublishVideo(string filename, string vimeoId = null) { if (System.IO.File.Exists(filename)) { Debug.Log("[VimeoRecorder] Uploading to Vimeo"); - m_vimeoUploader.Upload(filename); + m_vimeoUploader.Upload(filename, vimeoId); } else { Debug.LogError("File doesn't exist, try recording it again"); } @@ -115,10 +123,12 @@ void UploadProgress(string status, float progress) private void UploadComplete(string video_url) { - if (recorder.openInBrowser == true) { + if (recorder.openInBrowser == true) + { OpenVideo(); } - if (OnUploadProgress != null) { + if (OnUploadProgress != null) + { OnUploadProgress("UploadComplete", 1f); } @@ -149,8 +159,8 @@ private void OnVideoUpdated(string response) private void NetworkError(string error_message) { - if (OnNetworkError != null) { - OnNetworkError("It seems like you are not connected to the internet or are having connection problems."); + if (OnUploadError != null) { + OnUploadError("It seems like you are not connected to the internet or are having connection problems."); } } @@ -158,20 +168,29 @@ private void ApiError(string response) { JSONNode json = JSONNode.Parse(response); - if (json["invalid_parameters"] != null) { + if (!string.IsNullOrEmpty(json["error"])) + { + Debug.LogError("Vimeo Upload Error: " + json["error"]); + Debug.LogError("Vimeo Upload Error: " + json["developer_message"]); + if (OnUploadError != null) + { + OnUploadError("Vimeo Upload Error " + json["error_code"] + ": " + json["error"]); + } + } + else if (json["invalid_parameters"] != null) { for (int i = 0; i < json["invalid_parameters"].Count; i++) { // TODO use .Value if (json["invalid_parameters"][i]["field"].ToString() == "\"privacy.download\"") { - if (OnNetworkError != null) { - OnNetworkError("You must upgrade your Vimeo account in order to access this privacy feature. https://vimeo.com/upgrade"); + if (OnUploadError != null) { + OnUploadError("You must upgrade your Vimeo account in order to access this privacy feature. https://vimeo.com/upgrade"); } } else if (json["invalid_parameters"][i]["field"].ToString() == "\"privacy.view\"") { - if (OnNetworkError != null) { - OnNetworkError("You must upgrade your Vimeo account in order to access this privacy feature. https://vimeo.com/upgrade"); + if (OnUploadError != null) { + OnUploadError("You must upgrade your Vimeo account in order to access this privacy feature. https://vimeo.com/upgrade"); } } else { - if (OnNetworkError != null) { - OnNetworkError(json["invalid_parameters"][i]["field"] + ": " + json["invalid_parameters"][i]["error"]); + if (OnUploadError != null) { + OnUploadError(json["invalid_parameters"][i]["field"] + ": " + json["invalid_parameters"][i]["error"]); } } } diff --git a/Assets/Vimeo/Scripts/Recorder/VimeoRecorder.cs b/Assets/Vimeo/Scripts/Recorder/VimeoRecorder.cs index 941c7def..f6d3d044 100644 --- a/Assets/Vimeo/Scripts/Recorder/VimeoRecorder.cs +++ b/Assets/Vimeo/Scripts/Recorder/VimeoRecorder.cs @@ -2,6 +2,8 @@ using UnityEngine.Networking; using System.IO; using Vimeo; +using System; +using System.Collections; namespace Vimeo.Recorder { @@ -10,19 +12,25 @@ namespace Vimeo.Recorder public class VimeoRecorder : RecorderSettings { public delegate void RecordAction(); + public delegate void RecordActionMsg(string msg); + public delegate void RecordActionVal(float val); + public event RecordAction OnReady; + public event RecordActionVal OnUploadProgress; public event RecordAction OnUploadComplete; - public event RecordAction OnUploadError; + public event RecordActionMsg OnUploadError; public VimeoPublisher publisher; + public bool isReady = false; public bool isRecording = false; public bool isUploading = false; public float uploadProgress = 0; + + VimeoFetcher fetcher; + private int m_byteChunkSize = 1024 * 1024 * 128; - public int byteChunkSize - { - set - { + public int byteChunkSize { + set { m_byteChunkSize = value; } } @@ -37,6 +45,11 @@ public void Start() if (recordOnStart) { BeginRecording(); } + else if (replaceExisting) + { + // we want an updated video list, without a need for the editor + FetchVideos(); + } } public void BeginRecording() @@ -66,17 +79,57 @@ public void EndRecording() } } - public void CancelRecording() + public void Cancel() { isRecording = false; isUploading = false; - encoder.CancelRecording(); + //encoder.DeleteVideoFile(); Destroy(publisher); + encoder.CancelRecording(); + } + + void FetchVideos() + { + if (fetcher == null) + { + fetcher = gameObject.AddComponent(); + fetcher.Init(this); + fetcher.OnFetchComplete += OnFetchComplete; + fetcher.OnFetchError += OnFetchError; + fetcher.GetVideosInFolder(currentFolder); + } + } + + private void OnFetchError(string response) + { + DestroyFetcher(); + } + + private void OnFetchComplete(string response) + { + isReady = true; + + if (OnReady != null) + { + OnReady.Invoke(); + } + + DestroyFetcher(); + } + + private void DestroyFetcher() + { + if (fetcher != null) + { + Destroy(fetcher); + fetcher = null; + } } //Used if you want to publish the latest recorded video public void PublishVideo() { + Debug.Assert(isReady); isUploading = true; uploadProgress = 0; @@ -85,50 +138,105 @@ public void PublishVideo() publisher.Init(this, m_byteChunkSize); publisher.OnUploadProgress += UploadProgress; - publisher.OnNetworkError += NetworkError; + publisher.OnUploadError += UploadError; } - publisher.PublishVideo(encoder.GetVideoFilePath()); + if (replaceExisting) + { + if (fetcher != null) + { + // bad situation - need some waiting point + Debug.LogError("Videos fetching is not complete before replacing publishing"); + } + + if (string.IsNullOrEmpty(vimeoVideoId)) + { + if (!string.IsNullOrEmpty(videoName)) + { + SetVimeoIdFromName(); + } + } + else + { + SetVimeoVideoFromId(); + } + + publisher.PublishVideo(encoder.GetVideoFilePath(), vimeoVideoId); + } + else + { + publisher.PublishVideo(encoder.GetVideoFilePath()); + } + } + + internal IEnumerator WaitForReady() + { + while (!isReady) + { + yield return null; + } } private void UploadProgress(string status, float progress) { uploadProgress = progress; - if (status == "UploadComplete" || status == "UploadError") { + if (status == "UploadComplete") { publisher.OnUploadProgress -= UploadProgress; - publisher.OnNetworkError -= NetworkError; + publisher.OnUploadError -= UploadError; isUploading = false; encoder.DeleteVideoFile(); Destroy(publisher); - if (status == "UploadComplete") { - if (OnUploadComplete != null) { - OnUploadComplete(); - } - } else if (status == "UploadError") { - if (OnUploadError != null) { - OnUploadError(); - } + if (OnUploadComplete != null) { + OnUploadComplete(); } } + else if (status == "UploadError") + { + publisher.OnUploadProgress -= UploadProgress; + publisher.OnUploadError -= UploadError; + isUploading = false; + encoder.DeleteVideoFile(); + Destroy(publisher); + if (OnUploadError != null) + { + OnUploadError(status); + } + } + else + { + if (OnUploadProgress != null) + { + OnUploadProgress(progress); + } + } } - private void NetworkError(string status) + private void UploadError(string status) { Debug.LogError(status); + publisher.OnUploadProgress -= UploadProgress; + publisher.OnUploadError -= UploadError; + + isUploading = false; + //encoder.DeleteVideoFile(); + Destroy(publisher); + + if (OnUploadError != null) + { + OnUploadError(status); + } } private void Dispose() { - if (isRecording) { - CancelRecording(); - } + Cancel(); Destroy(encoder); - Destroy(publisher); + Destroy(fetcher); } void OnDisable() diff --git a/Assets/Vimeo/Scripts/Services/VimeoApi.cs b/Assets/Vimeo/Scripts/Services/VimeoApi.cs index 7953fb77..04c5de6e 100644 --- a/Assets/Vimeo/Scripts/Services/VimeoApi.cs +++ b/Assets/Vimeo/Scripts/Services/VimeoApi.cs @@ -6,6 +6,7 @@ using System.Text; using UnityEngine; using UnityEngine.Networking; +using Vimeo.SimpleJSON; namespace Vimeo { @@ -73,14 +74,16 @@ public void AddVideoToFolder(VimeoVideo video, VimeoFolder folder) } } - public void GetRecentUserVideos(string fields = "name,uri", int per_page = 100) + public void GetRecentUserVideos(string fields = "name,uri", int per_page = 100, string direction = "desc", string sort = "alphabetical") { - StartCoroutine("Request", "/me/videos?fields=" + fields + "&per_page=" + per_page); + StartCoroutine(PagedRequest(per_page, "/me/videos?fields=" + fields + "&direction=" + direction + "&sort=" + sort)); + //StartCoroutine("Request", "/me/videos?fields=" + fields + "&direction=" + direction + "&page=" + page + "&per_page=" + per_page + "&sort=" + sort); } - public void GetVideosInFolder(VimeoFolder folder, string fields = "name,uri", int per_page = 100) + public void GetVideosInFolder(VimeoFolder folder, string fields = "name,uri", int per_page = 100, string direction = "desc", string sort = "alphabetical") { - StartCoroutine("Request", "/me/folders/" + folder.id + "/videos?fields=" + fields + "&per_page=" + per_page); + StartCoroutine(PagedRequest(per_page, "/me/folders/" + folder.id + "/videos?fields=" + fields + "&direction=" + direction + "&sort=" + sort)); + //StartCoroutine("Request", "/me/folders/" + folder.id + "/videos?fields=" + fields + "&direction=" + direction + "&page=" + page + "&per_page=" + per_page + "&sort=" + sort); } public void SetVideoViewPrivacy(PrivacyModeDisplay mode) @@ -175,7 +178,7 @@ public IEnumerator Patch(string url) } } - public IEnumerator RequestTusResource(string api_path, long fileByteCount) + public IEnumerator TusUploadNew(long fileByteCount) { string tusResourceRequestBody = "{ \"upload\": { \"approach\": \"tus\", \"size\": \"" + fileByteCount.ToString() + "\" } }"; @@ -188,6 +191,21 @@ public IEnumerator RequestTusResource(string api_path, long fileByteCount) } } + public IEnumerator TusUploadReplace(string videoId, string file_name, long fileByteCount) + { + string tusResourceRequestBody = "{ \"file_name\": \"" + file_name + "\", \"upload\": { \"status\": \"in_progress\", \"size\": \"" + fileByteCount.ToString() + "\", \"approach\": \"tus\" } }"; + + if (token != null) + { + using (UnityWebRequest request = UnityWebRequest.Put("https://api.vimeo.com/videos/" + videoId + "/versions", tusResourceRequestBody)) + { + PrepareTusHeaders(request, true); + yield return VimeoApi.SendRequest(request); + ResponseHandler(request); + } + } + } + IEnumerator Put(string api_path) { if (token != null) { @@ -205,12 +223,14 @@ private void ResponseHandler(UnityWebRequest request) if (request.error != null) { if (request.responseCode == 401) { SendError("401 Unauthorized request. Are you using a valid token?", request.downloadHandler.text); - } else if (IsNetworkError(request)) { + } + else if (IsNetworkError(request)) { Debug.LogError("[VimeoApi] It seems like you are not connected to the internet or are having connection problems."); if (OnNetworkError != null) { OnNetworkError(request.error); } - } else { + } + else { SendError(request.url + " - " + request.downloadHandler.text, request.downloadHandler.text); } } else if (OnRequestComplete != null) { @@ -227,6 +247,60 @@ private void SendError(string msg, string error) } } + public IEnumerator PagedRequest(int per_page, string api_path) + { + int page = 1; + JSONNode data = JSONNode.Parse("[]"); + string response = null; + JSONNode responseJSON = null; + do + { + UnityWebRequest request = UnityWebRequest.Get(API_URL + api_path + "&page=" + page + "&per_page=" + per_page); + PrepareHeaders(request); + yield return VimeoApi.SendRequest(request); + + if (request.error != null) + { + if (request.responseCode == 401) + { + SendError("401 Unauthorized request. Are you using a valid token?", request.downloadHandler.text); + } + else if (IsNetworkError(request)) + { + Debug.LogError("[VimeoApi] It seems like you are not connected to the internet or are having connection problems."); + OnNetworkError?.Invoke(request.error); + } + else + { + SendError(request.url + " - " + request.downloadHandler.text, request.downloadHandler.text); + } + yield break; + } + + response = request.downloadHandler.text; + responseJSON = JSONNode.Parse(response); + JSONNode pageData = responseJSON["data"]; + for (int i = 0; i < pageData.Count; i++) + { + JSONNode element = pageData[i]; + data.Add(element); + } + if (pageData.Count < 100) + { + break; + } + page++; + } + while (true); + + if (responseJSON != null) + { + responseJSON.Remove("data"); + responseJSON.Add("data", data); + } + OnRequestComplete?.Invoke(responseJSON.ToString()); + } + public IEnumerator Request(string api_path) { if (token != null) { @@ -237,17 +311,20 @@ public IEnumerator Request(string api_path) } } - private void PrepareTusHeaders(UnityWebRequest r, string apiVersion = "3.4") + private void PrepareTusHeaders(UnityWebRequest r, bool withAuthorization = true, string apiVersion = "3.4") { r.method = "POST"; r.SetRequestHeader("Content-Type", "application/json"); - PrepareHeaders(r, apiVersion); + PrepareHeaders(r, withAuthorization, apiVersion); } - - private void PrepareHeaders(UnityWebRequest r, string apiVersion = "3.4") + + private void PrepareHeaders(UnityWebRequest r, bool withAuthorization = true, string apiVersion = "3.4") { r.chunkedTransfer = false; - r.SetRequestHeader("Authorization", "bearer " + token); + if (withAuthorization) + { + r.SetRequestHeader("Authorization", "bearer " + token); + } r.SetRequestHeader("Accept", "application/vnd.vimeo.*+json;version=" + apiVersion); } diff --git a/Assets/Vimeo/Scripts/Services/VimeoFetcher.cs b/Assets/Vimeo/Scripts/Services/VimeoFetcher.cs new file mode 100644 index 00000000..ed5bd0a1 --- /dev/null +++ b/Assets/Vimeo/Scripts/Services/VimeoFetcher.cs @@ -0,0 +1,222 @@ +#if UNITY_EDITOR +using UnityEditor; +#endif +using UnityEngine; +using Vimeo.Player; +using Vimeo.Recorder; +using Vimeo.SimpleJSON; + +namespace Vimeo +{ + public class VimeoFetcher : MonoBehaviour + { + VimeoSettings target; + VimeoApi api; + + public delegate void FetchAction(string response); + public event FetchAction OnFetchComplete; + public event FetchAction OnFetchError; + + private void Start() + { + this.hideFlags = HideFlags.HideInInspector; + } + + public void Init(VimeoSettings _settings) + { + target = _settings; + } + + public void FetchFolders() + { + var settings = target as VimeoSettings; + if (!settings.Authenticated()) return; + + InitAPI(); + settings.vimeoFolders.Clear(); + settings.vimeoFolders.Add( + new VimeoFolder("Loading...", null) + ); + + api.OnRequestComplete += GetFoldersComplete; + api.OnError += OnRequestError; + api.GetUserFolders(); + } + + public void GetVideosInFolder(VimeoFolder folder) + { + var settings = target as VimeoSettings; + if (!settings.Authenticated()) return; + InitAPI(); + + settings.vimeoVideos.Clear(); + settings.vimeoVideos.Add( + new VimeoVideo("Loading...", null) + ); + + api.OnRequestComplete += GetVideosComplete; + api.OnError += OnRequestError; + + api.GetVideosInFolder(folder, "name,uri,description"); // conserve description + } + + public void GetRecentVideos() + { + var settings = target as VimeoSettings; + if (!settings.Authenticated()) return; + InitAPI(); + + settings.vimeoVideos.Clear(); + settings.vimeoVideos.Add( + new VimeoVideo("Loading...", null) + ); + + api.OnRequestComplete += GetVideosComplete; + api.OnError += OnRequestError; + + api.GetRecentUserVideos(); + } + + private void InitAPI() + { + var settings = target as VimeoSettings; + if (api == null) + { + if (settings.gameObject.GetComponent()) + { + api = settings.gameObject.GetComponent(); + } + else + { + api = settings.gameObject.AddComponent(); + } + } + + api.token = settings.GetVimeoToken(); + } + + protected bool IsSelectExisting(VimeoSettings settings) + { + return (settings is VimeoPlayer) || + (settings is VimeoRecorder && (settings as VimeoRecorder).replaceExisting); + } + + private void GetVideosComplete(string response) + { + var settings = target as VimeoSettings; + settings.vimeoVideos.Clear(); + + api.OnRequestComplete -= GetVideosComplete; + api.OnError -= OnRequestError; + +#if UNITY_EDITOR + if (!EditorApplication.isPlaying) +#endif + { + DestroyImmediate(settings.gameObject.GetComponent()); + } + + var json = JSONNode.Parse(response); + JSONNode videoData = json["data"]; + + if (videoData.Count == 0) { + settings.vimeoVideos.Add(new VimeoVideo("(No videos found)")); + } + else { + settings.vimeoVideos.Add(new VimeoVideo("---- Select a video ----", null)); + + for (int i = 0; i < videoData.Count; i++) { + settings.vimeoVideos.Add( + new VimeoVideo(videoData[i]) + ); + } + } + + Debug.Log("[VimeoFetcher] Completed with " + (settings.vimeoVideos.Count - 1) + " existing videos"); + + if (OnFetchComplete != null) + { + OnFetchComplete.Invoke(response); + } + } + + private void OnRequestError(string error) + { + var settings = target as VimeoSettings; +#if UNITY_EDITOR + if (!EditorApplication.isPlaying) +#endif + { + DestroyImmediate(settings.gameObject.GetComponent()); + } + settings.signInError = true; + + if (OnFetchError != null) + { + OnFetchError.Invoke(""); + } + + Debug.LogError("[VimeoFetcher] Error: " + error); + } + + private void GetFoldersComplete(string response) + { + var settings = target as VimeoSettings; + settings.vimeoFolders.Clear(); + + api.OnRequestComplete -= GetFoldersComplete; + +#if UNITY_EDITOR + if (!EditorApplication.isPlaying) +#endif + { + DestroyImmediate(settings.gameObject.GetComponent()); + } + + var json = JSONNode.Parse(response); + var folderData = json["data"]; + + string folder_prefix = ""; + + if (IsSelectExisting(settings)) + { + var player = target as VimeoSettings; + player.vimeoFolders.Add(new VimeoFolder("---- Find a video ----", null)); + player.vimeoFolders.Add(new VimeoFolder("Get video by ID or URL", "custom")); + player.vimeoFolders.Add(new VimeoFolder("Most recent videos", "recent")); + + if (player.currentFolder == null || !player.currentFolder.IsValid()) + { + if (player.vimeoVideoId != null && player.vimeoVideoId != "") + { + player.currentFolder = player.vimeoFolders[1]; + } + else + { + player.currentFolder = player.vimeoFolders[0]; + } + } + folder_prefix = "Projects / "; + } + else + { + settings.vimeoFolders.Add(new VimeoFolder("No project", null)); + } + + for (int i = 0; i < folderData.Count; i++) + { + VimeoFolder folder = new VimeoFolder(folder_prefix + folderData[i]["name"], folderData[i]["uri"]); + settings.vimeoFolders.Add(folder); + } + + if (OnFetchComplete != null) + { + OnFetchComplete.Invoke(""); + } + + Debug.Log("[VimeoFetcher] Completed with " + (settings.vimeoFolders.Count - 1) + " existing folders"); + } + + + } +} diff --git a/Assets/Vimeo/Scripts/Services/VimeoFetcher.cs.meta b/Assets/Vimeo/Scripts/Services/VimeoFetcher.cs.meta new file mode 100644 index 00000000..7a23e29b --- /dev/null +++ b/Assets/Vimeo/Scripts/Services/VimeoFetcher.cs.meta @@ -0,0 +1,13 @@ +fileFormatVersion: 2 +guid: 8e8f98731cf74a64b8b42101466d733c +timeCreated: 1549788165 +licenseType: Free +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Vimeo/Scripts/Services/VimeoUploader.cs b/Assets/Vimeo/Scripts/Services/VimeoUploader.cs index 9ab84a7c..c1291e27 100644 --- a/Assets/Vimeo/Scripts/Services/VimeoUploader.cs +++ b/Assets/Vimeo/Scripts/Services/VimeoUploader.cs @@ -120,13 +120,20 @@ private void RequestComplete(string response) } } - public void Upload(string _file) + public void Upload(string _file, string vimeoId = null) { m_file = _file; m_fileInfo = new FileInfo(m_file); OnRequestComplete += RequestComplete; - StartCoroutine(RequestTusResource("me/videos", m_fileInfo.Length)); + if (!string.IsNullOrEmpty(vimeoId)) + { + StartCoroutine(TusUploadReplace(vimeoId, Path.GetFileName(m_file), m_fileInfo.Length)); + } + else + { + StartCoroutine(TusUploadNew(m_fileInfo.Length)); + } m_isUploading = true; } diff --git a/Assets/Vimeo/Scripts/Utils/SimpleJSON.cs b/Assets/Vimeo/Scripts/Utils/SimpleJSON.cs index ab0c2d3d..c827463f 100644 --- a/Assets/Vimeo/Scripts/Utils/SimpleJSON.cs +++ b/Assets/Vimeo/Scripts/Utils/SimpleJSON.cs @@ -158,6 +158,11 @@ public virtual bool IsNull get { return Tag == JSONBinaryTag.Null; } } + public static bool IsNullNode(JSONNode node) + { + return node == null || node.Tag == JSONBinaryTag.Null; + } + public virtual int AsInt { get