MediaPlayerEditor_Source.cs 13 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389
  1. using UnityEngine;
  2. using UnityEditor;
  3. using System.Collections.Generic;
  4. //-----------------------------------------------------------------------------
  5. // Copyright 2015-2021 RenderHeads Ltd. All rights reserved.
  6. //-----------------------------------------------------------------------------
  7. namespace RenderHeads.Media.AVProVideo.Editor
  8. {
  9. /// <summary>
  10. /// Editor for the MediaPlayer component
  11. /// </summary>
  12. public partial class MediaPlayerEditor : UnityEditor.Editor
  13. {
  14. #if UNITY_EDITOR_OSX
  15. internal const string MediaFileExtensions = "mp4,m4v,mov,mpg,avi,mp3,m4a,aac,ac3,au,aiff,caf,wav,m3u8";
  16. #else
  17. internal const string MediaFileExtensions = "Media Files;*.mp4;*.mov;*.m4v;*.avi;*.mkv;*.ts;*.webm;*.flv;*.vob;*.ogg;*.ogv;*.mpg;*.wmv;*.3gp;*.mxf;Audio Files;*wav;*.mp3;*.mp2;*.m4a;*.wma;*.aac;*.au;*.flac;*.m3u8;*.mpd;*.ism;";
  18. #endif
  19. private readonly static GUIContent[] _fileFormatGuiNames =
  20. {
  21. new GUIContent("Automatic (by extension)"),
  22. new GUIContent("Apple HLS (.m3u8)"),
  23. new GUIContent("MPEG-DASH (.mdp)"),
  24. new GUIContent("MS Smooth Streaming (.ism)"),
  25. };
  26. private SerializedProperty _propMediaSource;
  27. private SerializedProperty _propMediaReference;
  28. private SerializedProperty _propMediaPath;
  29. private void OnInspectorGUI_Source()
  30. {
  31. // Display the file name and buttons to load new files
  32. MediaPlayer mediaPlayer = (this.target) as MediaPlayer;
  33. EditorGUILayout.PropertyField(_propMediaSource);
  34. if (MediaSource.Reference == (MediaSource)_propMediaSource.enumValueIndex)
  35. {
  36. EditorGUILayout.PropertyField(_propMediaReference);
  37. }
  38. EditorGUILayout.BeginVertical(GUI.skin.box);
  39. if (MediaSource.Reference != (MediaSource)_propMediaSource.enumValueIndex)
  40. {
  41. OnInspectorGUI_CopyableFilename(mediaPlayer.MediaPath.Path);
  42. EditorGUILayout.PropertyField(_propMediaPath);
  43. }
  44. //if (!Application.isPlaying)
  45. {
  46. GUI.color = Color.white;
  47. GUILayout.BeginHorizontal();
  48. if (_allowDeveloperMode)
  49. {
  50. if (GUILayout.Button("Rewind"))
  51. {
  52. mediaPlayer.Rewind(true);
  53. }
  54. if (GUILayout.Button("Preroll"))
  55. {
  56. mediaPlayer.RewindPrerollPause();
  57. }
  58. if (GUILayout.Button("End"))
  59. {
  60. mediaPlayer.Control.Seek(mediaPlayer.Info.GetDuration());
  61. }
  62. }
  63. if (GUILayout.Button("Close"))
  64. {
  65. mediaPlayer.CloseMedia();
  66. }
  67. if (GUILayout.Button("Load"))
  68. {
  69. if (mediaPlayer.MediaSource == MediaSource.Path)
  70. {
  71. mediaPlayer.OpenMedia(mediaPlayer.MediaPath.PathType, mediaPlayer.MediaPath.Path, mediaPlayer.AutoStart);
  72. }
  73. else if (mediaPlayer.MediaSource == MediaSource.Reference)
  74. {
  75. mediaPlayer.OpenMedia(mediaPlayer.MediaReference, mediaPlayer.AutoStart);
  76. }
  77. }
  78. /*if (media.Control != null)
  79. {
  80. if (GUILayout.Button("Unload"))
  81. {
  82. media.CloseVideo();
  83. }
  84. }*/
  85. if (EditorGUIUtility.GetObjectPickerControlID() == 100 &&
  86. Event.current.commandName == "ObjectSelectorClosed")
  87. {
  88. MediaReference mediaRef = (MediaReference)EditorGUIUtility.GetObjectPickerObject();
  89. if (mediaRef)
  90. {
  91. _propMediaSource.enumValueIndex = (int)MediaSource.Reference;
  92. _propMediaReference.objectReferenceValue = mediaRef;
  93. }
  94. }
  95. GUI.color = Color.green;
  96. MediaPathDrawer.ShowBrowseButtonIcon(_propMediaPath, _propMediaSource);
  97. GUI.color = Color.white;
  98. GUILayout.EndHorizontal();
  99. //MediaPath mediaPath = new MediaPath(_propMediaPath.FindPropertyRelative("_path").stringValue, (MediaPathType)_propMediaPath.FindPropertyRelative("_pathType").enumValueIndex);
  100. //ShowFileWarningMessages((MediaSource)_propMediaSource.enumValueIndex, mediaPath, (MediaReference)_propMediaReference.objectReferenceValue, mediaPlayer.AutoOpen, Platform.Unknown);
  101. GUI.color = Color.white;
  102. }
  103. if (MediaSource.Reference != (MediaSource)_propMediaSource.enumValueIndex)
  104. {
  105. GUILayout.Label("Fallback Media Hints", EditorStyles.boldLabel);
  106. EditorGUILayout.PropertyField(_propFallbackMediaHints);
  107. }
  108. EditorGUILayout.EndVertical();
  109. }
  110. internal static void OnInspectorGUI_CopyableFilename(string path)
  111. {
  112. if (EditorGUIUtility.isProSkin)
  113. {
  114. GUI.backgroundColor = Color.black;
  115. GUI.color = Color.cyan;
  116. }
  117. EditorHelper.IMGUI.CopyableFilename(path);
  118. GUI.color = Color.white;
  119. GUI.backgroundColor = Color.white;
  120. }
  121. internal static void ShowFileWarningMessages(MediaSource mediaSource, MediaPath mediaPath, MediaReference mediaReference, bool isAutoOpen, Platform platform)
  122. {
  123. MediaPath result = null;
  124. if (mediaSource == MediaSource.Path)
  125. {
  126. if (mediaPath != null)
  127. {
  128. result = mediaPath;
  129. }
  130. }
  131. else if (mediaSource == MediaSource.Reference)
  132. {
  133. if (mediaReference != null)
  134. {
  135. result = mediaReference.GetCurrentPlatformMediaReference().MediaPath;
  136. }
  137. }
  138. ShowFileWarningMessages(result, isAutoOpen, platform);
  139. }
  140. internal static void ShowFileWarningMessages(string filePath, MediaPathType fileLocation, MediaReference mediaReference, MediaSource mediaSource, bool isAutoOpen, Platform platform)
  141. {
  142. MediaPath mediaPath = null;
  143. if (mediaSource == MediaSource.Path)
  144. {
  145. mediaPath = new MediaPath(filePath, fileLocation);
  146. }
  147. else if (mediaSource == MediaSource.Reference)
  148. {
  149. if (mediaReference != null)
  150. {
  151. mediaPath = mediaReference.GetCurrentPlatformMediaReference().MediaPath;
  152. }
  153. }
  154. ShowFileWarningMessages(mediaPath, isAutoOpen, platform);
  155. }
  156. internal static void ShowFileWarningMessages(MediaPath mediaPath, bool isAutoOpen, Platform platform)
  157. {
  158. string fullPath = string.Empty;
  159. if (mediaPath != null)
  160. {
  161. fullPath = mediaPath.GetResolvedFullPath();
  162. }
  163. if (string.IsNullOrEmpty(fullPath))
  164. {
  165. if (isAutoOpen)
  166. {
  167. EditorHelper.IMGUI.NoticeBox(MessageType.Error, "No media specified");
  168. }
  169. else
  170. {
  171. EditorHelper.IMGUI.NoticeBox(MessageType.Warning, "No media specified");
  172. }
  173. }
  174. else
  175. {
  176. bool isPlatformAndroid = (platform == Platform.Android) || (platform == Platform.Unknown && BuildTargetGroup.Android == UnityEditor.EditorUserBuildSettings.selectedBuildTargetGroup);
  177. bool isPlatformIOS = (platform == Platform.iOS);
  178. isPlatformIOS |= (platform == Platform.Unknown && BuildTargetGroup.iOS == UnityEditor.EditorUserBuildSettings.selectedBuildTargetGroup);
  179. bool isPlatformTVOS = (platform == Platform.tvOS);
  180. isPlatformTVOS |= (platform == Platform.Unknown && BuildTargetGroup.tvOS == UnityEditor.EditorUserBuildSettings.selectedBuildTargetGroup);
  181. // Test file extensions
  182. {
  183. bool isExtensionAVI = fullPath.ToLower().EndsWith(".avi");
  184. bool isExtensionMOV = fullPath.ToLower().EndsWith(".mov");
  185. bool isExtensionMKV = fullPath.ToLower().EndsWith(".mkv");
  186. if (isPlatformAndroid && isExtensionMOV)
  187. {
  188. EditorHelper.IMGUI.NoticeBox(MessageType.Warning, "MOV file detected. Android doesn't support MOV files, you should change the container file.");
  189. }
  190. if (isPlatformAndroid && isExtensionAVI)
  191. {
  192. EditorHelper.IMGUI.NoticeBox(MessageType.Warning, "AVI file detected. Android doesn't support AVI files, you should change the container file.");
  193. }
  194. if (isPlatformAndroid && isExtensionMKV)
  195. {
  196. EditorHelper.IMGUI.NoticeBox(MessageType.Warning, "MKV file detected. Android doesn't support MKV files until Android 5.0.");
  197. }
  198. if (isPlatformIOS && isExtensionAVI)
  199. {
  200. EditorHelper.IMGUI.NoticeBox(MessageType.Warning, "AVI file detected. iOS doesn't support AVI files, you should change the container file.");
  201. }
  202. }
  203. if (fullPath.Contains("://"))
  204. {
  205. if (fullPath.ToLower().Contains("rtmp://"))
  206. {
  207. EditorHelper.IMGUI.NoticeBox(MessageType.Warning, "RTMP protocol is not supported by AVPro Video, except when Windows DirectShow is used with an external codec library (eg LAV Filters)");
  208. }
  209. if (fullPath.ToLower().Contains("youtube.com/watch"))
  210. {
  211. EditorHelper.IMGUI.NoticeBox(MessageType.Warning, "YouTube URL detected. YouTube website URL contains no media, a direct media file URL (eg MP4 or M3U8) is required. See the documentation FAQ for YouTube support.");
  212. }
  213. if (mediaPath.PathType != MediaPathType.AbsolutePathOrURL)
  214. {
  215. EditorHelper.IMGUI.NoticeBox(MessageType.Warning, "URL detected, change location type to URL?");
  216. }
  217. else
  218. {
  219. // Display warning to iOS users if they're trying to use HTTP url without setting the permission
  220. if (isPlatformIOS || isPlatformTVOS)
  221. {
  222. if (!PlayerSettings.iOS.allowHTTPDownload && fullPath.StartsWith("http://"))
  223. {
  224. EditorHelper.IMGUI.NoticeBox(MessageType.Warning, "Starting with iOS 9 'allow HTTP downloads' must be enabled for HTTP connections (see Player Settings)");
  225. }
  226. }
  227. #if UNITY_ANDROID
  228. if (fullPath.StartsWith("http://"))
  229. {
  230. EditorHelper.IMGUI.NoticeBox(MessageType.Warning, "Starting with Android 8 unsecure HTTP is not allowed by default and HTTPS must be used, unless a custom cleartext security policy is assigned");
  231. }
  232. #endif
  233. // Display warning for Android users if they're trying to use a URL without setting permission
  234. if (isPlatformAndroid && !PlayerSettings.Android.forceInternetPermission)
  235. {
  236. EditorHelper.IMGUI.NoticeBox(MessageType.Warning, "You need to set 'Internet Access' to 'require' in your Player Settings for Android builds when using URLs");
  237. }
  238. // Display warning for UWP users if they're trying to use a URL without setting permission
  239. if (platform == Platform.WindowsUWP || (platform == Platform.Unknown && (
  240. BuildTargetGroup.WSA == UnityEditor.EditorUserBuildSettings.selectedBuildTargetGroup
  241. )))
  242. {
  243. if (!PlayerSettings.WSA.GetCapability(PlayerSettings.WSACapability.InternetClient))
  244. {
  245. EditorHelper.IMGUI.NoticeBox(MessageType.Warning, "You need to set 'InternetClient' capability in your Player Settings when using URLs");
  246. }
  247. }
  248. }
  249. }
  250. else
  251. {
  252. // [MOZ] All paths on (i|mac|tv)OS are absolute so this check just results in an incorrect warning being shown
  253. #if !UNITY_EDITOR_OSX
  254. if (mediaPath.PathType != MediaPathType.AbsolutePathOrURL && fullPath.StartsWith("/"))
  255. {
  256. EditorHelper.IMGUI.NoticeBox(MessageType.Warning, "Absolute path detected, change location to Absolute path?");
  257. }
  258. #endif
  259. // Display warning for Android users if they're trying to use absolute file path without permission
  260. if (isPlatformAndroid && !PlayerSettings.Android.forceSDCardPermission)
  261. {
  262. EditorHelper.IMGUI.NoticeBox(MessageType.Warning, "You may need to access the local file system you may need to set 'Write Access' to 'External(SDCard)' in your Player Settings for Android");
  263. }
  264. if (platform == Platform.Unknown || platform == MediaPlayer.GetPlatform())
  265. {
  266. if (!System.IO.File.Exists(fullPath))
  267. {
  268. EditorHelper.IMGUI.NoticeBox(MessageType.Error, "File not found");
  269. }
  270. else
  271. {
  272. // Check the case
  273. // This approach is very slow, so we only run it when the app isn't playing
  274. if (!Application.isPlaying)
  275. {
  276. string comparePath = fullPath.Replace('\\', '/');
  277. string folderPath = System.IO.Path.GetDirectoryName(comparePath);
  278. if (!string.IsNullOrEmpty(folderPath))
  279. {
  280. string[] files = System.IO.Directory.GetFiles(folderPath, "*", System.IO.SearchOption.TopDirectoryOnly);
  281. bool caseMatch = false;
  282. if (files != null && files.Length > 0)
  283. {
  284. for (int i = 0; i < files.Length; i++)
  285. {
  286. if (files[i].Replace('\\', '/') == comparePath)
  287. {
  288. caseMatch = true;
  289. break;
  290. }
  291. }
  292. }
  293. if (!caseMatch)
  294. {
  295. EditorHelper.IMGUI.NoticeBox(MessageType.Warning, "File found but case doesn't match");
  296. }
  297. }
  298. }
  299. }
  300. }
  301. }
  302. }
  303. if (mediaPath != null && mediaPath.PathType == MediaPathType.RelativeToStreamingAssetsFolder)
  304. {
  305. if (!System.IO.Directory.Exists(Application.streamingAssetsPath))
  306. {
  307. GUILayout.BeginHorizontal();
  308. GUI.color = Color.yellow;
  309. GUILayout.TextArea("Warning: No StreamingAssets folder found");
  310. if (GUILayout.Button("Create Folder"))
  311. {
  312. System.IO.Directory.CreateDirectory(Application.streamingAssetsPath);
  313. AssetDatabase.Refresh();
  314. }
  315. GUILayout.EndHorizontal();
  316. }
  317. else
  318. {
  319. bool checkAndroidFileSize = false;
  320. #if UNITY_ANDROID
  321. if (platform == Platform.Unknown)
  322. {
  323. checkAndroidFileSize = true;
  324. }
  325. #endif
  326. if (platform == Platform.Android)
  327. {
  328. checkAndroidFileSize = true;
  329. }
  330. if (checkAndroidFileSize)
  331. {
  332. try
  333. {
  334. System.IO.FileInfo info = new System.IO.FileInfo(fullPath);
  335. if (info != null && info.Length > (1024 * 1024 * 512))
  336. {
  337. EditorHelper.IMGUI.NoticeBox(MessageType.Warning, "Using this very large file inside StreamingAssets folder on Android isn't recommended. Deployments will be slow and mapping the file from the StreamingAssets JAR may cause storage and memory issues. We recommend loading from another folder on the device.");
  338. }
  339. }
  340. catch (System.Exception)
  341. {
  342. }
  343. }
  344. }
  345. }
  346. GUI.color = Color.white;
  347. }
  348. }
  349. }