Example #1
0
        private void InitMembersAfterSoundtrackHasLoaded()
        {
            m_themeQueue.Clear();
            m_fadeVoices.Clear();


            foreach (Segment segment in m_soundtrack.m_snippets.Values)
            {
                segment.audioData.filePathRelativeToProjectDir = m_platformLayer.ConvertFilePathForPlatform(segment.audioData.filePathRelativeToProjectDir);
                #if !(PSAI_NOLOG)
                {
                    if (LogLevel.debug <= Logger.Instance.LogLevel)
                    {
                    	Logger.Instance.Log("converted path of segment " + segment.Name + " to " + segment.audioData.filePathRelativeToProjectDir, LogLevel.debug);
                    }
                }
                #endif
            }

            m_soundtrack.UpdateMaxPreBeatMsOfCompatibleMiddleOrBridgeSnippets();
            m_lastBasicMood = m_soundtrack.getThemeById(GetLastBasicMoodId());

            m_psaiState = PsaiState.silence;
            m_psaiStateIntended = PsaiState.silence;
            m_psaiPlayMode = PsaiPlayMode.regular;
            m_psaiPlayModeIntended = PsaiPlayMode.regular;

            m_returnToLastBasicMoodFlag = false;
            m_holdIntensity = false;

            m_nonInterruptingTriggerOfHighestPriority.themeId = -1;

            m_soundtrack.BuildAllIndirectionSequences();
        }
Example #2
0
	    internal PsaiResult MenuModeLeave()
	    {
		   // boost::recursive_mutex::scoped_lock block(m_pnxLogicMutex);

		    #if !(PSAI_NOLOG)
		    {
                if (LogLevel.info <= Logger.Instance.LogLevel)
                {
                	Logger.Instance.Log("MenuModeLeave", LogLevel.info);
                }

                if (LogLevel.debug <= Logger.Instance.LogLevel)
                {
	                StringBuilder sb = new StringBuilder();
	                sb.Append(" m_themeQueue.size()=");
	                sb.Append(m_themeQueue.Count);
	                Logger.Instance.Log(sb.ToString(), LogLevel.debug);
                }			    
		    }
		    #endif

		    if (m_initializationFailure)
		    {
			    #if !(PSAI_NOLOG)
			    {
                    Logger.Instance.Log(LOGMESSAGE_ABORTION_DUE_TO_INITIALIZATION_FAILURE, LogLevel.errors);
			    }
			    #endif

			    return PsaiResult.initialization_error;
		    }

		    //////////////////////////////////////////////////////////////////////////

            if (m_paused)
            {
                setPaused(false);
            }

		    if (m_psaiPlayMode == PsaiPlayMode.menuMode)
		    {
			    if (getFollowingThemeQueueEntry() != null)
			    {
				    PopAndPlayNextFollowingTheme(true);
				    return PsaiResult.OK;
			    }
			    else
			    {
				    m_psaiStateIntended = PsaiState.silence;
				    m_psaiState = PsaiState.silence;
				    SetPlayMode(PsaiPlayMode.regular);
				    m_psaiPlayModeIntended = PsaiPlayMode.regular;

				    StopMusic(true);
				    return PsaiResult.OK;
			    }
		    }
		    else
		    {
			    #if !(PSAI_NOLOG)
                    if (LogLevel.warnings <= Logger.Instance.LogLevel)
                    {
                    	Logger.Instance.Log("MenuModeLeave() ignored - MenuMode wasn't active. Call MenuModeEnter() first !", LogLevel.warnings);
                    }
			    #endif

			    return PsaiResult.commandIgnored;
		    }
	    }
Example #3
0
	    internal PsaiResult CutSceneLeave(bool immediately, bool reset)
	    {
		    //boost::recursive_mutex::scoped_lock block(m_pnxLogicMutex);

		    #if !(PSAI_NOLOG)
		    {
                if (LogLevel.info <= Logger.Instance.LogLevel)
                {
	                StringBuilder sb = new StringBuilder();
	                sb.Append("CutSceneLeave()  immediately=");
	                sb.Append(immediately);
	                sb.Append("  reset=");
	                sb.Append(reset);
	                Logger.Instance.Log(sb.ToString(), LogLevel.info);
                }

                if (LogLevel.debug <= Logger.Instance.LogLevel)
                {
	                StringBuilder sb2 = new StringBuilder();
	                sb2.Append("  m_themeQueue.size()=");
	                sb2.Append(m_themeQueue.Count);
	                Logger.Instance.Log(sb2.ToString(), LogLevel.debug);
                }
		    }
		    #endif

		    if (m_initializationFailure)
		    {
			    #if !(PSAI_NOLOG)
			    {
                    Logger.Instance.Log(LOGMESSAGE_ABORTION_DUE_TO_INITIALIZATION_FAILURE, LogLevel.errors);
			    }
			    #endif

			    return PsaiResult.initialization_error;
		    }

		    //////////////////////////////////////////////////////////////////////////

		    if (m_psaiPlayMode == PsaiPlayMode.cutScene && m_psaiPlayModeIntended == PsaiPlayMode.cutScene)
		    {

			    if (reset)
			    {
				    m_themeQueue.Clear();
				    #if !(PSAI_NOLOG)
				    {
                        if (LogLevel.debug <= Logger.Instance.LogLevel)
                        {
                        	Logger.Instance.Log("m_themeQueue cleared", LogLevel.debug);
                        }
				    }
				    #endif
			    }

			    if (getFollowingThemeQueueEntry() != null)
			    {
				    m_psaiPlayModeIntended = PsaiPlayMode.regular;
				    PopAndPlayNextFollowingTheme(immediately);
				    return PsaiResult.OK;
			    }
			    else
			    {
				    m_psaiStateIntended = PsaiState.silence;
				    m_psaiState = PsaiState.silence;
				    m_psaiPlayModeIntended = PsaiPlayMode.regular;
				    StopMusic(immediately);
				    return PsaiResult.OK;
			    }
		    }
		    else
		    {
			    #if !(PSAI_NOLOG)
                    if (LogLevel.warnings <= Logger.Instance.LogLevel)
                    {
                    	Logger.Instance.Log("CutSceneLeave() ignored - no CutScene was active. Call CutSceneEnter() first!", LogLevel.warnings);				    
                    }
			    #endif

			    return PsaiResult.commandIgnored;
		    }
	    }
Example #4
0
        void WakeUpFromRestHandler()
	    {
		    //boost::recursive_mutex::scoped_lock block(m_pnxLogicMutex);

		    #if !(PSAI_NOLOG)
		    {
                if (LogLevel.info <= Logger.Instance.LogLevel)
                {
                	Logger.Instance.Log("waking up from musical rest", LogLevel.info);
                }
		    }
		    #endif

		    if (m_effectiveTheme != null)
		    {
			    PlayThemeNowOrAtEndOfCurrentSegment(m_effectiveTheme.id, m_effectiveTheme.intensityAfterRest, m_effectiveTheme.musicDurationAfterRest, true, false);			
			    
			    m_psaiState = PsaiState.playing;
			    m_psaiStateIntended = PsaiState.playing;
		    }
	    }
