프로젝트

일반

사용자정보

통계
| 개정판:

t1 / TFDContents / Assets / VLC for Unity / Scripts / PlayVLC.cs @ 11

이력 | 보기 | 이력해설 | 다운로드 (66 KB)

1 11 YCH
/**************************************************************************************
2
*
3
*   VLC Mediaplayer Integration Script for UNITY - Version 1.06
4
*   (c) 2016 Christian Holzer
5
*
6
*   Thanks a lot for purchasing, I really hope this asset is useful to you. If you have any questions
7
*   or feature requests, you can contact me either per mail or you can post in this forum thread below.
8
*
9
*   Contact: chunityassets@gmail.com
10
*   Unity Forum Thread: http://forum.unity3d.com/threads/vlc-player-for-unity.387372/
11
*
12
*   1.06 - FIXES AND FEATURES:
13
14
    - Added warning and removed errors if VideoInBackground feature was used in Editor
15
    - More Control functions (experimental): Seek to Second, Next Video, Previous Video, Toggle Loop
16
    - You can now add your own VLC Command line options for unlimited possibilities
17
    - Access Video Statistics: Current Time, Length, Volume level, loop
18
    - various small fixes or improvements
19
*
20
*
21
**************************************************************************************/
22
23
using System;
24
using System.Collections;
25
using UnityEngine;
26
using System.Diagnostics;
27
using System.Drawing;
28
using System.IO;
29
using System.Net;
30
using System.Runtime.InteropServices;
31
using System.Text;
32
using System.Windows.Forms;
33
using System.Xml;
34
using UnityEngine.UI;
35
using Application = UnityEngine.Application;
36
using Color = System.Drawing.Color;
37
using Debug = UnityEngine.Debug;
38
using Screen = UnityEngine.Screen;
39
using System.Collections.Generic;
40
41
public class PlayVLC : MonoBehaviour
42
{
43
44
    #region PublicVariables
45
46
    [Header("Use built-in VLC Player in StreamingAssets")]
47
    [Tooltip("Want to use built-in VLC from StreamingAssets? This way your player must not have VLC player installed.")]
48
    public bool UseBuiltInVLC = true;
49
50
    [Header("Use installed VLC Player")]
51
    [Tooltip("If you don't want to bundle VLC with your app, but use the installed VLC Player on your users PC. Recommended VLC version is 2.0.8. Smaller Build: Delete vlc from StreamingAssets in Build!")]
52
    public string InstallPath = @"C:\Program Files\VideoLAN\VLC";
53
54
    [Header("Play from Streaming Assets")]
55
    [Tooltip("Want to play from StreamingAssets? Use this option if you package the video with the game.")]
56
    public bool PlayFromStreamingAssets = true;
57
    [Tooltip("Path or name with extension relative from StreamingAssets folder, eg. test.mp4")]
58
    public string StreamingAssetsVideoFilename = "";
59
    public string[] StreamingAssetsVideoPlaylistItems;
60
61
    [Header("Alternative: External video Path")]
62
    [Tooltip("Where is the video you want to play? Nearly all video formats are supported by VLC")]
63
    public string[] VideoPaths;
64
    public InputField ExternalField;
65
66
    [Header("SRT Subtitles")]
67
    public bool UseSubtitles = false;
68
    public string StreamingAssetsSubtitlePath;
69
70
    [Header(" Display Modes - Direct3D recommended")]
71
    public RenderMode UsedRenderMode;
72
    public enum RenderMode
73
    {
74
        Direct3DMode = 0,
75
        VLC_QT_InterfaceFullscreen = 1,
76
        FullScreenOverlayModePrimaryDisplay = 2
77
    }
78
79
    [Header("Playback Options")]
80
81
    [Tooltip("Use as Intro?")]
82
    public bool PlayOnStart = false;
83
    [Tooltip("Video will loop, make sure to enable skipping or call Kill.")]
84
    public bool LoopVideo = false;
85
    [Tooltip("Skip Video with any key. Forces Unity to remain the focused window.")]
86
    public bool SkipVideoWithAnyKey = true;
87
    [Tooltip("Call Play, Pause, Stop etc. fuctions from code or gui buttons. Only possible for 1 video at a time.")]
88
    public bool EnableVlcControls = false;
89
    [Tooltip("If enabled, video will be fullscreen even if Unity is windowed. If disabled, video will be shown over the whole unity window when playing it fullscreen.")]
90
    public bool CompleteFullscreen = false;
91
92
    [Header("Audio Options")]
93
    [Tooltip("When loading a video, just play the sound. Useful for Youtube music videos, for example.")]
94
    public bool AudioOnly = false;
95
    [Tooltip("Shows only the video without sound.")]
96
    public bool NoAudio = false;
97
98
    [Header("VLC Command Line Parameters to Use")]
99
    [Tooltip("For unlimited possibilities, you can put VLC command line parameters seperated by blank spaces here. See the VLC help for all available commands: https://wiki.videolan.org/VLC_command-line_help/")]
100
    public string ExtraCommandLineParameters = "";
101
102
    [Header("Windowed playback")]
103
    [Tooltip("Render \"windowed\" video on GUI RectTransform?.")]
104
    public bool UseGUIVideoPanelPosition = false;
105
    public RectTransform GuiVideoPanel;
106
    [Header("Skip Video Hint")]
107
    [Tooltip("Show a skip hint under the video.")]
108
    public bool ShowBottomSkipHint = false;
109
    public GameObject BottomSkipHint;
110
111
    [Header("Video in Background (Experimental)")]
112
    [Tooltip("If enabled, fullsceen video will be played under the rendered unity window. 3D Objects and UI will remain visible. Uses keying, modify VideoInBackgroundCameraPrefab prefab for a different color key, if there are any problems.")]
113
    public bool VideoInBackground = false;
114
    [Tooltip("Drag the Camera Prefab that comes with this package here, or create your own keying Camera.")]
115
    public GameObject VideoInBackgroundCameraPrefab;
116
117
    [Header("New features in 1.03 (Using VLC 2.2.1: Youtube streaming)")]
118
    [Tooltip("Obsolete if you check PinVideo. Otherwise, if you use a higher version than 2.0.8, you have to check this box - Otherwise there might be a problem introduced by a unfixed bug in VLC releases since 2.1.0.")]
119
    public bool UseVlc210OrHigher = true;
120
    [Tooltip("Pin the video to the UI panel or Unity window. You can then scale or move the UI elements dynamically, and the video will do the same and handle aspect automatically.")]
121
    public bool PinVideo = true;
122
123
124
    [Header("NEW: Control Requests - Additional Controls and Functionality, use different ports for more instances of PlayVLC (Experimental)")]
125
    [Tooltip("Use new control functionality - experimental")]
126
    public bool EnableControlRequests = true;
127
    //public string CustomHTTPRequestURL = "";
128
    [Tooltip("Specify custom port, use different ports for multiple videos at once!")]
129
    public string VLCControlPort = "8080";
130
    private string userName = "";
131
    private string userPassword = "vlcHttp";
132
133
    [HideInInspector]
134
    public Text Debtext;
135
    [Header("Debug - Only change when neccessary")]
136
137
    [Tooltip("This setting fixes the sometimes experieced green line bug that VLC has on certain AMD cards.")]
138
    public
139
    bool NoHardwareYUVConversion = false;
140
    [Tooltip("Interval that the video information is updated. Only if new Control Requests are enabled.")]
141
    public float VideoInfoUpdateInterval = 0.5f;
142
    public bool DisableHighDpiCompatibilityMode = false;
143
    [Tooltip("It is not recommended to disable this.")]
144
    public bool FlickerFix = true;
145
    private bool _focusInUpdate = false;
146
    public string Tex2DStreamPort = "1234";
147
    //--------------------------------------------------------
148
    private int nameSeed;
149
150
151
152
    #endregion PublicVariables
153
154
    #region PrivateVariables
155
156
    private Process _vlc;
157
    private IntPtr _unityHwnd;
158
    private IntPtr _vlcHwnd;
159
160
    private RECT _unityWindowRect;
161
    private RECT _vlcWindowRect;
162
163
    private uint _unityWindowID = 0;
164
165
    private float _mainMonitorWidth = 0;
166
    private Vector2 _realCurrentMonitorDeskopResolution;
167
    private Rect _realCurrentMonitorBounds;
168
    //private bool _pinToGuiRectDistanceTaken = false;
169
170
    private int _pinToGuiRectLeftOffset;
171
    private int _pinToGuiRectTopOffset;
172
173
    [HideInInspector]
174
    public bool _isPlaying = false;
175
    public bool IsPlaying
176
    {
177
        get { return _isPlaying; }
178
        set { _isPlaying = value; }
179
    }
180
181
    private bool _thisVlcProcessWasEnded = false;
182
    private bool _qtCheckEnabled = false;
183
184
    private Camera[] allCameras;
185
    private GameObject VideoInBackgroundCamera;
186
187
188
189
    private float _nXpos;
190
    private float _nYpos;
191
    private float _nWidth;
192
    private float _nHeight;
193
194
    // private Rect _oldPrect;
195
196
    private float _prev_nXpos;
197
    private float _prev_nYpos;
198
    private float _prev_nWidth;
199
    private float _prev_nHeight;
200
    private float highdpiscale;
201
202
    private PlayVLC[] videos;
203
    private float bottomSkipHintSize;
204
205
206
    //----------New in 1.04:------------------------------------
207
    private bool TextureStream = false;
208
    private bool TranscodeTextureStream = true;
209
210
    private int _currentAudioLevel = 100;
211
    private int _desiredAudioLevel;
212
213
    private bool VideoInBackground_CheckAllowed = false;
214
215
    //Video Info from HTTPRequests to VLC for current video
216
    private int _VideoInfo_CurrentTimeSeconds;
217
    private int _VideoInfo_DurationSeconds;
218
    private float _VideoInfo_PositionPercentage;
219
    private int _VideoInfo_CurrentVolume;
220
    private float _VideoInfo_PlayBackRate;
221
    private bool _VideoInfo_IsLooping;
222
    private bool _VideoInfo_IsRandomPlayback;
223
224
    //more additional Info coming soon
225
    //private string _VideoInfo_VideoCodec;
226
    //private string _VideoInfo_AudioCodec;
227
228
229
    #endregion PrivateVariables
230
231
    #region dll Import
232
233
    [DllImport("user32.dll")] public static extern IntPtr FindWindow(string className, string windowName);
234
    [DllImport("user32.dll")] internal static extern IntPtr SetForegroundWindow(IntPtr hWnd);
235
    [DllImport("user32.dll")] internal static extern bool ShowWindow(IntPtr hWnd, int nCmdShow);
236
    [DllImport("user32.dll")] static extern uint GetActiveWindow();
237
    [DllImport("user32.dll")] private static extern void keybd_event(byte bVk, byte bScan, uint dwFlags, int dwExtraInfo);
238
    [DllImport("user32.dll", CharSet = CharSet.Auto, CallingConvention = CallingConvention.StdCall, ExactSpelling = true, SetLastError = true)]
239
    internal static extern void MoveWindow(IntPtr hwnd, int X, int Y, int nWidth, int nHeight, bool bRepaint);
240
    [DllImport("User32.dll")] private static extern IntPtr MonitorFromPoint([In]Point pt, [In]uint dwFlags);
241
    [DllImport("Shcore.dll")] private static extern IntPtr GetDpiForMonitor([In]IntPtr hmonitor, [In]DpiType dpiType, [Out]out uint dpiX, [Out]out uint dpiY);
242
    [DllImport("user32.dll", SetLastError = true)]
243
    [return: MarshalAs(UnmanagedType.Bool)]
244
    static extern bool GetWindowRect(IntPtr hWnd, ref RECT lpRect);
245
246
    [StructLayout(LayoutKind.Sequential)]
247
    public struct RECT
248
    {
249
        public int Left;
250
        public int Top;
251
        public int Right;
252
        public int Bottom;
253
    }
254
255
    [DllImport("gdi32.dll")] static extern int GetDeviceCaps(IntPtr hdc, int nIndex);
256
    public enum DeviceCap
257
    {
258
        VERTRES = 10,
259
        DESKTOPVERTRES = 117,
260
    }
261
262
    public enum DpiType
263
    {
264
        Effective = 0,
265
        Angular = 1,
266
        Raw = 2,
267
    }
268
269
    [DllImport("user32.dll")] static extern IntPtr GetDC(IntPtr hWnd);
270
271
    #endregion
272
273
274
275
    private float GetMainSceenUserScalingFactor()
276
    {
277
#if !UNITY_EDITOR
278
  System.Drawing.Graphics g = System.Drawing.Graphics.FromHwnd(IntPtr.Zero);
279
  IntPtr desktop = g.GetHdc();
280
  int logicalScreenHeight = GetDeviceCaps(desktop, (int)DeviceCap.VERTRES);
281
  int physicalScreenHeight = GetDeviceCaps(desktop, (int)DeviceCap.DESKTOPVERTRES);
282
  float screenScalingFactor = (float)physicalScreenHeight / (float)logicalScreenHeight;
283
#else
284
        float screenScalingFactor = 1;
285
#endif
286
        return screenScalingFactor;
287
    }
288
289
    private bool UnityIsOnPrimaryScreen()
290
    {
291
        _unityWindowRect = new RECT();
292
        GetWindowRect(_unityHwnd, ref _unityWindowRect);
293
294
        if (_unityWindowRect.Left + 10 < 0 || _unityWindowRect.Left + 10 > _mainMonitorWidth)
295
        {
296
            return false;
297
        }
298
        else
299
        {
300
            return true;
301
        }
302
    }
303
304
    private void UpdateUnityWindowRect()
305
    {
306
        _unityWindowRect = new RECT();
307
        GetWindowRect(_unityHwnd, ref _unityWindowRect);
308
    }
309
310
    public void TextureStreamDontTranscode()
311
    {
312
        TranscodeTextureStream = false;
313
    }
314
315
    public void TextureStreamDoTranscode()
316
    {
317
        TranscodeTextureStream = true;
318
    }
319
320
    public void EnableTextureStream()
321
    {
322
        TextureStream = true;
323
    }
324
325
326
    private Vector2 GetCurrentMonitorDesktopResolution()
327
    {
328
        Vector2 v;
329
        Form f = new Form();
330
        f.BackColor = Color.Black;
331
        f.ForeColor = Color.Black;
332
        f.ShowInTaskbar = false;
333
        f.Opacity = 0.0f;
334
        f.Show();
335
        f.StartPosition = FormStartPosition.Manual;
336
        UpdateUnityWindowRect();
337
        f.Location = new Point(_unityWindowRect.Left, _unityWindowRect.Top);
338
339
        f.WindowState = FormWindowState.Maximized;
340
341
        float SF = GetMainSceenUserScalingFactor();
342
343
        if (UnityIsOnPrimaryScreen() && GetMainSceenUserScalingFactor() != 1)
344
        {
345
            v = new Vector2((f.DesktopBounds.Width - 16) * SF, (f.DesktopBounds.Height + 40 - 16) * SF);
346
            _realCurrentMonitorBounds = new Rect((f.DesktopBounds.Left + 8) * SF, (f.DesktopBounds.Top) * SF,
347
                (f.DesktopBounds.Width - 16) * SF, (f.DesktopBounds.Height + 40) * SF);
348
        }
349
        else
350
        {
351
            v = new Vector2(f.DesktopBounds.Width - 16, f.DesktopBounds.Height + 40 - 16);
352
            _realCurrentMonitorBounds = new Rect((f.DesktopBounds.Left + 8), (f.DesktopBounds.Top),
353
                (f.DesktopBounds.Width - 16), (f.DesktopBounds.Height + 40));
354
        }
355
356
        f.Close();
357
        _realCurrentMonitorDeskopResolution = v;
358
        return v;
359
    }
360
361
    private void CheckErrors()
362
    {
363
364
        //TODO: when playing YT videos, check if connected to the web first: else show warning https://stackoverflow.com/questions/2031824/what-is-the-best-way-to-check-for-internet-connectivity-using-net
365
366
        /* if (VideoPath.Length > 5 && VideoPath.StartsWith("https://www.youtube.com/watch?") && !PlayFromStreamingAssets){
367
             Debug.LogWarning("You are streaming from youtube, make sure you've got a internet connection. Seeking might be less performant, depending on your internet speed.");
368
         } */
369
370
        if (StreamingAssetsVideoFilename.Length < 1 && PlayFromStreamingAssets && !File.Exists(Application.dataPath.Replace("/", "\\") + "\\StreamingAssets\\" + StreamingAssetsVideoFilename))
371
        {
372
            Debug.LogError("Please enter a valid video file name!");
373
        }
374
        /*  if (VideoPath.Length < 1 && !PlayFromStreamingAssets && !ExternalField.gameObject.activeSelf) {
375
              Debug.LogError("Please enter a valid video file name!");
376
          } */
377
        if ((!VideoInBackground && LoopVideo && (CompleteFullscreen || !UseGUIVideoPanelPosition) && !SkipVideoWithAnyKey &&
378
            !ShowBottomSkipHint) || (UsedRenderMode == RenderMode.FullScreenOverlayModePrimaryDisplay && !SkipVideoWithAnyKey))
379
        {
380
            Debug.LogWarning("You are possibly playing a looping fullscreen video you can't skip! Consider using skipping features, or your players won't be able to get past this video.");
381
        }
382
        if (UseGUIVideoPanelPosition && !GuiVideoPanel)
383
        {
384
            Debug.LogError("If you want to play on a Gui Panel, get the one from the prefabs folder and assign it to this script.");
385
        }
386
        if (ShowBottomSkipHint && !BottomSkipHint)
387
        {
388
            Debug.LogError("If you want to show the prefab skip hint, place the prefab in your GUI and assign it to this script.");
389
        }
390
        if (UsedRenderMode != RenderMode.Direct3DMode)
391
        {
392
            Debug.LogWarning("Please consider using Direct3D Mode. Other modes are experimental or less performant.");
393
        }
394
        if (!UseBuiltInVLC)
395
        {
396
            Debug.LogWarning("Consider using built-in VLC, unless you know you'll have it installed on your target machine.");
397
        }
398
399
        if (UseSubtitles && !File.Exists(Application.dataPath.Replace("/", "\\") + "\\StreamingAssets\\" + StreamingAssetsSubtitlePath))
400
        {
401
            Debug.LogError("Subtitle not found. Did you enter the correct path to the subtitle file?");
402
        }
403
404
        if (SkipVideoWithAnyKey)
405
        {
406
            EnableVlcControls = false;
407
            EnableControlRequests = false;
408
            Debug.LogWarning("[SkipVideoWithAnyKey] is checked on PlayVLC-Instance on GameObject \"" + this.gameObject.name + "\", disabling [EnableVlcControls] and [EnableHTTPRequests]");
409
        }
410
411
        if (CompleteFullscreen)
412
        {
413
            UseGUIVideoPanelPosition = false;
414
            Debug.LogWarning("[CompleteFullscreen] is checked on PlayVLC-Instance on GameObject \"" + this.gameObject.name + "\", disabling [UseGUIVideoPanelPosition]");
415
        }
416
417
    }
418
419
    void Awake()
420
    {
421
        nameSeed = (int)(UnityEngine.Random.value * 1000000);
422
423
        CheckErrors();
424
        _mainMonitorWidth = SystemInformation.PrimaryMonitorMaximizedWindowSize.Width * GetMainSceenUserScalingFactor();
425
        _unityHwnd = (IntPtr)GetActiveWindow();
426
        _unityWindowRect = new RECT();
427
        GetWindowRect(_unityHwnd, ref _unityWindowRect);
428
        _realCurrentMonitorDeskopResolution = GetCurrentMonitorDesktopResolution();
429
        _unityWindowID = GetActiveWindow();
430
    }
431
432
    void Start()
433
    {
434
435
        videos = GameObject.FindObjectsOfType<PlayVLC>();
436
437
        Play();
438
        if (PlayOnStart)
439
        {
440
            Play();
441
        }
442
    }
443
444
    public static Rect RectTransformToScreenSpace(RectTransform transform)
445
    {
446
        Vector2 size = Vector2.Scale(transform.rect.size, transform.lossyScale);
447
        return new Rect(transform.position.x, Screen.height - transform.position.y, size.x, size.y);
448
    }
449
450
    private uint GetCurrentMonitorDPI()
451
    {
452
        var monitor = MonitorFromPoint(new Point(_unityWindowRect.Left + 15, _unityWindowRect.Top), 2);
453
        uint CurrentMonitorDPI_X, CurrentMonitorDPI_Y;
454
        GetDpiForMonitor(monitor, DpiType.Raw, out CurrentMonitorDPI_X, out CurrentMonitorDPI_Y);
455
        return CurrentMonitorDPI_X;
456
    }
457
458
    public void QuitAllVideos()
459
    {
460
        if (videos != null && videos.Length > 0)
461
        {
462
            foreach (PlayVLC video in videos)
463
            {
464
                if (video.IsPlaying)
465
                    video.StopVideo();
466
            }
467
        }
468
    }
469
470
    #region Controls
471
472
    private string GetShortCutCodes()
473
    {
474
        string p = "";
475
        if (EnableVlcControls)
476
        {
477
            //p += " --global-key-play-pause \"p\" ";
478
            //p += " --global-key-jump+short \"4\" ";
479
            //p += " --global-key-jump+medium \"5\" ";
480
            //p += " --global-key-jump+long \"6\" ";
481
            //p += " --global-key-jump-long \"1\" ";
482
            //p += " --global-key-jump-medium \"2\" ";
483
            //p += " --global-key-jump-short \"3\" ";
484
            //p += " --global-key-vol-down \"7\" ";
485
            //p += " --global-key-vol-up \"8\" ";
486
            //p += " --global-key-vol-mute \"9\" ";
487
        }
488
        return p;
489
    }
490
491
    /// <summary>
492
    /// Incease Volume. Depreciated, use Control Requests to VLC --> SetVolumeLevel
493
    /// </summary>
494
    /// <param name="newAudioLevel"></param>
495
    public void VolumeUp()
496
    {
497
        if (_isPlaying && EnableVlcControls)
498
        {
499
            keybd_event((byte)0x38, 0x89, 0x1 | 0, 0);
500
            keybd_event((byte)0x38, 0x89, 0x1 | 0x2, 0);
501
            _currentAudioLevel += 5;
502
        }
503
    }
504
505
    /// <summary>
506
    /// Decrease Volume. Depreciated, use Control Requests to VLC --> SetVolumeLevel
507
    /// </summary>
508
    /// <param name="newAudioLevel"></param>
509
    public void VolumeDown()
510
    {
511
        if (_isPlaying && EnableVlcControls)
512
        {
513
            keybd_event((byte)0x37, 0x88, 0x1 | 0, 0);
514
            keybd_event((byte)0x37, 0x88, 0x1 | 0x2, 0);
515
            _currentAudioLevel -= 5;
516
        }
517
    }
518
519
    /// <summary>
520
    /// Set volume to a value. Depreciated, use Control Requests to VLC --> SetVolumeLevel
521
    /// </summary>
522
    /// <param name="newAudioLevel"></param>
523
    public void SetVolumeTo(int newAudioLevel)
524
    {
525
        _desiredAudioLevel = newAudioLevel;
526
527
        int num = Mathf.Abs(_desiredAudioLevel - _currentAudioLevel) / 5;
528
        for (int i = 0; i < num; i++)
529
        {
530
            if (_currentAudioLevel > _desiredAudioLevel)
531
            {
532
                VolumeDown();
533
            }
534
            else if (_currentAudioLevel < _desiredAudioLevel)
535
            {
536
                VolumeUp();
537
            }
538
        }
539
    }
540
    /// <summary>
541
    /// Toggle Mute
542
    /// </summary>
543
    public void ToggleMute()
544
    {
545
        if (_isPlaying && EnableVlcControls)
546
        {
547
            keybd_event((byte)0x39, 0x8A, 0x1 | 0, 0);
548
            keybd_event((byte)0x39, 0x8A, 0x1 | 0x2, 0);
549
        }
550
    }
551
552
    /// <summary>
553
    /// Pause or Resume the current video, you can use the new CR_TogglePlayPause()-function instead.
554
    /// </summary>
555
    public void Pause()
556
    {
557
        if (_isPlaying && EnableVlcControls)
558
        {
559
            keybd_event((byte)0x50, 0x99, 0x1 | 0, 0);
560
            keybd_event((byte)0x50, 0x99, 0x1 | 0x2, 0);
561
        }
562
    }
563
564
565
    /// <summary>
566
    /// Seek forward for a short amount of time, you can use the new -function instead.
567
    /// </summary>
568
    public void SeekForwardShort()
569
    {
570
        if (_isPlaying && EnableVlcControls)
571
        {
572
            keybd_event(0x34, 0x85, 0x1 | 0, 0);
573
            keybd_event(0x34, 0x85, 0x1 | 0x2, 0);
574
575
        }
576
    }
577
    /// <summary>
578
    /// Seek forward for a medium amount of time, you can use the new -function instead.
579
    /// </summary>
580
    public void SeekForwardMedium()
581
    {
582
        if (_isPlaying && EnableVlcControls)
583
        {
584
            keybd_event(0x35, 0x86, 0x1 | 0, 0);
585
            keybd_event(0x35, 0x86, 0x1 | 0x2, 0);
586
        }
587
    }
588
    /// <summary>
589
    /// Seek forward for a longer time, you can use the new -function instead.
590
    /// </summary>
591
    public void SeekForwardLong()
592
    {
593
        if (_isPlaying && EnableVlcControls)
594
        {
595
            keybd_event(0x36, 0x87, 0x1 | 0, 0);
596
            keybd_event(0x36, 0x87, 0x1 | 0x2, 0);
597
        }
598
    }
599
    /// <summary>
600
    /// Seek backward for a short amount of time, you can use the new -function instead.
601
    /// </summary>
602
    public void SeekBackwardShort()
603
    {
604
        if (_isPlaying && EnableVlcControls)
605
        {
606
            keybd_event(0x33, 0x84, 0x1 | 0, 0);
607
            keybd_event(0x33, 0x84, 0x1 | 0x2, 0);
608
        }
609
    }
610
    /// <summary>
611
    /// Seek backward for a medium amount of time, you can use the new -function instead.
612
    /// </summary>
613
    public void SeekBackwardMedium()
614
    {
615
        if (_isPlaying && EnableVlcControls)
616
        {
617
            keybd_event(0x32, 0x83, 0x1 | 0, 0);
618
            keybd_event(0x32, 0x83, 0x1 | 0x2, 0);
619
        }
620
    }
621
    /// <summary>
622
    /// Seek forward for a longer time, you can use the new -function instead.
623
    /// </summary>
624
    public void SeekBackwardLong()
625
    {
626
        if (_isPlaying && EnableVlcControls)
627
        {
628
            keybd_event(0x31, 0x82, 0x1 | 0, 0);
629
            keybd_event(0x31, 0x82, 0x1 | 0x2, 0);
630
        }
631
    }
632
633
    #endregion
634
635
    #region CONTROL REQUESTS
636
    /*NEW CONTROL AND INFO FUNCTIONS: Control multiple videos at the same time with these new and improved control functions! */
637
638
    /// <summary>
639
    /// Print Video Information to console
640
    /// </summary>
641
    public void CR_PrintVideoInfo()
642
    {
643
        if (EnableControlRequests)
644
        {
645
            PrintSavedVideoInfoToConsole();
646
        }
647
        else
648
        {
649
            Debug.LogWarning("Please enable Control Requests");
650
        }
651
    }
652
653
    private void UpdateVideoInformation()
654
    {
655
        if (IsPlaying && VLCWindowIsRendered())
656
        {
657
            var request = WebRequest.Create("http://localhost:" + VLCControlPort + "/requests/status.xml");
658
            string authInfo = userName + ":" + userPassword;
659
            authInfo = Convert.ToBase64String(Encoding.Default.GetBytes(authInfo));
660
            request.Headers["Authorization"] = "Basic " + authInfo;
661
            request.BeginGetResponse(new AsyncCallback(VideoDataFinishRequest), request);
662
        }
663
    }
664
665
    void VideoDataFinishRequest(IAsyncResult result)
666
    {
667
        using (HttpWebResponse response = (result.AsyncState as HttpWebRequest).EndGetResponse(result) as HttpWebResponse)
668
        {
669
            StreamReader sr = new StreamReader(response.GetResponseStream());
670
            string xmlString = sr.ReadToEnd();
671
            sr.Close();
672
673
            XmlDocument xmlDoc = new XmlDocument();
674
            xmlDoc.LoadXml(xmlString);
675
676
            _VideoInfo_CurrentTimeSeconds = Convert.ToInt16(xmlDoc["root"]["time"].InnerText);
677
            _VideoInfo_DurationSeconds = Convert.ToInt16(xmlDoc["root"]["length"].InnerText);
678
            _VideoInfo_CurrentVolume = Convert.ToInt16(xmlDoc["root"]["volume"].InnerText);
679
            _VideoInfo_PlayBackRate = Convert.ToSingle(xmlDoc["root"]["rate"].InnerText);
680
            _VideoInfo_PositionPercentage = Convert.ToSingle(xmlDoc["root"]["position"].InnerText);
681
            _VideoInfo_IsLooping = Convert.ToBoolean(xmlDoc["root"]["loop"].InnerText);
682
            _VideoInfo_IsRandomPlayback = Convert.ToBoolean(xmlDoc["root"]["random"].InnerText);
683
        }
684
    }
685
686
    private void PrintSavedVideoInfoToConsole()
687
    {
688
        if (IsPlaying)
689
        {
690
            print("Current Time in Seconds : " + _VideoInfo_CurrentTimeSeconds);
691
            print("Duration in Seconds: " + _VideoInfo_DurationSeconds);
692
            print("Current Volume Level: " + _VideoInfo_CurrentVolume);
693
            print("Current Playback Rate: " + _VideoInfo_PlayBackRate);
694
            print("Current Position Percentage in Timeline: " + _VideoInfo_PositionPercentage);
695
            print("Is Looping: " + _VideoInfo_IsLooping);
696
            print("Is Random Playback: " + _VideoInfo_IsRandomPlayback);
697
        }
698
        else
699
        {
700
            Debug.LogWarning("Play a video to access the video info. Command requests must be activated in the settings.");
701
        }
702
703
    }
704
705
    /// <summary>
706
    /// Get current time in seconds.
707
    /// </summary>
708
    /// <returns>current time in seconds ,returns -1 if not playing</returns>
709
    public int CR_GetCurrentTime()
710
    {
711
        if (IsPlaying)
712
        {
713
            return _VideoInfo_CurrentTimeSeconds;
714
        }
715
        else
716
        {
717
            return -1;
718
        }
719
    }
720
721
    public void CR_LoadPlayList()
722
    {
723
        if (EnableControlRequests && EnableVlcControls)
724
        {
725
            WebRequest request = WebRequest.Create("http://localhost:" + VLCControlPort + "/requests/playlist.xml");
726
            request.Headers["Authorization"] = "Basic " + Convert.ToBase64String(Encoding.Default.GetBytes(userName + ":" + userPassword));
727
            request.BeginGetResponse(new AsyncCallback(FinishPlayList), request);
728
        }
729
    }
730
    public int[] playListID;
731
732
    private void FinishPlayList(IAsyncResult result)
733
    {
734
        using (HttpWebResponse response = (result.AsyncState as HttpWebRequest).EndGetResponse(result) as HttpWebResponse)
735
        {
736
            StreamReader sr = new StreamReader(response.GetResponseStream());
737
            string xmlString = sr.ReadToEnd();
738
            sr.Close();
739
            XmlDocument doc = new XmlDocument();
740
            doc.LoadXml(xmlString);
741
            XmlNode rootNode = doc.DocumentElement;
742
743
            foreach (XmlElement child in rootNode.ChildNodes)
744
            {
745
                if (child.GetAttribute("name") == "Playlist")
746
                {
747
                    playListID = new int[StreamingAssetsVideoPlaylistItems.Length];
748
                    for (int i = 0; i < StreamingAssetsVideoPlaylistItems.Length; i++)
749
                    {
750
                        foreach (XmlElement videos in child.ChildNodes)
751
                        {
752
                            if (videos.GetAttribute("name") == StreamingAssetsVideoPlaylistItems[i])
753
                            {
754
                                playListID[i] = int.Parse(videos.GetAttribute("id"));
755
                                break;
756
                            }
757
                        }
758
                    }
759
760
                    break;
761
                }
762
            }
763
        }
764
    }
765
766
    /// <summary>
767
    /// Get length of the current video in seconds.
768
    /// </summary>
769
    /// <returns> video length in seconds, returns -1 if not playing</returns>
770
    public int CR_GetVideoDuration()
771
    {
772
        if (IsPlaying)
773
        {
774
            return _VideoInfo_DurationSeconds;
775
        }
776
        else
777
        {
778
            return -1;
779
        }
780
    }
781
    /// <summary>
782
    /// Get current volume level
783
    /// </summary>
784
    /// <returns>current volume level, returns -1 if not playing</returns>
785
    public int CR_GetCurrentVolumeLevel()
786
    {
787
        if (IsPlaying)
788
        {
789
            return _VideoInfo_CurrentTimeSeconds;
790
        }
791
        else
792
        {
793
            return -1;
794
        }
795
    }
796
    /// <summary>
797
    /// Returns playback rate
798
    /// </summary>
799
    /// <returns>Playback multiplier, returns -1 if not playing</returns>
800
    public float CR_GetCurrentPlaybackRate()
801
    {
802
        if (IsPlaying)
803
        {
804
            return _VideoInfo_CurrentTimeSeconds;
805
        }
806
        else
807
        {
808
            return -1;
809
        }
810
    }
811
812
    /// <summary>
813
    /// Returns the current position in the timeline
814
    /// </summary>
815
    /// <returns> current position in the timeline from 0 to 1, returns -1 if not playing</returns>
816
    public float CR_GetCurrentVideoSeekPosition()
817
    {
818
        if (IsPlaying)
819
        {
820
            return _VideoInfo_PositionPercentage;
821
        }
822
        else
823
        {
824
            return -1;
825
        }
826
    }
827
828
    /// <summary>
829
    /// Is the video looping?
830
    /// </summary>
831
    /// <returns></returns>
832
    public bool CR_IsVideoLooping()
833
    {
834
835
        if (IsPlaying)
836
        {
837
            return _VideoInfo_IsLooping;
838
        }
839
840
        return false;
841
    }
842
843
    /// <summary>
844
    /// Is the video playlist set random playback?
845
    /// </summary>
846
    /// <returns></returns>
847
    public bool CR_IsRandomPlayback()
848
    {
849
        if (IsPlaying)
850
        {
851
            return _VideoInfo_IsRandomPlayback;
852
        }
853
        return false;
854
    }
855
856
    /// <summary>
857
    /// Toggle Pause / Play
858
    /// </summary>
859
    public void CR_TogglePlayPause()
860
    {
861
        if (EnableControlRequests)
862
        {
863
            DoVLCCommandWebRequest("http://localhost:" + VLCControlPort + "/requests/status.xml?command=pl_pause");
864
        }
865
        else
866
        {
867
            Debug.LogWarning("Please enable Control Requests for CR_TogglePlayPause()");
868
        }
869
    }
870
871
    /// <summary>
872
    /// Jump to a specific second in the timeline of the video
873
    /// </summary>
874
    /// <param name="second">Second to jump to</param>
875
    public void CR_JumpToSecond(int second)
876
    {
877
        if (EnableControlRequests)
878
        {
879
            DoVLCCommandWebRequest("http://localhost:" + VLCControlPort + "/requests/status.xml?command=seek&val=" + second);
880
        }
881
        else
882
        {
883
            Debug.LogWarning("Please enable Control Requests for CR_JumpToSecond(int second)");
884
        }
885
    }
886
    /*
887
888
         */
889
890
    public void CR_SetPersentage(int idx, int persent)
891
    {
892
        if (playListID == null) return;
893
        //?command=pl_play&id=<id>
894
        if (EnableControlRequests)
895
        {
896
            if (IsPlaying && EnableControlRequests && EnableVlcControls)
897
            {
898
                WebRequest request = WebRequest.Create("http://localhost:" + VLCControlPort + "/requests/status.xml?command=seek&val=" + persent + "%");
899
900
                request.Headers["Authorization"] = "Basic " + Convert.ToBase64String(Encoding.Default.GetBytes(userName + ":" + userPassword));
901
                request.Timeout = 5000;
902
                WebResponse wr = request.GetResponse();
903
904
                wr.Close();
905
906
                request = WebRequest.Create("http://localhost:" + VLCControlPort + "/requests/status.xml?command=pl_pause");
907
908
                request.Headers["Authorization"] = "Basic " + Convert.ToBase64String(Encoding.Default.GetBytes(userName + ":" + userPassword));
909
                request.Timeout = 5000;
910
                wr = request.GetResponse();
911
912
                wr.Close();
913
            }
914
915
        }
916
        else
917
        {
918
            Debug.LogWarning("Please enable Control Requests for CR_JumpToSecond(int second)");
919
        }
920
    }
921
    public void CR_PlayItem(int idx, int second)
922
    {
923
        if (playListID == null) return;
924
        //?command=pl_play&id=<id>
925
        if (EnableControlRequests)
926
        {
927
            if (IsPlaying && EnableControlRequests && EnableVlcControls)
928
            {
929
                //float time =+ Time.deltaTime;
930
                //Debug.Log(second);
931
                DoVLCCommandWebRequest("http://localhost:" + VLCControlPort + "/requests/status.xml?command=seek&val=" + second);
932
933
                /*
934
                 WebRequest request = WebRequest.Create("http://localhost:" + VLCControlPort + "/requests/status.xml?command=pl_pause");
935
                 request.Headers["Authorization"] = "Basic " + Convert.ToBase64String(Encoding.Default.GetBytes(userName + ":" + userPassword));
936
                 request.Timeout = 5000;
937
                 WebResponse wr = request.GetResponse();
938
                 wr.Close();
939
940
                 request = WebRequest.Create("http://localhost:" + VLCControlPort + "/requests/status.xml?command=pl_play&id=" + playListID[idx]);
941
                 request.Headers["Authorization"] = "Basic " + Convert.ToBase64String(Encoding.Default.GetBytes(userName + ":" + userPassword));
942
                 request.Timeout = 5000;
943
                 wr = request.GetResponse();
944
                 wr.Close();*/
945
946
                //CR_SeekAdditive(persent);
947
            }
948
949
        }
950
        else
951
        {
952
            Debug.LogWarning("Please enable Control Requests for CR_JumpToSecond(int second)");
953
        }
954
    }
955
956
    /// <summary>
957
    /// Jump forward or backward for a specific amount of time
958
    /// </summary>
959
    /// <param name="second">Number of seconds to go forward (+ positive int) or backward (- negative int)</param>
960
    public void CR_SeekAdditive(int second)
961
    {
962
        if (EnableControlRequests)
963
        {
964
            DoVLCCommandWebRequest("http://localhost:" + VLCControlPort + "/requests/status.xml?command=seek&val=" + ((second >= 0) ? "+" : "-") + second);
965
        }
966
        else
967
        {
968
            Debug.LogWarning("Please enable Control Requests for CR_SeekAdditive(int second)");
969
        }
970
    }
971
972
    /// <summary>
973
    /// When having multiple videos, jump to the next video in the list
974
    /// </summary>
975
    public void CR_NextVideoInList()
976
    {
977
        if (EnableControlRequests)
978
        {
979
            DoVLCCommandWebRequest("http://localhost:" + VLCControlPort + "/requests/status.xml?command=pl_next");
980
        }
981
        else
982
        {
983
            Debug.LogWarning("Please enable Control Requests for CR_NextVideoInList()");
984
        }
985
    }
986
    /// <summary>
987
    /// When having multiple videos, jump to the previous video in the list
988
    /// </summary>
989
    public void CR_PreviousVideoInList()
990
    {
991
        if (EnableControlRequests)
992
        {
993
            DoVLCCommandWebRequest("http://localhost:" + VLCControlPort + "/requests/status.xml?command=pl_previous");
994
        }
995
        else
996
        {
997
            Debug.LogWarning("Please enable Control Requests for CR_PreviousVideoInList()");
998
        }
999
    }
1000
1001
    /// <summary>
1002
    /// Set the value for the playback speed
1003
    /// </summary>
1004
    /// <param name="multi">Playback speed multiplier</param>
1005
    public void CR_SetPlayBackspeedMultiplier(float multi)
1006
    {
1007
        if (EnableControlRequests && multi > 0)
1008
        {
1009
            DoVLCCommandWebRequest("http://localhost:" + VLCControlPort + "/requests/status.xml?command=rate&val=" + multi);
1010
        }
1011
        else
1012
        {
1013
            Debug.LogWarning("Please enable Control Requests for CR_SetPlayBackspeedMultiplier(float multi), multiplier supplied must be > 0");
1014
        }
1015
    }
1016
1017
    /// <summary>
1018
    /// Set Volume in %
1019
    /// </summary>
1020
    /// <param name="percent">new audio volume in percent</param>
1021
    public void SetVolumeLevelPercent(int percent)
1022
    {
1023
        if (EnableControlRequests)
1024
        {
1025
1026
            print("http://localhost:" + VLCControlPort + "/requests/status.xml?command=volume&val=" + percent + "%");
1027
            DoVLCCommandWebRequest("http://localhost:" + VLCControlPort + "/requests/status.xml?command=volume&val=" + percent + "%");
1028
        }
1029
        else
1030
        {
1031
            Debug.LogWarning("Please enable Control Requests for SetVolumeLevelPercent(int percent)");
1032
        }
1033
    }
1034
1035
    /// <summary>
1036
    /// Set the absolute audio level
1037
    /// </summary>
1038
    /// <param name="val">new audio level, 255 is standard</param>
1039
    public void CR_SetVolumeLevelAbsolute(int val)
1040
    {
1041
        if (EnableControlRequests)
1042
        {
1043
            DoVLCCommandWebRequest("http://localhost:" + VLCControlPort + "/requests/status.xml?command=volume&val=" + val);
1044
        }
1045
        else
1046
        {
1047
            Debug.LogWarning("Please enable Control Requests for CR_SetVolumeLevelAbsolute(int val)");
1048
        }
1049
    }
1050
1051
    /// <summary>
1052
    /// Add or remove a value to/from audio level
1053
    /// </summary>
1054
    /// <param name="val">If positive int, increase volume. If negative, decrease volume.</param>
1055
    public void CR_SetVolumeAdditive(int val)
1056
    {
1057
        if (EnableControlRequests)
1058
        {
1059
            DoVLCCommandWebRequest("http://localhost:" + VLCControlPort + "/requests/status.xml?command=volume&val=" + ((val >= 0) ? "+" : "-") + val);
1060
        }
1061
        else
1062
        {
1063
            Debug.LogWarning("Please enable Control Requests for CR_SetVolumeAdditive(int val)");
1064
        }
1065
    }
1066
1067
    /// <summary>
1068
    /// Toggle loop for this instance
1069
    /// </summary>
1070
    public void CR_ToggleLoopWhilePlaying()
1071
    {
1072
        if (EnableControlRequests)
1073
        {
1074
            DoVLCCommandWebRequest("http://localhost:" + VLCControlPort + "/requests/status.xml?command=pl_loop");
1075
        }
1076
        else
1077
        {
1078
            Debug.LogWarning("Please enable Control Requests for CR_ToggleLoopWhilePlaying()");
1079
        }
1080
    }
1081
1082
    /// <summary>
1083
    /// Toggle random playback for the videos, if using a multiple videos
1084
    /// </summary>
1085
    public void CR_ToggleRandomPlayback()
1086
    {
1087
        if (EnableControlRequests)
1088
        {
1089
            DoVLCCommandWebRequest("http://localhost:" + VLCControlPort + "/requests/status.xml?command=pl_random");
1090
        }
1091
        else
1092
        {
1093
            Debug.LogWarning("Please enable Control Requests for CR_ToggleRandomPlayback()");
1094
        }
1095
    }
1096
1097
    //TODO: There seems to be a bug with the current vlc version in this regard, investigate!
1098
    /// <summary>
1099
    /// Add a video that is in streaming assets. Make sure it is really there before calling this function
1100
    /// </summary>
1101
    /// <param name="path">filepath to the media file, starting from Streaming Assets folder</param>
1102
    /* public void CR_AddStreamingAssetsVideoToCurrentPlaylist(string path) {
1103
         if (EnableControlRequests){
1104
             string SAPath= "\"" + Application.dataPath.Replace("/", "\\") + "\\StreamingAssets\\" + path + "\"";
1105
             DoVLCCommandWebRequest("http://localhost:" +     + "/requests/status.xml?command=in_enqueue&input=" + SAPath);
1106
         }else{
1107
             Debug.LogWarning("Please enable Control Requests for  CR_AddStreamingAssetsVideoToCurrentPlaylist(string path)");
1108
         }
1109
     }*/
1110
1111
    //TODO: There seems to be a bug with the current vlc version in this regard, investigate!
1112
1113
    /// <summary>
1114
    ///  Add a external video to the playlist
1115
    /// </summary>
1116
    /// <param name="URL">external url to a media file</param>
1117
    /*public void CR_AddExternalVideoToCurrentPlaylist(string URL){
1118
        if (EnableControlRequests){
1119
            DoVLCCommandWebRequest("http://localhost:" + VLCControlPort + "/requests/status.xml?command=in_enqueue&input=" + URL);
1120
        }else{
1121
            Debug.LogWarning("Please enable Control Requests for CR_AddExternalVideoToCurrentPlaylist(string URL)");
1122
        }
1123
    }*/
1124
1125
    private void DoVLCCommandWebRequest(string url, bool async = true)
1126
    {
1127
        if (IsPlaying && EnableControlRequests && EnableVlcControls)
1128
        {
1129
            WebRequest request = WebRequest.Create(url);
1130
            request.Headers["Authorization"] = "Basic " + Convert.ToBase64String(Encoding.Default.GetBytes(userName + ":" + userPassword));
1131
1132
            if (async)
1133
            {
1134
                request.BeginGetResponse(new AsyncCallback(FinishWebRequest), request);
1135
            }
1136
            else
1137
            {
1138
                request.Timeout = 100;
1139
                WebResponse wr = request.GetResponse();
1140
                wr.Close();
1141
            }
1142
        }
1143
    }
1144
1145
    void FinishWebRequest(IAsyncResult result)
1146
    {
1147
        using (HttpWebResponse response = (result.AsyncState as HttpWebRequest).EndGetResponse(result) as HttpWebResponse)
1148
        {
1149
        }
1150
    }
1151
1152
    #endregion
1153
1154
    private bool CheckQTAllowed()
1155
    {
1156
        if (UsedRenderMode == RenderMode.VLC_QT_InterfaceFullscreen)
1157
        {
1158
#if !UNITY_EDITOR
1159
            return Screen.fullScreen;
1160
#else
1161
            return true;
1162
#endif
1163
        }
1164
        else
1165
        {
1166
            return true;
1167
        }
1168
    }
1169
1170
    private float GetHighDPIScale()
1171
    {
1172
        float highdpiscale = 1;
1173
1174
        if (!DisableHighDpiCompatibilityMode)
1175
        {
1176
            if (UnityIsOnPrimaryScreen() && GetMainSceenUserScalingFactor() > 1)
1177
            {
1178
#if !UNITY_EDITOR && UNITY_STANDALONE_WIN
1179
                    highdpiscale = GetMainSceenUserScalingFactor();
1180
#endif
1181
            }
1182
        }
1183
1184
        return highdpiscale;
1185
    }
1186
1187
    private Rect GetPanelRect()
1188
    {
1189
        float highdpiscale = GetHighDPIScale();
1190
1191
        Rect panel = RectTransformToScreenSpace(GuiVideoPanel);
1192
1193
        float leftOffset = 0;
1194
        float topOffset = 0;
1195
1196
        if (!Screen.fullScreen)
1197
        {
1198
#if UNITY_EDITOR_WIN
1199
            leftOffset = 7;
1200
            topOffset = 47;
1201
#endif
1202
1203
#if !UNITY_EDITOR && UNITY_STANDALONE_WIN
1204
                leftOffset = 3;
1205
                topOffset = 20;
1206
#endif
1207
        }
1208
1209
        float fullScreenResolutionModifierX = 1;
1210
        float fullScreenResolutionModifierY = 1;
1211
        float blackBorderOffsetX = 0;
1212
1213
        if (Screen.fullScreen)
1214
        {
1215
            fullScreenResolutionModifierX = _realCurrentMonitorDeskopResolution.x / (float)Screen.currentResolution.width;
1216
            fullScreenResolutionModifierY = _realCurrentMonitorDeskopResolution.y / (float)Screen.currentResolution.height;
1217
1218
            float aspectMonitor = _realCurrentMonitorDeskopResolution.x / _realCurrentMonitorDeskopResolution.y;
1219
            float aspectUnity = (float)Screen.currentResolution.width / (float)Screen.currentResolution.height;
1220
            blackBorderOffsetX = (_realCurrentMonitorDeskopResolution.x - ((aspectUnity / aspectMonitor) * _realCurrentMonitorDeskopResolution.x)) / 2;
1221
        }
1222
1223
        float aspectOffsetX = (_realCurrentMonitorDeskopResolution.x - blackBorderOffsetX * 2) / _realCurrentMonitorDeskopResolution.x;
1224
        float left = panel.xMin * fullScreenResolutionModifierX * aspectOffsetX + _unityWindowRect.Left + leftOffset;
1225
        float top = panel.yMin * fullScreenResolutionModifierY + _unityWindowRect.Top + topOffset;
1226
1227
        _nXpos = ((blackBorderOffsetX + left * highdpiscale));
1228
        _nYpos = top * highdpiscale;
1229
        _nWidth = (panel.width * fullScreenResolutionModifierX * aspectOffsetX) * highdpiscale;
1230
        _nHeight = panel.height * highdpiscale * fullScreenResolutionModifierY;
1231
        return new Rect(_nXpos, _nYpos, _nWidth, _nHeight);
1232
    }
1233
1234
    private Rect GetFullscreenRect()
1235
    {
1236
        return new Rect();
1237
    }
1238
1239
    private Rect GetCompleteFullscreenRect()
1240
    {
1241
        return new Rect();
1242
    }
1243
1244
    public void Play()
1245
    {
1246
        _currentAudioLevel = 100;
1247
        CR_LoadPlayList();
1248
1249
        bool qtPlayAllowed = CheckQTAllowed();
1250
1251
        if (!_isPlaying && qtPlayAllowed)
1252
        {
1253
1254
            if (EnableControlRequests)
1255
            {
1256
                InvokeRepeating("UpdateVideoInformation", 1f, 1f);
1257
            }
1258
1259
            //  QuitAllVideos();
1260
            _realCurrentMonitorDeskopResolution = GetCurrentMonitorDesktopResolution();
1261
1262
            _isPlaying = true;
1263
            _thisVlcProcessWasEnded = false;
1264
            if (GuiVideoPanel != null)
1265
            {
1266
                //  GuiVideoPanel.GetComponent<UnityEngine.UI.Image>().enabled = false;
1267
            }
1268
1269
            //------------------------------FILE--------------------------------------------------
1270
1271
            string usedVideoPath = "";
1272
1273
            if (PlayFromStreamingAssets)
1274
            {
1275
                if (StreamingAssetsVideoFilename.Length > 0)
1276
                {
1277
                    usedVideoPath = "\"" + Application.dataPath.Replace("/", "\\") + "\\StreamingAssets\\" +
1278
                                    StreamingAssetsVideoFilename + "\"";
1279
1280
                    if (StreamingAssetsVideoPlaylistItems.Length > 0)
1281
                    {
1282
                        for (int i = 0; i < StreamingAssetsVideoPlaylistItems.Length; i++)
1283
                        {
1284
                            string s = StreamingAssetsVideoPlaylistItems[i];
1285
                            usedVideoPath += " \"" + Application.dataPath.Replace("/", "\\") + "\\StreamingAssets\\" +
1286
                                s + "\" ";
1287
                        }
1288
                    }
1289
                }
1290
                else
1291
                {
1292
                    Debug.LogError("ERROR: No StreamingAssets video path(s) set.");
1293
                }
1294
            }
1295
            else
1296
            {
1297
1298
                if (ExternalField != null && ExternalField.text.Length > 0)
1299
                {
1300
                    //use external field
1301
                    usedVideoPath = "\"" + ExternalField.text + "\"";
1302
                    print(usedVideoPath + " will be used.");
1303
                }
1304
                else if (VideoPaths.Length > 0)
1305
                {
1306
                    //use string array
1307
                    string s = "";
1308
1309
                    foreach (string videoPath in VideoPaths)
1310
                    {
1311
                        if (videoPath.Length > 0)
1312
                        {
1313
                            s += "\"" + videoPath + "\" ";
1314
                        }
1315
                    }
1316
                    usedVideoPath = s;
1317
                }
1318
                else
1319
                {
1320
                    Debug.LogError("ERROR: No URL video path(s) set.");
1321
                }
1322
1323
            }
1324
1325
            if (UseSubtitles)
1326
            {
1327
                usedVideoPath += " --sub-file \"" + Application.dataPath.Replace("/", "\\") + "\\StreamingAssets\\" + StreamingAssetsSubtitlePath + "\" ";
1328
            }
1329
1330
            string _path = usedVideoPath + " --ignore-config --no-crashdump " + GetShortCutCodes();
1331
1332
            //print(usedVideoPath);
1333
1334
            if (!TextureStream)
1335
            {
1336
                //------------------------------DIRECT3D--------------------------------------------------
1337
1338
                if (UsedRenderMode == RenderMode.Direct3DMode)
1339
                {
1340
                    _unityWindowRect = new RECT();
1341
                    GetWindowRect(_unityHwnd, ref _unityWindowRect);
1342
1343
                    int width = Mathf.Abs(_unityWindowRect.Right - _unityWindowRect.Left);
1344
                    int height = Mathf.Abs(_unityWindowRect.Bottom - _unityWindowRect.Top);
1345
1346
                    highdpiscale = GetHighDPIScale();
1347
1348
                    _path += @" -I=dummy --no-mouse-events --no-interact --no-video-deco "; //
1349
1350
                    if (!VideoInBackground)
1351
                    {
1352
                        _path += @" --video-on-top ";
1353
                    }
1354
1355
                    //--------------------------- ON UI----------------------------------------------------------
1356
1357
1358
                    if (UseGUIVideoPanelPosition && GuiVideoPanel)
1359
                    {
1360
                        Rect pRect = GetPanelRect();
1361
1362
                        if (!UseVlc210OrHigher)
1363
                        {
1364
                            _path += @" --video-x=" + pRect.xMin + " --video-y=" + pRect.yMin + " --width=" +
1365
                                     (pRect.xMax - pRect.xMin) + " --height=" + (pRect.yMax - pRect.yMin) + " ";
1366
                        }
1367
                        else
1368
                        {
1369
                            _path += @" --video-x=" + 6000 + " --video-y=" + 6000;
1370
1371
                            //   _path += @" --video-x=" + pRect.left + " --video-y=" + pRect.top + " --width=" +
1372
                            //      (pRect.xMax - pRect.xMin) + " --height=" + (pRect.yMax - pRect.yMin) + " ";
1373
1374
                        }
1375
                    }
1376
                    else
1377
                    {
1378
                        //--------------------------- NORMAL FS-----------------------------------------
1379
1380
                        float bottomSkipHintSize = 0;
1381
1382
                        if (ShowBottomSkipHint)
1383
                        {
1384
                            BottomSkipHint.SetActive(true);
1385
1386
                            //Add click to skip hint when not skipping with any button
1387
                            BottomSkipHint.GetComponent<UnityEngine.UI.Button>().onClick.AddListener(KillVLCProcess);
1388
1389
                            if (UnityIsOnPrimaryScreen() && GetMainSceenUserScalingFactor() > 1)
1390
                            {
1391
                                bottomSkipHintSize =
1392
                                    RectTransformToScreenSpace(BottomSkipHint.GetComponent<RectTransform>()).height *
1393
                                    GetMainSceenUserScalingFactor();
1394
                            }
1395
                            else
1396
                            {
1397
                                bottomSkipHintSize =
1398
                                    RectTransformToScreenSpace(BottomSkipHint.GetComponent<RectTransform>()).height;
1399
                            }
1400
#if UNITY_EDITOR_WIN
1401
                            bottomSkipHintSize =
1402
                                RectTransformToScreenSpace(BottomSkipHint.GetComponent<RectTransform>()).height;
1403
#endif
1404
                        }
1405
1406
                        if (_unityWindowRect.Top == 0)
1407
                        {
1408
                            _unityWindowRect.Top = -1;
1409
                            height += 2;
1410
                        }
1411
                        if (_unityWindowRect.Left == 0)
1412
                        {
1413
                            _unityWindowRect.Left = -1;
1414
                            width += 2;
1415
                        }
1416
1417
                        //--------------------------- COMPLETE FS-----------------------------------------
1418
                        if (CompleteFullscreen)
1419
                        {
1420
1421
                            GetCurrentMonitorDesktopResolution();
1422
1423
                            _path += @" --video-x=" + _realCurrentMonitorBounds.xMin + " --video-y=" +
1424
                                     _realCurrentMonitorBounds.yMin + " --width=" + _realCurrentMonitorBounds.width +
1425
                                     " --height=" + (_realCurrentMonitorBounds.height + 4) + " ";
1426
                            //  print(_realCurrentMonitorBounds);
1427
1428
                        }
1429
                        else
1430
                        {
1431
                            if (Screen.fullScreen)
1432
                            {
1433
                                _path += @" --video-x=" + _unityWindowRect.Left * highdpiscale + " --video-y=" +
1434
                                         (_unityWindowRect.Top - 1) * highdpiscale + " --width=" + width * highdpiscale +
1435
                                         " --height=" + (height - bottomSkipHintSize) * highdpiscale + " ";
1436
                            }
1437
                            else
1438
                            {
1439
                                float leftOffset = 7;
1440
#if !UNITY_EDITOR_WIN && UNITY_STANDALONE_WIN
1441
                            leftOffset = 3;
1442
#endif
1443
                                _path += @" --video-x=" + (_unityWindowRect.Left + leftOffset) * highdpiscale + " --video-y=" +
1444
                                         (_unityWindowRect.Top - 1) * highdpiscale + " --width=" +
1445
                                         (width - leftOffset * 2) * highdpiscale +
1446
                                         " --height=" + (height - bottomSkipHintSize) * highdpiscale + " ";
1447
                            }
1448
                        }
1449
                    }
1450
                }
1451
1452
                //------------------------------END DIRECT3D--------------------------------------------------
1453
1454
                if (UsedRenderMode == RenderMode.FullScreenOverlayModePrimaryDisplay ||
1455
                    UsedRenderMode == RenderMode.VLC_QT_InterfaceFullscreen)
1456
                {
1457
                    _path += @"--fullscreen ";
1458
                    if (UsedRenderMode == RenderMode.FullScreenOverlayModePrimaryDisplay)
1459
                    {
1460
                        _path += @" -I=dummy ";
1461
                    }
1462
                    else
1463
                    {
1464
                        //QT
1465
                        _path += @" --no-qt-privacy-ask --no-interact ";
1466
1467
                        int val = PlayerPrefs.GetInt("UnitySelectMonitor"); //0=left 1=right
1468
1469
#if UNITY_EDITOR_WIN
1470
                        val = 0;
1471
#endif
1472
                        if (val == 1 && UnityIsOnPrimaryScreen())
1473
                            _path += " --qt-fullscreen-screennumber=0";
1474
                        if (val == 0 && !UnityIsOnPrimaryScreen())
1475
                            _path += " --qt-fullscreen-screennumber=1";
1476
                        if (val == 1 && !UnityIsOnPrimaryScreen())
1477
                            _path += " --qt-fullscreen-screennumber=1";
1478
                        if (val == 0 && UnityIsOnPrimaryScreen())
1479
                            _path += " --qt-fullscreen-screennumber=0";
1480
                    }
1481
                }
1482
                else
1483
                {
1484
                    _path += @" --no-qt-privacy-ask --qt-minimal-view ";
1485
                }
1486
1487
                //--------------------------------------------------------------------------------
1488
1489
                _path += " --play-and-exit --no-keyboard-events --video-title-timeout=0 --no-interact --video-title=" + nameSeed + "  ";
1490
1491
                if (!LoopVideo /*&& !VideoInBackground*/)
1492
                {
1493
                    _path += " --no-repeat --no-loop";
1494
                }
1495
                else
1496
                {
1497
                    _path += "  --loop --repeat";
1498
                }
1499
1500
                if (AudioOnly)
1501
                {
1502
                    _path += " --no-video ";
1503
                }
1504
                if (NoAudio)
1505
                {
1506
                    _path += " --no-audio ";
1507
                }
1508
                if (NoHardwareYUVConversion)
1509
                {
1510
                    _path += " --no-directx-hw-yuv ";
1511
                }
1512
1513
                if (ExtraCommandLineParameters.Length > 0)
1514
                {
1515
                    _path += " " + @ExtraCommandLineParameters + " ";
1516
                }
1517
1518
                if (EnableControlRequests)
1519
                {
1520
                    _path += " --extraintf=http --http-password=vlcHttp - --http-port=" + VLCControlPort + " ";
1521
                }
1522
1523
1524
1525
            }
1526
            else if (TextureStream)
1527
            {
1528
1529
                if (TranscodeTextureStream)
1530
                {
1531
                    _path += @" -I=dummy :sout-transcode-threads=4 :sout=#transcode{vcodec=h264,acodec=mpga,ab=128,channels=2,samplerate=44100}:http{mux=ffmpeg{mux=flv},dst=:" + Tex2DStreamPort + "/stream} :sout-keep ";
1532
1533
                }
1534
                else
1535
                {
1536
                    _path += @" -I=dummy :sout=#http{mux=ffmpeg{mux=flv},dst=:" + Tex2DStreamPort + "/stream} :sout-keep ";
1537
                }
1538
1539
1540
1541
1542
            }
1543
1544
1545
            //----------------------------VLC PROCESS --------------------
1546
            _vlc = new Process();
1547
1548
            if (UseBuiltInVLC)
1549
            {
1550
                _vlc.StartInfo.FileName = Application.dataPath + @"/StreamingAssets/vlc/vlc.exe";
1551
            }
1552
            else
1553
            {
1554
                _vlc.StartInfo.FileName = @"C:\Program Files\VideoLAN\VLC";
1555
            }
1556
1557
            // print(_path);
1558
1559
            _vlc.StartInfo.Arguments = @_path;
1560
            _vlc.StartInfo.CreateNoWindow = true;
1561
            _vlc.StartInfo.WindowStyle = ProcessWindowStyle.Hidden;
1562
            _vlc.Start();
1563
1564
            if (!TextureStream)
1565
            {
1566
1567
                if (UsedRenderMode == RenderMode.VLC_QT_InterfaceFullscreen)
1568
                {
1569
                    //InvokeRepeating("FocusUnity", 3f, 1f);
1570
                }
1571
                else
1572
                {
1573
1574
                    //New in 1.01
1575
                    if (FlickerFix)
1576
                    {
1577
                        _focusInUpdate = true;
1578
                    }
1579
                    else
1580
                    {
1581
                        InvokeRepeating("FocusUnity", 0.025f, .05f);
1582
                    }
1583
                }
1584
1585
                if (VideoInBackground)
1586
                {
1587
                    StartCoroutine("HandleBackgroundVideo");
1588
                }
1589
            }
1590
1591
        }
1592
    }
1593
1594
    private IEnumerator HandleBackgroundVideo()
1595
    {
1596
1597
        yield return new WaitForSeconds(3);
1598
        allCameras = FindObjectsOfType<Camera>();
1599
        foreach (Camera c in allCameras)
1600
        {
1601
            c.gameObject.SetActive(false);
1602
        }
1603
        Debtext.text += "Starting BG video \n";
1604
        VideoInBackgroundCamera = Instantiate(VideoInBackgroundCameraPrefab);
1605
        VideoInBackgroundCamera.GetComponent<BackgroundKey>().ActivateTransparency(_unityHwnd);
1606
        yield return new WaitForSeconds(1);
1607
        VideoInBackground_CheckAllowed = true;
1608
    }
1609
1610
    private void ResetBackgroundVideo()
1611
    {
1612
#if !UNITY_EDITOR
1613
         if (VideoInBackgroundCamera != null){
1614
            VideoInBackgroundCamera.GetComponent<BackgroundKey>().DisableTransparency();
1615
            Destroy(VideoInBackgroundCamera);
1616
        }
1617
1618
        foreach (Camera c in allCameras) {
1619
            if (c != VideoInBackgroundCamera) {
1620
                c.gameObject.SetActive(true);
1621
            }
1622
        }
1623
#else
1624
        Debug.LogWarning("PLEASE BUILD THE SCENE FOR THE VIDEO IN BACKGROUND FEATURE, OTHERWISE IT WILL NOT WORK!");
1625
#endif
1626
    }
1627
1628
    void FocusUnity()
1629
    {
1630
        GetFocus();
1631
    }
1632
1633
    public void StopVideo()
1634
    {
1635
        if (VideoInBackground)
1636
        {
1637
1638
            VideoInBackground_CheckAllowed = false;
1639
            ResetBackgroundVideo();
1640
        }
1641
        if (_isPlaying)
1642
            KillVLCProcess();
1643
    }
1644
1645
    private void KillVLCProcess()
1646
    {
1647
        try
1648
        {
1649
            _vlc.Kill();
1650
        }
1651
        catch (Exception) { }
1652
    }
1653
1654
    private bool VLCWindowIsRendered()
1655
    {
1656
        GetWindowRect(_vlcHwnd, ref _vlcWindowRect);
1657
        return ((_vlcWindowRect.Top - _vlcWindowRect.Bottom) != 0);
1658
    }
1659
1660
    private void Pin()
1661
    {
1662
1663
        if (_isPlaying && (PinVideo || UseVlc210OrHigher))
1664
        {
1665
1666
            // if (_vlcHwnd == IntPtr.Zero ){ //Hwnd changes with next playlist item apparently
1667
            _vlcHwnd = FindWindow(null, nameSeed.ToString());
1668
            //  }
1669
1670
            GetWindowRect(_vlcHwnd, ref _vlcWindowRect);
1671
1672
            if (VLCWindowIsRendered())
1673
            {
1674
                if (UseGUIVideoPanelPosition && GuiVideoPanel)
1675
                {
1676
1677
                    Rect pRect = GetPanelRect();
1678
                    //TODO: This doesnt get called on a fullscreen switch while playing videos, since windowpos did not change apparently
1679
                    if (Math.Abs(_vlcWindowRect.Top - (int)pRect.yMin) > 3 || Math.Abs(_vlcWindowRect.Bottom - (int)pRect.yMax) > 3 || Math.Abs(_vlcWindowRect.Left - (int)pRect.xMin) > 3 || Math.Abs(_vlcWindowRect.Right - (int)pRect.xMax) > 3)
1680
                    {  //TODO FERTIG MACHEN
1681
1682
                        MoveWindow(_vlcHwnd, (int)pRect.xMin, (int)pRect.yMin, (int)(pRect.xMax - pRect.xMin), (int)(pRect.yMax - pRect.yMin), true);
1683
                    }
1684
1685
                }
1686
                else if (CompleteFullscreen)
1687
                {
1688
1689
                    if (Math.Abs(_vlcWindowRect.Top - (int)_realCurrentMonitorBounds.yMin) > 3 || Math.Abs(_vlcWindowRect.Bottom - (int)_realCurrentMonitorBounds.yMax) > 3 || Math.Abs(_vlcWindowRect.Left - (int)_realCurrentMonitorBounds.xMin) > 3 || Math.Abs(_vlcWindowRect.Right - (int)_realCurrentMonitorBounds.xMax) > 3)
1690
                    {
1691
                        MoveWindow(_vlcHwnd, (int)_realCurrentMonitorBounds.xMin, (int)_realCurrentMonitorBounds.yMin, (int)_realCurrentMonitorBounds.width, (int)_realCurrentMonitorBounds.height, true);
1692
                    }
1693
                }
1694
                else
1695
                {
1696
                    if (ShowBottomSkipHint)
1697
                    {
1698
                        if (UnityIsOnPrimaryScreen())
1699
                        {
1700
                            bottomSkipHintSize = RectTransformToScreenSpace(BottomSkipHint.GetComponent<RectTransform>()).height * GetMainSceenUserScalingFactor();
1701
                        }
1702
                        else
1703
                        {
1704
                            bottomSkipHintSize = RectTransformToScreenSpace(BottomSkipHint.GetComponent<RectTransform>()).height;
1705
                        }
1706
                    }
1707
                    else
1708
                    {
1709
                        bottomSkipHintSize = 0;
1710
                    }
1711
1712
                    if (Math.Abs(_vlcWindowRect.Top - (int)_unityWindowRect.Top) > 3 || Math.Abs(_vlcWindowRect.Bottom - ((int)_unityWindowRect.Bottom - (int)bottomSkipHintSize)) > 3 || Math.Abs(_vlcWindowRect.Left - (int)_unityWindowRect.Left) > 3 || Math.Abs(_vlcWindowRect.Right - (int)_unityWindowRect.Right) > 3)
1713
                    {
1714
                        MoveWindow(_vlcHwnd, _unityWindowRect.Left, _unityWindowRect.Top, _unityWindowRect.Right - _unityWindowRect.Left, _unityWindowRect.Bottom - _unityWindowRect.Top - (int)bottomSkipHintSize, true);
1715
                    }
1716
                }
1717
            }
1718
        }
1719
    }
1720
1721
    void LateUpdate()
1722
    {
1723
        Pin();
1724
    }
1725
1726
    void Update()
1727
    {
1728
        if (_isPlaying)
1729
        {
1730
1731
            if (_focusInUpdate /*&& FlickerFix*/ && UsedRenderMode == RenderMode.Direct3DMode)
1732
                FocusUnity();
1733
1734
            try
1735
            {
1736
                if (_vlc.HasExited && !_thisVlcProcessWasEnded)
1737
                {
1738
1739
                    ShowWindow(_unityHwnd, 1);
1740
1741
                    _thisVlcProcessWasEnded = true;
1742
                    CancelInvoke("FocusUnity");
1743
1744
                    if (EnableControlRequests)
1745
                        CancelInvoke("UpdateVideoInformation");
1746
1747
                    _isPlaying = _qtCheckEnabled = _focusInUpdate = false;
1748
1749
                    _vlcHwnd = IntPtr.Zero;
1750
1751
                    if (BottomSkipHint)
1752
                    {
1753
                        BottomSkipHint.GetComponent<UnityEngine.UI.Button>().onClick.RemoveAllListeners();
1754
                        BottomSkipHint.SetActive(false);
1755
                    }
1756
                    if (GuiVideoPanel != null)
1757
                    {
1758
                        GuiVideoPanel.GetComponent<UnityEngine.UI.Image>().enabled = true;
1759
                    }
1760
1761
                    if (VLCWindowIsRendered() == false && VideoInBackground && VideoInBackground_CheckAllowed)
1762
                    {
1763
                        ResetBackgroundVideo();
1764
                        Debtext.text += "VIDEO AUS - RESET \n";
1765
                    }
1766
1767
                    VideoInBackground_CheckAllowed = false;
1768
                }
1769
            }
1770
            catch (Exception)
1771
            {
1772
            }
1773
            /*
1774
            if (SkipVideoWithAnyKey) {
1775
                if (_isPlaying) {
1776
                    if ((!Input.GetKeyDown(KeyCode.LeftAlt) && !Input.GetKeyDown(KeyCode.RightAlt) && Input.anyKeyDown) ||
1777
                        Input.GetKeyUp(KeyCode.Space)) {
1778
                        KillVLCProcess();
1779
                        ShowWindow(_unityHwnd, 5);
1780
                    }
1781
                }
1782
            }*/
1783
        }
1784
    }
1785
1786
1787
    private void QTCheckFullScreenEnd()
1788
    {
1789
1790
        float SF = 1;
1791
1792
        if (UnityIsOnPrimaryScreen())
1793
        {
1794
            SF = GetMainSceenUserScalingFactor();
1795
        }
1796
1797
        SetForegroundWindow(_vlcHwnd);
1798
        ShowWindow(_vlcHwnd, 5);
1799
1800
        RECT vlcSize = new RECT();
1801
        GetWindowRect(_vlcHwnd, ref vlcSize);
1802
1803
        if ((vlcSize.Right - vlcSize.Left) * SF > 0 && (vlcSize.Right - vlcSize.Left) * SF != (int)GetCurrentMonitorDesktopResolution().x && (vlcSize.Bottom - vlcSize.Top) * SF > 0 && (vlcSize.Bottom - vlcSize.Top) * SF != GetCurrentMonitorDesktopResolution().y)
1804
        {
1805
            KillVLCProcess();
1806
        }
1807
    }
1808
1809
1810
    private void GetFocus()
1811
    {
1812
1813
        if (_unityWindowID != GetActiveWindow() && _isPlaying)
1814
        {
1815
1816
            keybd_event((byte)0xA4, 0x45, 0x1 | 0, 0);
1817
            keybd_event((byte)0xA4, 0x45, 0x1 | 0x2, 0);
1818
1819
1820
            if (UsedRenderMode == RenderMode.VLC_QT_InterfaceFullscreen && !_qtCheckEnabled)
1821
            {
1822
                QTCheckFullScreenEnd();
1823
                _qtCheckEnabled = true;
1824
                _vlcHwnd = FindWindow(null, nameSeed.ToString());
1825
            }
1826
            else
1827
            {
1828
                if (!_qtCheckEnabled)
1829
                {
1830
                    SetForegroundWindow(_unityHwnd);
1831
                    ShowWindow(_unityHwnd, 5);
1832
                }
1833
            }
1834
        }
1835
1836
        if (_isPlaying && UsedRenderMode == RenderMode.VLC_QT_InterfaceFullscreen && _qtCheckEnabled)
1837
        {
1838
            QTCheckFullScreenEnd();
1839
        }
1840
    }
1841
    void OnApplicationQuit()
1842
    {
1843
        try
1844
        {
1845
            if (_isPlaying && !_thisVlcProcessWasEnded)
1846
                _vlc.Kill();
1847
        }
1848
        catch (Exception) { }
1849
1850
    }
1851
}