/// <summary>
        /// Attempts to auto choose a subtitle option
        /// based on the prefered languages
        /// </summary>
        private SubtitleOption CheckForPreferedLanguage()
        {
            Log.Debug("SubtitleSelector: CheckForPreferedLanguage");
            List <SubtitleOption> options = CollectOptions();

            Log.Debug("Has {0} options", options.Count);

            SubtitleOption prefered     = null;
            int            priority     = int.MaxValue;
            int            prefOptIndex = -1;

            for (int optIndex = 1; optIndex < options.Count; optIndex++)
            {
                SubtitleOption opt   = options[optIndex];
                int            index = preferedLanguages.IndexOf(opt.language);
                Log.Debug(opt + " Pref index " + index);

                if (index >= 0 && index < priority)
                {
                    Log.Debug("Setting as pref");
                    prefered     = opt;
                    priority     = index;
                    prefOptIndex = optIndex;
                }
            }
            return(prefered);
        }
 public override bool Equals(object o)
 {
     if (o == null)
     {
         return(false);
     }
     if (o is SubtitleOption)
     {
         SubtitleOption other = o as SubtitleOption;
         if (other.type != this.type)
         {
             return(false);
         }
         else if (other.bitmapIndex != this.bitmapIndex)
         {
             return(false);
         }
         else if (!other.language.Equals(this.language))
         {
             return(false);
         }
         else if ((this.entry != null && !this.entry.Equals(other.entry)) || this.entry == null && other.entry != null)
         {
             return(false);
         }
         else
         {
             return(true);
         }
     }
     else
     {
         return(false);
     }
 }
        private void OnPageInfo(TeletextPageEntry entry)
        {
            lock (syncLock)
            {
                if (!pageEntries.ContainsKey(entry.page))
                {
                    pageEntries.Add(entry.page, entry);
                    if (currentOption != null && currentOption.isAuto)
                    {
                        SubtitleOption prefered = CheckForPreferedLanguage();
                        if (prefered != null)
                        {
                            currentOption.bitmapIndex = prefered.bitmapIndex;
                            currentOption.entry       = prefered.entry;
                            currentOption.language    = prefered.language;
                            currentOption.type        = prefered.type;
                            Log.Debug("Auto-selection of " + currentOption);
                        }
                        else
                        {
                            currentOption.type     = SubtitleType.None;
                            currentOption.language = "None";
                        }

                        if (subRender != null)
                        {
                            subRender.SetSubtitleOption(currentOption);
                        }

                        // we cannot update the bitmap sub stream here
                    }
                }
            }
        }
        // ONLY call from MP main thread!
        private void RetrieveBitmapSubtitles()
        {
            bitmapSubtitleCache.Clear();

            try
            {
                // collect dvb bitmap subtitle options
                int streamCount = 0;
                dvbStreams.GetSubtitleStreamCount(ref streamCount);
                Debug.Assert(streamCount >= 0 && streamCount <= 100);

                for (int i = 0; i < streamCount; i++)
                {
                    TSReaderPlayer.SUBTITLE_LANGUAGE subLang = new TSReaderPlayer.SUBTITLE_LANGUAGE();
                    dvbStreams.GetSubtitleStreamLanguage(i, ref subLang);
                    SubtitleOption option = new SubtitleOption();
                    option.type        = SubtitleType.Bitmap;
                    option.language    = subLang.lang;
                    option.bitmapIndex = i;
                    bitmapSubtitleCache.Add(option);
                    Log.Debug("Retrieved bitmap option Lang : " + option.ToString());
                }
            }
            catch (Exception e)
            {
                Log.Error(e);
            }
        }
        private int OnSubtitleReset(int count, IntPtr pOpts, ref int selected_bitmap_index)
        {
            Log.Debug("OnSubtitleReset");
            Log.Debug("selected_bitmap_index " + selected_bitmap_index);
            lock (syncLock)
            {
                bitmapSubtitleCache.Clear();
                pageEntries.Clear();

                Log.Debug("Number of bitmap options {0}", count);
                IntPtr current = pOpts;
                for (int i = 0; i < count; i++)
                {
                    Log.Debug("Bitmap index " + i);
                    SUBTITLESTREAM bOpt = (SUBTITLESTREAM)Marshal.PtrToStructure(current, typeof(SUBTITLESTREAM));
                    SubtitleOption opt  = new SubtitleOption();
                    opt.bitmapIndex = i;
                    opt.type        = SubtitleType.Bitmap;
                    opt.language    = "" + (char)bOpt.lang0 + (char)bOpt.lang1 + (char)bOpt.lang2;
                    Log.Debug(opt.ToString());
                    bitmapSubtitleCache.Add(opt);
                    current = (IntPtr)(((int)current) + Marshal.SizeOf(bOpt));
                }

                selected_bitmap_index = -1; // we didnt select a bitmap index

                if (currentOption != null && currentOption.isAuto)
                {
                    SubtitleOption prefered = CheckForPreferedLanguage();
                    if (prefered != null)
                    {
                        currentOption.bitmapIndex = prefered.bitmapIndex;
                        currentOption.entry       = prefered.entry;
                        currentOption.language    = prefered.language;
                        currentOption.type        = prefered.type;
                        Log.Debug("Auto-selection of " + currentOption);
                    }
                    else
                    {
                        currentOption.language = "None";
                        currentOption.type     = SubtitleType.None;
                    }

                    if (subRender != null)
                    {
                        subRender.SetSubtitleOption(currentOption);
                    }

                    if (currentOption.type == SubtitleType.Bitmap)
                    {
                        selected_bitmap_index = currentOption.bitmapIndex;
                        Log.Debug("Returns selected_bitmap_index == {0} to ISubStream", selected_bitmap_index);
                    }
                }
            }
            return(0);
        }
        /// <summary>
        /// Attempts to auto choose a subtitle option
        /// based on the prefered languages
        /// </summary>
        private SubtitleOption CheckForPreferedLanguage()
        {
            Log.Debug("SubtitleSelector: CheckForPreferedLanguage");
            List <SubtitleOption> options = CollectOptions();

            Log.Debug("Has {0} options", options.Count);

            SubtitleOption prefered     = null;
            int            priority     = int.MaxValue;
            int            prefOptIndex = -1;
            int            prefPage     = 0;

            try
            {
                using (MPSettings xmlreader = new MPSettings())
                {
                    // get the currently found active subtitle page set by TeletextReceiver
                    string defSub = xmlreader.GetValueAsString("tvservice", "dvbdefttxtsubtitles", "999;999");
                    prefPage = Convert.ToInt16(defSub.Split(';')[0]);
                }
            }
            catch { }
            for (int optIndex = 1; optIndex < options.Count; optIndex++)
            {
                SubtitleOption opt   = options[optIndex];
                int            index = preferedLanguages.IndexOf(opt.language);
                Log.Debug(opt + " Pref index " + index);

                bool pref = false;
                if (opt.type == SubtitleType.Bitmap)
                {
                    if (index >= 0 && index < priority)
                    {
                        pref = true;
                    }
                }
                else
                {
                    if (prefPage == opt.entry.page)
                    {
                        pref = true;
                    }
                }
                if (pref)
                {
                    Log.Debug("Setting as pref");
                    prefered     = opt;
                    priority     = index;
                    prefOptIndex = optIndex;
                }
            }
            return(prefered);
        }
        /// <summary>
        /// Call only on MP main thread
        /// </summary>
        /// <param name="index"></param>
        public void SetOption(int index)
        {
            Log.Debug("SetOption {0}", index);
            List <SubtitleOption> options = CollectOptions();

            if (index >= options.Count)
            {
                //Log.Error("SetOption with too large index!");
                return;
            }
            SubtitleOption option = options[index];

            lastSubtitleIndex = index;
            currentOption     = option;

            if (option.isAuto)
            {
                Log.Debug("SubtitleSelector : Set autoselect mode");
                SubtitleOption prefered = CheckForPreferedLanguage();
                if (prefered != null)
                {
                    option.bitmapIndex = prefered.bitmapIndex;
                    option.entry       = prefered.entry;
                    option.language    = prefered.language;
                    option.type        = prefered.type;
                    Log.Debug("Auto-selection of " + option);
                }
                else
                {
                    option.type            = SubtitleType.None;
                    currentOption.language = "None";

                    if (subRender != null)
                    {
                        subRender.SetSubtitleOption(option);
                    }
                }
            }

            if (option.type == SubtitleType.Bitmap)
            {
                dvbStreams.SetSubtitleStream(option.bitmapIndex);
            }
            Log.Debug("Subtitle is now " + currentOption.ToString());

            if (subRender != null)
            {
                subRender.SetSubtitleOption(option);
            }
        }
 public void SetSubtitleOption(SubtitleOption option)
 {
     if (option.type == SubtitleType.None)
     {
         _useBitmap     = false;
         _activeSubPage = 0;
     }
     else if (option.type == SubtitleType.Teletext)
     {
         _useBitmap     = false;
         _activeSubPage = option.entry.page;
         Log.Debug("SubtitleRender: Now rendering {0} teletext subtitle page {1}", option.language, _activeSubPage);
     }
     else if (option.type == SubtitleType.Bitmap)
     {
         _useBitmap = true;
         Log.Debug("SubtitleRender: Now rendering bitmap subtitles in language {0}", option.language);
     }
     else
     {
         Log.Error("Unknown subtitle option " + option);
     }
 }
        private List <SubtitleOption> CollectOptions()
        {
            //Log.Debug("SubtitleSelector: CollectOptions");
            List <SubtitleOption> options = new List <SubtitleOption>();

            if (autoSelectOption != null)
            {
                options.Add(autoSelectOption);
            }

            options.AddRange(bitmapSubtitleCache);

            // collect teletext options
            foreach (KeyValuePair <int, TeletextPageEntry> p in pageEntries)
            {
                SubtitleOption option = new SubtitleOption();
                option.type     = SubtitleType.Teletext;
                option.language = p.Value.language;
                option.entry    = p.Value;
                options.Add(option);
                Log.Debug("Added Teletext option Lang : " + option.ToString());
            }
            return(options);
        }
        public SubtitleSelector(TSReaderPlayer.ISubtitleStream dvbStreams, SubtitleRenderer subRender,
                                TeletextSubtitleDecoder subDecoder)
        {
            Log.Debug("SubtitleSelector ctor");
            this.dvbStreams = dvbStreams;
            this.subRender  = subRender;

            // load preferences
            using (Settings reader = new MPSettings())
            {
                preferedLanguages = new List <string>();
                string languages;
                if (g_Player.IsDVD)
                {
                    languages = BDPlayer.Settings.subtitleLang;
                }
                else
                {
                    languages = reader.GetValueAsString("tvservice", "preferredsublanguages", "");
                }
                Log.Debug("SubtitleSelector: sublangs entry content: " + languages);
                StringTokenizer st = new StringTokenizer(languages, ";");
                while (st.HasMore)
                {
                    string lang = st.NextToken();
                    if (lang.Length != 3)
                    {
                        Log.Warn("Language {0} is not in the correct format!", lang);
                    }
                    else
                    {
                        preferedLanguages.Add(lang);
                        Log.Info("Prefered language {0} is {1}", preferedLanguages.Count, lang);
                    }
                }
            }

            pageEntries = new Dictionary <int, TeletextPageEntry>();

            bitmapSubtitleCache = new List <SubtitleOption>();

            lock (syncLock)
            {
                if (subDecoder != null)
                {
                    subDecoder.SetPageInfoCallback(new TeletextSubtitleDecoder.PageInfoCallback(OnPageInfo));
                }

                if (dvbStreams != null)
                {
                    RetrieveBitmapSubtitles();
                    subStreamCallback = new SubtitleStreamEventCallback(OnSubtitleReset);
                    IntPtr pSubStreamCallback = Marshal.GetFunctionPointerForDelegate(subStreamCallback);
                    Log.Debug("Calling SetSubtitleStreamEventCallback");
                    dvbStreams.SetSubtitleResetCallback(pSubStreamCallback);
                }

                if (preferedLanguages.Count > 0)
                {
                    autoSelectOption          = new SubtitleOption();
                    autoSelectOption.language = "None";
                    autoSelectOption.isAuto   = true;
                    autoSelectOption.type     = SubtitleType.None;

                    SetOption(0); // the autoselect mode will have index 0 (ugly)
                }
            }
            Log.Debug("End SubtitleSelector ctor");
        }
    private List<SubtitleOption> CollectOptions()
    {
      //Log.Debug("SubtitleSelector: CollectOptions");
      List<SubtitleOption> options = new List<SubtitleOption>();

      if (autoSelectOption != null)
      {
        options.Add(autoSelectOption);
      }

      options.AddRange(bitmapSubtitleCache);

      // collect teletext options
      foreach (KeyValuePair<int, TeletextPageEntry> p in pageEntries)
      {
        SubtitleOption option = new SubtitleOption();
        option.type = SubtitleType.Teletext;
        option.language = p.Value.language;
        option.entry = p.Value;
        options.Add(option);
        Log.Debug("Added Teletext option Lang : " + option.ToString());
      }
      return options;
    }
    private int OnSubtitleReset(int count, IntPtr pOpts, ref int selected_bitmap_index)
    {
      Log.Debug("OnSubtitleReset");
      Log.Debug("selected_bitmap_index " + selected_bitmap_index);
      lock (syncLock)
      {
        bitmapSubtitleCache.Clear();
        pageEntries.Clear();

        Log.Debug("Number of bitmap options {0}", count);
        IntPtr current = pOpts;
        for (int i = 0; i < count; i++)
        {
          Log.Debug("Bitmap index " + i);
          SUBTITLESTREAM bOpt = (SUBTITLESTREAM)Marshal.PtrToStructure(current, typeof(SUBTITLESTREAM));
          SubtitleOption opt = new SubtitleOption();
          opt.bitmapIndex = i;
          opt.type = SubtitleType.Bitmap;
          opt.language = "" + (char)bOpt.lang0 + (char)bOpt.lang1 + (char)bOpt.lang2;
          Log.Debug(opt.ToString());
          bitmapSubtitleCache.Add(opt);
          current = (IntPtr)(((int)current) + Marshal.SizeOf(bOpt));
        }

        selected_bitmap_index = -1; // we didnt select a bitmap index

        if (currentOption != null && currentOption.isAuto)
        {
          SubtitleOption prefered = CheckForPreferedLanguage();
          if (prefered != null)
          {
            currentOption.bitmapIndex = prefered.bitmapIndex;
            currentOption.entry = prefered.entry;
            currentOption.language = prefered.language;
            currentOption.type = prefered.type;
            Log.Debug("Auto-selection of " + currentOption);
          }
          else
          {
            currentOption.language = "None";
            currentOption.type = SubtitleType.None;
          }

          if (subRender != null)
          {
            subRender.SetSubtitleOption(currentOption);
          }

          if (currentOption.type == SubtitleType.Bitmap)
          {
            selected_bitmap_index = currentOption.bitmapIndex;
            Log.Debug("Returns selected_bitmap_index == {0} to ISubStream", selected_bitmap_index);
          }
        }
      }
      return 0;
    }
    // ONLY call from MP main thread!
    private void RetrieveBitmapSubtitles()
    {
      bitmapSubtitleCache.Clear();

      try
      {
        // collect dvb bitmap subtitle options
        int streamCount = 0;
        dvbStreams.GetSubtitleStreamCount(ref streamCount);
        Debug.Assert(streamCount >= 0 && streamCount <= 100);

        for (int i = 0; i < streamCount; i++)
        {
          TSReaderPlayer.SUBTITLE_LANGUAGE subLang = new TSReaderPlayer.SUBTITLE_LANGUAGE();
          dvbStreams.GetSubtitleStreamLanguage(i, ref subLang);
          SubtitleOption option = new SubtitleOption();
          option.type = SubtitleType.Bitmap;
          option.language = subLang.lang;
          option.bitmapIndex = i;
          bitmapSubtitleCache.Add(option);
          Log.Debug("Retrieved bitmap option Lang : " + option.ToString());
        }
      }
      catch (Exception e)
      {
        Log.Error(e);
      }
    }
    public SubtitleSelector(TSReaderPlayer.ISubtitleStream dvbStreams, SubtitleRenderer subRender,
                            TeletextSubtitleDecoder subDecoder)
    {
      Log.Debug("SubtitleSelector ctor");
      this.dvbStreams = dvbStreams;
      this.subRender = subRender;

      // load preferences
      using (Settings reader = new MPSettings())
      {
        preferedLanguages = new List<string>();
        string languages;
        if (g_Player.IsDVD)
        {
          languages = BDPlayer.Settings.subtitleLang;          
        }
        else
        {
          languages = reader.GetValueAsString("tvservice", "preferredsublanguages", "");
        }
        Log.Debug("SubtitleSelector: sublangs entry content: " + languages);
        StringTokenizer st = new StringTokenizer(languages, ";");
        while (st.HasMore)
        {
          string lang = st.NextToken();
          if (lang.Length != 3)
          {
            Log.Warn("Language {0} is not in the correct format!", lang);
          }
          else
          {
            preferedLanguages.Add(lang);
            Log.Info("Prefered language {0} is {1}", preferedLanguages.Count, lang);
          }
        }
      }

      pageEntries = new Dictionary<int, TeletextPageEntry>();

      bitmapSubtitleCache = new List<SubtitleOption>();

      lock (syncLock)
      {
        if (subDecoder != null)
        {
          subDecoder.SetPageInfoCallback(new TeletextSubtitleDecoder.PageInfoCallback(OnPageInfo));
        }

        if (dvbStreams != null)
        {
          RetrieveBitmapSubtitles();
          subStreamCallback = new SubtitleStreamEventCallback(OnSubtitleReset);
          IntPtr pSubStreamCallback = Marshal.GetFunctionPointerForDelegate(subStreamCallback);
          Log.Debug("Calling SetSubtitleStreamEventCallback");
          dvbStreams.SetSubtitleResetCallback(pSubStreamCallback);
        }

        if (preferedLanguages.Count > 0)
        {
          autoSelectOption = new SubtitleOption();
          autoSelectOption.language = "None";
          autoSelectOption.isAuto = true;
          autoSelectOption.type = SubtitleType.None;

          SetOption(0); // the autoselect mode will have index 0 (ugly)
        }
      }
      Log.Debug("End SubtitleSelector ctor");
    }
 public void SetSubtitleOption(SubtitleOption option)
 {
   if (option.type == SubtitleType.None)
   {
     _useBitmap = false;
     _activeSubPage = 0;
   }
   else if (option.type == SubtitleType.Teletext)
   {
     _useBitmap = false;
     _activeSubPage = option.entry.page;
     Log.Debug("SubtitleRender: Now rendering {0} teletext subtitle page {1}", option.language, _activeSubPage);
   }
   else if (option.type == SubtitleType.Bitmap)
   {
     _useBitmap = true;
     Log.Debug("SubtitleRender: Now rendering bitmap subtitles in language {0}", option.language);
   }
   else
   {
     Log.Error("Unknown subtitle option " + option);
   }
 }