2014-06-18 02:28:07 +00:00
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.")]
2014-06-18 02:28:07 +00:00
public class SynclessRecorder : IVideoWriter
{
2017-04-18 17:27:44 +00:00
public void Dispose ( )
{
}
2014-06-18 02:28:07 +00:00
2017-04-18 17:27:44 +00:00
public void SetVideoCodecToken ( IDisposable token )
{
}
2014-06-18 02:28:07 +00:00
2017-04-18 17:27:44 +00:00
public void SetDefaultVideoCodecToken ( )
{
}
2014-06-18 02:28:07 +00:00
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 ;
2014-06-18 02:28:07 +00:00
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 ( )
{
}
2014-06-18 02:28:07 +00:00
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 ;
2016-03-05 23:19:12 +00:00
2017-04-18 17:27:44 +00:00
public bool UsesVideo = > true ;
private class DummyDisposable : IDisposable
{
public void Dispose ( )
{
}
}
2014-06-18 02:28:07 +00:00
2017-04-18 17:27:44 +00:00
public IDisposable AcquireVideoCodecToken ( IWin32Window hwnd )
{
return new DummyDisposable ( ) ;
}
2014-06-18 02:28:07 +00:00
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
2014-06-18 02:28:07 +00:00
}
2017-04-18 17:27:44 +00:00
private int paramSampleRate , paramChannels , paramBits ;
2014-06-18 02:28:07 +00:00
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
2014-06-18 02:28:07 +00:00
}
2017-04-18 17:27:44 +00:00
public string DesiredExtension ( )
{
return "syncless.txt" ;
}
2014-06-18 02:28:07 +00:00
/// <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 )
2014-06-18 02:28:07 +00:00
{
2017-04-18 17:27:44 +00:00
if ( len = = 0 )
{
throw new ArgumentException ( "Invalid len" , nameof ( len ) ) ;
}
2014-06-18 02:28:07 +00:00
int numChunks = ( s . Length + len - 1 ) / len ;
2017-04-18 17:27:44 +00:00
var output = new List < string > ( numChunks ) ;
2014-06-18 02:28:07 +00:00
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 ;
}
2014-06-18 02:28:07 +00:00
output . Add ( s . Substring ( j , todo ) ) ;
}
2017-04-18 17:27:44 +00:00
2014-06-18 02:28:07 +00:00
return output ;
}
2017-04-18 17:27:44 +00:00
private string GetAndCreatePathForFrameNum ( int index )
2014-06-18 02:28:07 +00:00
{
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
}