protected virtual void Awake()
 {
     m_logger                 = new Logger(this);
     m_screenQueue            = new PlayableContentQueue();
     m_narratorQueue          = new PlayableContentQueue();
     m_queues                 = new Dictionary <string, PlayableContentQueue>();
     m_locativeAudioProcessor = new LocativeAudioContentProcessor();
 }
        public override void StopPlaying(ResourceActivationContext ctxt, PlayableContent playable, bool interrupt = false)
        {
            PlayableContentQueue queue = null;

            lock (m_queues)
            {
                m_queues.TryGetValue(ctxt.InstanceId, out queue);
            }

            var audioContent = playable.Content as LocalizedAudioContent;

            if (audioContent != null)
            {
                if (AudioContentPlayer.Instance.StopPlaying(ctxt.InstanceId, interrupt))
                {
                    // If audio content player didn't stop in this call, the playable will
                    // stop playing and call back, we can remove it from the queue then
                    if (queue != null)
                    {
                        queue.Remove(playable);
                    }
                }
            }
            else if (playable.Content is LocativeAudioContent)
            {
                m_locativeAudioProcessor.DeactivateResource(ctxt, playable.Content as LocativeAudioContent);
            }
            else
            {
                if (queue != null)
                {
                    queue.Remove(playable);
                }
            }

            lock (m_queues)
            {
                m_queues.Remove(ctxt.InstanceId);
            }

            if (queue != null)
            {
                PlayNextSequentialContent(queue);
            }
        }
        void PlayNextSequentialContent(PlayableContentQueue queue)
        {
            QueuedPlayableContext ctxt = null;

            lock (queue.SyncRoot)
            {
                if (queue.CurrentlyPlaying != null)
                {
                    return;
                }

                ctxt = queue.GetNext();
            }

            Action next = () =>
            {
                if (ctxt.OnClose != null)
                {
                    ctxt.OnClose();
                }

                lock (queue.SyncRoot)
                {
                    queue.FinishedPlaying(ctxt);
                }

                PlayNextSequentialContent(queue);
            };

            if (ctxt != null)
            {
                var playable = ctxt.Playable;

                if (ctxt.OnPlay != null)
                {
                    ctxt.OnPlay(ctxt.ActivationContext, playable, next);
                }
                else if (ctxt.OnClose != null)
                {
                    next();
                }
            }
        }
        protected virtual void AddToQueue(PlayableContentQueue queue, ResourceActivationContext activationContext, PlayableContent playable, PlayContentDelegate onPlay, Action onClose)
        {
            lock (m_queues)
            {
                m_queues.Add(activationContext.InstanceId, queue);
            }

            switch (playable.Priority)
            {
            case PlayableContentPriority.High:
                // Todo: actually want to be a bit more clever and *don't* move in front of
                // other high priority ones.
                queue.AddToFront(
                    new QueuedPlayableContext
                {
                    ActivationContext = activationContext,
                    Playable          = playable,
                    OnClose           = onClose,
                    OnPlay            = onPlay
                });

                PlayNextSequentialContent(queue);
                break;

            case PlayableContentPriority.Interrupt:
                QueuedPlayableContext toStop = null;

                lock (queue.SyncRoot)
                {
                    toStop = queue.CurrentlyPlaying;
                }

                if (toStop != null)
                {
                    StopPlaying(toStop.ActivationContext, toStop.Playable, true);
                    toStop.ActivationContext.Close();
                }

                queue.AddToFront(
                    new QueuedPlayableContext
                {
                    ActivationContext = activationContext,
                    Playable          = playable,
                    OnClose           = onClose,
                    OnPlay            = onPlay
                });

                PlayNextSequentialContent(queue);
                break;

            case PlayableContentPriority.Filler:
                // Only if nothing has played on this queue for a while...
                bool doPlay = false;

                lock (queue.SyncRoot)
                {
                    doPlay = queue.CurrentlyPlaying == null &&
                             (DateTime.Now - queue.LastPlayFinish).TotalSeconds >= MinFillerDelay;
                }

                if (doPlay)
                {
                    queue.Add(
                        new QueuedPlayableContext
                    {
                        ActivationContext = activationContext,
                        Playable          = playable,
                        OnClose           = onClose,
                        OnPlay            = onPlay
                    });

                    PlayNextSequentialContent(queue);
                }
                break;

            case PlayableContentPriority.Normal:
            default:
                queue.Add(
                    new QueuedPlayableContext
                {
                    ActivationContext = activationContext,
                    Playable          = playable,
                    OnClose           = onClose,
                    OnPlay            = onPlay
                });

                PlayNextSequentialContent(queue);
                break;
            }
        }