forked from Mirrors/openclonk
167 lines
5.7 KiB
Python
167 lines
5.7 KiB
Python
#! /usr/bin/env python
|
|
|
|
import fnmatch
|
|
import os
|
|
import sys
|
|
import re
|
|
|
|
|
|
###############
|
|
## functions ##
|
|
###############
|
|
|
|
|
|
# converts a sound path to a name string
|
|
def sound_path_to_name(sound_path):
|
|
sound_name = os.path.splitext(os.path.basename(sound_path))[0]
|
|
dir_name = os.path.dirname(sound_path)
|
|
# sound is inside an object definition: return DEF::NAME
|
|
if fnmatch.fnmatch(dir_name, '*.ocd'):
|
|
return get_namespace_ocd(dir_name) + sound_name
|
|
# sound is inside a .ocg folder: return FOLDER::NAME
|
|
if fnmatch.fnmatch(dir_name, '*.ocg'):
|
|
return get_namespace_ocg(dir_name) + sound_name
|
|
# sound is inside a .ocs or .ocs folder: return NAME
|
|
if fnmatch.fnmatch(dir_name, '*.ocs') or fnmatch.fnmatch(dir_name, '*.ocf'):
|
|
return sound_name
|
|
# return a warning, this should not happen
|
|
return "Warning: sound found in illegal location (i.e. not in scenario, scenario folder, Sound.ocg folder or subfolerd, object definition."
|
|
|
|
# gets the sound namespace of object definition
|
|
def get_namespace_ocd(ocd_path):
|
|
if not os.path.isfile(os.path.join(ocd_path, "DefCore.txt")):
|
|
return "NOTFOUND::"
|
|
with open(os.path.join(ocd_path, "DefCore.txt"), "r") as read_defcore:
|
|
for line in read_defcore:
|
|
if "id=" in line:
|
|
return str(line).split('=')[-1].replace('\n', '') + "::"
|
|
return "NOTFOUND::"
|
|
|
|
# gets the sound namespace of an ocg folder
|
|
def get_namespace_ocg(ocg_path):
|
|
dirname = ocg_path
|
|
namespace = ""
|
|
while not fnmatch.fnmatch(dirname, '*Sound.ocg') and not fnmatch.fnmatch(dirname, '*Music.ocg'):
|
|
basename = os.path.basename(dirname)
|
|
dirname = os.path.dirname(dirname)
|
|
namespace = os.path.splitext(basename)[0] + "::" + namespace
|
|
return namespace
|
|
|
|
# finds all sound calls in a script file
|
|
def find_sound_calls_script(script_file):
|
|
with open(script_file, "r") as read_script:
|
|
script = read_script.read()
|
|
# regular call: Sound("FooBar")
|
|
calls = re.findall('Sound\(\s*.*\)', script)
|
|
calls = (str(re.sub('Sound\(\s*"', '', call).split('"')[0]) for call in calls)
|
|
# regular call: SoundAt("FooBar")
|
|
callsat = re.findall('SoundAt\(\s*.*\)', script)
|
|
callsat = (str(re.sub('SoundAt\(\s*"', '', call).split('"')[0]) for call in callsat)
|
|
# ActMap property: Sound = "FooBar"
|
|
actprops = re.findall('Sound\s*=\s*.*\n', script)
|
|
actprops = (str(re.sub('Sound\s*=\s*"', '', prop).split('"')[0]) for prop in actprops)
|
|
all_calls = []
|
|
for call in calls:
|
|
all_calls.append(call)
|
|
for call in callsat:
|
|
all_calls.append(call)
|
|
for prop in actprops:
|
|
all_calls.append(prop)
|
|
return all_calls
|
|
|
|
# finds all sound calls in a source file
|
|
def find_sound_calls_source(source_file):
|
|
with open(source_file, "r") as read_source:
|
|
source = read_source.read()
|
|
calls = re.findall('GUISound\(.*\)|StartSoundEffectAt\(.*\)|StartSoundEffect\(.*\)', source)
|
|
calls = (call.replace('GUISound("', '').replace('StartSoundEffectAt("', '').replace('StartSoundEffect("', '').split('"')[0] for call in calls)
|
|
return calls
|
|
|
|
|
|
#############
|
|
## program ##
|
|
#############
|
|
|
|
|
|
# program arguments: planet directory and source directory
|
|
planet_dir = "../planet"
|
|
source_dir = "../src"
|
|
if len(sys.argv) >= 2:
|
|
planet_dir = sys.argv[1]
|
|
if len(sys.argv) >= 3:
|
|
source_dir = sys.argv[2]
|
|
|
|
# find all sound and script files in planet
|
|
sound_files = []
|
|
script_files = []
|
|
for root, directories, filenames in os.walk(planet_dir):
|
|
for filename in filenames:
|
|
full_filename = os.path.join(root, filename)
|
|
# get the sound files
|
|
if fnmatch.fnmatch(full_filename, '*.ogg') or fnmatch.fnmatch(full_filename, '*.wav'):
|
|
sound_files.append(full_filename)
|
|
# get the script files
|
|
if fnmatch.fnmatch(full_filename, '*.c'):
|
|
script_files.append(full_filename)
|
|
|
|
# remove music files from sound files
|
|
sound_files[:] = (sound_path for sound_path in sound_files if not fnmatch.fnmatch(sound_path, '*Music.ocg*'))
|
|
|
|
# find all engine files in source
|
|
source_files = []
|
|
for root, directories, filenames in os.walk(source_dir):
|
|
for filename in filenames:
|
|
full_filename = os.path.join(root, filename)
|
|
# get the source files
|
|
if fnmatch.fnmatch(full_filename, '*.cpp') or fnmatch.fnmatch(full_filename, '*.h'):
|
|
source_files.append(full_filename)
|
|
|
|
|
|
# get all sound calls from the script and the source files
|
|
sound_calls_script = []
|
|
for script in script_files:
|
|
for call in find_sound_calls_script(script):
|
|
sound_calls_script.append(call)
|
|
sound_calls_source = []
|
|
for source in source_files:
|
|
for call in find_sound_calls_source(source):
|
|
sound_calls_source.append(call)
|
|
|
|
# check for all found sound files if there is an occurence in the script
|
|
print "Looking for unused sounds in the planet directory: \n\t", planet_dir
|
|
print "WARNING: always double check if the sound really is not played by searching for the sound name in all engine and script files."
|
|
print "\nChecking", len(sound_files), "sound files ..."
|
|
cnt_unused_sounds = 0
|
|
for sound_path in sound_files:
|
|
sound = sound_path_to_name(sound_path)
|
|
found = False
|
|
for call in sound_calls_script + sound_calls_source:
|
|
if fnmatch.fnmatch(sound, call):
|
|
found = True
|
|
break
|
|
if not found:
|
|
cnt_unused_sounds += 1
|
|
print sound_path + " (" + sound + ")" + " has not been found"
|
|
print "Out of the", len(sound_files), "found sound files, the above", cnt_unused_sounds, "may be unused."
|
|
|
|
|
|
|
|
# script for finding non-normal calls to sound only turn on if needed
|
|
if False:
|
|
for script_file in script_files:
|
|
with open(script_file, "r") as read_script:
|
|
script = read_script.read()
|
|
calls = re.findall('Sound\(\s*.*\)', script)
|
|
for call in calls:
|
|
if re.search('Sound\(\s*"', call) is None:
|
|
print call
|
|
calls = re.findall('SoundAt\(\s*.*\)', script)
|
|
for call in calls:
|
|
if re.search('SoundAt\(\s*"', call) is None:
|
|
print call
|
|
calls = re.findall('Sound\s*=\s*.*', script)
|
|
for call in calls:
|
|
if re.search('Sound\s*=\s*".*".*', call) is None:
|
|
print call
|
|
|