Example #5
0
        private void EnterSilenceMode()
	    {
		    // enter silence mode
		   #if !(PSAI_NOLOG)
		    if (LogLevel.info <= Logger.Instance.LogLevel)
		    {
		    	Logger.Instance.Log("entering Silence Mode", LogLevel.info);
		    }
		   #endif
            
            m_timerStartSnippetPlayback.Stop();
            m_timerSegmentEndApproaching.Stop();

            m_targetSegment = null;
            m_effectiveTheme = null;
            m_scheduleFadeoutUponSnippetPlayback = false;

            m_psaiStateIntended = PsaiState.silence;
            m_psaiState = PsaiState.silence;        
	    }
Example #6
0
        /* sets the psaiState to PSAISTATE_REST, where no music is played for a period defined in the themes.psai file.
	    * param themeId the theme that will affect the duration of the rest, and will be played automatically when the rest is over.
	    * param restMillis the milliseconds to rest. Pass 0 to have the resting millis calculated based on the authored data.
	    */
	    void EnterRestMode(int themeIdToWakeUpWith, int themeIdToUseForRestingTimeCalculation)
	    {
		    //boost::recursive_mutex::scoped_lock block(m_pnxLogicMutex);

		    #if !(PSAI_NOLOG)
            {
                if (LogLevel.info <= Logger.Instance.LogLevel)
                {
	                StringBuilder sb = new StringBuilder();
	                sb.Append("--- Entering rest mode. Will wake up with Theme ");
	                sb.Append(themeIdToWakeUpWith);
	                Logger.Instance.Log(sb.ToString(), LogLevel.info);
                }
            }
		    #endif

		    m_psaiState = PsaiState.rest;
            m_holdIntensity = false;
            m_timerStartSnippetPlayback.Stop();     // may be necessary if we have been fading out immediately
            m_timerSegmentEndApproaching.Stop();    // may be necessary if we have been fading out immediately
            m_timerWakeUpFromRest.Stop();

            m_effectiveTheme = m_soundtrack.getThemeById(themeIdToWakeUpWith);      // the effective Theme is also valid during Rest Mode

		    if (m_effectiveTheme != null)
		    {
                int millisTimerRest = 0;

                if (m_restModeSecondsOverride > 0)
                {

          		    #if !(PSAI_NOLOG)
                    {
                        if (LogLevel.info <= Logger.Instance.LogLevel)
                        {
	                        StringBuilder sb = new StringBuilder();
	                        sb.Append("--- resting time is based on override values.");
	                        Logger.Instance.Log(sb.ToString(), LogLevel.info);
                        }
                    }
		            #endif

                    millisTimerRest = m_restModeSecondsOverride;
                    m_restModeSecondsOverride = -1;
                }
                else
                {
                    Theme themeRest = m_soundtrack.getThemeById(themeIdToUseForRestingTimeCalculation);
                    if (themeRest != null)
                    {
                        #if !(PSAI_NOLOG)
                        {
                            if (LogLevel.info <= Logger.Instance.LogLevel)
                            {
	                            StringBuilder sb = new StringBuilder();
	                            sb.Append("--- resting time is based on Theme ");
                                sb.Append(themeRest.Name);
	                            Logger.Instance.Log(sb.ToString(), LogLevel.info);
                            }
                        }
                        #endif

                        millisTimerRest = GetRandomInt(themeRest.restSecondsMin, themeRest.restSecondsMax) * 1000;
                    }
                    else
                    {
                        #if !(PSAI_NOLOG)
                        {
                            if (LogLevel.warnings <= Logger.Instance.LogLevel)
                            {
                                StringBuilder sb = new StringBuilder();
                                sb.Append("--- resting time is based on Theme ");
                                sb.Append(m_effectiveTheme.Name);
                                sb.Append("(themeIdToUseForRestingTimeCalculation was not found: ");
                                sb.Append(themeIdToUseForRestingTimeCalculation);
                                sb.Append(" )");
                                Logger.Instance.Log(sb.ToString(), LogLevel.warnings);
                            }
                        }
                        #endif

                        millisTimerRest = GetRandomInt(m_effectiveTheme.restSecondsMin, m_effectiveTheme.restSecondsMax) * 1000;
                    }
                }


			    if (millisTimerRest > 0)
			    {
				    m_timeStampRestStart = GetTimestampMillisElapsedSinceInitialisation();

				    #if !(PSAI_NOLOG)
				    {
                        if (LogLevel.info <= Logger.Instance.LogLevel)
                        {
	                        StringBuilder sb = new StringBuilder();
	                        sb.Append("...resting for ");
						    sb.Append(millisTimerRest);
	                        sb.Append(" ms");
	                        Logger.Instance.Log(sb.ToString(), LogLevel.info);
                        }
				    }
				    #endif

                    m_timerWakeUpFromRest.SetTimer(millisTimerRest, 0);				    
			    }
			    else
			    {
				    #if !(PSAI_NOLOG)
				    {
                        if (LogLevel.info <= Logger.Instance.LogLevel)
                        {
                        	Logger.Instance.Log("resting time is zero, starting again immediately.", LogLevel.info);
                        }
				    }
				    #endif

				    WakeUpFromRestHandler();
			    }
		    }
		    else
		    {
			    #if !(PSAI_NOLOG)
			    {
                    if (LogLevel.errors <= Logger.Instance.LogLevel)
                    {
                    	Logger.Instance.Log("can't go to rest because Theme wasn't found!", LogLevel.errors);
                    }
			    }
			    #endif
		    }
        }
Example #7
0
        internal Logik()
        {
            #if PSAI_STANDALONE
                m_platformLayer = new PlatformLayerStandalone(this);
            #else
                m_platformLayer = new PlatformLayerUnity();
            #endif

            m_platformLayer.Initialize();

            m_soundtrack = new Soundtrack();
            m_themeQueue = new List<ThemeQueueEntry>();                        
            m_fadeVoices = new List<FadeData>();

            for (int i = 0; i < PSAI_CHANNEL_COUNT; i++)
            {
                m_playbackChannels[i] = new PlaybackChannel();
            }


            m_hilightVoiceIndex = -1;
            m_lastRegularVoiceNumberReturned = -1;
            m_currentVoiceNumber = -1;
            m_targetVoice = -1;

            m_psaiMasterVolume = 1.0f;  		   

            m_effectiveTheme = null;
            m_currentSegmentPlaying = null;
            m_currentSnippetTypeRequested = 0; 
            m_targetSegment = null;
            m_targetSegmentSuitabilitiesRequested = 0;

            m_psaiState = PsaiState.notready;
            m_psaiStateIntended = PsaiState.notready;

            m_paused = false;
            
            m_fullVersionString = "psai Version " + PSAI_VERSION;
            #if !(PSAI_NOLOG)
                Logger.Instance.LogLevel = LogLevel.info;
                Logger.Instance.Log(m_fullVersionString, LogLevel.info);
            #endif


            s_instance = this;
        }
