Rename Selected Source Media.fh_lua

--[[
@Title: Rename Selected Source Media 
@Type: Standard
@Author: Joop van Beek
@Contributors: Calico-Pie
@Version: 1.5
@Keywords: 
@LastUpdated: 03-03-2021
@Licence: This plugin is copyright (c) 2020 Joop van Beek & contributors and is licensed under the MIT License which is hereby incorporated by reference (see https://pluginstore.family-historian.co.uk/fh-plugin-licence)
@Description: This plugin renames the Media records and also the media files (in the Media project folder or external) that are associated with the selected Source records,
so that their names match the Source record title as closely as possible. It will add a numeric suffix to ensure uniqueness if necessary.

Caution:
This plugin renames external Windows media files associated with source records. 'Undo plugin updates' won't restore the original filename.

When renaming a media file that is used in other projects as well, links to that media file in the other projects will no longer work, unless and until you repair them.

@V1.1 Source Title replaced by Source in result set (as suggested by Helen Wright)
@V1.2 Support for accented characters added (advice from Helen Wright and Mike Tate) and code optimization
@V1.3 Convert unsupported accented characters to a close second best and report it in the result set
@V1.4 Change unsupported characters after conversion to ~
@V1.5 Support for accented characters redone by using Microsoft Scripting.FileSystemObject (tip from Helen Wright)
]]

fhInitialise(7,0,0)
fh = require ("fhUtils")

require "luacom"

function main()

	local tFileStatus = {}		-- changes to File name due to e.g. file system limitations (filename to long)
	local tMediaStatus = {}		-- changes to Media name
	local tTitleStatus = {}		-- changes to Media Title in case of illegal chacters for Windows filename
	local tSource = {}			-- source

	local fso    = luacom.CreateObject("Scripting.FileSystemObject")

	local pSource = fhPromptUserForRecordSel('SOUR')
	for i, p in ipairs (pSource) do
		tSource[i] = pSource[i]
		local sTitle, n = cleanTitle(fhGetDisplayText(p))
		if n > 0 then
			tTitleStatus[i] = n .. ' character(s) replaced'
		end

		local pMedia = fhGetItemPtr(p,'~.OBJE')
		if not pMedia or pMedia:IsNull() then
			tMediaStatus[i] = 'no media record'
		end
		while pMedia and pMedia:IsNotNull() do
			local pFile = fhNewItemPtr()
			pFile:MoveTo(pMedia,'~>FILE')
			local oldFileName = fhGetValueAsText(pFile)
			if fso:FileExists(oldFileName) then
				local path,name,ext = splitFilename(oldFileName)
				local newFileName = path .. sTitle .. '.' .. ext
				if oldFileName ~= newFileName then
					local j = 1
					while fso:FileExists(newFileName) do
						j = j + 1
						newFileName = path .. sTitle .. ' #' .. j .. '.' .. ext
					end
					if j > 1 then
						sTitle = sTitle .. ' #' .. j
					end
					local result = fso:MoveFile(oldFileName,newFileName)
					if not result then 
						fhSetValueAsText(pFile,newFileName)
						tFileStatus[i] = 'Renamed'
						local pTitle = fhNewItemPtr()
						pTitle:MoveTo(pFile,'~.TITL')
						if fhGetValueAsText(pTitle) ~= sTitle then
							fhSetValueAsText(pTitle,sTitle)
							tMediaStatus[i] = 'Renamed'
						end
					elseif #newFileName >255 then
						tFileStatus[i] = 'filename too long'
					else
						tFileStatus[i] = 'error: ' .. result
					end
				end
			else
				tFileStatus[i] = 'no media file'
			end
			pMedia:MoveNext('SAME_TAG')
		end
	end

	-- display results
	fhOutputResultSetColumn("Source", "item", tSource, #pSource, 400, "align_left")
	fhOutputResultSetColumn("Media title", "text", tTitleStatus, #pSource, 95, "align_left")
	fhOutputResultSetColumn("Media record", "text", tMediaStatus, #pSource, 80, "align_left")
	fhOutputResultSetColumn("Media file", "text", tFileStatus, #pSource, 80, "align_left")

	fhOutputResultSetTitles("Rename selected source media results")

end

function cleanTitle(sTitle)
--
-- Replace all characters that are invalid for Windows with ~

	local tblList = {'\\','/',':','*','?','|','>','<','"'}
	local n, m = 0
	for i, v in ipairs(tblList) do
		sTitle, m = sTitle:gsub(v, "~")
		n = n + m
	end
	sTitle = sTitle:gsub("~+", "~")
	return sTitle, n
end

function splitFilename(sFilename)
--
-- Returns the Path, Filename, and Extension as 3 values

	return string.match(sFilename, "(.-)([^\\/]-%.?([^%.\\/]*))$")
end

main()

Source:Rename-Selected-Source-Media-4.fh_lua