/// <summary>
        /// Switches to the next track, but smooth
        /// This does NOT work as intended without RadioContentWatcher's ApplySmoothTransition!
        /// </summary>
        /// <returns><c>true</c>, if track smooth was nexted, <c>false</c> otherwise.</returns>
        public static bool NextTrack_Smooth()
        {
            AudioManager mgr = Singleton <AudioManager> .instance;

            // musicFileIsRadio is false if no radio channel is active. We cannot
            // do anything in this case.
            if (ReflectionHelper.GetPrivateField <bool>(mgr, "m_musicFileIsRadio"))
            {
                ushort activechannel = ReflectionHelper.GetPrivateField <ushort>(mgr, "m_activeRadioChannel");

                if (activechannel >= 0)
                {
                    RadioChannelData data = mgr.m_radioChannels[activechannel];
                    data.m_currentContent = 0;
                    mgr.m_radioChannels[activechannel] = data;



                    return(true);
                }
                else
                {
                    return(false);
                }
            }
            else
            {
                return(true);
            }
        }
        /// <summary>
        /// Returns the currently active channel data
        /// </summary>
        /// <returns>The active channel.</returns>
        public static RadioChannelData?GetActiveChannelData()
        {
            AudioManager mgr           = Singleton <AudioManager> .instance;
            ushort       activechannel = ReflectionHelper.GetPrivateField <ushort>(mgr, "m_activeRadioChannel");

            if (activechannel >= 0)
            {
                RadioChannelData data = mgr.m_radioChannels[activechannel];
                return(data);
            }
            else
            {
                return(null);
            }
        }
        /// <summary>
        /// Tells the vanilla radio system to issue a rebuild of the internal song list of the active channel
        /// </summary>
        /// <returns><c>true</c>, if track with rebuild was nexted, <c>false</c> otherwise.</returns>
        public static bool TriggerRebuildInternalSongList()
        {
            // Note: there is GetActiveChannelData. But radio channels are structs, so we need to access directly.
            AudioManager mgr           = Singleton <AudioManager> .instance;
            ushort       activechannel = ReflectionHelper.GetPrivateField <ushort>(mgr, "m_activeRadioChannel");

            if (activechannel >= 0)
            {
                RadioChannelData data = mgr.m_radioChannels[activechannel];
                data.m_nextContent = 0;
                mgr.m_radioChannels[activechannel] = data; // Did you know that you don't need this in C++?

                return(true);
            }
            else
            {
                return(false);
            }
        }
