using System; using LuaInterface; namespace BizHawk.Client.Common { public sealed class MovieLuaLibrary : LuaLibraryBase { public MovieLuaLibrary(Lua lua) : base(lua) { } public MovieLuaLibrary(Lua lua, Action logOutputCallback) : base(lua, logOutputCallback) { } public override string Name { get { return "movie"; } } [LuaMethodAttributes( "startsfromsavestate", "Returns whether or not the movie is a savestate-anchored movie" )] public bool StartsFromSavestate() { return Global.MovieSession.Movie.IsActive && Global.MovieSession.Movie.StartsFromSavestate; } [LuaMethodAttributes( "startsfromsaveram", "Returns whether or not the movie is a saveram-anchored movie" )] public bool StartsFromSaveram() { return Global.MovieSession.Movie.IsActive && Global.MovieSession.Movie.StartsFromSaveRam; } [LuaMethodAttributes( "filename", "Returns the file name including path of the currently loaded movie" )] public static string Filename() { return Global.MovieSession.Movie.Filename; } [LuaMethodAttributes( "getinput", "Returns a table of buttons pressed on a given frame of the loaded movie" )] public LuaTable GetInput(int frame) { var input = Lua.NewTable(); var adapter = Global.MovieSession.Movie.GetInputState(frame); foreach (var button in adapter.Type.BoolButtons) { input[button] = adapter[button]; } foreach (var button in adapter.Type.FloatControls) { input[button] = adapter[button]; } return input; } [LuaMethodAttributes( "getinputasmnemonic", "Returns the input of a given frame of the loaded movie in a raw inputlog string" )] public string GetInputAsMnemonic(int frame) { if (Global.MovieSession.Movie.IsActive && frame < Global.MovieSession.Movie.InputLogLength) { var lg = Global.MovieSession.LogGeneratorInstance(); lg.SetSource(Global.MovieSession.Movie.GetInputState(frame)); return lg.GenerateLogEntry(); } return string.Empty; } [LuaMethodAttributes( "getreadonly", "Returns true if the movie is in read-only mode, false if in read+write" )] public static bool GetReadOnly() { return Global.MovieSession.ReadOnly; } [LuaMethodAttributes( "getrerecordcount", "Gets the rerecord count of the current movie." )] public static ulong GetRerecordCount() { return Global.MovieSession.Movie.Rerecords; } [LuaMethodAttributes( "getrerecordcounting", "Returns whether or not the current movie is incrementing rerecords on loadstate" )] public static bool GetRerecordCounting() { return Global.MovieSession.Movie.IsCountingRerecords; } [LuaMethodAttributes( "isloaded", "Returns true if a movie is loaded in memory (play, record, or finished modes), false if not (inactive mode)" )] public static bool IsLoaded() { return Global.MovieSession.Movie.IsActive; } [LuaMethodAttributes( "length", "Returns the total number of frames of the loaded movie" )] public static double Length() { return Global.MovieSession.Movie.FrameCount; } [LuaMethodAttributes( "mode", "Returns the mode of the current movie. Possible modes: PLAY, RECORD, FINISHED, INACTIVE" )] public static string Mode() { if (Global.MovieSession.Movie.IsFinished) { return "FINISHED"; } if (Global.MovieSession.Movie.IsPlaying) { return "PLAY"; } if (Global.MovieSession.Movie.IsRecording) { return "RECORD"; } return "INACTIVE"; } [LuaMethodAttributes( "rerecordcount", "[Deprecated] Alias of getrerecordcount" )] public static string RerecordCount() { return GetRerecordCount().ToString(); } [LuaMethodAttributes( "setreadonly", "Sets the read-only state to the given value. true for read only, false for read+write" )] public static void SetReadOnly(bool readOnly) { Global.MovieSession.ReadOnly = readOnly; } [LuaMethodAttributes( "setrerecordcount", "Sets the rerecord count of the current movie." )] public static void SetRerecordCount(double count) { // Lua numbers are always double, integer precision holds up // to 53 bits, so throw an error if it's bigger than that. const double precisionLimit = 9007199254740992d; if (count > precisionLimit) throw new Exception("Rerecord count exceeds Lua integer precision."); Global.MovieSession.Movie.Rerecords = (ulong)count; } [LuaMethodAttributes( "setrerecordcounting", "Sets whether or not the current movie will increment the rerecord counter on loadstate" )] public static void SetRerecordCounting(bool counting) { Global.MovieSession.Movie.IsCountingRerecords = counting; } [LuaMethodAttributes( "stop", "Stops the current movie" )] public static void Stop() { Global.MovieSession.Movie.Stop(); } [LuaMethodAttributes( "getfps", "If a movie is loaded, gets the frames per second used by the movie to determine the movie length time" )] public static double GetFps() { if (Global.MovieSession.Movie.IsActive) { var movie = Global.MovieSession.Movie; var system = movie.HeaderEntries[HeaderKeys.PLATFORM]; var pal = movie.HeaderEntries.ContainsKey(HeaderKeys.PAL) && movie.HeaderEntries[HeaderKeys.PAL] == "1"; return new PlatformFrameRates()[system, pal]; } return 0.0; } [LuaMethodAttributes( "getheader", "If a movie is active, will return the movie header as a lua table" )] public LuaTable GetHeader() { var luaTable = Lua.NewTable(); if (Global.MovieSession.Movie.IsActive) { foreach (var kvp in Global.MovieSession.Movie.HeaderEntries) { luaTable[kvp.Key] = kvp.Value; } } return luaTable; } [LuaMethodAttributes( "getcomments", "If a movie is active, will return the movie comments as a lua table" )] public LuaTable GetComments() { var luaTable = Lua.NewTable(); if (Global.MovieSession.Movie.IsActive) { for (int i = 0; i < Global.MovieSession.Movie.Comments.Count; i++) { luaTable[i] = Global.MovieSession.Movie.Comments[i]; } } return luaTable; } [LuaMethodAttributes( "getsubtitles", "If a movie is active, will return the movie subtitles as a lua table" )] public LuaTable GetSubtitles() { var luaTable = Lua.NewTable(); if (Global.MovieSession.Movie.IsActive) { for (int i = 0; i < Global.MovieSession.Movie.Subtitles.Count; i++) { luaTable[i] = Global.MovieSession.Movie.Subtitles[i].ToString(); } } return luaTable; } } }