Example #8
0
        PsaiResult HandleNonInterruptingTriggerCall(Theme argTheme, float intensity, int musicDuration)
        {
            #if !(PSAI_NOLOG)
            {            
                if (LogLevel.debug <= Logger.Instance.LogLevel)
                {
	                StringBuilder sb = new StringBuilder();
	                sb.Append("HandleNonInterruptingTriggerCall() argTheme=");
	                sb.Append(argTheme.Name);
	                sb.Append("  intensity=");
	                sb.Append(intensity);
	                sb.Append("  musicDuration=");
	                sb.Append(musicDuration);
	                Logger.Instance.Log(sb.ToString(), LogLevel.debug);
                }
            }
            #endif


            bool updateTqe = false;
            if (m_nonInterruptingTriggerOfHighestPriority.themeId != -1)
            {                
                m_nonInterruptingTriggerOfHighestPriority.themeId = -1;
                updateTqe = true;

                /*
                #if !(PSAI_NOLOG)
                {
                    if (LogLevel.debug <= Logger.Instance.LogLevel)
                    {
	                    StringBuilder sb = new StringBuilder();
	                    sb.Append("previouslyTriggeredTheme was null");
	                    Logger.Instance.Log(sb.ToString(), LogLevel.debug);
                    }
                }
                #endif
                */
            }
            else
            {
                // check if the trigger call differs from the last one
                if ( m_nonInterruptingTriggerOfHighestPriority.themeId != argTheme.id         ||
                    m_nonInterruptingTriggerOfHighestPriority.startIntensity != intensity
                    )
                {
                        #if !(PSAI_NOLOG)
                        {
                            /*
                            if (LogLevel.debug <= Logger.Instance.LogLevel)
                            {
	                            StringBuilder sb = new StringBuilder();
	                            sb.Append("differing trigger -> update");
	                            Logger.Instance.Log(sb.ToString(), LogLevel.debug);
                            }
                             */
                        }
                        #endif

                    updateTqe = true;
                }
            }

            if (updateTqe)
            {
                m_nonInterruptingTriggerOfHighestPriority.themeId = argTheme.id;
                m_nonInterruptingTriggerOfHighestPriority.startIntensity = intensity;
                m_nonInterruptingTriggerOfHighestPriority.musicDuration = musicDuration;
                m_psaiStateIntended = PsaiState.playing;
                return PsaiResult.OK;
            }
            else
            {
                #if !(PSAI_NOLOG)
                    if (LogLevel.debug <= Logger.Instance.LogLevel)
                    {
                    	Logger.Instance.Log("... no update necessary", LogLevel.debug);
                    }
                #endif

                return PsaiResult.OK;    
            }
        }
Example #9
0
        void InitiateTransitionToRestMode()
	    {

            #if !(PSAI_NOLOG)
            {
                if (LogLevel.debug <= Logger.Instance.LogLevel)
                {
                    Logger.Instance.Log("InitiateTransitionToRestMode()", LogLevel.debug);
                }
            }
            #endif

		    if (m_currentSegmentPlaying != null)
		    {
			    if ( m_currentSegmentPlaying.IsUsableAs(SegmentSuitability.end) )
			    {
                    EnterRestMode(GetLastBasicMoodId(), getEffectiveThemeId());
			    }
			    else if (CheckIfThereIsAPathToEndSegmentForEffectiveSegmentAndLogWarningIfThereIsnt() == false)
			    {
				    startFade(m_currentVoiceNumber, GetRemainingMillisecondsOfCurrentSegmentPlayback(), 0);
				    EnterRestMode(GetLastBasicMoodId(), getEffectiveThemeId());
			    }
			    else
			    {
				    WriteLogWarningIfThereIsNoDirectPathForEffectiveSnippetToEndSnippet();
				    PlaySegment(m_currentSegmentPlaying.nextSnippetToShortestEndSequence, false);
				    m_psaiStateIntended = PsaiState.rest;
			    }
		    }
	    }
Example #10
0
        internal PsaiResult StopMusic(bool immediately)
	    {
		    //boost::recursive_mutex::scoped_lock blockieren(m_pnxLogicMutex);

		    #if !(PSAI_NOLOG)
            {
                if (LogLevel.info <= Logger.Instance.LogLevel)
                {
	                StringBuilder sb = new StringBuilder();
	                sb.Append("StopMusic(");
	                sb.Append(immediately);
	                sb.Append(") called");
	                Logger.Instance.Log(sb.ToString(), LogLevel.info);
                }
            }
		    #endif


            if (m_paused)
            {
                setPaused(false);
            }


		    // return immediately in menu mode
		    if (m_psaiPlayMode == PsaiPlayMode.menuMode)
		    {
			    #if !(PSAI_NOLOG)
                    if (LogLevel.warnings <= Logger.Instance.LogLevel)
                    {
                    	Logger.Instance.Log("StopMusic() ignored: Menu Mode is active", LogLevel.warnings);
                    }
			    #endif

			    return PsaiResult.commandIgnoredMenuModeActive;
		    }

		    // return immediately in cutscene mode
		    if (m_psaiPlayModeIntended == PsaiPlayMode.cutScene)
		    {
			    #if !(PSAI_NOLOG)
                    if (LogLevel.warnings <= Logger.Instance.LogLevel)
                    {
                    	Logger.Instance.Log("StopMusic() ignored: Cutscene is active", LogLevel.warnings);
                    }
			    #endif

			    return PsaiResult.commandIgnoredCutsceneActive;
		    }

		    if (m_initializationFailure)
		    {
			    #if !(PSAI_NOLOG)
			    {
                    Logger.Instance.Log(LOGMESSAGE_ABORTION_DUE_TO_INITIALIZATION_FAILURE, LogLevel.errors);
			    }
			    #endif

			    return PsaiResult.initialization_error;
		    }

       		if (m_psaiStateIntended == PsaiState.silence && !immediately)
		    {
			    #if !(PSAI_NOLOG)
			    {
				    if (LogLevel.warnings <= Logger.Instance.LogLevel)
				    {
				    	Logger.Instance.Log("StopMusic() ignored - psai is currently already transitioning to SILENCE mode", LogLevel.warnings);
				    }
			    }
			    #endif

			    return PsaiResult.commandIgnored;
		    }

            m_returnToLastBasicMoodFlag = false;
            m_holdIntensity = false;

		    //////////////////////////////////////////////////////////////////////////

		    switch (m_psaiState)
		    {
			    case PsaiState.playing:
			    case PsaiState.silence:		// SILENCE will be set if we are leaving the menu and were in SILENCE when we entered it
			    {
				    Segment effectiveSnippet = GetEffectiveSegment();

				    if (effectiveSnippet != null)
				    {				
					    bool validPathToEndSegmentExists = false;					
					    if (!immediately)
					    {
						    validPathToEndSegmentExists = CheckIfThereIsAPathToEndSegmentForEffectiveSegmentAndLogWarningIfThereIsnt();
					    }

					    if (immediately || !validPathToEndSegmentExists)
					    {
						    startFade(m_currentVoiceNumber, PSAI_FADEOUTMILLIS_STOPMUSIC, 0);
						    EnterSilenceMode();
					    }
					    else
					    {	
						    #if !(PSAI_NOLOG)
						    {
							    WriteLogWarningIfThereIsNoDirectPathForEffectiveSnippetToEndSnippet();                             
						    }
						    #endif

                            if (m_nonInterruptingTriggerOfHighestPriority.themeId != -1)
                            {
                                m_nonInterruptingTriggerOfHighestPriority.themeId = -1;

                                #if !(PSAI_NOLOG)
                                {
                                    if (LogLevel.debug <= Logger.Instance.LogLevel)
                                    {
                                    	Logger.Instance.Log("cleared noninterrupting trigger", LogLevel.debug);
                                    }
                                }
                                #endif
                            }

						    m_psaiStateIntended = PsaiState.silence;
					    }
				    }
			    }
			    break;

			    case PsaiState.rest:
			    {
                    EnterSilenceMode();
			    }
			    break;
		    }

		    return PsaiResult.OK;
	    }
