BizHawk/BizHawk.Client.EmuHawk/AVOut/SynclessRecorder.cs

165 lines
4.0 KiB
C#
Raw Normal View History

using System;
using System.IO;
using System.Collections.Generic;
using System.Text;
using System.Windows.Forms;
using BizHawk.Emulation.Common;
using BizHawk.Bizware.BizwareGL;
namespace BizHawk.Client.EmuHawk
{
2014-10-10 18:09:00 +00:00
[VideoWriter("syncless", "Syncless Recording", "Writes each frame to a directory as a PNG and WAV pair, identified by frame number. The results can be exported into one video file.")]
public class SynclessRecorder : IVideoWriter
{
2017-04-18 17:27:44 +00:00
public void Dispose()
{
}
2017-04-18 17:27:44 +00:00
public void SetVideoCodecToken(IDisposable token)
{
}
2017-04-18 17:27:44 +00:00
public void SetDefaultVideoCodecToken()
{
}
public void SetFrame(int frame)
{
mCurrFrame = frame;
}
2017-04-18 17:27:44 +00:00
private int mCurrFrame;
private string mBaseDirectory, mFramesDirectory;
private string mProjectFile;
public void OpenFile(string projFile)
{
mProjectFile = projFile;
mBaseDirectory = Path.GetDirectoryName(mProjectFile);
string basename = Path.GetFileNameWithoutExtension(projFile);
string framesDirFragment = basename + "_frames";
mFramesDirectory = Path.Combine(mBaseDirectory, framesDirFragment);
StringBuilder sb = new StringBuilder();
sb.AppendLine("version=1");
sb.AppendLine("framesdir=" + framesDirFragment);
File.WriteAllText(mProjectFile, sb.ToString());
}
2017-04-18 17:27:44 +00:00
public void CloseFile()
{
}
public void AddFrame(IVideoProvider source)
{
using (var bb = new BitmapBuffer(source.BufferWidth, source.BufferHeight, source.GetVideoBuffer()))
{
string subpath = GetAndCreatePathForFrameNum(mCurrFrame);
string path = subpath + ".png";
bb.ToSysdrawingBitmap().Save(path, System.Drawing.Imaging.ImageFormat.Png);
}
}
public void AddSamples(short[] samples)
{
string subpath = GetAndCreatePathForFrameNum(mCurrFrame);
string path = subpath + ".wav";
WavWriterV wwv = new WavWriterV();
wwv.SetAudioParameters(paramSampleRate, paramChannels, paramBits);
wwv.OpenFile(path);
wwv.AddSamples(samples);
wwv.CloseFile();
wwv.Dispose();
}
2017-04-18 17:27:44 +00:00
public bool UsesAudio => true;
2017-04-18 17:27:44 +00:00
public bool UsesVideo => true;
private class DummyDisposable : IDisposable
{
public void Dispose()
{
}
}
2017-04-18 17:27:44 +00:00
public IDisposable AcquireVideoCodecToken(IWin32Window hwnd)
{
return new DummyDisposable();
}
public void SetMovieParameters(int fpsnum, int fpsden)
{
//should probably todo in here
}
public void SetVideoParameters(int width, int height)
{
2017-04-18 17:27:44 +00:00
// may want to todo
}
2017-04-18 17:27:44 +00:00
private int paramSampleRate, paramChannels, paramBits;
public void SetAudioParameters(int sampleRate, int channels, int bits)
{
paramSampleRate = sampleRate;
paramChannels = channels;
paramBits = bits;
}
public void SetMetaData(string gameName, string authors, UInt64 lengthMS, UInt64 rerecords)
{
2017-04-18 17:27:44 +00:00
// not needed
}
2017-04-18 17:27:44 +00:00
public string DesiredExtension()
{
return "syncless.txt";
}
/// <summary>
/// splits the string into chunks of length s
/// </summary>
2017-04-18 17:27:44 +00:00
private static List<string> StringChunkSplit(string s, int len)
{
2017-04-18 17:27:44 +00:00
if (len == 0)
{
throw new ArgumentException("Invalid len", nameof(len));
}
int numChunks = (s.Length + len - 1) / len;
2017-04-18 17:27:44 +00:00
var output = new List<string>(numChunks);
for (int i = 0, j = 0; i < numChunks; i++, j += len)
{
int todo = len;
int remain = s.Length - j;
2017-04-18 17:27:44 +00:00
if (remain < todo)
{
todo = remain;
}
output.Add(s.Substring(j, todo));
}
2017-04-18 17:27:44 +00:00
return output;
}
2017-04-18 17:27:44 +00:00
private string GetAndCreatePathForFrameNum(int index)
{
string subpath = GetPathFragmentForFrameNum(index);
string path = mFramesDirectory;
path = Path.Combine(path, subpath);
string fpath = path + ".nothing";
Directory.CreateDirectory(Path.GetDirectoryName(fpath));
return path;
}
public static string GetPathFragmentForFrameNum(int index)
{
var chunks = StringChunkSplit(index.ToString(), 2);
string subpath = string.Join("/", chunks);
return subpath;
}
}
2014-10-10 18:09:00 +00:00
}