VLC rename current item with lua script - windows

I am using this script as a template to rename a file in VLC: https://github.com/surrim/vlc-delete/
The Script works as intended.
My code looks like this:
function descriptor()
return {
title = "VLC Rename";
version = "0.1";
author = "I";
shortdesc = "Rename current file";
description = [[
<h1>vlc-rename</h1>"
When you're playing a file, use VLC Rename
to rename the current file]];
}
end
function removeItem()
local id = vlc.playlist.current()
vlc.playlist.delete(id)
vlc.playlist.gotoitem(id + 1)
vlc.deactivate()
end
function activate()
local item = vlc.input.item()
local uri = item:uri()
oldFile = vlc.strings.decode_uri(string.gsub(uri, "^file:///", ""))
d = vlc.dialog( "Rename Dialog" )
d:add_label("Filename")
w = d:add_text_input(oldFile, 1, 5,200 ,30)
d:add_button("OK", click_ok)
d:show()
end
function click_ok()
local newFile = w:get_text()
vlc.msg.info("[vlc-rename] renaming: " .. oldFile .. " with " .. newFile)
if newFile ~= oldFile then
removeItem()
retval, err = os.rename(oldFile,newFile)
vlc.msg.info("[vlc-rename] end rename")
if (retval == nil) then
vlc.msg.err("[vlc-rename] fail: " .. err)
end
end
d:delete()
vlc.deactivate()
end
function deactivate()
vlc.deactivate()
end
function close()
deactivate()
end
function meta_changed()
end
This code outputs an error from the os.rename() function:
lua error: [vlc-rename] fail: [my filename] Permission denied
Regardless of elevation level.
I am using windows 10 64bit and VLC 3.03.
Since this is my first lua script I welcome any input.

I might be wrong, but maybe the file you are trying to rename is already opened elsewhere or by VLC (you said you want to rename the "current file").

Related

Lua - FlashAir card CONFIG file gets damaged

