using System; using System.Collections.Generic; using System.Drawing; using System.Text; using System.Windows.Forms; using System.IO; namespace BizHawk.MultiClient { public partial class PlayMovie : Form { private readonly List MovieList = new List(); private bool sortReverse; private string sortedCol; public PlayMovie() { InitializeComponent(); MovieView.QueryItemText += MovieView_QueryItemText; MovieView.QueryItemBkColor += MovieView_QueryItemBkColor; MovieView.VirtualMode = true; sortReverse = false; sortedCol = ""; } void MovieView_QueryItemText(int index, int column, out string text) { text = ""; if (column == 0) //File { text = Path.GetFileName(MovieList[index].Filename); } if (column == 1) //System { text = MovieList[index].SysID; } if (column == 2) //Game { text = MovieList[index].GameName; } if (column == 3) //Time { text = MovieList[index].GetTime(true); } } private void MovieView_QueryItemBkColor(int index, int column, ref Color color) { } private void Cancel_Click(object sender, EventArgs e) { Close(); } private void Run() { ListView.SelectedIndexCollection indexes = MovieView.SelectedIndices; if (indexes.Count == 0) { return; } //Import file if necessary Global.MainForm.StartNewMovie(MovieList[MovieView.SelectedIndices[0]], false); } private void OK_Click(object sender, EventArgs e) { Global.MainForm.ReadOnly = ReadOnlyCheckBox.Checked; Run(); Close(); } private void BrowseMovies_Click(object sender, EventArgs e) { OpenFileDialog ofd = new OpenFileDialog {InitialDirectory = PathManager.MakeAbsolutePath(Global.Config.MoviesPath)}; string filter = "Movie Files (*." + Global.Config.MovieExtension + ")|*." + Global.Config.MovieExtension + "|Savestates|*.state|All Files|*.*"; ofd.Filter = filter; Global.Sound.StopSound(); var result = ofd.ShowDialog(); Global.Sound.StartSound(); if (result == DialogResult.OK) { var file = new FileInfo(ofd.FileName); if (!file.Exists) return; else { if (file.Extension.ToUpper() == "STATE") { Movie m = new Movie(file.FullName); m.LoadMovie(); //State files will have to load everything unfortunately if (m.Frames == 0) { MessageBox.Show("No input log detected in this savestate, aborting", "Can not load file", MessageBoxButtons.OK, MessageBoxIcon.Hand); return; } } int x = AddMovieToList(ofd.FileName, true); if (x > 0) { MovieView.SelectedIndices.Clear(); MovieView.setSelection(x); MovieView.SelectItem(x, true); } } } } private void AddStateToList(string filename) { using (var file = new HawkFile(filename)) { if (file.Exists) { int x = IsDuplicate(filename); if (x == 0) { Movie m = new Movie(file.CanonicalFullPath); m.LoadMovie(); //State files will have to load everything unfortunately if (m.Frames > 0) { MovieList.Add(m); sortReverse = false; sortedCol = ""; } } } } } private int AddMovieToList(string filename, bool force) { using (var file = new HawkFile(filename)) { if (!file.Exists) return 0; else { int x = IsDuplicate(filename); if (x == 0) { PreLoadMovieFile(file, force); MovieView.ItemCount = MovieList.Count; UpdateList(); sortReverse = false; sortedCol = ""; x = MovieList.Count - 1; } return x; } } } private int IsDuplicate(string filename) { for (int x = 0; x < MovieList.Count; x++) { if (MovieList[x].Filename == filename) { return x; } } return 0; } private void PreLoadMovieFile(HawkFile path, bool force) { Movie m = new Movie(path.CanonicalFullPath); m.PreLoadText(); if (path.Extension == ".FM2") { m.Header.SetHeaderLine(MovieHeader.PLATFORM, "NES"); } else if (path.Extension == ".MC2") { m.Header.SetHeaderLine(MovieHeader.PLATFORM, "PCE"); } //Don't do this from browse if (m.Header.GetHeaderLine(MovieHeader.GAMENAME) == Global.Game.Name || Global.Config.PlayMovie_MatchGameName == false || force) { MovieList.Add(m); } } private void UpdateList() { MovieView.Refresh(); UpdateMovieCount(); } private void UpdateMovieCount() { int x = MovieList.Count; if (x == 1) { MovieCount.Text = x.ToString() + " movie"; } else { MovieCount.Text = x.ToString() + " movies"; } } private void PreHighlightMovie() { if (Global.Game == null) return; List Indexes = new List(); //Pull out matching names for (int x = 0; x < MovieList.Count; x++) { if (PathManager.FilesystemSafeName(Global.Game) == MovieList[x].GameName) Indexes.Add(x); } if (Indexes.Count == 0) return; if (Indexes.Count == 1) { HighlightMovie(Indexes[0]); return; } //Prefer tas files List TAS = new List(); for (int x = 0; x < Indexes.Count; x++) { if (Path.GetExtension(MovieList[Indexes[x]].Filename).ToUpper() == "." + Global.Config.MovieExtension) { TAS.Add(x); } } if (TAS.Count == 1) { HighlightMovie(TAS[0]); return; } else if (TAS.Count > 1) { Indexes = new List(TAS); } //Final tie breaker - Last used file FileInfo f = new FileInfo(MovieList[Indexes[0]].Filename); DateTime t = f.LastAccessTime; int mostRecent = Indexes[0]; for (int x = 1; x < Indexes.Count; x++) { f = new FileInfo(MovieList[Indexes[0]].Filename); if (f.LastAccessTime > t) { t = f.LastAccessTime; mostRecent = Indexes[x]; } } HighlightMovie(mostRecent); return; } private void HighlightMovie(int index) { MovieView.SelectedIndices.Clear(); MovieView.setSelection(index); MovieView.SelectItem(index, true); } private void ClearList() { MovieList.Clear(); MovieView.ItemCount = 0; MovieView.Update(); } private void ScanFiles() { ClearList(); string d = PathManager.MakeAbsolutePath(Global.Config.MoviesPath); if (!Directory.Exists(d)) { Directory.CreateDirectory(d); } foreach (string f in Directory.GetFiles(d, "*." + Global.Config.MovieExtension)) { AddMovieToList(f, false); } if (Global.Config.MovieExtension != "*.tas") { foreach (string f in Directory.GetFiles(d, "*.tas")) { AddMovieToList(f, false); } } else if (Global.Config.MovieExtension != "*.bkm") { foreach (string f in Directory.GetFiles(d, "*.bkm")) { AddMovieToList(f, false); } } if (Global.Config.PlayMovie_ShowStateFiles) { foreach (string f in Directory.GetFiles(d, "*.state")) { AddStateToList(f); } } if (Global.Config.PlayMovie_IncludeSubdir) { string[] subs = Directory.GetDirectories(d); foreach (string dir in subs) { foreach (string f in Directory.GetFiles(dir, "*." + Global.Config.MovieExtension)) { AddMovieToList(f, false); } if (Global.Config.PlayMovie_ShowStateFiles) { foreach (string f in Directory.GetFiles(d, "*.state")) { AddStateToList(f); } } } } } private void PlayMovie_Load(object sender, EventArgs e) { IncludeSubDirectories.Checked = Global.Config.PlayMovie_IncludeSubdir; ShowStateFiles.Checked = Global.Config.PlayMovie_ShowStateFiles; MatchGameNameCheckBox.Checked = Global.Config.PlayMovie_MatchGameName; ScanFiles(); PreHighlightMovie(); } private void MovieView_SelectedIndexChanged(object sender, EventArgs e) { toolTip1.SetToolTip(DetailsView, ""); DetailsView.Items.Clear(); if (MovieView.SelectedIndices.Count < 1) { OK.Enabled = false; return; } else OK.Enabled = true; int x = MovieView.SelectedIndices[0]; MovieView.ensureVisible(x); Dictionary h = MovieList[x].Header.HeaderParams; foreach (var kvp in h) { ListViewItem item = new ListViewItem(kvp.Key); item.SubItems.Add(kvp.Value); switch (kvp.Key) { case MovieHeader.SHA1: if (kvp.Value != Global.Game.Hash) { item.BackColor = Color.Pink; toolTip1.SetToolTip(DetailsView, "Current SHA1: " + Global.Game.Hash); } break; case MovieHeader.MOVIEVERSION: if (kvp.Value != MovieHeader.MovieVersion) { item.BackColor = Color.Yellow; } break; case MovieHeader.EMULATIONVERSION: if (kvp.Value != Global.MainForm.GetEmuVersion()) { item.BackColor = Color.Yellow; } break; case MovieHeader.PLATFORM: if (kvp.Value != Global.Game.System) { item.BackColor = Color.Pink; } break; } DetailsView.Items.Add(item); } if (MovieList[x].Header.Comments.Count > 0) { button1.Enabled = true; } else { button1.Enabled = false; } if (MovieList[x].Subtitles.Count > 0) { button2.Enabled = true; } else { button2.Enabled = false; } } private void button1_Click(object sender, EventArgs e) { ListView.SelectedIndexCollection indexes = MovieView.SelectedIndices; if (indexes.Count == 0) return; EditCommentsForm c = new EditCommentsForm {ReadOnly = true}; c.GetMovie(MovieList[MovieView.SelectedIndices[0]]); c.Show(); } private void button2_Click(object sender, EventArgs e) { ListView.SelectedIndexCollection indexes = MovieView.SelectedIndices; if (indexes.Count == 0) return; EditSubtitlesForm s = new EditSubtitlesForm {ReadOnly = true}; s.GetMovie(MovieList[MovieView.SelectedIndices[0]]); s.Show(); } private void MovieView_DoubleClick(object sender, EventArgs e) { Run(); Close(); } private void MovieView_DragEnter(object sender, DragEventArgs e) { e.Effect = e.Data.GetDataPresent(DataFormats.FileDrop) ? DragDropEffects.Copy : DragDropEffects.None; } private void MovieView_DragDrop(object sender, DragEventArgs e) { string[] filePaths = (string[])e.Data.GetData(DataFormats.FileDrop); foreach (string path in filePaths) { if (Path.GetExtension(path) == "." + Global.Config.MovieExtension) AddMovieToList(path, true); } } private void MovieView_ColumnClick(object sender, ColumnClickEventArgs e) { OrderColumn(e.Column); } private void OrderColumn(int columnToOrder) { string columnName = MovieView.Columns[columnToOrder].Text; if (sortedCol.CompareTo(columnName) != 0) sortReverse = false; MovieList.Sort((x, y) => x.CompareTo(y, columnName) * (sortReverse ? -1 : 1)); sortedCol = columnName; sortReverse = !(sortReverse); MovieView.Refresh(); } private void IncludeSubDirectories_CheckedChanged(object sender, EventArgs e) { Global.Config.PlayMovie_IncludeSubdir = IncludeSubDirectories.Checked; ScanFiles(); PreHighlightMovie(); } private void ShowStateFiles_CheckedChanged(object sender, EventArgs e) { Global.Config.PlayMovie_ShowStateFiles = ShowStateFiles.Checked; ScanFiles(); PreHighlightMovie(); } private void Scan_Click(object sender, EventArgs e) { ScanFiles(); PreHighlightMovie(); } private void MatchGameNameCheckBox_CheckedChanged(object sender, EventArgs e) { Global.Config.PlayMovie_MatchGameName = MatchGameNameCheckBox.Checked; ScanFiles(); PreHighlightMovie(); } private void MovieView_KeyDown(object sender, KeyEventArgs e) { if (e.Control && e.KeyCode == Keys.C) { ListView.SelectedIndexCollection indexes = MovieView.SelectedIndices; if (indexes.Count > 0) { StringBuilder copyStr = new StringBuilder(); foreach (int index in indexes) { copyStr.Append(MovieList[index].Filename); copyStr.Append('\t'); copyStr.Append(MovieList[index].SysID); copyStr.Append('\t'); copyStr.Append(MovieList[index].GameName); copyStr.Append('\t'); copyStr.Append(MovieList[index].GetTime(true)); copyStr.Append('\n'); Clipboard.SetDataObject(copyStr.ToString()); } } } } } }