public IObservable <IRxn> Process(StartStopRecording @event) { return(RxObservable.Create <IRxn>(() => { if (_tape != null) { OnVerbose("Tape {0} goes for {1}".FormatWith(_tape.Name, _tape.Source.Duration)); _recording.Dispose(); _recording.Clear(); _tape.Source.Dispose(); _tape = null; return; } _tape = _tapeRepository.GetOrCreate(@event.TapeName); _appNav.CurrentView.Select(view => _automator.AutomateUserActions(view.Page, view.Model, Input, Input.OnNext)) .Switch() .Until(OnError) .DisposedBy(_recording); _recorder.Record(_tape, Input.Where(e => !e.GetType().ImplementsInterface <INotRecorded>())).DisposedBy(_recording); OnVerbose("Recording {0} has started".FormatWith(@event.TapeName)); })); }
public PlaybackStream Play(ITapeStuff tape, PlaybackSettings settings = null) { settings = settings ?? new PlaybackSettings(); var playBackStream = new Subject <IRxn>(); var position = new Subject <TimeSpan>(); //todo: join buffers up using a gate to stop more actions buffering before they //have been played var sourceEventBuffer = RxObservable.DfrCreate <ICapturedRxn>(o => { return(tape.Source .Contents .ToObservableSequence() .Buffer(settings.ActionBuffer) .Do(events => { @events.ForEach(e => o.OnNext(e)); }) .FinallyR(() => { Debug.WriteLine("End of tape"); o.OnCompleted(); }) .Subscribe(_ => { }, e => o.OnError(e))); }); var isPaused = new BehaviorSubject <bool>(false); var setupOnPlayBack = RxObservable.DfrCreate <IRxn>(o => { var sincePlay = TimeSpan.Zero; var playbackBuffer = new Queue <ICapturedRxn>(); var playbackQueue = sourceEventBuffer.Do(buffered => { playbackBuffer.Enqueue(buffered); }) .Subscribe(_ => { }, () => { Debug.WriteLine("finsihed playbackQueue"); }); var realTimeClock = RxObservable.TimerWithPause(DateTimeOffset.MinValue, TimeSpan.FromSeconds(settings.TickSpeed), isPaused, _playbackScheduler) .Skip(1) //so we can buffer the stream. need a better mechanism!? .Do(tick => { //pause sincePlay = sincePlay.Add(TimeSpan.FromSeconds(settings.Speed)); CurrentThreadScheduler.Instance.Run(() => position.OnNext(sincePlay)); if (playbackBuffer.Count < 1) //todo: improve this when better buffreing mechanism implemented { o.OnCompleted(); return; } //finally play any events that have occoured based on the offset info while (playbackBuffer.Count > 0 && playbackBuffer.Peek().Offset < sincePlay) { playBackStream.OnNext(playbackBuffer.Dequeue().Recorded); } }) .Subscribe(_ => { }, o.OnError, () => { Debug.WriteLine("Finished position"); }); return(new CompositeDisposable(realTimeClock, playbackQueue, position, playBackStream.Subscribe(o), isPaused)); }); return(new PlaybackStream(tape.Name, setupOnPlayBack, position, isPaused)); }
public IDisposable Record(ITapeStuff tape, IObservable <IRxn> stream) { var recording = tape.Source.StartRecording(); return(stream.Do(@e => recording.Record(@e)).FinallyR(() => recording.Dispose()).Subscribe()); }