Example #4
0
        private void RebuildList()
        {
            AudioManager mgr = Singleton <AudioManager> .instance;

            ushort activechannel = ReflectionHelper.GetPrivateField <ushort>(mgr, "m_activeRadioChannel");

            //Debug.Log("Selected active channel " + activechannel + " of " + mgr.m_radioChannelCount);

            //Dictionary<RadioContentInfo, String> entrytexts = new Dictionary<RadioContentInfo, string>();

            if (activechannel >= 0)
            {
                RadioChannelData channeldata = mgr.m_radioChannels[activechannel];
                RadioChannelInfo info        = channeldata.Info;

                m_CurrentContent.Clear();

                if (info != null)
                {
                    // Only show supported content entries
                    HashSet <RadioContentInfo.ContentType> supported_content = new HashSet <RadioContentInfo.ContentType>();

                    foreach (var state in info.m_stateChain)
                    {
                        supported_content.Add(state.m_contentType);
                    }

                    for (uint i = 0; i < PrefabCollection <RadioContentInfo> .PrefabCount(); ++i)
                    {
                        var c = PrefabCollection <RadioContentInfo> .GetPrefab(i);

                        if (c == null)
                        {
                            continue;
                        }
                        if (c.m_radioChannels == null)
                        {
                            continue;
                        }

                        if (supported_content.Contains(c.m_contentType) && c.m_radioChannels.Contains(info))
                        {
                            //entrytexts[c] = GetEntryTextFor(c);

                            //if(!IsFiltered(entrytexts[c]))
                            if (!IsFiltered(AudioManagerHelper.GetContentName(c)))
                            {
                                m_CurrentContent.Add(c);
                            }
                        }
                    }
                }

                m_RadioChannelInfo.isVisible = m_CurrentContent.Count == 0;

                //Debug.Log(m_CurrentContent.Count + " entries ");
            }

            m_CurrentContent.Sort((RadioContentInfo x, RadioContentInfo y) =>
            {
                if (m_SortAscending)
                {
                    //return string.Compare(entrytexts[x], entrytexts[y], StringComparison.CurrentCulture);
                    return(string.Compare(AudioManagerHelper.GetContentName(x), AudioManagerHelper.GetContentName(y), StringComparison.CurrentCulture));
                }
                else
                {
                    //return string.Compare(entrytexts[y], entrytexts[x], StringComparison.CurrentCulture);
                    return(string.Compare(AudioManagerHelper.GetContentName(y), AudioManagerHelper.GetContentName(x), StringComparison.CurrentCulture));
                }
            });

            RefreshListWidget();
        }
        /// <summary>
        /// Switches to a specific radio content (music)
        /// </summary>
        /// <returns><c>true</c>, if the switch was successful, <c>false</c> otherwise.</returns>
        /// <param name="info">Info.</param>
        public static bool SwitchToContent(RadioContentInfo info)
        {
            AudioManager mgr = Singleton <AudioManager> .instance;

            // musicFileIsRadio is false if no radio channel is active. We cannot
            // do anything in this case.
            if (ReflectionHelper.GetPrivateField <bool>(mgr, "m_musicFileIsRadio"))
            {
                ushort contentindex = 0;
                bool   found        = false;

                for (int i = 0; i < mgr.m_radioContentCount; ++i)
                {
                    RadioContentData data = mgr.m_radioContents[i];

                    //Debug.Log("CC: " + data + " + " + data.Info + " == " + info);

                    if (data.Info == info)
                    {
                        contentindex = (ushort)i;
                        //Debug.Log("Found content index for " + info);
                        found = true;
                        break;
                    }
                }

                if (!found)
                {
                    CSLMusicMod.Log("Switching to unloaded music " + info);

                    if (!mgr.CreateRadioContent(out contentindex, info))
                    {
                        CSLMusicMod.Log("... failed to create content " + info);
                        return(false);
                    }
                }

                CSLMusicMod.Log("Radio switches to track " + info);

                //Debug.Log("Content index: " + contentindex);

                // Next content
                ushort activechannel = ReflectionHelper.GetPrivateField <ushort>(mgr, "m_activeRadioChannel");

                if (activechannel >= 0)
                {
                    RadioChannelData data = mgr.m_radioChannels[activechannel];
                    data.m_currentContent = contentindex;
                    //data.m_nextContent = contentindex;
                    mgr.m_radioChannels[activechannel] = data;
                    //mgr.m_radioChannels[activechannel].ChangeContent(activechannel);

                    return(true);
                }

                //var player = ReflectionHelper.GetPrivateField<AudioManager.AudioPlayer>(mgr, "m_currentRadioPlayer");
                //player.m_source.Stop();

                return(false);
            }
            else
            {
                return(false);
            }
        }
        /// <summary>
        /// Rebuilds the allowed content for a channel.
        /// </summary>
        /// <param name="channel">Channel.</param>
        private void RebuildDisallowedContentForChannel(RadioChannelData channel)
        {
            if (channel.Info == null)
            {
                return;
            }

            HashSet <RadioContentInfo> disallowed;

            if (!DisallowedContent.TryGetValue(channel.Info, out disallowed))
            {
                disallowed = new HashSet <RadioContentInfo>();
                DisallowedContent[channel.Info] = disallowed;
            }
            else
            {
                disallowed.Clear();
            }

            UserRadioChannel userchannel = AudioManagerHelper.GetUserChannelInfo(channel.Info);

            if (userchannel != null)
            {
                // If the channel is a custom channel, we can check for context and for content disabling
                // The method returns NULL if all songs apply!
                var allowedsongs = userchannel.GetApplyingSongs();

                if (allowedsongs == null)
                {
                    if (ModOptions.Instance.EnableDisabledContent && ModOptions.Instance.DisabledContent.Count != 0)
                    {
                        foreach (UserRadioContent usercontent in userchannel.m_Content)
                        {
                            if (usercontent.m_VanillaContentInfo != null)
                            {
                                bool isenabled = (!ModOptions.Instance.EnableDisabledContent || AudioManagerHelper.ContentIsEnabled(usercontent.m_VanillaContentInfo));

                                if (!isenabled)
                                {
                                    disallowed.Add(usercontent.m_VanillaContentInfo);
                                }
                            }
                        }
                    }
                }
                else
                {
                    foreach (UserRadioContent usercontent in userchannel.m_Content)
                    {
                        if (usercontent.m_VanillaContentInfo != null)
                        {
                            bool isincontext = (!ModOptions.Instance.EnableContextSensitivity || allowedsongs.Contains(usercontent));
                            bool isenabled   = (!ModOptions.Instance.EnableDisabledContent || AudioManagerHelper.ContentIsEnabled(usercontent.m_VanillaContentInfo));

                            if (!isincontext || !isenabled)
                            {
                                disallowed.Add(usercontent.m_VanillaContentInfo);
                            }
                        }
                    }
                }
            }
            else
            {
                // If the channel is a vanilla channel, we can still disable content
                AudioManager mgr = Singleton <AudioManager> .instance;

                if (mgr.m_radioContents.m_size > 0)
                {
                    for (int i = 0; i < mgr.m_radioContents.m_size; ++i)
                    {
                        var content = mgr.m_radioContents[i];
                        if (content.Info != null && content.Info.m_radioChannels != null && content.Info.m_radioChannels.Contains(channel.Info))
                        {
                            if (!AudioManagerHelper.ContentIsEnabled(content.Info))
                            {
                                disallowed.Add(content.Info);
                            }
                        }
                    }
                }
            }
        }