Example #11
0
        void SegmentEndApproachingHandler()
	    {
		    //boost::recursive_mutex::scoped_lock block(m_pnxLogicMutex);

		    #if !(PSAI_NOLOG)
		    {
                if (LogLevel.debug <= Logger.Instance.LogLevel)
                {
	                StringBuilder sb = new StringBuilder();
				    sb.Append("--- SegmentEndApproachingHandler()  m_psaiStateIntended=");
	                sb.Append(m_psaiStateIntended);
	                sb.Append("  m_nonInterruptingTriggerOfHighestPriority.themeId=");
	                sb.Append(m_nonInterruptingTriggerOfHighestPriority.themeId);
	                Logger.Instance.Log(sb.ToString(), LogLevel.debug);
                }
		    }
		    #endif


            // make sure we don't go to rest/sleep in case a non-interrupting trigger call
            // has been received 
            if (m_nonInterruptingTriggerOfHighestPriority.themeId != -1)
            {
                m_psaiState = PsaiState.playing;
                m_psaiStateIntended = PsaiState.playing;
            }

		    switch (m_psaiStateIntended)
		    {
			    case PsaiState.silence:
				    {
                        if (m_currentSegmentPlaying == null || m_currentSegmentPlaying.IsUsableAs(SegmentSuitability.end))
					    {
						    EnterSilenceMode();
					    }
					    else
					    {		
						    PlaySegment(m_currentSegmentPlaying.nextSnippetToShortestEndSequence, false);
					    }
				    }
				    break;

			    case PsaiState.rest:
				    {
                        if (m_currentSegmentPlaying == null || m_currentSegmentPlaying.IsUsableAs(SegmentSuitability.end))
                        {
                            if (m_psaiState != PsaiState.rest)  // m_psaiState will be PsaiState.rest if we already called GoToRest using a fadeout.
                            {
                                EnterRestMode(GetLastBasicMoodId(), getEffectiveThemeId());
                            }                            
                        }
                        else
                        {
                            PlaySegment(m_currentSegmentPlaying.nextSnippetToShortestEndSequence, false);
                        }
				    }
				    break;

			    default:
				    {
                        
					    if (m_returnToLastBasicMoodFlag)
					    {
						    #if !(PSAI_NOLOG)
						    {
                                if (LogLevel.debug <= Logger.Instance.LogLevel)
                                {
                                	Logger.Instance.Log("returnToLastBasicMoodFlag was set", LogLevel.debug);
                                }
						    }
						    #endif
					
						    // no End-Segment is playing and there is a valid transition to End - go on with the ending sequence.
						    if ( ((m_currentSegmentPlaying.SnippetTypeBitfield & (int)SegmentSuitability.end) == 0) &&
							     CheckIfThereIsAPathToEndSegmentForEffectiveSegmentAndLogWarningIfThereIsnt() == true
							    )
						    {
							    WriteLogWarningIfThereIsNoDirectPathForEffectiveSnippetToEndSnippet();

							    PlaySegment(m_currentSegmentPlaying.nextSnippetToShortestEndSequence, false);
							    return;
						    }
						    else
						    {
							    PlayThemeNowOrAtEndOfCurrentSegment(GetLastBasicMoodId(), m_lastBasicMood.intensityAfterRest, m_lastBasicMood.musicDurationGeneral, false, false);
							    m_returnToLastBasicMoodFlag = false;
							    return;
						    }
					    }


					    
                        // do we have received any trigger-Calls while playing? Then use the one with the 
                        // highest priority

                        if (m_psaiPlayMode == PsaiPlayMode.regular && m_nonInterruptingTriggerOfHighestPriority.themeId != -1)
                        {

                            Theme nonInterruptingTheme = m_soundtrack.getThemeById(m_nonInterruptingTriggerOfHighestPriority.themeId);

                            if (m_currentSegmentPlaying.CheckIfAtLeastOneDirectTransitionOrLayeringIsPossible(m_soundtrack, nonInterruptingTheme.id))
                            {
                                PlayThemeNowOrAtEndOfCurrentSegment(m_nonInterruptingTriggerOfHighestPriority.themeId, m_nonInterruptingTriggerOfHighestPriority.startIntensity, m_nonInterruptingTriggerOfHighestPriority.musicDuration, false, m_nonInterruptingTriggerOfHighestPriority.holdIntensity);
                                m_nonInterruptingTriggerOfHighestPriority.themeId = -1;
                            }
                            else
                            {
                                if (m_currentSegmentPlaying.MapOfNextTransitionSegmentToTheme.ContainsKey(nonInterruptingTheme.id))
                                {
                                    #if !(PSAI_NOLOG)
                                    {
                                        if (LogLevel.info <= Logger.Instance.LogLevel)
                                        {
	                                        StringBuilder sb = new StringBuilder();
	                                        sb.Append("No direct transition exists from Segment ");
	                                        sb.Append(m_currentSegmentPlaying.Name);
	                                        sb.Append(" to any MIDDLE or BRIDGE Segment of Theme ");
	                                        sb.Append(nonInterruptingTheme.Name);
	                                        sb.Append(", psai is therefore playing an indirect transition via the shortest path of compatible Segments. The next one will be ");
	                                        sb.Append(m_currentSegmentPlaying.MapOfNextTransitionSegmentToTheme[nonInterruptingTheme.id]);
	                                        Logger.Instance.Log(sb.ToString(), LogLevel.info);
                                        }
                                    }
                                    #endif

                                    PlaySegment(m_currentSegmentPlaying.MapOfNextTransitionSegmentToTheme[nonInterruptingTheme.id], false);
                                }
                                else
                                {
                                    #if !(PSAI_NOLOG)
                                    {
                                        if (LogLevel.warnings <= Logger.Instance.LogLevel)
                                        {
	                                        StringBuilder sb = new StringBuilder();
	                                        sb.Append("Could not perform any transition from Segment ");
	                                        sb.Append(m_currentSegmentPlaying.Name);
	                                        sb.Append(" to Theme ");
	                                        sb.Append(nonInterruptingTheme.Name);
	                                        sb.Append(" as no direct or indirect path of compatible Segments exists. Psai is therefore switching Themes by crossfading.");
	                                        Logger.Instance.Log(sb.ToString(), LogLevel.warnings);
                                        }
                                    }
                                    #endif

                                    PlayThemeNowOrAtEndOfCurrentSegment(m_nonInterruptingTriggerOfHighestPriority.themeId, m_nonInterruptingTriggerOfHighestPriority.startIntensity, m_nonInterruptingTriggerOfHighestPriority.musicDuration, true, m_nonInterruptingTriggerOfHighestPriority.holdIntensity);
                                    m_nonInterruptingTriggerOfHighestPriority.themeId = -1;
                                }
                            }
                        }
                        else
                        {
                            // business as usual: get the next snippet of the current theme
                            float currentIntensity = getCurrentIntensity();
                            if (currentIntensity > 0.0f)
                            {
                                m_nonInterruptingTriggerOfHighestPriority.themeId = -1;
                                PlaySegmentOfCurrentTheme(SegmentSuitability.middle);
                            }
                            else
                            {
                                IntensityZeroHandler();
                            }
                        }					    
				    }
				    break;
		    }
	    }
