/// <summary> /// Loads a video from a given stream /// </summary> /// <param name="videoStream">the video stream</param> public void Load(Stream videoStream) { if (Application == null) { throw new InvalidOperationException("Can't load until the control has been added to an application"); } Task.Factory.StartNew(() => { try { var reader = new ConsoleBitmapStreamReader(videoStream); reader.ReadToEnd((videoWithProgressInfo) => { inMemoryVideo = inMemoryVideo ?? videoWithProgressInfo; this.duration = videoWithProgressInfo.Duration; Application.InvokeNextCycle(() => { if (this.CurrentFrame == null) { this.CurrentFrame = videoWithProgressInfo.Frames[0].Bitmap; playerProgressBar.ShowPlayCursor = true; playButton.CanFocus = true; seekToBeginningButton.CanFocus = true; seekBack10SButton.CanFocus = true; seekForward10SButton.CanFocus = true; seekToEndButton.CanFocus = true; State = PlayerState.Stopped; if (Application.FocusManager.FocusedControl == null) { Application.FocusManager.TrySetFocus(playButton); } } playerProgressBar.LoadProgressPosition = inMemoryVideo.LoadProgress; }); if (AfterFrameLoadDelay.HasValue) { Thread.Sleep(AfterFrameLoadDelay.Value); } }); } catch (Exception ex) { #if DEBUG failedMessage = ex.ToString(); #else failedMessage = ex.Message; #endif Application.InvokeNextCycle(() => { State = PlayerState.Failed; }); } }); }
/// <summary> /// Reads the stream to the end, providing progress information along the way /// </summary> /// <param name="progressCallback">a callback that will be called each time there is a new frame available</param> /// <returns>The complete video in its in fully expanded in memory structure</returns> public InMemoryConsoleBitmapVideo ReadToEnd(Action <InMemoryConsoleBitmapVideo> progressCallback = null) { var ret = new InMemoryConsoleBitmapVideo(); while (ReadFrame().CurrentFrame != null) { ret.Frames.Add(new InMemoryConsoleBitmapFrame() { Bitmap = CurrentBitmap.Clone(), // clone the current frame since we paint over it every time FrameTime = CurrentFrame.Timestamp, }); // Duration will be set after the first frame is read so no need to check HasValue ret.LoadProgress = CurrentFrame.Timestamp.TotalSeconds / Duration.Value.TotalSeconds; ret.Duration = Duration.Value; // proxy the known duration to the video object so the progress callback can get at it progressCallback?.Invoke(ret); } return(ret); }
private bool TryOpenVisualFormat(string filePath) { try { var lines = File.ReadAllLines(filePath); string currentFrame = ""; var foundStartOfFrame = false; var isParsingColorPallateNow = false; var fullHashLineRegex = "^#+$"; var animation = new InMemoryConsoleBitmapVideo(); for (var i = 0; i < lines.Length; i++) { var line = lines[i]; // expect new bitmap if (foundStartOfFrame == false) { // expect hashes to start bitmap if (Regex.IsMatch(line, fullHashLineRegex) == false) { return(false); } foundStartOfFrame = true; currentFrame += line + "\n"; } // parsing optional color pallate info after closing hashes else if (isParsingColorPallateNow == true) { // check for start of next frame and send loop back by one if true if (Regex.IsMatch(line, fullHashLineRegex)) { var parsed = ConsoleBitmapVisualSerializer.Deserialize(currentFrame); animation.Frames.Add(new InMemoryConsoleBitmapFrame() { Bitmap = parsed, FrameTime = TimeSpan.FromSeconds(animation.Frames.Count) }); currentFrame = ""; isParsingColorPallateNow = false; foundStartOfFrame = false; i--; } // else consider this a pallate line else { currentFrame += line + "\n"; } } // detect end of bitmap else if (Regex.IsMatch(line, fullHashLineRegex)) { currentFrame += line + "\n"; isParsingColorPallateNow = true; } // continue bitmap else { currentFrame += line + "\n"; } } // grab the final frame if (string.IsNullOrWhiteSpace(currentFrame) == false) { var parsed = ConsoleBitmapVisualSerializer.Deserialize(currentFrame); animation.Frames.Add(new InMemoryConsoleBitmapFrame() { Bitmap = parsed, FrameTime = TimeSpan.FromSeconds(animation.Frames.Count) }); } this.animation.Frames.Clear(); this.animation.Frames.AddRange(animation.Frames); CurrentFrameIndex = 0; return(true); } catch (Exception) { return(false); } }