Runs a websocket on the given port. Useful for high-frequency messages (like audio levels) and allows the backend to send messages to the client. About ports... we could have a single server that is used to pass any number of messages. We could have a single connection on the client with a means to distribute messages around the client depending on, say, a message identifier. Or we could have multiple connections (sockets) from various parts in the client, each just filtering out the message stream to the ones they are interested in. Alternatively, you could have multiple instances of this class, each with its own "port" parameter, and intended for use by a single, simple end point. That is the case as this is introduced in Bloom 3.6, for getting the peak level of the audio coming from a microphone.
Inheritance: IDisposable
        public CommandAvailabilityPublisher(IEnumerable <ICommand> commands)
        {
            foreach (var command in commands)
            {
                command.EnabledChanged += command_EnabledChanged;
            }

            FleckLog.Level = LogLevel.Warn;
            _allSockets    = new List <IWebSocketConnection>();
            _server        = new WebSocketServer("ws://127.0.0.1:8189");
            try
            {
                _server.Start(socket =>
                {
                    socket.OnOpen = () =>
                    {
                        Debug.WriteLine("Backend received an request to open a CommandAvailabilityPublisher socket");
                        _allSockets.Add(socket);
                    };
                    socket.OnClose = () =>
                    {
                        Debug.WriteLine("Backend received an request to close  CommandAvailabilityPublisher socket");
                        _allSockets.Remove(socket);
                    };
                });
            }
            catch (SocketException ex)
            {
                BloomWebSocketServer.ReportSocketExceptionAndExit(ex, _server);
            }
        }
 public AudioRecording(BookSelection bookSelection, BloomWebSocketServer bloomWebSocketServer)
 {
     _bookSelection = bookSelection;
     _startRecordingTimer = new Timer();
     _startRecordingTimer.Interval = 300; //  ms from click to actual recording
     _startRecordingTimer.Tick += OnStartRecordingTimer_Elapsed;
     _backupPath = System.IO.Path.GetTempFileName();
     CurrentRecording = this;
     _webSocketServer = bloomWebSocketServer;
 }
        //autofac uses this
        public EditingModel(BookSelection bookSelection, PageSelection pageSelection,
			TemplateInsertionCommand templateInsertionCommand,
			PageListChangedEvent pageListChangedEvent,
			RelocatePageEvent relocatePageEvent,
			BookRefreshEvent bookRefreshEvent,
			PageRefreshEvent pageRefreshEvent,
			DuplicatePageCommand duplicatePageCommand,
			DeletePageCommand deletePageCommand,
			SelectedTabChangedEvent selectedTabChangedEvent,
			SelectedTabAboutToChangeEvent selectedTabAboutToChangeEvent,
			LibraryClosing libraryClosingEvent,
			LocalizationChangedEvent localizationChangedEvent,
			CollectionSettings collectionSettings,
			//SendReceiver sendReceiver,
			EnhancedImageServer server,
			BloomWebSocketServer webSocketServer)
        {
            _bookSelection = bookSelection;
            _pageSelection = pageSelection;
            _duplicatePageCommand = duplicatePageCommand;
            _deletePageCommand = deletePageCommand;
            _collectionSettings = collectionSettings;
            //_sendReceiver = sendReceiver;
            _server = server;
            _webSocketServer = webSocketServer;
            _templatePagesDict = null;

            bookSelection.SelectionChanged += new EventHandler(OnBookSelectionChanged);
            pageSelection.SelectionChanged += new EventHandler(OnPageSelectionChanged);
            pageSelection.SelectionChanging += OnPageSelectionChanging;
            templateInsertionCommand.InsertPage += new EventHandler(OnInsertTemplatePage);

            bookRefreshEvent.Subscribe((book) => OnBookSelectionChanged(null, null));
            pageRefreshEvent.Subscribe((PageRefreshEvent.SaveBehavior behavior) =>
            {
                switch (behavior)
                {
                    case PageRefreshEvent.SaveBehavior.SaveBeforeRefresh:
                        RethinkPageAndReloadIt(null);
                        break;

                    case PageRefreshEvent.SaveBehavior.JustRedisplay:
                        RefreshDisplayOfCurrentPage();
                        break;
                }
            });

            selectedTabChangedEvent.Subscribe(OnTabChanged);
            selectedTabAboutToChangeEvent.Subscribe(OnTabAboutToChange);
            duplicatePageCommand.Implementer = OnDuplicatePage;
            deletePageCommand.Implementer = OnDeletePage;
            pageListChangedEvent.Subscribe(x => _view.UpdatePageList(false));
            relocatePageEvent.Subscribe(OnRelocatePage);
            libraryClosingEvent.Subscribe(o =>
            {
                if (Visible)
                    SaveNow();
            });
            localizationChangedEvent.Subscribe(o =>
            {
                //this is visible was added for https://jira.sil.org/browse/BL-267, where the edit tab has never been
                //shown so the view has never been full constructed, so we're not in a good state to do a refresh
                if (Visible)
                {
                    SaveNow();
                    _view.UpdateButtonLocalizations();
                    RefreshDisplayOfCurrentPage();
                    //_view.UpdateDisplay();
                    _view.UpdatePageList(false);
                }
                else if (_view != null)
                {
                    // otherwise changing UI language in Publish tab (for instance) won't update these localizations
                    _view.UpdateButtonLocalizations();
                }
            });
            _contentLanguages = new List<ContentLanguage>();
            _server.CurrentCollectionSettings = _collectionSettings;
        }