private List <String> playSounds(List <String> eventNames, Boolean isImmediateMessages, out Boolean wasInterrupted) { Console.WriteLine("Playing sounds, events: " + String.Join(", ", eventNames)); List <String> soundsProcessed = new List <String>(); OrderedDictionary thisQueue = isImmediateMessages ? immediateClips : queuedClips; wasInterrupted = false; int playedEventCount = 0; foreach (String eventName in eventNames) { // if there's anything in the immediateClips queue, stop processing if (isImmediateMessages || immediateClips.Count == 0) { if (thisQueue.Contains(eventName)) { QueuedMessage thisMessage = (QueuedMessage)thisQueue[eventName]; if (!isImmediateMessages && playedEventCount > 0 && pauseBetweenMessages > 0) { Console.WriteLine("Pausing before " + eventName); Thread.Sleep(TimeSpan.FromSeconds(pauseBetweenMessages)); } // now double check this is still valid if (!isImmediateMessages) { Boolean messageHasExpired = thisMessage.expiryTime != 0 && thisMessage.expiryTime < DateTime.Now.Ticks / TimeSpan.TicksPerMillisecond;; Boolean messageIsStillValid = thisMessage.isMessageStillValid(eventName, crewChief.currentGameState); Boolean hasJustPlayedAsAnImmediateMessage = lastImmediateMessageName != null && eventName == lastImmediateMessageName && DateTime.Now - lastImmediateMessageTime < TimeSpan.FromSeconds(5); if (messageHasExpired || !messageIsStillValid || hasJustPlayedAsAnImmediateMessage) { soundsProcessed.Add(eventName); continue; } } if (clipIsPearlOfWisdom(eventName)) { soundsProcessed.Add(eventName); if (hasPearlJustBeenPlayed()) { Console.WriteLine("Rejecting pearl of wisdom " + eventName + " because one has been played in the last " + minTimeBetweenPearlsOfWisdom + " seconds"); continue; } else if (!allowPearlsOnNextPlay) { Console.WriteLine("Rejecting pearl of wisdom " + eventName + " because they've been temporarily disabled"); continue; } else if (disablePearlsOfWisdom) { Console.WriteLine("Rejecting pearl of wisdom " + eventName + " because pearls have been disabled for the last phase of the race"); continue; } else { timeLastPearlOfWisdomPlayed = DateTime.Now; if (!mute) { soundCache.Play(eventName); timeOfLastMessageEnd = DateTime.Now; } } } else { if (thisMessage.messageName != AudioPlayer.folderDidntUnderstand && thisMessage.messageName != AudioPlayer.folderStandBy) { // only cache the last message for repeat if it's an actual message lastMessagePlayed = thisMessage; } lastMessagePlayed = thisMessage; if (!mute) { soundCache.Play(thisMessage.messageFolders); timeOfLastMessageEnd = DateTime.Now; } if (playedMessagesCount.ContainsKey(eventName)) { int count = playedMessagesCount[eventName] + 1; playedMessagesCount[eventName] = count; } else { playedMessagesCount.Add(eventName, 1); } soundsProcessed.Add(eventName); } playedEventCount++; } } else { Console.WriteLine("we've been interrupted after playing " + playedEventCount + " events"); wasInterrupted = true; break; } } if (soundsProcessed.Count == 0) { Console.WriteLine("Processed no messages in this queue"); } else { Console.WriteLine("*** Processed " + String.Join(", ", soundsProcessed.ToArray())); } return(soundsProcessed); }
private void playQueueContents(OrderedDictionary queueToPlay, Boolean isImmediateMessages) { long milliseconds = DateTime.Now.Ticks / TimeSpan.TicksPerMillisecond; List <String> keysToPlay = new List <String>(); List <String> soundsProcessed = new List <String>(); Boolean oneOrMoreEventsEnabled = false; lock (queueToPlay) { int willBePlayedCount = queueToPlay.Count; String firstMovableEventWithPrefixOrSuffix = null; foreach (String key in queueToPlay.Keys) { QueuedMessage queuedMessage = (QueuedMessage)queueToPlay[key]; if (isImmediateMessages || queuedMessage.dueTime <= milliseconds) { Boolean messageHasExpired = queuedMessage.expiryTime != 0 && queuedMessage.expiryTime < milliseconds; Boolean messageIsStillValid = queuedMessage.isMessageStillValid(key, crewChief.currentGameState); Boolean queueTooLongForMessage = queuedMessage.maxPermittedQueueLengthForMessage != 0 && willBePlayedCount > queuedMessage.maxPermittedQueueLengthForMessage; Boolean hasJustPlayedAsAnImmediateMessage = !isImmediateMessages && lastImmediateMessageName != null && key == lastImmediateMessageName && DateTime.Now - lastImmediateMessageTime < TimeSpan.FromSeconds(5); if ((isImmediateMessages || !keepQuiet || queuedMessage.playEvenWhenSilenced) && queuedMessage.canBePlayed && messageIsStillValid && !keysToPlay.Contains(key) && !queueTooLongForMessage && !messageHasExpired && !hasJustPlayedAsAnImmediateMessage) { // special case for 'get ready' event here - we don't want to move this to the top of the queue because // it makes it sound shit. Bit of a hack, needs a better solution if (firstMovableEventWithPrefixOrSuffix == null && key != LapCounter.folderGetReady && soundCache.eventHasPersonalisedPrefixOrSuffix(key)) { firstMovableEventWithPrefixOrSuffix = key; } else { keysToPlay.Add(key); } } else { if (!messageIsStillValid) { Console.WriteLine("Clip " + key + " is not valid"); } else if (messageHasExpired) { Console.WriteLine("Clip " + key + " has expired"); } else if (queueTooLongForMessage) { List <String> keysToDisplay = new List <string>(); foreach (String keyToDisplay in queueToPlay.Keys) { keysToDisplay.Add(keyToDisplay); } Console.WriteLine("Queue is too long to play clip " + key + " max permitted items for this message = " + queuedMessage.maxPermittedQueueLengthForMessage + " queue: " + String.Join(", ", keysToDisplay)); } else if (!queuedMessage.canBePlayed) { Console.WriteLine("Clip " + key + " has some missing sound files"); } else if (hasJustPlayedAsAnImmediateMessage) { Console.WriteLine("Clip " + key + " has just been played in response to a voice command, skipping"); } soundsProcessed.Add(key); willBePlayedCount--; } } } if (firstMovableEventWithPrefixOrSuffix != null) { keysToPlay.Insert(0, firstMovableEventWithPrefixOrSuffix); } if (keysToPlay.Count > 0) { if (keysToPlay.Count == 1 && clipIsPearlOfWisdom(keysToPlay[0])) { if (hasPearlJustBeenPlayed()) { Console.WriteLine("Rejecting pearl of wisdom " + keysToPlay[0] + " because one has been played in the last " + minTimeBetweenPearlsOfWisdom + " seconds"); soundsProcessed.Add(keysToPlay[0]); } else if (disablePearlsOfWisdom) { Console.WriteLine("Rejecting pearl of wisdom " + keysToPlay[0] + " because pearls have been disabled for the last phase of the race"); soundsProcessed.Add(keysToPlay[0]); } } else { oneOrMoreEventsEnabled = true; } } } Boolean wasInterrupted = false; if (oneOrMoreEventsEnabled) { openRadioChannelInternal(); soundsProcessed.AddRange(playSounds(keysToPlay, isImmediateMessages, out wasInterrupted)); } else { soundsProcessed.AddRange(keysToPlay); } if (soundsProcessed.Count > 0) { lock (queueToPlay) { foreach (String key in soundsProcessed) { if (queueToPlay.Contains(key)) { queueToPlay.Remove(key); } } } } // now we go back and play anything else that's been inserted into the queue since we started, but only if // we've not been interrupted if (queueHasDueMessages(queueToPlay, isImmediateMessages) && (isImmediateMessages || !wasInterrupted)) { Console.WriteLine("There are " + queueToPlay.Count + " more events in the queue, playing them..."); playQueueContents(queueToPlay, isImmediateMessages); } }