Example #12
0
        /** internal function to initiate the playback of a theme.
	    * @param themeId     id of the theme to be played 
	    * @param intensity   the desired intensity level [0.0f ... 1.0f]
	    * @param immediately true: play instantly   false: play at end of current snippet
	    * @param SnippetType
	    * @param recalculateIntensitySlope pass true if the intensity slope needs to be reinitialized to the full musical period as defined in the authoring software.
	    * @param holdIntensity pass true if the intensity should be held on a constant level, false otherwise (default is false)
	    * @return PsaiResult.OK ok, theme will be played
	    *		PSAI_INFO_TRIGGER_DENIED trigger was denied as a theme transition is not guaranteed due to missing snippet transitions, and error handling was set to DENY_TRIGGER
	    *		PSAI_ERR_ESSENTIAL_SNIPPET_MISSING a transition could not be achieved because there was no compatible follower to the current snippet, and error handling was set to ABORT or STOP_MUSIC
	    *		
	    */
	    PsaiResult PlayThemeNowOrAtEndOfCurrentSegment(int themeId, float intensity, int musicDuration, bool immediately, bool holdIntensity)
	    {
		    #if !(PSAI_NOLOG)
		    {
                if (LogLevel.debug <= Logger.Instance.LogLevel)
                {
	                Theme theme = m_soundtrack.getThemeById(themeId);
	
	                StringBuilder sb = new StringBuilder();
	                sb.Append("PlayThemeNowOrAtEndOfCurrentSegment()  themeId=");
	                sb.Append(themeId);
	
	                if (theme == null)
	                {
	                    sb.Append("THEME NOT FOUND!");
	                }
	                else
	                {
	                    sb.Append(" [");
	                    sb.Append(theme.Name);
	                    sb.Append("]  themeType=");
	                    sb.Append(theme.themeType);
	                }
	
	                sb.Append( " intensity=");
	                sb.Append(intensity);
	                sb.Append(" immediately=");
	                sb.Append(immediately);
	                sb.Append(" holdIntensity=");
	                sb.Append(holdIntensity);
	                sb.Append(" musicDuration=");
	                sb.Append(musicDuration);
	                sb.Append(" m_currentSegmentPlaying=");
	                sb.Append(m_currentSegmentPlaying);
	
	                Logger.Instance.Log(sb.ToString(), LogLevel.debug);
                }
		    }
		    #endif

            SetCurrentIntensityAndMusicDuration(intensity, musicDuration, true);

            m_psaiStateIntended = PsaiState.playing;
            m_heldIntensity = intensity;

		    // if we're interrupting rest mode, kill the rest wake up timer		    
            if (m_psaiState == PsaiState.rest)
		    {
                m_timerWakeUpFromRest.Stop();
		    }


            

            // choice of Segment Suitability:
            // * Use Start Segments:
            //      1. when playing out of silence
            //      2. if a pure END-Segment is currently playing
            // * Use Middle Segments when staying within the current Theme.
            // * Use Bridge or Middle Segments when transitioning to another Theme.            
            m_targetSegmentSuitabilitiesRequested = (int)SegmentSuitability.start;

            if (m_psaiState == PsaiState.playing)
            {               
                if (m_currentSegmentPlaying != null)
                {
                    if (m_currentSegmentPlaying.IsUsableOnlyAs(SegmentSuitability.end))
                    {
                        m_targetSegmentSuitabilitiesRequested = (int)SegmentSuitability.start;
                    }
                    else
                    {
                        if (getEffectiveThemeId() == themeId)
                        {
                            // we stay within the same Theme, so choose a MIDDLE Segment
                            // NOTE: this may only happen if we return from the Menu or a CutScene to the same Theme. Otherwise,
                            // PlayThemeNowOrAtEndOfCurrentSegment should not be called explicitly
                            m_targetSegmentSuitabilitiesRequested = (int)SegmentSuitability.middle;
                        }
                        else
                        {
                            // upon Theme changes we play BRIDGE or MIDDLE Segments
                            m_targetSegmentSuitabilitiesRequested = SNIPPET_TYPE_MIDDLE_OR_BRIDGE;
                        }
                    }
                }
            }

            m_effectiveTheme = m_soundtrack.getThemeById(themeId);

            Segment targetSnippet;
            if ((m_targetSegmentSuitabilitiesRequested & (int)SegmentSuitability.start) > 0 || GetEffectiveSegment() == null)
            {
                targetSnippet = GetBestStartSegmentForTheme(themeId, intensity);
            }
            else
            {
                targetSnippet = GetBestCompatibleSegment(GetEffectiveSegment(), themeId, intensity, m_targetSegmentSuitabilitiesRequested);
            }


		    //////////////////////////////////////////////////////////////////////////
		    // no compatible Segment could be found !
		    //////////////////////////////////////////////////////////////////////////
		    if (targetSnippet == null)
		    {
				#if !(PSAI_NOLOG)
				{
                    Logger.Instance.Log("essential Segment could not be found! Trying to substitute...", LogLevel.errors);
				}
				#endif

				targetSnippet = substituteSegment(themeId);

				if (targetSnippet == null)
				{
					#if !(PSAI_NOLOG)
					{
                        Logger.Instance.Log("failed to substitute Segment. Stopping music.", LogLevel.errors);
					}
					#endif

					StopMusic(true);
					return PsaiResult.essential_segment_missing;
				}
		    }

		    // ////////////////////////////////////////////////
		    // at this point, the target Segment has to be set! (internal error otherwise)
		    // ////////////////////////////////////////////////

		    m_holdIntensity = holdIntensity;
            
            // starting a Theme immediately when any other Theme is already playing should result in
            // fading out that other Theme.
            if (immediately && GetEffectiveSegment() != null)
            {
                m_scheduleFadeoutUponSnippetPlayback = true;
            }

		    if (targetSnippet != null)
		    {
                return PlaySegment(targetSnippet, immediately);	
		    }
		    else
		    {
			    #if !(PSAI_NOLOG)
			    {
                    Logger.Instance.Log("fatal internal error! entered code section in PlayTheme that is supposed to be unreachable!", LogLevel.errors);
			    }
			    #endif

			    return PsaiResult.internal_error;
		    }
	    }