I am using Toshiba FlashAir card to wirelessly upload photos from my drone to my web server via Lua script installed on FlashAir card. The card works fine most of the time, but sometimes the photos doesn't upload. When I connect to the card via my mac, I get this message, "CONFIG" is damaged and can't be opened.
Not sure why this is happening. The ftpUpload.lua script that does the uploading is listed below:
require("Settings")
local blackList = {}
local dateTable = {}
local parseThreads = 0
local ftpstring = "ftp://"..user..":"..passwd.."#"..server.."/"..serverDir.."/"
local lockdir = "/uploaded/" -- trailing slash required, and folder must already exist
local fileTable = {}
--Options
local sortByFileName = false -- If true sorts alphabetically by file else sorts by modified date
local jpegsOnly = true --Excludes .RAW files if set to true
local function exists(path)
if lfs.attributes(path) then
return true
else
return false
end
end
local function is_uploaded(path)
local hash = fa.hash("md5", path, "")
return exists(lockdir .. hash)
end
local function set_uploaded(path)
local hash = fa.hash("md5", path, "")
local file = io.open(lockdir .. hash, "w")
file:close()
end
local function delete(path)
-- Both of the following methods cause the next photo to be lost / not stored.
fa.remove(path)
-- fa.request("http://127.0.0.1/upload.cgi?DEL="..path)
end
--Format file date to something meanigful
local function FatDateTimeToTable(datetime_fat)
local function getbits(x, from, to)
local mask = bit32.lshift(1, to - from + 1) - 1
local shifted = bit32.rshift(x, from)
return bit32.band(shifted, mask)
end
local fatdate = bit32.rshift(datetime_fat, 16)
local day = getbits(fatdate, 0, 4)
local month = getbits(fatdate, 5, 8)
local year = getbits(fatdate, 9, 15) + 1980
local fattime = getbits(datetime_fat, 0, 15)
local sec = getbits(fattime, 0, 4) * 2
local min = getbits(fattime, 5, 10)
local hour = getbits(fattime, 11, 15)
return {
year = string.format('%02d', year),
month = string.format('%02d', month),
day = string.format('%02d', day),
hour = string.format('%02d', hour),
min = string.format('%02d', min),
sec = string.format('%02d', sec),
}
end
--Looks for value in table
local function exists_in_table(tbl, val)
for i = 1, #tbl do
if (tbl[i] == val) then
return true
end
end
return false
end
local function create_thumbs()
print("Creating Thumbs!")
for i = 1, #dateTable do
local message = "d="..dateTable[i]
local headers = {
["Content-Length"] = string.len(message),
["Content-Type"] = "application/x-www-form-urlencoded"
}
local b, c, h = fa.request{
url = "http://"..server.."/"..serverDir.."/ct.php",
method = "POST",
headers = headers,
body = message
}
end
print("COMPLETE!")
end
local function upload_file(folder, file, subfolder)
local path = folder .. "/" .. file
-- Open the log file
local outfile = io.open(logfile, "a")
outfile:write(file .. " ... ")
local url = ftpstring..subfolder.."/"..file
local response = fa.ftp("put", url, path)
--print("Uploading", url)
--Check to see if it worked, and log the result!
if response ~= nil then
print("Success!")
outfile:write(" Success!\n")
set_uploaded(path)
if delete_after_upload == true then
print("Deleting " .. file)
outfile:write("Deleting " .. file .. "\n")
sleep(1000)
delete(path)
sleep(1000)
end
else
print(" Fail ")
outfile:write(" Fail\n")
end
--Close our log file
outfile:close()
end
local function sort_upload_table()
if (sortByFileName) then
print("Sorting filenames alphabetically")
table.sort(fileTable, function(a,b)
return a.file>b.file
end)
else
print("Sorting filenames by modded date")
table.sort(fileTable, function(a,b)
return a.sortDate>b.sortDate
end)
end
end
local function run_upload()
print("Starting upload")
for i = 1, #fileTable do
local ft = fileTable[i]
print("Uploading:", ft.folder, ft.file, ft.dateString)
upload_file(ft.folder, ft.file, ft.dateString)
end
create_thumbs()
end
local function walk_directory(folder)
parseThreads = parseThreads+1
for file in lfs.dir(folder) do
local path = folder .. "/" .. file
local skip = string.sub( file, 1, 2 ) == "._"
local attr = lfs.attributes(path)
local dt={}
if (not skip) then
print( "Found "..attr.mode..": " .. path )
if attr.mode == "file" then
local dateString = ""
if (attr.modification~=nil) then
dt = FatDateTimeToTable(attr.modification)
dateString = dt.day.."-"..dt.month.."-"..dt.year
end
if not is_uploaded(path) then
if (not exists_in_table(blackList, dateString)) then
local s,f = true, true
if (jpegsOnly) then
s,f = string.find(string.lower(file), ".jpg")
end
if (s and f) then
fileTable[#fileTable+1] =
{
folder = folder,
file = file,
dateString = dateString,
sortDate=dt.year..dt.month..dt.day..dt.hour..dt.min..dt.sec
}
--upload_file(folder, file, dateString)
end
else
print("Skipping ".. dateString.." - Blacklisted")
end
else
print(path .. " previously uploaded, skipping")
end
elseif attr.mode == "directory" then
print("Entering " .. path)
walk_directory(path)
end
end
end
parseThreads = parseThreads-1
if (parseThreads == 0) then
--create_thumbs()
sort_upload_table()
run_upload()
end
end
local function create_folders(folder)
if (#dateTable==0) then
print("ERROR: DID NOT FIND ANY DATES!")
return
end
for i = 1, #dateTable do
local message = "d="..dateTable[i]
local headers = {
["Content-Length"] = string.len(message),
["Content-Type"] = "application/x-www-form-urlencoded"
}
local b, c, h = fa.request{
url = "http://"..server.."/"..serverDir.."/cd.php",
method = "POST",
headers = headers,
body = message
}
if (b~=nil) then
b = string.gsub(b, "\n", "")
b = string.gsub(b, "\r", "")
end
if (b and b == "success") then
print("SUCCESS FROM SERVER FOR FOLDER:"..dateTable[i].."<<")
else
print("FAILED RESPONSE FROM SERVER FOR FOLDER:"..dateTable[i].."<<")
print("ADDING TO BLACKLIST")
blackList[#blackList+1] = dateTable[i]
end
end
print("OK FTP Starting...")
walk_directory(folder)
end
local function get_folders(folder)
parseThreads = parseThreads+1
local tableCount = 1
--Get the date range from the file
for file in lfs.dir(folder) do
local path = folder .. "/" .. file
local skip = string.sub( file, 1, 2 ) == "._"
local attr = lfs.attributes(path)
if (not skip) then
if (attr.mode == "file") then
print( "Datesearch Found "..attr.mode..": " .. path )
local dateString = ""
if (attr.modification~=nil) then
local dt = FatDateTimeToTable(attr.modification)
dateString = dt.day.."-"..dt.month.."-"..dt.year
end
if (not exists_in_table(dateTable, dateString)) then
dateTable[#dateTable+1] = dateString
end
elseif attr.mode == "directory" then
print("Datesearch Entering " .. path)
get_folders(path)
end
end
end
parseThreads = parseThreads-1
if (parseThreads == 0) then
create_folders(folder)
end
end
-- wait for wifi to connect
while string.sub(fa.ReadStatusReg(),13,13) ~= "a" do
print("Wifi not connected. Waiting...")
sleep(1000)
end
sleep(30*1000)
get_folders(folder)

Computercraft log in system not working with fs API

I'm working on a Windows 8 mock-up OS for Computercraft, and my log in system isn't working. I have been trying to figure it out for the past hour or so and it's really frustrating.
Here's the log in code:
-- Log-in and User Definition Service
--- Variables
userExists = fs.exists("/Users/.config/userConfig.cfg")
termx, termy = term.getSize()
halfx = math.floor(termx*0.5)
halfy = math.floor(termy*0.5)
prompt = "Welcome"
uprompt = "Username: "
pprompt = "Password: "
userConfig = fs.open("/Users/.config/userConfig.cfg", "r")
edituserConfig = fs.open("/Users/.config/userConfig.cfg", "w")
--- Functions
function login(user)
if user == "admin" then
term.setCursorPos(1,1)
term.setTextColor(256)
print (user)
elseif user == "guest" then
print (user)
else
print ("nil")
end
end
function userCheck()
if userExists == true then
term.clear()
term.setBackgroundColor(8)
term.setCursorPos(halfx-0.5*#prompt, halfy - 4)
term.clear()
print (prompt)
term.setCursorPos((halfx-#uprompt), (halfy - 2))
write (uprompt)
term.setCursorPos((halfx-#uprompt), (halfy - 1))
write (pprompt)
term.setCursorPos((halfx), (halfy - 2))
upin = read()
term.setCursorPos((halfx), (halfy - 1))
ppin = read("*")
if upin == userConfig.readLine(21) and ppin == userConfig.readLine(24) then
print ("ADMIN")
elseif upin == userConfig.readLine(33) and ppin == userConfig.readLine(36) then
login("guest")
end
elseif userExists == false then
elseif userExists == nil then
end
end
--- Main
userCheck()
userConfig.cfg:
-- Format as follows:
--
-- (name):
--
-- (prop):
-- "(value)"
--
-- (prop):
-- "(value)"
--
-- (prop):
-- "(value)"
--
--
-- (name):
-- [etc.]
Admin:
user:
"Admin"
pass:
"admin"
auth:
"1"
Guest:
user:
"Admin"
pass:
nil
auth:
"0"
Root:
user:
nil
pass:
nil
auth:
"2"
readLine does not accept arguments and only reads the next line. Your best bet would be to use tables and textutils.serialize to write it all to a file and then when reading use textutils.unserialize to have it inside a table.
Admin:
user:
"Admin"
pass:
"admin"
auth:
"1"
Can be written inside a table such as
{
Admin = {
user = "Admin"
pass = "admin"
auth = "1"
}
Guest = {
user = "Admin"
pass = nil
auth = "0"
}
}
This would work much in the way that you want, and allows for more variability as well as expansion. Of course to read from it is a different story, and i would use a function to find and send either the auth code back, or nil if it didn't work.
Such as
local function findUsers(username,password)
--This will read the file and put all it's data inside a table, and then close it.
local file = fs.open("userConfig.cfg","r")
local userRanks = textutils.unserialize(file.readAll())
file.close()
--To read all the data in a table, i'm going to do this.
for a,v in pairs(userRanks) do
if type(v) == "table" then
if userRanks[a].user == username and userRanks[a].pass == password then
return userRanks[a].auth
end
end
end
--[[If we look through the entire file table, and the username and password aren't the same
as on file, then we say we couldn't find it by returning nil]]--
return nil
end
Now for your input area all you have to do is when they input the username and password just call this afterwards, also if allows you to have the auth code
local auth = findUsers(upin,ppin)
--If they inputted an actual username and password
if auth ~= nil then
--If the auth code from the rank is "1"
if auth == "1" then
--Do whatever stuff you want
elseif auth == "2" then
--Do whatever other stuff for this auth code
end
elseif auth == nil then
print("Oh no you inputted an invalid username and/or password, please try again!"
end
To expand on Dragon53535's answer:
Here's a quick routine I threw together that reads a file into a table:
local function fileToTable(path)
-- first we make sure that the path can be opened
assert(fs.exists(path), path..' does not exist!')
assert(not fs.isDir(path), path..' is a directory!')
local tSrc = {}
local inFile = fs.open(path, 'r')
-- we set line to a non-nil value
local line = ''
-- we continue the loop until line is nil
while line do
-- we read a line from the file
line = inFile.readLine()
-- now we save the value of line to our table
-- line will be nil at EOF
tSrc[#tSrc+1] = line
end
inFile.close()
return tSrc
end
After running userConfig = fileToTable('/Users/.config/userConfig.cfg'), you'd replace something like userConfig.readLine(24) with userConfig[24].
Alternatively, you could check out CC's implementation of the io library. It's a standard Lua library (though in CC it's an fs wrapper), so code can be moved more easily out of CC.
In particular, io.lines() would be helpful here.
The above code rewritten to use io.lines:
local function fileToTable(path)
-- first we make sure that the path can be opened
assert(fs.exists(path), path..' does not exist!')
assert(not fs.isDir(path), path..' is a directory!')
local tSrc = {}
-- iterate over file
-- io.lines is neat, since it opens and closes the file automatically
for line in io.lines(path) do
tSrc[#tSrc+1] = line
end
return tSrc
end
As you can see, this is much smaller (only 9 lines of code!) and more manageable. The reason it's not my preferred solution in CC is that io sits on top of fs, so it's probably better to remove the middleman.
Hope this helps.

Reading gibberish filename (FTP/FSO)

Looking at my server, i see filenames, that theur characters have been messed up.
Example: ôøùú-ô÷åãé-1.mp3
should should be Hebrew letters.
While the files can be read in a browser and FTP, they cannot be read always - for example, in an online audio player, or VBScript FSO (File system object)
is there something that can be done to change the charset or something, so that i can read and then rename these files?
Thanks!
solved, using this link: http://pastebin.com/yXRWDggY
function convertChar(letter)
lat = array("à","á","â","ã","ä","å","æ","ç","è","é","ê","ë","ì","í","î","ï","ð","ñ","ò","ó","ô","õ","ö","÷","ø","ù","ú", " " )
heb = array("א","ב","ג","ד","ה","ו","ז","ח","ט","י","ך","כ","ל","ם","מ","ן","נ","ס","ע","ף","פ","ץ","צ","ק","ר","ש","ת", " ")
inarray = false
for ii = 0 to ubound(heb)
if letter = heb(ii) then
convertChar = lat(ii)
inarray = true
exit for
end if
next
if inarray = false then convertChar = letter
end function

Why is this lua script unable to open a Windows subdirectory?

I'm trying to determine if one of several directories are present from within a lua script. It works on OSX, but not on Windows (linux is currently untested, but I expect that one to work). When the following code runs, I get an error:
failed with this C:\Program Files (x86)\VideoLAN\VLC\lua\playlist\: No such file or directory
I can confirm that that directory exists. I've escaped the slashes, I'm not sure what else could be the issue.
local oses = { "/Applications/VLC.app/Contents/MacOS/share/lua/playlist/"; "C:\\Program Files\\VideoLAN\\VLC\\lua\\playlist\\"; "C:\\Program Files (x86)\\VideoLAN\\VLC\\lua\\playlist\\"; "/usr/lib/vlc/lua/playlist" }
-- Determine which OS this is (and where to find share/lua).
local f,err = io.open( oses[1], "r")
if not err then
opsys = "OSX"
scriptpath = oses[1] .. script
f:close()
else
f,err = io.open( oses[2], "r")
if not err then
opsys = "Win32"
scriptpath = oses[2] .. script
f:close()
else
f,err = io.open( oses[3], "r")
vlc.msg.dbg( dhead .. 'failed with this ' .. err .. dtail )
if not err then
opsys = "Win64"
scriptpath = oses[3] .. script
f:close()
else
f,err = io.open( oses[4], "r")
if not err then
opsys = "Linux/Unix"
scriptpath = oses[4] .. script
f:close()
else
return false
end
end
end
end
The file "C:\Program Files\VideoLAN\VLC\lua\playlist\" does not exist. If you were to remove the trailing slash, you'd be trying to open a directory and probably get a permissions error. It's not going to work either way. If you're going to use this method of determining OS, you should be trying to open files.
For instance, build your script path, try to open that file, and use that to determine pass/fail.
Side note, the structure of your code could be vastly improved. Any time you have a bunch of duplicate code that differs by an index, you should be using a loop. For instance, we can replace your code with this:
local oses = {
["OSX"] = "/Applications/VLC.app/Contents/MacOS/share/lua/playlist/",
["Win32"] = "C:\\Program Files\\VideoLAN\\VLC\\lua\\playlist\\",
["Win64"] = "C:\\Program Files (x86)\\VideoLAN\\VLC\\lua\\playlist\\",
["Linux/Unix"] = "/usr/lib/vlc/lua/playlist",
}
for osname, directory in pairs(oses) do
local scriptpath = directory..script
local f,err = io.open( scriptpath, "r")
if not err then
f:close()
return scriptpath, osname
end
end

Improving Lua error messages

Whenever an error occurs in a Lua script, I'd like it to write the values of all local and global variables to the screen/optionally to a file - in addition to the usual stack trace.
How could I get this to be the default behavior for all errors?
If you're using the standard Lua interpreter, replace debug.traceback with your own function. If you're embedding Lua in your program, use your traceback function in lua_pcall.
The StackTracePlus module does what you want, displaying local variables at each level of the stack trace. It doesn't dump the entire globals table, but that is probably overkill.
To install it with LuaRocks, use
luarocks install stacktraceplus
Then in your code, do:
local STP = require "StackTracePlus"
debug.traceback = STP.stacktrace
In Lua 5.1 this will automatically convert all stack traces; for Lua 5.2 code you need to wrap your code with an xpcall as suggested in other answers.
A more proper solution would be to use xpcall around your whole code.
local function myerrhandler ( errobj )
print(debug.traceback())
for k,v in pairs(_G) do print("GLOBAL:" , k,v) end
return false
end
xpcall( function ()
--Your code here
end , myerrhandler )
Your error handler may be overwritten. If you're calling Lua from C, to always print the stack you can hook in to the luaG_errormsg function.
In lua, write :
local _HandlingError = 0
function _ErrorHandler ( errobj )
if( _HandlingError == 0 ) then
_HandlingError = 1
local errStr = tostring(errobj) or ""
if( type(errobj)=='table' ) then
errStr = "Table: {" .. table.concat(errobj, ',') .. "}"
end
print("Error: \"" .. errStr .. "\"")
--for k,v in pairs(_G) do print("GLOBAL:" , k,v) end
if( type(errobj)=='thread' ) then
print(debug.traceback(errobj))
else
print(debug.traceback('',2))
end
_HandlingError = 0
end
return false
end
Then in ldebug.c, add to luaG_errormsg after if(L->errfunc != 0)
else
{
lua_getfield(L, LUA_GLOBALSINDEX, "_ErrorHandler");
if (!lua_isfunction(L, -1)) {
lua_pop(L, 1);
}
else {
lua_pushvalue(L, 1);
lua_call(L, 2, 1);
lua_pop(L, 1);
}
}

Resources