Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- local tArgs = { ... } -- Capture arguments.
- --[[
- Recorder PaymentOption
- 22 January 2013
- This is a simple implementation of
- screen recording software that seems
- to be so popular now-a-days.
- ]]--
- -- Variables --
- local NATIVE_TERM = {} -- A copy of the native terminal.
- local recordingTerm = {} -- The terminal which will house edited functions for recording.
- local recordingTable = {} -- The table that will record all calls by the terminal.
- local RECORDING_PATH = nil -- The path that the user wants to save a new recording to.
- local END_RECORDING = "Recording finished." -- The string that is returned by the shell thread when it has exited.
- -- Below is the thread which houses the shell which will be used to record the terminal output of the computer.
- -- This thread returns once the user has exited the shell by running the 'exit' program on their machine.
- local shellThread = coroutine.create(function()
- while true do
- local eventData = { os.pullEvent() }
- local hasFinished = coroutine.resume(os.run({["shell"] = shell}, "rom/programs/shell"), unpack(eventData))
- -- In the case that this shell is exited because the 'exit' program was run, then we need to mimic the shell
- -- and almost shutdown the computer, except we'll just return from this recording.
- if hasFinished then
- return END_RECORDING
- end
- end
- end)
- -- Variables --
- -- Terminal Functions --
- -- Creates and returns a copy of the current terminal table.
- function createTerminalCopy()
- local copy = {}
- for itemName, item in pairs(term.native) do
- copy[itemName] = item
- end
- return copy
- end
- -- Takes a terminal table and recording table and modifies the functions of
- -- the terminal table to record the screen.
- -- In a recording table, entries are made in the format: t[n] = {functionName = (string), parameters = (variable number of arguemts ( ... ))}
- function modifyTerminalForRecording(terminalTable, recordingTable)
- -- Returns a modified function that acts as an old terminal function by
- -- adding the call of the function to the recording table and calling the old
- -- function from the terminalTable.
- local function modifyFunction(functionName, recordingTable)
- return function ( ... )
- recordingTable[#recordingTable + 1] = {functionName = functionName, parameters = { ... }, currentTime = os.clock()}
- return NATIVE_TERM[functionName]( ... )
- end
- end
- for itemName, item in pairs(terminalTable) do
- terminalTable[itemName] = modifyFunction(itemName, recordingTable)
- end
- return terminalTable
- end
- -- Terminal Functions --
- -- File Functions --
- -- Writes a recording to a file. Takes a recording table.
- function writeRecordingToFile(recordingTable, filePath)
- local fileHandle = fs.open(filePath, 'w')
- print("Saving recording... ")
- fileHandle.writeLine(textutils.serialize(recordingTable))
- fileHandle.close()
- end
- -- Reads a recording from a file. Returns the recording table.
- function readRecordingFromFile(filePath)
- local fileHandle = fs.open(filePath, 'r')
- local recordingTable = textutils.unserialize(fileHandle.readLine())
- fileHandle.close()
- return recordingTable
- end
- -- File Functions --
- -- Playback Functions --
- -- Plays back a recording table.
- function playRecording(recordingTable)
- NATIVE_TERM.clear()
- NATIVE_TERM.setCursorPos(1, 1)
- print(#recordingTable)
- -- Sleep the difference between each call, assuming this isn't the first call.
- for itemIndex, item in pairs(recordingTable) do
- -- Make sure that the difference for sleeping is greater than 0.3. If this isn't the case, then don't sleep at all.
- if itemIndex > 1 and item.currentTime - recordingTable[itemIndex - 1].currentTime > 0 then
- sleep(item.currentTime - recordingTable[itemIndex - 1].currentTime)
- end
- NATIVE_TERM[item.functionName](unpack(item.parameters))
- end
- NATIVE_TERM.clear()
- NATIVE_TERM.setCursorPos(1, 1)
- end
- -- Playback Functions --
- -- Initialization --
- NATIVE_TERM = createTerminalCopy()
- recordingTerm = createTerminalCopy()
- recordingTerm = modifyTerminalForRecording(recordingTerm, recordingTable)
- -- Initialization --
- -- Handle arguments.
- if #tArgs > 0 then
- -- If the user wants to play a recording, then attempt to load it.
- if fs.exists(tArgs[1]) and not fs.isDir(tArgs[1]) then
- playRecording(readRecordingFromFile(tArgs[1]))
- print("End of recording at " .. tArgs[1] .. '.')
- return
- -- If the user wants to record a new recording, then do that.
- -- Don't return here.
- elseif tArgs[1] == "record" and not fs.exists(tArgs[2]) then
- RECORDING_PATH = tArgs[2]
- term.clear()
- term.setCursorPos(1, 1)
- print("Run the 'exit' program in the shell to stop recording and save.")
- sleep(1)
- else
- -- If none of the argument setups match, then print the usage.
- print("Usage: " .. shell.getRunningProgram() .. " <recording path>")
- print(" " .. shell.getRunningProgram() .. " record <new recording path>")
- return
- end
- else
- -- If none of the argument setups match, then print the usage.
- print("Usage: " .. shell.getRunningProgram() .. " <recording path>")
- print(" " .. shell.getRunningProgram() .. " record <new recording path>")
- return
- end
- -- Handle arguments.
- -- Main entry point --
- -- Redirect terminal output to the modified terminal table.
- term.redirect(recordingTerm)
- term.clear()
- term.setCursorPos(1, 1)
- -- Queue a couple of events to get the shell going.
- os.queueEvent("char", '')
- os.queueEvent("char", '')
- while coroutine.status(shellThread) ~= "dead" do
- local eventData = { os.pullEvent() }
- coroutine.resume(shellThread, unpack(eventData))
- end
- -- Once the thread has died, redirect the terminal output back to the standard terminal
- -- and replay the recording.
- term.redirect(NATIVE_TERM)
- NATIVE_TERM.clear()
- NATIVE_TERM.setCursorPos(1, 1)
- writeRecordingToFile(recordingTable, RECORDING_PATH)
- print("Finished recording. Saved as " .. RECORDING_PATH)
- -- Main entry point --
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement