public InputStream(string streamUrl, Dictionary<string, string> addonProperties, StreamPreferences preferences)
    {
      SubtitlePaths = new List<string>();
      string addonName;
      if (!addonProperties.TryGetValue(KEY_INPUTSTREAM_ADDON, out addonName))
        throw new ArgumentException("Missing inputstreamaddon key", "addonProperties");

      _preferences = preferences;
      _wrapper = new DllAddonWrapper<InputStreamAddonFunctions>();

      var pluginRoot = Path.GetDirectoryName(GetType().Assembly.Location);
      // Add to windows DLL search path to find widevine dll
      var res = NativeMethods.SetDllDirectory(pluginRoot);
      var addonDllPath = Path.Combine(pluginRoot, string.Format("{0}\\{0}.dll", addonName));
      _wrapper.Init(addonDllPath);
      var cb = new AddonCB { LibPath = pluginRoot + "\\" };

      var status = _wrapper.Create(ref cb, IntPtr.Zero);
      if (status != AddonStatus.Ok)
        throw new Exception("Failed to create addon.");

      _addonFunctions = _wrapper.Addon;

      // The path contains 2 dummy folders, because the InputStream.mpd plugin creates the cdm folder 2 levels higher.
      string profileFolder = ServiceRegistration.Get<IPathManager>().GetPath(string.Format("<DATA>\\OnlineVideos\\InputStream\\addons\\{0}\\", addonName));
      if (!Directory.Exists(profileFolder))
        Directory.CreateDirectory(profileFolder);

      var inputStreamConfig = new InputStreamConfig
      {
        Url = streamUrl,
        LibFolder = Path.Combine(profileFolder, "cdm"),
        ProfileFolder = profileFolder,
        Properties = new ListItemProperty[InputStreamConfig.MAX_INFO_COUNT]
      };

      int idx = 0;
      foreach (var addonProperty in addonProperties)
      {
        if (addonProperty.Key == KEY_INPUTSTREAM_ADDON)
          continue;

        inputStreamConfig.Properties[idx++] = new ListItemProperty(addonProperty.Key, addonProperty.Value);
      }
      inputStreamConfig.CountInfoValues = (uint)idx;

      if (preferences.Width.HasValue && preferences.Height.HasValue)
        Functions.SetVideoResolution(preferences.Width.Value, preferences.Height.Value);

      Functions.Open(ref inputStreamConfig);

      _caps = Functions.GetCapabilities();

      UpdateStreams();

      GetPreferredStreams(_inputstreamInfos, _preferences);

      // Tell the inputstream to enable selected stream IDs
      EnableStreams();
    }
        public InputStream(string streamUrl, Dictionary <string, string> addonProperties, StreamPreferences preferences)
        {
            SubtitlePaths = new List <string>();
            string addonName;

            if (!addonProperties.TryGetValue(KEY_INPUTSTREAM_ADDON, out addonName))
            {
                throw new ArgumentException("Missing inputstreamaddon key", "addonProperties");
            }

            _preferences = preferences;
            _wrapper     = new DllAddonWrapper <InputStreamAddonFunctions>();

            var pluginRoot = Path.GetDirectoryName(GetType().Assembly.Location);
            // Add to windows DLL search path to find widevine dll
            var res          = NativeMethods.SetDllDirectory(pluginRoot);
            var addonDllPath = Path.Combine(pluginRoot, string.Format("{0}\\{0}.dll", addonName));

            _wrapper.Init(addonDllPath);
            var cb = new AddonCB {
                LibPath = pluginRoot + "\\"
            };

            var status = _wrapper.Create(ref cb, IntPtr.Zero);

            if (status != AddonStatus.Ok)
            {
                throw new Exception("Failed to create addon.");
            }

            _addonFunctions = _wrapper.Addon;

            // The path contains 2 dummy folders, because the InputStream.mpd plugin creates the cdm folder 2 levels higher.
            string profileFolder = Path.Combine(Path.GetDirectoryName(OnlineVideos.OnlineVideoSettings.Instance.DllsDir), string.Format("InputStream\\addons\\{0}\\", addonName));

            if (!Directory.Exists(profileFolder))
            {
                Directory.CreateDirectory(profileFolder);
            }

            var inputStreamConfig = new InputStreamConfig
            {
                Url           = streamUrl,
                LibFolder     = Path.Combine(profileFolder, "cdm"),
                ProfileFolder = profileFolder,
                Properties    = new ListItemProperty[InputStreamConfig.MAX_INFO_COUNT]
            };

            int idx = 0;

            foreach (var addonProperty in addonProperties)
            {
                if (addonProperty.Key == KEY_INPUTSTREAM_ADDON)
                {
                    continue;
                }

                inputStreamConfig.Properties[idx++] = new ListItemProperty(addonProperty.Key, addonProperty.Value);
            }
            inputStreamConfig.CountInfoValues = (uint)idx;

            if (preferences.Width.HasValue && preferences.Height.HasValue)
            {
                Functions.SetVideoResolution(preferences.Width.Value, preferences.Height.Value);
            }

            Functions.Open(ref inputStreamConfig);

            _caps = Functions.GetCapabilities();

            UpdateStreams();

            GetPreferredStreams(_inputstreamInfos, _preferences);

            // Tell the inputstream to enable selected stream IDs
            EnableStreams();
        }
    private void GetPreferredStreams(Dictionary<uint, InputstreamInfo> inputstreamInfos, StreamPreferences preferences)
    {
      List<int> selectedIds = new List<int>();
      // Video
      var videoStreamId = inputstreamInfos.Values.FirstOrDefault(i => i.StreamType == StreamType.Video).StreamId;
      if (videoStreamId != 0)
        selectedIds.Add((int)videoStreamId);

      // Audio, prefer language then multichannel
      var audioStreams = inputstreamInfos.Values.Where(i => i.StreamType == StreamType.Audio).ToList();
      var langStreams = audioStreams.Where(i => i.Language == preferences.ThreeLetterLangCode).ToList();

      // Prefer matching language, then all languages
      foreach (var streams in new[] { langStreams, audioStreams })
      {
        var matchingStreams = preferences.PreferMultiChannel ?
          streams.OrderByDescending(i => i.Channels).ThenBy(i => i.CodecInternalName) :
          streams.OrderBy(CustomChannelCountSorting).ThenBy(i => i.CodecInternalName);

        var audioStream = matchingStreams.Any() ? matchingStreams.First().StreamId : 0;
        if (audioStream != 0)
        {
          selectedIds.Add((int)audioStream);
          break;
        }
      }
      _enabledStreams = selectedIds.ToList();
    }
        private void GetPreferredStreams(Dictionary <uint, InputstreamInfo> inputstreamInfos, StreamPreferences preferences)
        {
            List <int> selectedIds = new List <int>();
            // Video
            var videoStreamId = inputstreamInfos.Values.FirstOrDefault(i => i.StreamType == StreamType.Video).StreamId;

            if (videoStreamId != 0)
            {
                selectedIds.Add((int)videoStreamId);
            }

            // Audio, prefer language then multichannel
            var audioStreams = inputstreamInfos.Values.Where(i => i.StreamType == StreamType.Audio).ToList();
            var langStreams  = audioStreams.Where(i => i.Language == preferences.ThreeLetterLangCode).ToList();

            // Prefer matching language, then all languages
            foreach (var streams in new[] { langStreams, audioStreams })
            {
                var matchingStreams = preferences.PreferMultiChannel ?
                                      streams.OrderByDescending(i => i.Channels).ThenBy(i => i.CodecInternalName) :
                                      streams.OrderBy(CustomChannelCountSorting).ThenBy(i => i.CodecInternalName);

                var audioStream = matchingStreams.Any() ? matchingStreams.First().StreamId : 0;
                if (audioStream != 0)
                {
                    selectedIds.Add((int)audioStream);
                    break;
                }
            }
            _enabledStreams = selectedIds.ToList();
        }