Example #13
0
        /* This method will play the target Segment with minimum delay, and set the m_targetSnipet to m_currentSnippet, and m_targetVoice to m_currentVoice.
         */        
	    void PlayTargetSegmentImmediately()
	    {
            #if !(PSAI_NOLOG)
            {
                if (LogLevel.debug <= Logger.Instance.LogLevel)
                {
	                StringBuilder sb = new StringBuilder();
	                sb.Append("PlayTargetSegmentImmediately()  m_targetSegmentTypesRequested=");
	                sb.Append(Segment.GetStringFromSegmentSuitabilities(m_targetSegmentSuitabilitiesRequested));
	                sb.Append("  targetSegment=");
	                sb.Append(m_targetSegment.Name);
	                sb.Append("  id=");
	                sb.Append(m_targetSegment.Id);
	                sb.Append("  m_targetVoice=");
	                sb.Append(m_targetVoice);
	                sb.Append("  themeId=");
	                sb.Append(m_targetSegment.ThemeId);
	                sb.Append("  playbackChannel.Segment=" );
	                sb.Append(m_playbackChannels[m_targetVoice].Segment.Name);
	                sb.Append("  millisSinceSegmentLoad=");
	                sb.Append(  m_playbackChannels[m_targetVoice].GetMillisecondsSinceSegmentLoad());
	                Logger.Instance.Log(sb.ToString(), LogLevel.debug);
                }
            }
            #endif

            int snippetPlaybackDelayMillis = 0;            
            if (m_playbackChannels[m_targetVoice].CheckIfSegmentHadEnoughTimeToLoad())
            {
                snippetPlaybackDelayMillis = m_estimatedTimestampOfTargetSnippetPlayback - GetTimestampMillisElapsedSinceInitialisation();

                #if !(PSAI_NOLOG)
                   if (LogLevel.debug <= Logger.Instance.LogLevel)
                   {
                       Logger.Instance.Log("Segment had enough time to load.   m_estimatedTimestampOfTargetSnippetPlayback=" + m_estimatedTimestampOfTargetSnippetPlayback.ToString(), LogLevel.debug);
                   }
                #endif                
            }
            else
            {
                int millisUntilLoadingWillHaveFinished = m_playbackChannels[m_targetVoice].GetMillisecondsUntilLoadingWillHaveFinished();
                #if !(PSAI_NOLOG)
                {
                    if (LogLevel.debug <= Logger.Instance.LogLevel)
                    {
                    	Logger.Instance.Log("Segment DID NOT have enough time to load!  missing milliSeconds=" + millisUntilLoadingWillHaveFinished, LogLevel.debug);
                    }
                }
                #endif

                snippetPlaybackDelayMillis = millisUntilLoadingWillHaveFinished + s_audioLayerMaximumLatencyForPlayingbackPrebufferedSounds;
            }

            m_playbackChannels[m_targetVoice].FadeOutVolume = 1.0f;
            m_playbackChannels[m_targetVoice].ScheduleSegmentPlayback(m_targetSegment, snippetPlaybackDelayMillis);            

            if (m_scheduleFadeoutUponSnippetPlayback)
            {
                startFade(m_currentVoiceNumber, PSAI_FADEOUTMILLIS_PLAYIMMEDIATELY, m_targetSegment.audioData.GetPreBeatZoneInMilliseconds() + snippetPlaybackDelayMillis);
                m_scheduleFadeoutUponSnippetPlayback = false;
            }

            m_psaiPlayMode = m_psaiPlayModeIntended;
            m_currentVoiceNumber = m_targetVoice;

            m_currentSegmentPlaying = m_targetSegment;
            m_currentSnippetTypeRequested = m_targetSegmentSuitabilitiesRequested;
            m_currentSegmentPlaying.Playcount++;			//TODO: this should not be increased within menu mode, should it?

            m_timeStampCurrentSnippetPlaycall = GetTimestampMillisElapsedSinceInitialisation() + snippetPlaybackDelayMillis;

            // now set the timers for snippet end approaching and snippet end reached	
            int millisUntilUpcomingSnippetEnd = m_targetSegment.audioData.GetFullLengthInMilliseconds() + snippetPlaybackDelayMillis;            
            int millisUntilNextCalculateCall = (int)(millisUntilUpcomingSnippetEnd 
                - m_targetSegment.audioData.GetPostBeatZoneInMilliseconds() 
                - m_targetSegment.MaxPreBeatMsOfCompatibleSnippetsWithinSameTheme 
                - s_audioLayerMaximumLatencyForPlayingBackUnbufferedSounds      // deterministic calculation up to here...
                -  2 * s_updateIntervalMillis);  // ... now add some extra headroom for processing time


            if (millisUntilNextCalculateCall < 0)
            {                
                #if !(PSAI_NOLOG)
                {
                    if (LogLevel.warnings <= Logger.Instance.LogLevel)
                    {
	                    StringBuilder sb = new StringBuilder();
	                    sb.Append(" psai did not have enough time to evaluate the next Segment in time (missing milliseconds: ");
	                    sb.Append(millisUntilNextCalculateCall);
	                    sb.Append(").");
	                    sb.Append(" This means that either the main region of Segment '");
                        sb.Append(m_currentSegmentPlaying.Name);
                        sb.Append("' (ThemeId=");
                        sb.Append(m_currentSegmentPlaying.ThemeId);
                        sb.Append(") is too short, or that the Prebeat region of at least one of its compatible Segments is too long. ");
                        sb.Append("See the 'best practice' section in the psai manual for more information.");
	                    Logger.Instance.Log(sb.ToString(), LogLevel.warnings);
                    }
                }
#endif

                millisUntilNextCalculateCall = 0;
            }          

            m_targetSegment = null;
            m_psaiState = PsaiState.playing;

            if (millisUntilNextCalculateCall < 0)
            {
                millisUntilNextCalculateCall = 0;
            }
            m_timerSegmentEndApproaching.SetTimer(millisUntilNextCalculateCall, s_updateIntervalMillis);


            // at the moment the SnippetEndReached Timer only fires for the very last snippet
            // so it will be extended with every following snippet
            m_timerSegmentEndReached.SetTimer(millisUntilUpcomingSnippetEnd, 0);

            #if !(PSAI_NOLOG)
            {
                /*
                if (LogLevel.debug <= Logger.Instance.LogLevel)
                {
	                StringBuilder sb = new StringBuilder();
	                sb.Append("m_timer_SegmentEndApproaching should fire in ");
	                sb.Append(millisUntilNextCalculateCall);
	                sb.Append(" ms");
	                Logger.Instance.Log(sb.ToString(), LogLevel.debug);
	
	                
	                StringBuilder sb2 = new StringBuilder();
	                sb2.Append("m_timer_SegmentEndReached should fire in ");
	                sb2.Append(millisUntilUpcomingSnippetEnd);
	                sb2.Append(" ms");
	                Logger.Instance.Log(sb2.ToString(), LogLevel.debug); 
                }               
                */
            }
            #endif            
	    }
Example #14
0
        	/** basic internal function for setting the first theme that will be played as soon as the
	    * current theme's intensity has dropped (or has been set) to zero. This method behaves as a push operation, so the parameter will be
	    * the first theme on the theme queue stack.
	    * @param clearThemeQueue pass true to clear the themeQueue, false to enqueue the followingTheme in the themeQueue
	    * @param restTimeMillis if the theme should start in rest mode, pass the resting millis. 0 otherwise.
	    * @param playMode the playMode that will be entered when the theme is popped.
	    * @param holdIntensity true for holding the intensity at a constant level
	    */
	    bool pushThemeToThemeQueue(int themeId, float intensity, int musicDuration, bool clearThemeQueue, int restTimeMillis, PsaiPlayMode playMode, bool holdIntensity)
	    {
		    //boost::recursive_mutex::scoped_lock block(m_pnxLogicMutex);

		    #if !(PSAI_NOLOG)
		    {
                if (LogLevel.info <= Logger.Instance.LogLevel)
                {
	                StringBuilder sb = new StringBuilder();
	                sb.Append("setting the Following Theme to ");
	                sb.Append(themeId);

                    if (LogLevel.debug <= Logger.Instance.LogLevel)
                    {
        	            sb.Append("  intensity= ");
	                    sb.Append(intensity);
	                    sb.Append("  clearThemeQueue=");
	                    sb.Append(clearThemeQueue);
	                    sb.Append("  playmode=");
	                    sb.Append(playMode);
	                    sb.Append("  holdIntensity=");
	                    sb.Append(holdIntensity);
	                    sb.Append("  musicDuration=");
	                    sb.Append(musicDuration);
                    }
	                Logger.Instance.Log(sb.ToString(), LogLevel.info);
                }
		    }
#endif

            if (clearThemeQueue)
		    {
			    m_themeQueue.Clear();
		    }

            Theme theme = m_soundtrack.getThemeById(themeId);
		    if (theme != null)
		    {
			    ThemeQueueEntry newEntry = new ThemeQueueEntry();
			    newEntry.themeId = themeId;
			    newEntry.startIntensity = intensity;
                newEntry.musicDuration = musicDuration;
			    newEntry.restTimeMillis = restTimeMillis;
			    newEntry.playmode = playMode;
			    newEntry.holdIntensity = holdIntensity;

			    #if !(PSAI_NOLOG)
			    {
                    if (LogLevel.debug <= Logger.Instance.LogLevel)
                    {
	                    StringBuilder sb = new StringBuilder();
	                    sb.Append(" m_themeQueue.size()=");
	                    sb.Append(m_themeQueue.Count);
	               	    for (int i=0; i<m_themeQueue.Count; i++)
					    {
						    ThemeQueueEntry tmpEntry = m_themeQueue[i];
	                        sb.Append("   [");
	                        sb.Append(i);
	                        sb.Append("] themeId=");
	                        sb.Append(tmpEntry.themeId);
	                        sb.Append(" startIntensity=");
	                        sb.Append(tmpEntry.startIntensity);
	                    }
	                    Logger.Instance.Log(sb.ToString(), LogLevel.debug);
                    }
			    }
			    #endif

                m_themeQueue.Insert(0, newEntry);
                m_psaiStateIntended = PsaiState.playing;		// in case IntensityZeroHandler() had already been called, we need to reset the psaiStateIntended here
                return true;
		    }
		    else
		    {
			    return false;
		    }
	    }
