Made saving a little more convenient by putting it in its own thread. Might be very buggy still.

Also temporarily disabled reading TAStudio settings in PlaybackBox because of a NullReferenceException
This commit is contained in:
christoph.boehmwalder 2015-01-03 02:29:55 +00:00
parent c10682b147
commit c3f51f8b39
6 changed files with 986 additions and 892 deletions

View File

@ -7,6 +7,8 @@ using System.Text;
using BizHawk.Common; using BizHawk.Common;
using BizHawk.Common.CollectionExtensions; using BizHawk.Common.CollectionExtensions;
using BizHawk.Common.IOExtensions; using BizHawk.Common.IOExtensions;
using System.Diagnostics;
using System.ComponentModel;
namespace BizHawk.Client.Common namespace BizHawk.Client.Common
{ {
@ -14,9 +16,26 @@ namespace BizHawk.Client.Common
{ {
public Func<string> ClientSettingsForSave { get; set; } public Func<string> ClientSettingsForSave { get; set; }
public Action<string> GetClientSettingsOnLoad { get; set; } public Action<string> GetClientSettingsOnLoad { get; set; }
private const double PROGRESS_STEP = 100 / 12; // TODO hardcoded for now, there might be a better way of doing this
private double _totalProgress = 0;
private void ReportProgress(double percent)
{
if (_progressReportWorker != null)
{
_totalProgress += percent;
_progressReportWorker.ReportProgress((int)_totalProgress);
}
}
protected override void Write(string fn) protected override void Write(string fn)
{ {
_totalProgress = 0;
var file = new FileInfo(fn); var file = new FileInfo(fn);
if (!file.Directory.Exists) if (!file.Directory.Exists)
{ {
@ -26,22 +45,29 @@ namespace BizHawk.Client.Common
using (var bs = new BinaryStateSaver(fn, false)) using (var bs = new BinaryStateSaver(fn, false))
{ {
bs.PutLump(BinaryStateLump.Movieheader, tw => tw.WriteLine(Header.ToString())); bs.PutLump(BinaryStateLump.Movieheader, tw => tw.WriteLine(Header.ToString()));
bs.PutLump(BinaryStateLump.Comments, tw => tw.WriteLine(CommentsString())); ReportProgress(PROGRESS_STEP);
bs.PutLump(BinaryStateLump.Subtitles, tw => tw.WriteLine(Subtitles.ToString())); bs.PutLump(BinaryStateLump.Comments, tw => tw.WriteLine(CommentsString()));
bs.PutLump(BinaryStateLump.SyncSettings, tw => tw.WriteLine(SyncSettingsJson)); ReportProgress(PROGRESS_STEP);
bs.PutLump(BinaryStateLump.Subtitles, tw => tw.WriteLine(Subtitles.ToString()));
bs.PutLump(BinaryStateLump.Input, tw => tw.WriteLine(RawInputLog())); ReportProgress(PROGRESS_STEP);
bs.PutLump(BinaryStateLump.SyncSettings, tw => tw.WriteLine(SyncSettingsJson));
ReportProgress(PROGRESS_STEP);
bs.PutLump(BinaryStateLump.Input, tw => tw.WriteLine(RawInputLog()));
ReportProgress(PROGRESS_STEP);
// TasProj extras // TasProj extras
bs.PutLump(BinaryStateLump.GreenzoneSettings, tw => tw.WriteLine(StateManager.Settings.ToString()));
bs.PutLump(BinaryStateLump.GreenzoneSettings, tw => tw.WriteLine(StateManager.Settings.ToString())); ReportProgress(PROGRESS_STEP);
if (StateManager.Settings.SaveGreenzone) if (StateManager.Settings.SaveGreenzone)
{ {
bs.PutLump(BinaryStateLump.Greenzone, (BinaryWriter bw) => StateManager.Save(bw)); bs.PutLump(BinaryStateLump.Greenzone, (BinaryWriter bw) => StateManager.Save(bw));
} }
ReportProgress(PROGRESS_STEP);
bs.PutLump(BinaryStateLump.LagLog, (BinaryWriter bw) => LagLog.Save(bw)); bs.PutLump(BinaryStateLump.LagLog, (BinaryWriter bw) => LagLog.Save(bw));
bs.PutLump(BinaryStateLump.Markers, tw => tw.WriteLine(Markers.ToString())); ReportProgress(PROGRESS_STEP);
bs.PutLump(BinaryStateLump.Markers, tw => tw.WriteLine(Markers.ToString()));
ReportProgress(PROGRESS_STEP);
if (StartsFromSavestate) if (StartsFromSavestate)
{ {
@ -53,18 +79,20 @@ namespace BizHawk.Client.Common
{ {
bs.PutLump(BinaryStateLump.Corestate, (BinaryWriter bw) => bw.Write(BinarySavestate)); bs.PutLump(BinaryStateLump.Corestate, (BinaryWriter bw) => bw.Write(BinarySavestate));
} }
} }
ReportProgress(PROGRESS_STEP);
if (ClientSettingsForSave != null) if (ClientSettingsForSave != null)
{ {
var clientSettingsJson = ClientSettingsForSave(); var clientSettingsJson = ClientSettingsForSave();
bs.PutLump(BinaryStateLump.ClientSettings, (TextWriter tw) => tw.Write(clientSettingsJson)); bs.PutLump(BinaryStateLump.ClientSettings, (TextWriter tw) => tw.Write(clientSettingsJson));
} }
ReportProgress(PROGRESS_STEP);
if (VerificationLog.Any()) if (VerificationLog.Any())
{ {
bs.PutLump(BinaryStateLump.VerificationLog, tw => tw.WriteLine(InputLogToString(VerificationLog))); bs.PutLump(BinaryStateLump.VerificationLog, tw => tw.WriteLine(InputLogToString(VerificationLog)));
} }
ReportProgress(PROGRESS_STEP);
} }
Changes = false; Changes = false;

View File

@ -22,10 +22,12 @@ namespace BizHawk.Client.Common
private readonly Dictionary<int, IController> InputStateCache = new Dictionary<int, IController>(); private readonly Dictionary<int, IController> InputStateCache = new Dictionary<int, IController>();
private readonly List<string> VerificationLog = new List<string>(); // For movies that do not begin with power-on, this is the input required to get into the initial state private readonly List<string> VerificationLog = new List<string>(); // For movies that do not begin with power-on, this is the input required to get into the initial state
public TasMovie(string path, bool startsFromSavestate = false) : base(path) private BackgroundWorker _progressReportWorker = null;
public TasMovie(string path, bool startsFromSavestate = false, BackgroundWorker progressReportWorker = null) : base(path)
{ {
// TODO: how to call the default constructor AND the base(path) constructor? And is base(path) calling base() ? // TODO: how to call the default constructor AND the base(path) constructor? And is base(path) calling base() ?
_progressReportWorker = progressReportWorker;
if (!Global.Emulator.HasSavestates()) if (!Global.Emulator.HasSavestates())
{ {
throw new InvalidOperationException("Cannot create a TasMovie against a core that does not implement IStatable"); throw new InvalidOperationException("Cannot create a TasMovie against a core that does not implement IStatable");
@ -38,9 +40,10 @@ namespace BizHawk.Client.Common
Markers.Add(0, startsFromSavestate ? "Savestate" : "Power on"); Markers.Add(0, startsFromSavestate ? "Savestate" : "Power on");
} }
public TasMovie(bool startsFromSavestate = false) public TasMovie(bool startsFromSavestate = false, BackgroundWorker progressReportWorker = null)
: base() : base()
{ {
_progressReportWorker = progressReportWorker;
if (!Global.Emulator.HasSavestates()) if (!Global.Emulator.HasSavestates())
{ {
throw new InvalidOperationException("Cannot create a TasMovie against a core that does not implement IStatable"); throw new InvalidOperationException("Cannot create a TasMovie against a core that does not implement IStatable");

View File

@ -53,12 +53,15 @@ namespace BizHawk.Client.EmuHawk
{ {
get get
{ {
return Tastudio.Settings.FollowCursor; return false;
// FIXME
//return Tastudio.Settings.FollowCursor;
} }
set set
{ {
FollowCursorCheckbox.Checked = Tastudio.Settings.FollowCursor = value; // FIXME
//FollowCursorCheckbox.Checked = Tastudio.Settings.FollowCursor = value;
} }
} }
@ -80,8 +83,9 @@ namespace BizHawk.Client.EmuHawk
if (Tastudio != null) // For the designer if (Tastudio != null) // For the designer
{ {
AutoRestoreCheckbox.Checked = Tastudio.Settings.AutoRestoreLastPosition; // FIXME
FollowCursorCheckbox.Checked = Tastudio.Settings.FollowCursor; //AutoRestoreCheckbox.Checked = Tastudio.Settings.AutoRestoreLastPosition;
//FollowCursorCheckbox.Checked = Tastudio.Settings.FollowCursor;
} }
_programmaticallyChangingValue = false; _programmaticallyChangingValue = false;

File diff suppressed because it is too large Load Diff

View File

@ -77,8 +77,9 @@ namespace BizHawk.Client.EmuHawk
} }
else else
{ {
CurrentTasMovie.Save(); //CurrentTasMovie.Save();
MessageStatusLabel.Text = Path.GetFileName(CurrentTasMovie.Filename) + " saved."; //MessageStatusLabel.Text = Path.GetFileName(CurrentTasMovie.Filename) + " saved.";
_saveBackgroundWorker.RunWorkerAsync();
Settings.RecentTas.Add(CurrentTasMovie.Filename); Settings.RecentTas.Add(CurrentTasMovie.Filename);
} }
} }
@ -95,9 +96,11 @@ namespace BizHawk.Client.EmuHawk
if (file != null) if (file != null)
{ {
CurrentTasMovie.Filename = file.FullName; CurrentTasMovie.Filename = file.FullName;
CurrentTasMovie.Save();
//CurrentTasMovie.Save();
_saveBackgroundWorker.RunWorkerAsync();
Settings.RecentTas.Add(CurrentTasMovie.Filename); Settings.RecentTas.Add(CurrentTasMovie.Filename);
MessageStatusLabel.Text = Path.GetFileName(CurrentTasMovie.Filename) + " saved."; //MessageStatusLabel.Text = Path.GetFileName(CurrentTasMovie.Filename) + " saved.";
SetTextProperty(); SetTextProperty();
} }
} }

View File

@ -24,6 +24,8 @@ namespace BizHawk.Client.EmuHawk
private readonly List<TasClipboardEntry> _tasClipboard = new List<TasClipboardEntry>(); private readonly List<TasClipboardEntry> _tasClipboard = new List<TasClipboardEntry>();
private BackgroundWorker _saveBackgroundWorker;
private MovieEndAction _originalEndAction; // The movie end behavior selected by the user (that is overridden by TAStudio) private MovieEndAction _originalEndAction; // The movie end behavior selected by the user (that is overridden by TAStudio)
private Dictionary<string, string> GenerateColumnNames() private Dictionary<string, string> GenerateColumnNames()
{ {
@ -65,6 +67,39 @@ namespace BizHawk.Client.EmuHawk
InitializeComponent(); InitializeComponent();
Settings = new TAStudioSettings(); Settings = new TAStudioSettings();
// TODO: show this at all times or hide it when saving is done?
this.SavingProgressBar.Visible = false;
_saveBackgroundWorker = new BackgroundWorker();
_saveBackgroundWorker.WorkerReportsProgress = true;
_saveBackgroundWorker.DoWork += (s, e) =>
{
this.Invoke(() => this.MessageStatusLabel.Text = "Saving " + Path.GetFileName(CurrentTasMovie.Filename) + "...");
this.Invoke(() => this.SavingProgressBar.Visible = true);
CurrentTasMovie.Save();
};
_saveBackgroundWorker.ProgressChanged += (s, e) =>
{
SavingProgressBar.Value = e.ProgressPercentage;
};
_saveBackgroundWorker.RunWorkerCompleted += (s, e) =>
{
this.Invoke(() => this.MessageStatusLabel.Text = Path.GetFileName(CurrentTasMovie.Filename) + " saved.");
this.Invoke(() => this.SavingProgressBar.Visible = false);
// SUPER HACKY, and i'm not even sure it's necessary
Timer t = new Timer();
t.Tick += (a, b) =>
{
this.Invoke(() => this.MessageStatusLabel.Text = "TAStudio engaged.");
t.Stop();
};
t.Interval = 5000;
t.Start();
};
WantsToControlStopMovie = true; WantsToControlStopMovie = true;
TasPlaybackBox.Tastudio = this; TasPlaybackBox.Tastudio = this;
MarkerControl.Tastudio = this; MarkerControl.Tastudio = this;
@ -77,6 +112,7 @@ namespace BizHawk.Client.EmuHawk
TasView.MultiSelect = true; TasView.MultiSelect = true;
TasView.MaxCharactersInHorizontal = 1; TasView.MaxCharactersInHorizontal = 1;
WantsToControlRestartMovie = true; WantsToControlRestartMovie = true;
} }
private void TastudioToStopMovie() private void TastudioToStopMovie()
@ -120,7 +156,7 @@ namespace BizHawk.Client.EmuHawk
private void NewTasMovie() private void NewTasMovie()
{ {
Global.MovieSession.Movie = new TasMovie(); Global.MovieSession.Movie = new TasMovie(false, _saveBackgroundWorker);
SetTasMovieCallbacks(); SetTasMovieCallbacks();
CurrentTasMovie.PropertyChanged += new PropertyChangedEventHandler(this.TasMovie_OnPropertyChanged); CurrentTasMovie.PropertyChanged += new PropertyChangedEventHandler(this.TasMovie_OnPropertyChanged);
CurrentTasMovie.Filename = DefaultTasProjName(); // TODO don't do this, take over any mainform actions that can crash without a filename CurrentTasMovie.Filename = DefaultTasProjName(); // TODO don't do this, take over any mainform actions that can crash without a filename
@ -194,14 +230,17 @@ namespace BizHawk.Client.EmuHawk
text += " - " + CurrentTasMovie.Name + (CurrentTasMovie.Changes ? "*" : ""); text += " - " + CurrentTasMovie.Name + (CurrentTasMovie.Changes ? "*" : "");
} }
Text = text; if (this.InvokeRequired)
this.Invoke(() => Text = text);
else
Text = text;
} }
public bool LoadProject(string path) public bool LoadProject(string path)
{ {
if (AskSaveChanges()) if (AskSaveChanges())
{ {
var movie = new TasMovie var movie = new TasMovie(false, _saveBackgroundWorker)
{ {
Filename = path, Filename = path,
ClientSettingsForSave = ClientSettingsForSave, ClientSettingsForSave = ClientSettingsForSave,