private static string BuildRequirementsToolTip(KStudioEventStream stream, IEnumerable streams, KStudioEventStreamSelectorRequirementFlags process)
        {
            string value = null;

            process = process &= KStudioEventStreamSelectorRequirementFlags.ProcessMask;

            if ((stream != null) && (stream.EventStreamSelectorRequirements != null))
            {
                EventStreamState state = (EventStreamState)stream.UserState;

                StringBuilder sb = new StringBuilder();

                KStudioEventStreamIdentifier emptyIdentifier = new KStudioEventStreamIdentifier();

                foreach (KStudioEventStreamSelectorRequirement requirement in stream.EventStreamSelectorRequirements)
                {
                    if ((requirement.Flags & KStudioEventStreamSelectorRequirementFlags.ProcessMask) == process)
                    {
                        switch (requirement.Flags & KStudioEventStreamSelectorRequirementFlags.OperationMask)
                        {
                        case KStudioEventStreamSelectorRequirementFlags.OperationAll:
                        {
                            string temp = EventStreamState.GetStreamNames((KStudioEventStreamIdentifier)requirement.Identifier0, emptyIdentifier, streams);
                            if (!String.IsNullOrWhiteSpace(temp))
                            {
                                if (sb.Length > 0)
                                {
                                    sb.AppendLine();
                                }

                                sb.AppendFormat(Strings.StreamRequirement_All_Format, temp);
                            }
                        }
                            {
                                string temp = EventStreamState.GetStreamNames((KStudioEventStreamIdentifier)requirement.Identifier1, emptyIdentifier, streams);
                                if (!String.IsNullOrWhiteSpace(temp))
                                {
                                    if (sb.Length > 0)
                                    {
                                        sb.AppendLine();
                                    }

                                    sb.AppendFormat(Strings.StreamRequirement_All_Format, temp);
                                }
                            }
                            break;

                        case KStudioEventStreamSelectorRequirementFlags.OperationNone:
                        {
                            string temp = EventStreamState.GetStreamNames((KStudioEventStreamIdentifier)requirement.Identifier0, (KStudioEventStreamIdentifier)requirement.Identifier1, streams);
                            if (!String.IsNullOrWhiteSpace(temp))
                            {
                                if (sb.Length > 0)
                                {
                                    sb.AppendLine();
                                }

                                sb.AppendFormat(Strings.StreamRequirement_None_Format, temp);
                            }
                        }
                        break;

                        case KStudioEventStreamSelectorRequirementFlags.OperationOr:
                        {
                            string temp = EventStreamState.GetStreamNames((KStudioEventStreamIdentifier)requirement.Identifier0, (KStudioEventStreamIdentifier)requirement.Identifier1, streams);
                            if (!String.IsNullOrWhiteSpace(temp))
                            {
                                if (sb.Length > 0)
                                {
                                    sb.AppendLine();
                                }

                                sb.AppendFormat(Strings.StreamRequirement_Or_Format, temp);
                            }
                        }
                        break;

                        case KStudioEventStreamSelectorRequirementFlags.OperationXor:
                        {
                            string temp = EventStreamState.GetStreamNames((KStudioEventStreamIdentifier)requirement.Identifier0, (KStudioEventStreamIdentifier)requirement.Identifier1, streams);
                            if (!String.IsNullOrWhiteSpace(temp))
                            {
                                if (sb.Length > 0)
                                {
                                    sb.AppendLine();
                                }

                                sb.AppendFormat(Strings.StreamRequirement_Xor_Format, temp);
                            }
                        }
                        break;
                        }
                    }
                }

                value = sb.ToString();
            }

            return(value);
        }
        private static string GetStreamNames(KStudioEventStreamIdentifier id0, KStudioEventStreamIdentifier id1, IEnumerable streams)
        {
            StringBuilder sb = new StringBuilder();

            for (int i = 0; i < 2; ++i)
            {
                KStudioEventStreamIdentifier id = i == 0 ? id0 : id1;

                if (id.DataTypeId != Guid.Empty)
                {
                    if (streams == null)
                    {
                        if (sb.Length > 0)
                        {
                            sb.AppendLine();
                        }

                        if (id.SemanticId == Guid.Empty)
                        {
                            sb.AppendFormat(CultureInfo.CurrentCulture, Strings.StreamRequirement_Unavailable_Type_Format, id.DataTypeId);
                        }
                        else
                        {
                            sb.AppendFormat(CultureInfo.CurrentCulture, Strings.StreamRequirement_Unavailable_Identifier_Format, id.DataTypeId, id.SemanticId);
                        }
                    }
                    else
                    {
                        foreach (KStudioEventStream stream in streams)
                        {
                            if ((stream.DataTypeId == id.DataTypeId) && (id.SemanticId == Guid.Empty) ||
                                (stream.DataTypeId == id.DataTypeId) && (stream.SemanticId == id.SemanticId))
                            {
                                if (sb.Length > 0)
                                {
                                    sb.AppendLine();
                                }

                                StringBuilder sbName = new StringBuilder();
                                if (!String.IsNullOrWhiteSpace(stream.DataTypeName))
                                {
                                    sbName.Append(stream.DataTypeName);
                                    sbName.Append(" - ");
                                }
                                if (!String.IsNullOrWhiteSpace(stream.Name))
                                {
                                    sbName.Append(stream.Name);
                                    sbName.Append(" - ");
                                }
                                sbName.Append(stream.DataTypeId);
                                sbName.Append(":");
                                sbName.Append(stream.SemanticId);

                                sb.AppendFormat(CultureInfo.CurrentCulture, Strings.StreamRequirement_Unavailable_Name_Format, sbName.ToString());
                            }
                        }
                    }
                }
            }

            return(sb.ToString());
        }
        private void ObjectInitializer(KStudioObject obj)
        {
            KStudioEventStream eventStream = obj as KStudioEventStream;
            if (eventStream != null)
            {
                KStudioEventStreamIdentifier identifier = new KStudioEventStreamIdentifier(eventStream.DataTypeId, eventStream.SemanticId);

                bool obscureStream =
                    this.obscureStreams.Contains(identifier);

                obj.UserState = new EventStreamState(eventStream, this, obscureStream);
            }
        }
        public bool ConnectToTarget(IPAddress targetAddress, string targetAlias)
        {
            DebugHelper.AssertUIThread();

            bool result = false;

            if (targetAddress == null)
            {
                throw new ArgumentNullException("targetAddress");
            }

            if (targetAlias == null)
            {
                targetAlias = String.Format(CultureInfo.CurrentCulture, Strings.TargetAlias_Unknown, targetAddress.ToString());
            }

            if (this.client != null)
            {
                if (this.client.IsServiceConnected && (targetAddress.Equals(this.targetAddress)) && (targetAlias == this.targetAlias))
                {
                    return true;
                }

                this.DisconnectFromTarget();

                this.TargetAlias = targetAlias;
                this.TargetAddress = targetAddress;

                try
                {
                    this.client.ConnectToService();
                    result = true;
                }
                catch (Exception ex)
                {
                    result = false;

                    this.HandleConnectError(ex, this.targetAddress);
                }
            }

            if (result)
            {
                HashSet<KStudioEventStreamIdentifier> lastRecorded = this.lastRecordedStreams.HashSet;
                if (lastRecorded.Count == 0)
                {
                    lastRecorded = this.defaultRecordingStreams;
                }

                HashSet<KStudioEventStreamIdentifier> lastHiddenRecordable = this.lastHiddenRecordableStreams.HashSet;
                if (lastHiddenRecordable.Count == 0)
                {
                    lastHiddenRecordable = this.defaultHiddenRecordableStreams;
                }

                foreach (KStudioEventStream stream in this.targetRecordableStreams)
                {
                    KStudioEventStreamIdentifier identifier = new KStudioEventStreamIdentifier(stream.DataTypeId, stream.SemanticId);

                    EventStreamState eventStreamState = stream.UserState as EventStreamState;
                    if (eventStreamState != null)
                    {
                        if (lastRecorded.Contains(identifier))
                        {
                            eventStreamState.IsSelectedForTargetRecording = this.DoTargetRecordingDance(stream, true);
                        }

                        eventStreamState.IsVisibleForTargetRecording = !lastHiddenRecordable.Contains(identifier);
                    }
                }

                HashSet<KStudioEventStreamIdentifier> lastMonitored = this.lastMonitoredStreams.HashSet;
                if (lastMonitored.Count == 0)
                {
                    lastMonitored = this.defaultMonitorStreams;
                }

                HashSet<KStudioEventStreamIdentifier> lastHiddenMonitorable = this.lastHiddenMonitorableStreams.HashSet;
                if (lastHiddenMonitorable.Count == 0)
                {
                    lastHiddenMonitorable = this.defaultHiddenMonitorableStreams;
                }

                foreach (KStudioEventStream stream in this.targetMonitorableStreams)
                {
                    KStudioEventStreamIdentifier identifier = new KStudioEventStreamIdentifier(stream.DataTypeId, stream.SemanticId);

                    EventStreamState eventStreamState = stream.UserState as EventStreamState;
                    if (eventStreamState != null)
                    {
                        if (lastMonitored.Contains(identifier))
                        {
                            eventStreamState.IsSelectedForTargetMonitor = this.DoTargetMonitorDance(stream, true);
                        }

                        eventStreamState.IsVisibleForTargetMonitor = !lastHiddenMonitorable.Contains(identifier);
                    }
                }

                if ((this.settings != null) && this.settings.AutoMonitorOnTargetConnect)
                {
                    this.StartMonitor();
                }
            }

            return result;
        }
        private void OpenPlayback(string filePath, bool asReadOnly, bool localPlayback)
        {
            DebugHelper.AssertUIThread();

            if (String.IsNullOrWhiteSpace(filePath))
            {
                throw new ArgumentNullException("filePath");
            }

            if ((this.playbackFilePath == filePath) && (this.IsPlaybackFileReadOnly == asReadOnly))
            {
                return;
            }

            this.CloseRecording(false);
            this.ClosePlayback();

            this.playbackFileLocal = localPlayback;
            RaisePropertyChanged("IsPlaybackFileOnTarget");

            if ((this.client != null) && (this.recording == null) && (this.playback == null))
            {
                this.PlaybackTime = TimeSpan.Zero;

                if (!asReadOnly)
                {
                    try
                    {
                        this.playbackFile = this.client.OpenEventFileForEdit(filePath, localPlayback ? KStudioEventFileFlags.None : KStudioEventFileFlags.OnService);
                    }
#if OPEN_FOR_EDIT
                    catch (IOException ex)
                    {
                        if (ex.Message == "access denied")
                        {
                            // read-only, so ignore
                            if (this.loggingService != null)
                            {
                                this.loggingService.LogLine(Strings.FileOpen_Error_CantOpenForEdit_Format, filePath);
                            }
                        }
                        else
                        {
                            this.HandleFileOpenError(ex, filePath);
                            return;
                        }
                    }
#endif // OPEN_FOR_EDIT
                    catch (Exception ex)
                    {
                        this.HandleFileOpenError(ex, filePath);
                        return;
                    }
                }

                try
                {
                    if (this.playbackFile == null)
                    {
                        this.playbackFile = this.client.OpenEventFile(filePath, localPlayback ? KStudioEventFileFlags.None : KStudioEventFileFlags.OnService);
                    }

                    this.PlaybackFilePath = this.playbackFile.FilePath;
                    PlaybackFileSettings playbackFileSettings = new PlaybackFileSettings(this.fileSettingsService, this.targetAlias, this.playbackFile);
                    this.playbackFile.UserState = playbackFileSettings;

                    this.PlaybackLoopCount = playbackFileSettings.LoadSetting("playback", "loopCount", 0);

                    bool actuallyReadOnly = !(this.playbackFile is KStudioWritableEventFile);

                    if (actuallyReadOnly)
                    {
                        this.PlaybackMetadata = new MetadataInfo(true, Strings.PlaybackMetadata_Title,
                            this.playbackFilePath,
                            this.playbackFile.GetMetadata(KStudioMetadataType.Public),
                            this.playbackFile.GetMetadata(KStudioMetadataType.PersonallyIdentifiableInformation));
                    }
                    else
                    {
                        this.PlaybackMetadata = new MetadataInfo(false, Strings.PlaybackMetadata_Title,
                            this.playbackFilePath,
                            new WritableMetadataProxy(this.playbackFile, this.playbackFile.GetMetadata(KStudioMetadataType.Public)),
                            new WritableMetadataProxy(this.playbackFile, this.playbackFile.GetMetadata(KStudioMetadataType.PersonallyIdentifiableInformation)));
                    }

                    this.PlaybackFileMarkers = new TimelineMarkersCollection(this.targetAlias, this.playbackFile);
                    this.PlaybackPausePoints = new TimelinePausePointsCollection(this.targetAlias, this.playbackFile, this.PlaybackFileMarkers);
                    this.PlaybackInOutPoints = new TimelineInOutPointsCollection(this.targetAlias, this.playbackFile);

                    foreach (KStudioEventStream s in this.playbackFile.EventStreams)
                    {
                        EventStreamState streamState = s.UserState as EventStreamState;
                        if (streamState != null)
                        {
                            streamState.SetDuration(this.playbackFile.Duration);

                            if (actuallyReadOnly)
                            {
                                streamState.Metadata = new MetadataInfo(false, streamState.ShortName,
                                    this.playbackFilePath + "\n" + streamState.LongName,
                                    s.GetMetadata(KStudioMetadataType.Public),
                                    s.GetMetadata(KStudioMetadataType.PersonallyIdentifiableInformation));
                            }
                            else
                            {
                                streamState.Metadata = new MetadataInfo(false, streamState.ShortName,
                                    this.playbackFilePath + "\n" + streamState.LongName,
                                    new WritableMetadataProxy(this.playbackFile, s.GetMetadata(KStudioMetadataType.Public)),
                                    new WritableMetadataProxy(this.playbackFile, s.GetMetadata(KStudioMetadataType.PersonallyIdentifiableInformation)));
                            }

                            streamState.SetupForPlayback(this.client.EventStreams);
                        }
                    }

                    if (!localPlayback)
                    {
                        IReadOnlyCollection<Tuple<KStudioEventStreamSelectorItem, bool>> lastStreamSelection = playbackFileSettings.GetLastStreamSelection();

                        if (lastStreamSelection == null)
                        {
                            // match up file streams to live streams if unambiguous

                            Dictionary<Guid, KStudioEventStream> liveEventStreams = new Dictionary<Guid, KStudioEventStream>();
                            foreach (KStudioEventStream liveEventStream in this.targetPlaybackableStreams)
                            {
                                KStudioEventStream multipleExist;
                                if (liveEventStreams.TryGetValue(liveEventStream.DataTypeId, out multipleExist))
                                {
                                    liveEventStreams[liveEventStream.DataTypeId] = null;
                                }
                                else
                                {
                                    liveEventStreams[liveEventStream.DataTypeId] = liveEventStream;
                                }
                            }

                            Dictionary<Guid, bool> fileEventStreams = new Dictionary<Guid, bool>();
                            foreach (KStudioEventStream fileEventStream in this.playbackFile.EventStreams)
                            {
                                bool multipleExist;
                                if (fileEventStreams.TryGetValue(fileEventStream.DataTypeId, out multipleExist))
                                {
                                    fileEventStreams[fileEventStream.DataTypeId] = true;
                                }
                                else
                                {
                                    fileEventStreams[fileEventStream.DataTypeId] = false;
                                }
                            }

                            foreach (KStudioEventStream fileStream in this.playbackFile.EventStreams)
                            {
                                EventStreamState fileStreamState = fileStream.UserState as EventStreamState;
                                if (fileStreamState != null)
                                {
                                    bool multipleFileExist;

                                    if (fileEventStreams.TryGetValue(fileStream.DataTypeId, out multipleFileExist))
                                    {
                                        if (!multipleFileExist)
                                        {
                                            KStudioEventStream multipleLiveExist;

                                            if (liveEventStreams.TryGetValue(fileStream.DataTypeId, out multipleLiveExist))
                                            {
                                                if (multipleLiveExist != null)
                                                {
                                                    fileStreamState.SelectedLivePlaybackStream = multipleLiveExist;
                                                }
                                            }
                                        }
                                    }
                                }
                            }

                            foreach (KStudioEventStream liveStream in this.targetPlaybackableStreams)
                            {
                                KStudioEventStreamIdentifier identifier = new KStudioEventStreamIdentifier(liveStream.DataTypeId, liveStream.SemanticId);
                                if (this.defaultPlaybackStreams.Contains(identifier))
                                {
                                    EventStreamState eventStreamState = liveStream.UserState as EventStreamState;
                                    if (eventStreamState != null)
                                    {
                                        if (eventStreamState.SelectedFilePlaybackStream != null)
                                        {
                                            eventStreamState.IsSelectedForTargetPlayback = this.DoTargetPlaybackDance(liveStream, true);
                                        }
                                    }
                                }
                            }
                        }
                        else
                        {
                            Dictionary<KStudioEventStream, bool?> selectedStreams = new Dictionary<KStudioEventStream, bool?>();

                            foreach (var item in lastStreamSelection)
                            {
                                KStudioEventStream fileStream = this.playbackFile.EventStreams.FirstOrDefault(s => (s.DataTypeId == item.Item1.DataTypeId) && (s.SemanticId == item.Item1.SourceSemanticId));

                                if (fileStream != null)
                                {
                                    KStudioEventStream liveStream = null;
                                    foreach (KStudioEventStream s in this.targetPlaybackableStreams)
                                    {
                                        if ((s.DataTypeId == item.Item1.DataTypeId) && (s.SemanticId == item.Item1.DestinationSemanticId))
                                        {
                                            liveStream = s;
                                            break;
                                        }
                                    }

                                    if (liveStream != null)
                                    {
                                        EventStreamState ess = fileStream.UserState as EventStreamState;
                                        if (ess != null)
                                        {
                                            ess.SelectedLivePlaybackStream = liveStream;

                                            if (item.Item2)
                                            {
                                                EventStreamState ess2 = liveStream.UserState as EventStreamState;
                                                if (ess2 != null)
                                                {
                                                    // do NoCheck here so that it doesn't auto turn on the tag-alongs
                                                    ess2.IsSelectedForTargetPlaybackNoCheck = true;

                                                    selectedStreams.Add(liveStream, true);
                                                }
                                            }
                                        }
                                    }
                                }
                            }

                            // now update the CanPlayback

                            if (selectedStreams.Count > 0)
                            {
                                this.selectedTargetStreamsPlaybackable = true;

                                foreach (KStudioEventStream liveStream in selectedStreams.Keys)
                                {
                                    if (!liveStream.HasSelectionRequirements(KStudioEventStreamSelectorRequirementFlags.ProcessPlayback, selectedStreams))
                                    {
                                        this.selectedTargetStreamsPlaybackable = false;
                                        break;
                                    }
                                }
                            }
                        }
                    }

                    this.PlaybackableFileStreams = this.playbackFile.EventStreams;

                    HashSet<KStudioEventStreamIdentifier> lastHiddenPlaybackable = this.lastHiddenPlaybackableStreams.HashSet;
                    if (lastHiddenPlaybackable.Count == 0)
                    {
                        lastHiddenPlaybackable = this.defaultHiddenPlaybackableStreams;
                    }

                    foreach (KStudioEventStream stream in this.playbackFile.EventStreams)
                    {
                        EventStreamState streamState = stream.UserState as EventStreamState;
                        if (streamState != null)
                        {
                            KStudioEventStreamIdentifier identifier = new KStudioEventStreamIdentifier(stream.DataTypeId, stream.SemanticId);

                            streamState.IsVisibleForPlayback = !lastHiddenPlaybackable.Contains(identifier);
                        }
                    }

                    foreach (KStudioEventStream liveStream in this.targetPlaybackableStreams)
                    {
                        KStudioEventStreamIdentifier identifier = new KStudioEventStreamIdentifier(liveStream.DataTypeId, liveStream.SemanticId);
                        if (this.defaultPlaybackStreams.Contains(identifier))
                        {
                            EventStreamState eventStreamState = liveStream.UserState as EventStreamState;
                            if (eventStreamState != null)
                            {
                                if (eventStreamState.SelectedFilePlaybackStream != null)
                                {
                                    eventStreamState.IsSelectedForTargetPlayback = this.DoTargetPlaybackDance(liveStream, true);
                                }

                                eventStreamState.IsVisibleForPlayback = !lastHiddenPlaybackable.Contains(identifier);
                            }
                        }
                    }

                    RaisePropertyChanged("HasPlaybackFile");
                    RaisePropertyChanged("IsPlaybackFileReadOnly");
                    RaisePropertyChanged("CanPlayback");
                    RaisePropertyChanged("ComboViewStateTitle");

                    if (this.mruService != null)
                    {
                        this.mruService.AddMostRecentlyUsedLocalFile(filePath);
                    }

                    this.SetDefaultMetadataViews(this.playbackMetadata);

                    EventHandler handler = PlaybackOpened;
                    if (handler != null)
                    {
                        handler(this, null);
                    }

                    TimeSpan firstTime = this.playbackFile.EventStreams.OfType<KStudioSeekableEventStream>().Min(s => s.StartRelativeTime);
                    this.SeekPlayback(firstTime);
                }
                catch (Exception ex)
                {
                    this.ClosePlayback();

                    this.HandleFileOpenError(ex, filePath);
                }
            }
        }
        public LastSelectedStreams(IServiceProvider serviceProvider, string name)
        {
            DebugHelper.AssertUIThread();

            if (String.IsNullOrWhiteSpace(name))
            {
                throw new ArgumentNullException("name");
            }

            this.name = name;

            if (serviceProvider != null)
            {
                this.sessionStateService = serviceProvider.GetService(typeof(ISessionStateService)) as ISessionStateService;
                if (this.sessionStateService != null)
                {
                    this.sessionStateService.StateSaveRequested += SessionStateService_StateSaveRequested;

                    XElement element = this.sessionStateService.GetSessionState(this.name);
                    if (element == null)
                    {
                        element = this.sessionStateService.GetSessionState("KStudioServiceLast" + this.name);

                        if (element != null)
                        {
                            XElement oldElement = element;
                            element = new XElement("last" + this.name);

                            XElement oldItemsElement = oldElement.Element("Items");
                            if (oldItemsElement != null)
                            {
                                List <XElement> oldElements = new List <XElement>(oldItemsElement.Elements("ListEntry"));

                                int count = oldElements.Count;
                                count = (count / 2) * 2;

                                for (int i = 0; i < count; i += 2)
                                {
                                    Guid dataTypeId = XmlExtensions.GetAttribute(oldElements[i], "Value", Guid.Empty);
                                    Guid semanticId = XmlExtensions.GetAttribute(oldElements[i + 1], "Value", Guid.Empty);

                                    XElement streamElement = new XElement("stream");

                                    streamElement.SetAttributeValue("dataTypeId", dataTypeId.ToString());
                                    streamElement.SetAttributeValue("semanticId", semanticId.ToString());

                                    element.Add(streamElement);
                                }
                            }

                            this.sessionStateService.SetSessionState("KStudioServiceLast" + this.name, null);
                            this.sessionStateService.SetSessionState(this.name, element);
                        }
                    }

                    if (element != null)
                    {
                        foreach (XElement streamElement in element.Elements("stream"))
                        {
                            Guid dataTypeId = XmlExtensions.GetAttribute(streamElement, "dataTypeId", Guid.Empty);
                            Guid semanticId = XmlExtensions.GetAttribute(streamElement, "semanticId", Guid.Empty);

                            KStudioEventStreamIdentifier identifier = new KStudioEventStreamIdentifier(dataTypeId, semanticId);

                            if (!this.hashSet.Contains(identifier))
                            {
                                this.hashSet.Add(identifier);
                            }
                        }
                    }
                }
            }
        }
        private static string GetStreamNames(KStudioEventStreamIdentifier id0, KStudioEventStreamIdentifier id1, IEnumerable streams)
        {
            StringBuilder sb = new StringBuilder();

            for (int i = 0; i < 2; ++i)
            {
                KStudioEventStreamIdentifier id = i == 0 ? id0 : id1;

                if (id.DataTypeId != Guid.Empty)
                {
                    if (streams == null)
                    {
                        if (sb.Length > 0)
                        {
                            sb.AppendLine();
                        }

                        if (id.SemanticId == Guid.Empty)
                        {
                            sb.AppendFormat(CultureInfo.CurrentCulture, Strings.StreamRequirement_Unavailable_Type_Format, id.DataTypeId);
                        }
                        else
                        {
                            sb.AppendFormat(CultureInfo.CurrentCulture, Strings.StreamRequirement_Unavailable_Identifier_Format, id.DataTypeId, id.SemanticId);
                        }
                    }
                    else
                    {
                        foreach (KStudioEventStream stream in streams)
                        {
                            if ((stream.DataTypeId == id.DataTypeId) && (id.SemanticId == Guid.Empty) ||
                                (stream.DataTypeId == id.DataTypeId) && (stream.SemanticId == id.SemanticId))
                            {
                                if (sb.Length > 0)
                                {
                                    sb.AppendLine();
                                }

                                StringBuilder sbName = new StringBuilder();
                                if (!String.IsNullOrWhiteSpace(stream.DataTypeName))
                                {
                                    sbName.Append(stream.DataTypeName);
                                    sbName.Append(" - ");
                                }
                                if (!String.IsNullOrWhiteSpace(stream.Name))
                                {
                                    sbName.Append(stream.Name);
                                    sbName.Append(" - ");
                                }
                                sbName.Append(stream.DataTypeId);
                                sbName.Append(":");
                                sbName.Append(stream.SemanticId);

                                sb.AppendFormat(CultureInfo.CurrentCulture, Strings.StreamRequirement_Unavailable_Name_Format, sbName.ToString());
                            }
                        }
                    }
                }
            }

            return sb.ToString();
        }
        private static string BuildRequirementsToolTip(KStudioEventStream stream, IEnumerable streams, KStudioEventStreamSelectorRequirementFlags process)
        {
            string value = null;

            process = process &= KStudioEventStreamSelectorRequirementFlags.ProcessMask;

            if ((stream != null) && (stream.EventStreamSelectorRequirements != null))
            {
                EventStreamState state = (EventStreamState)stream.UserState;

                StringBuilder sb = new StringBuilder();

                KStudioEventStreamIdentifier emptyIdentifier = new KStudioEventStreamIdentifier();

                foreach (KStudioEventStreamSelectorRequirement requirement in stream.EventStreamSelectorRequirements)
                {
                    if ((requirement.Flags & KStudioEventStreamSelectorRequirementFlags.ProcessMask) == process)
                    {
                        switch (requirement.Flags & KStudioEventStreamSelectorRequirementFlags.OperationMask)
                        {
                            case KStudioEventStreamSelectorRequirementFlags.OperationAll:
                                {
                                    string temp = EventStreamState.GetStreamNames((KStudioEventStreamIdentifier)requirement.Identifier0, emptyIdentifier, streams);
                                    if (!String.IsNullOrWhiteSpace(temp))
                                    {
                                        if (sb.Length > 0)
                                        {
                                            sb.AppendLine();
                                        }

                                        sb.AppendFormat(Strings.StreamRequirement_All_Format, temp);
                                    }
                                }
                                {
                                    string temp = EventStreamState.GetStreamNames((KStudioEventStreamIdentifier)requirement.Identifier1, emptyIdentifier, streams);
                                    if (!String.IsNullOrWhiteSpace(temp))
                                    {
                                        if (sb.Length > 0)
                                        {
                                            sb.AppendLine();
                                        }

                                        sb.AppendFormat(Strings.StreamRequirement_All_Format, temp);
                                    }
                                }
                                break;

                            case KStudioEventStreamSelectorRequirementFlags.OperationNone:
                                {
                                    string temp = EventStreamState.GetStreamNames((KStudioEventStreamIdentifier)requirement.Identifier0, (KStudioEventStreamIdentifier)requirement.Identifier1, streams);
                                    if (!String.IsNullOrWhiteSpace(temp))
                                    {
                                        if (sb.Length > 0)
                                        {
                                            sb.AppendLine();
                                        }

                                        sb.AppendFormat(Strings.StreamRequirement_None_Format, temp);
                                    }
                                }
                                break;

                            case KStudioEventStreamSelectorRequirementFlags.OperationOr:
                                {
                                    string temp = EventStreamState.GetStreamNames((KStudioEventStreamIdentifier)requirement.Identifier0, (KStudioEventStreamIdentifier)requirement.Identifier1, streams);
                                    if (!String.IsNullOrWhiteSpace(temp))
                                    {
                                        if (sb.Length > 0)
                                        {
                                            sb.AppendLine();
                                        }

                                        sb.AppendFormat(Strings.StreamRequirement_Or_Format, temp);
                                    }
                                }
                                break;

                            case KStudioEventStreamSelectorRequirementFlags.OperationXor:
                                {
                                    string temp = EventStreamState.GetStreamNames((KStudioEventStreamIdentifier)requirement.Identifier0, (KStudioEventStreamIdentifier)requirement.Identifier1, streams);
                                    if (!String.IsNullOrWhiteSpace(temp))
                                    {
                                        if (sb.Length > 0)
                                        {
                                            sb.AppendLine();
                                        }

                                        sb.AppendFormat(Strings.StreamRequirement_Xor_Format, temp);
                                    }
                                }
                                break;
                        }
                    }
                }

                value = sb.ToString();
            }

            return value;
        }
        public LastSelectedStreams(IServiceProvider serviceProvider, string name)
        {
            DebugHelper.AssertUIThread();

            if (String.IsNullOrWhiteSpace(name))
            {
                throw new ArgumentNullException("name");
            }

            this.name = name;

            if (serviceProvider != null)
            {
                this.sessionStateService = serviceProvider.GetService(typeof(ISessionStateService)) as ISessionStateService;
                if (this.sessionStateService != null)
                {
                    this.sessionStateService.StateSaveRequested += SessionStateService_StateSaveRequested;

                    XElement element = this.sessionStateService.GetSessionState(this.name);
                    if (element == null)
                    {
                        element = this.sessionStateService.GetSessionState("KStudioServiceLast" + this.name);

                        if (element != null)
                        {
                            XElement oldElement = element;
                            element = new XElement("last" + this.name);

                            XElement oldItemsElement  = oldElement.Element("Items");
                            if (oldItemsElement != null)
                            {
                                List<XElement> oldElements = new List<XElement>(oldItemsElement.Elements("ListEntry"));

                                int count = oldElements.Count;
                                count = (count / 2) * 2;

                                for (int i = 0; i < count; i += 2)
                                {
                                    Guid dataTypeId = XmlExtensions.GetAttribute(oldElements[i], "Value", Guid.Empty);
                                    Guid semanticId = XmlExtensions.GetAttribute(oldElements[i + 1], "Value", Guid.Empty);

                                    XElement streamElement = new XElement("stream");

                                    streamElement.SetAttributeValue("dataTypeId", dataTypeId.ToString());
                                    streamElement.SetAttributeValue("semanticId", semanticId.ToString());

                                    element.Add(streamElement);
                                }
                            }

                            this.sessionStateService.SetSessionState("KStudioServiceLast" + this.name, null);
                            this.sessionStateService.SetSessionState(this.name, element);
                        }
                    }

                    if (element != null)
                    {
                        foreach (XElement streamElement in element.Elements("stream"))
                        {
                            Guid dataTypeId = XmlExtensions.GetAttribute(streamElement, "dataTypeId", Guid.Empty);
                            Guid semanticId = XmlExtensions.GetAttribute(streamElement, "semanticId", Guid.Empty);

                            KStudioEventStreamIdentifier identifier = new KStudioEventStreamIdentifier(dataTypeId, semanticId);

                            if (!this.hashSet.Contains(identifier))
                            {
                                this.hashSet.Add(identifier);
                            }
                        }
                    }
                }
            }
        }