Example #15
0
        internal PsaiResult TriggerMusicTheme(Theme argTheme, float argIntensity, int argMusicDuration)
        {
            if (m_initializationFailure)
            {
                #if !(PSAI_NOLOG)
                {
                    if (LogLevel.errors <= Logger.Instance.LogLevel)
                    {
                    	Logger.Instance.Log(LOGMESSAGE_ABORTION_DUE_TO_INITIALIZATION_FAILURE, LogLevel.errors);
                    }
                }
                #endif

                return PsaiResult.initialization_error;
            }

		    //////////////////////////////////////////////////////////////////////////

            if (m_paused)
            {
                setPaused(false);
            }

            Segment effectiveSegment = GetEffectiveSegment();

            // special treatment for Highlights
            if (argTheme.themeType == ThemeType.highlightLayer)
            {
   				if (CheckIfAnyThemeIsCurrentlyPlaying() == true)
				{
					if (m_effectiveTheme != null && effectiveSegment != null && effectiveSegment.CheckIfAtLeastOneDirectTransitionOrLayeringIsPossible(m_soundtrack, argTheme.id) == false)
					{
						#if !(PSAI_NOLOG)
						{
                            Logger.Instance.Log(LOGMESSAGE_TRIGGER_DENIED, LogLevel.warnings);
						}
						#endif	
						return PsaiResult.triggerDenied;
					};
				}

				return startHighlight(argTheme);
            }


		    // return immediately in menu mode
		    if (m_psaiPlayMode == PsaiPlayMode.menuMode)
		    {

			    #if !(PSAI_NOLOG)
                    if (LogLevel.warnings <= Logger.Instance.LogLevel)
                    {
                    	Logger.Instance.Log("TriggerMusicTheme() ignored: Menu Mode is active", LogLevel.warnings);
                    }
			    #endif

			    return PsaiResult.commandIgnoredMenuModeActive;
		    }

		    else if (m_psaiPlayModeIntended == PsaiPlayMode.cutScene)
		    {
			    #if !(PSAI_NOLOG)
                    if (LogLevel.warnings <= Logger.Instance.LogLevel)
                    {
                    	Logger.Instance.Log("TriggerMusicTheme() ignored: Cutscene is active", LogLevel.warnings);
                    }
			    #endif

			    return PsaiResult.commandIgnoredCutsceneActive;
		    }

		    else if (m_psaiPlayMode == PsaiPlayMode.cutScene && m_psaiStateIntended == PsaiState.silence && m_currentSegmentPlaying != null)
		    {
			    #if !(PSAI_NOLOG)
			    {
                    if (LogLevel.info <= Logger.Instance.LogLevel)
                    {
                    	Logger.Instance.Log("special case: Cutscene Theme is still playing, continuing with theme " + argTheme.Name, LogLevel.info);
                    }
			    }
			    #endif

			    m_psaiState = PsaiState.playing;
			    m_psaiStateIntended = PsaiState.playing;

                return PlayThemeNowOrAtEndOfCurrentSegment(argTheme.id, argIntensity, argMusicDuration, true, false);						
		    }




		    //////////////////////////////////////////////////////////////////////////
		    // regular Mode
		    //////////////////////////////////////////////////////////////////////////


            // if we trigger a BasicMood shortly after ReturnToBasicMood(by End) has been called, we don't want to cancel the
            // return, but instead switch the Last Basic Mood to return to. In all other cases, cancel the Return process.
            if (m_returnToLastBasicMoodFlag)
            {
                if (argTheme.themeType != ThemeType.basicMood)
                {
                    m_returnToLastBasicMoodFlag = false;
                }                
            }


            if (argTheme.themeType == ThemeType.basicMood)
		    {
			    SetThemeAsLastBasicMood(argTheme);
		    }


            // always clear the Theme Queue, as the most recent trigger call is the one that counts.
            removeFirstFollowingThemeQueueEntry();

		
		    // nothing is playing -> play immediately
		    if (effectiveSegment == null || m_psaiState == PsaiState.silence || m_psaiState == PsaiState.rest)
		    {
                return PlayThemeNowOrAtEndOfCurrentSegment(argTheme.id, argIntensity, argMusicDuration, true, false);
		    }


            // special case: StopMusic(by End Segment) is in progress, and a Theme of lower or same priority is triggered
		    // -> conduct a seamless transition.
		    if (m_psaiStateIntended == PsaiState.silence && effectiveSegment != null)
		    {
                Theme effectiveTheme1 = m_soundtrack.getThemeById(effectiveSegment.ThemeId);
			    ThemeInterruptionBehavior tib = Theme.GetThemeInterruptionBehavior(effectiveTheme1.themeType, argTheme.themeType);

                if (tib == ThemeInterruptionBehavior.at_end_of_current_snippet || tib == ThemeInterruptionBehavior.never)
			    {
				    m_psaiStateIntended = PsaiState.playing;
				    return PlayThemeNowOrAtEndOfCurrentSegment(argTheme.id, argIntensity, argMusicDuration, false, false);
			    }			
		    }


		    // the effective Theme was triggered again? 
		    if (effectiveSegment.ThemeId == argTheme.id)
		    {
			    #if !(PSAI_NOLOG)
			    {
                    /*
                    if (LogLevel.debug <= Logger.Instance.LogLevel)
                    {
	                    StringBuilder sb = new StringBuilder();
	                    sb.Append("theme ");
	                    sb.Append(argTheme.Name);
	                    sb.Append(" is already playing and the SegmentEndApproaching timer is pending. Updating intensity to ");
	                    sb.Append(argIntensity);
	                    Logger.Instance.Log(sb.ToString(), LogLevel.debug);
                    }
                    */
			    }
			    #endif
                
                m_nonInterruptingTriggerOfHighestPriority.themeId = -1;		// clear any non-interrupting trigger call we may have received recently!  

                SetCurrentIntensityAndMusicDuration(argIntensity, argMusicDuration, true);
                m_psaiStateIntended = PsaiState.playing;
                return PsaiResult.OK;
		    }

            Theme effectiveTheme = m_soundtrack.getThemeById(effectiveSegment.ThemeId);
		    ThemeInterruptionBehavior themeInteruptionBehavior = Theme.GetThemeInterruptionBehavior(effectiveTheme.themeType, argTheme.themeType);

		    switch (themeInteruptionBehavior)
		    {
		    case ThemeInterruptionBehavior.immediately:
			    {
                    // don't push the interrupted Theme on the stack if GoToRest() or StopMusic() has just been called.
                    if (argTheme.themeType == ThemeType.shock && m_psaiStateIntended == PsaiState.playing) 
                    {
                        PushEffectiveThemeToThemeQueue(PsaiPlayMode.regular);
                    }
                    else
                    {
                        m_nonInterruptingTriggerOfHighestPriority.themeId = -1;
                    }

                    return PlayThemeNowOrAtEndOfCurrentSegment(argTheme.id, argIntensity, argMusicDuration, true, false);                
			    }
			    //break;

		    case ThemeInterruptionBehavior.at_end_of_current_snippet:
			    {
				    return HandleNonInterruptingTriggerCall(argTheme, argIntensity, argMusicDuration);				
			    }
			    //break;

		    case ThemeInterruptionBehavior.never:
			    {
                    if (argTheme.themeType != ThemeType.basicMood)
				    {
					    pushThemeToThemeQueue(argTheme.id, argIntensity, argMusicDuration, false, 0, PsaiPlayMode.regular, false);

					    #if !(PSAI_NOLOG)
					    {
                            if (LogLevel.info <= Logger.Instance.LogLevel)
                            {
	                            StringBuilder sb = new StringBuilder();
	                            sb.Append("Theme ");
	                            sb.Append(argTheme.Name);
	                            sb.Append(" has been queued for direct playback after the intensity of the current Theme has dropped to zero.");
							    Logger.Instance.Log(sb.ToString(), LogLevel.info);
                            }
					    }
					    #endif
				    }
				    return PsaiResult.OK;
			    }
			    //break;
		    }

		

		    #if !(PSAI_NOLOG)
		    {
                if (LogLevel.errors <= Logger.Instance.LogLevel)
                {
	                StringBuilder sb = new StringBuilder();
	                sb.Append("INTERNAL ERROR: end of TriggerMusicTheme() reached without returning a proper returnCode. ");
	                sb.Append("argThemeId=");
	                sb.Append(argTheme.id);
	                sb.Append(" m_currentTheme=");
	                sb.Append(m_effectiveTheme);
	                if (m_effectiveTheme != null)
	                {
	                    sb.Append(" m_currentTheme id=");
	                    sb.Append(m_effectiveTheme.id);
	                    sb.Append("  m_currentTheme themeType=");
	                    sb.Append(m_effectiveTheme.themeType);
	                }
	                Logger.Instance.Log(sb.ToString(), LogLevel.errors);
                }
		    }
		    #endif

		    return PsaiResult.internal_error;
        }
Example #16
0
        internal PsaiResult ReturnToLastBasicMood(bool immediately)
	    {				
		    #if !(PSAI_NOLOG)
                {
                    if (LogLevel.info <= Logger.Instance.LogLevel)
                    {
	                    StringBuilder sb = new StringBuilder();
	                    sb.Append("ReturnToBasicMood(");
	                    sb.Append(immediately);
	                    sb.Append(")  m_psaiState=");
	                    sb.Append(m_psaiState);
	                    sb.Append("  m_currentSnippetTypesRequested=");
	                    sb.Append(Segment.GetStringFromSegmentSuitabilities(m_currentSnippetTypeRequested));
	                    Logger.Instance.Log(sb.ToString(), LogLevel.info);
                    }
                }
		    #endif

		    if (m_initializationFailure)
		    {
			    return PsaiResult.initialization_error;
		    }

		    //////////////////////////////////////////////////////////////////////////

            if (m_paused)
            {
                setPaused(false);
            }


		    if (m_psaiPlayModeIntended == PsaiPlayMode.regular)
		    {
			    switch(m_psaiState)
			    {
                    case PsaiState.playing:
				    {
                        m_themeQueue.Clear();
                        m_holdIntensity = false;
                        m_nonInterruptingTriggerOfHighestPriority.themeId = -1;                        

						if (m_currentSegmentPlaying != null && m_effectiveTheme.themeType != ThemeType.basicMood)
						{
							bool validPathToEndSnippetExists = false;					
							if (!immediately)
							{
								validPathToEndSnippetExists = CheckIfThereIsAPathToEndSegmentForEffectiveSegmentAndLogWarningIfThereIsnt();
							}

							if (immediately || !validPathToEndSnippetExists)
							{
								PlayThemeNowOrAtEndOfCurrentSegment(GetLastBasicMoodId(), m_lastBasicMood.intensityAfterRest, m_lastBasicMood.musicDurationGeneral, true, false);
							}
							else
							{		
								m_psaiStateIntended = PsaiState.playing;		// in case we are interrupting a transition to SILENCE after StopMusic(0) was called
								m_returnToLastBasicMoodFlag = true;
							}
							return PsaiResult.OK;
						}
						else
						{
							#if !(PSAI_NOLOG)
								if (LogLevel.warnings <= Logger.Instance.LogLevel)
								{
									Logger.Instance.Log("ReturnToLastBasicMood() ignored: base theme is already playing", LogLevel.warnings);
								}
							#endif

							return PsaiResult.commandIgnored;
						}
					}
					//break;

				    case PsaiState.rest:
				    case PsaiState.silence:
					    {
						    PlayThemeNowOrAtEndOfCurrentSegment(GetLastBasicMoodId(), m_lastBasicMood.intensityAfterRest, m_lastBasicMood.musicDurationGeneral, true, false);
						    return PsaiResult.OK;
					    }
					    //break;

				    default:
                        {
                            #if !(PSAI_NOLOG)
                            {
                                if (LogLevel.debug <= Logger.Instance.LogLevel)
                                {
                                    StringBuilder sb = new StringBuilder();
                                    sb.Append("INTERNAL ERROR: unconsidered psaiState in ReturnToLastBasicMood()! m_psaiState=");
                                    sb.Append(m_psaiState);
                                    Logger.Instance.Log(sb.ToString(), LogLevel.debug);
                                }
                            }
                            #endif
                            return PsaiResult.internal_error;
                        }
			    }
		    }
		    else
		    {
			    if (m_psaiPlayModeIntended == PsaiPlayMode.menuMode)
			    {
				    #if !(PSAI_NOLOG)
                        if (LogLevel.warnings <= Logger.Instance.LogLevel)
                        {
                        	Logger.Instance.Log("ReturnToLastBasicMood() ignored: MenuMode is active. Call MenuModeLeave() first.", LogLevel.warnings);
                        }
                    #endif

                    return PsaiResult.commandIgnoredMenuModeActive;
			    }
			    else if (m_psaiPlayModeIntended == PsaiPlayMode.cutScene)
			    {
				    #if !(PSAI_NOLOG)
                        if (LogLevel.warnings <= Logger.Instance.LogLevel)
                        {
                        	Logger.Instance.Log("ReturnToLastBasicMood() ignored: CutScene is active. Call CutsceneLeave() first.", LogLevel.warnings);
                        }
                    #endif

                    return PsaiResult.commandIgnoredCutsceneActive;
			    }
		    }

		    return PsaiResult.internal_error;		// should never be reached
	    }