Skip to content

Commit

Permalink
Add more details to file listings, fix import/migration bugs
Browse files Browse the repository at this point in the history
  • Loading branch information
HEnquist committed Oct 13, 2024
1 parent 80e58ee commit 4a4446c
Show file tree
Hide file tree
Showing 3 changed files with 120 additions and 22 deletions.
39 changes: 30 additions & 9 deletions backend/filemanagement.py
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,8 @@

from camilladsp import CamillaError

from .legacy_config_import import identify_version

DEFAULT_STATEFILE = {
"config_path": None,
"mute": [False, False, False, False, False],
Expand Down Expand Up @@ -63,7 +65,7 @@ async def store_files(folder, request):
return web.Response(text="Saved {} file(s)".format(i))


def list_of_files_in_directory(folder, file_stats=True, title_and_desc=False):
def list_of_files_in_directory(folder, file_stats=True, title_and_desc=False, validator=None):
"""
Return a list of files (name and modification date) in a folder.
"""
Expand All @@ -83,25 +85,44 @@ def list_of_files_in_directory(folder, file_stats=True, title_and_desc=False):
file_data["size"] = getsize(filepath)

if title_and_desc:
valid = False
version = None
errors = None
title = None
desc = None
with open(filepath) as f:
try:
parsed = yaml.safe_load(f)
title = parsed.get("title")
desc = parsed.get("description")
version = identify_version(parsed)
if version == 3 and validator is not None:
parsed_abs = make_config_filter_paths_absolute(parsed, folder)
validator.validate_config(parsed_abs)
error_list = validator.get_errors()
if len(error_list) > 0:
errors = error_list
else:
valid = True
elif version < 3:
valid = False
errors = [([], f"This config is made for the previuos version {version} of CamillaDSP.")]
except yaml.YAMLError as e:
title = "(YAML syntax error)"
desc = "This config file has a YAML syntax error."
if hasattr(e, 'problem_mark'):
mark = e.problem_mark
desc = f"This file has a YAML syntax error on line: {mark.line + 1}, column: {mark.column + 1}"
except (AttributeError, UnicodeDecodeError):
title = "(not a YAML file)"
desc = "This does not appear to be a YAML file."
errordesc = f"This file has a YAML syntax error on line: {mark.line + 1}, column: {mark.column + 1}"
else:
errordesc = "This config file has a YAML syntax error."
errors = [([], errordesc)]
except (AttributeError, UnicodeDecodeError) as e:
errors = [([], "This does not appear to be a YAML file.")]
except Exception as e:
title = "(error reading file)"
desc = f"Error: {e}"
errors = [([], f"Error: {e}")]
file_data["title"] = title
file_data["description"] = desc
file_data["version"] = version
file_data["valid"] = valid
file_data["errors"] = errors
files_list.append(file_data)

sorted_files = sorted(files_list, key=lambda x: x["name"].lower())
Expand Down
97 changes: 85 additions & 12 deletions backend/legacy_config_import.py
Original file line number Diff line number Diff line change
@@ -1,15 +1,16 @@
# v1->v2 introduces the default volume control, remove old volume filters
def _remove_volume_filters(config):
"""
Remove any Volume filter
Remove any Volume filter without a "fader" parameter
"""
if "filters" in config:
if "filters" in config and isinstance(config["filters"], dict):
volume_names = []
for name, params in list(config["filters"].items()):
if params["type"] == "Volume":
if params["type"] == "Volume" and "fader" not in params["parameters"]:
volume_names.append(name)
del config["filters"][name]

if "pipeline" in config:
if "pipeline" in config and isinstance(config["pipeline"], list):
for step in list(config["pipeline"]):
if step["type"] == "Filter":
step["names"] = [
Expand All @@ -18,12 +19,12 @@ def _remove_volume_filters(config):
if len(step["names"]) == 0:
config["pipeline"].remove(step)


# v1->v2 removes "ramp_time" from loudness filters
def _modify_loundness_filters(config):
"""
Modify Loudness filters
"""
if "filters" in config:
if "filters" in config and isinstance(config["filters"], dict):
for name, params in config["filters"].items():
if params["type"] == "Loudness":
if "ramp_time" in params["parameters"]:
Expand All @@ -32,6 +33,7 @@ def _modify_loundness_filters(config):
params["parameters"]["attenuate_mid"] = False


# v1->v2 changes the resampler config
def _modify_resampler(config):
"""
Update the resampler config
Expand Down Expand Up @@ -88,11 +90,12 @@ def _modify_devices(config):
if "playback" in config["devices"]:
dev = config["devices"]["playback"]
_modify_coreaudio_device(dev)
_modify_file_playback_device(dev)

# Resampler
_modify_resampler(config)


# v1->v2 removes the "change_format" and makes "format" optional
def _modify_coreaudio_device(dev):
if dev["type"] == "CoreAudio":
if "change_format" in dev:
Expand All @@ -102,14 +105,19 @@ def _modify_coreaudio_device(dev):
else:
dev["format"] = None

# vx-vx changes some of the file playback types
def _modify_file_playback_device(dev):
if dev["type"] == "File":
dev["type"] = "RawFile"

# v1->v2 changes some names for dither filters
def _modify_dither(config):
"""
Update Dither filters, some names have changed.
Uniform -> Flat
Simple -> Highpass
"""
if "filters" in config:
if "filters" in config and isinstance(config["filters"], dict):
for _name, params in config["filters"].items():
if params["type"] == "Dither":
if params["parameters"]["type"] == "Uniform":
Expand All @@ -131,11 +139,14 @@ def _fix_rew_pipeline(config):
config["pipeline"] = [pipeline]


# v2->v3 changes scalar "channel" to array "channels"
def _modify_pipeline_filter_steps(config):
for step in config.get("pipeline", []):
if step["type"] == "Filter":
step["channels"] = [step["channel"]]
del step["channel"]
if "pipeline" in config and isinstance(config["pipeline"], list):
for step in config["pipeline"]:
if step["type"] == "Filter":
if "channel" in step:
step["channels"] = [step["channel"]]
del step["channel"]


def migrate_legacy_config(config):
Expand All @@ -149,3 +160,65 @@ def migrate_legacy_config(config):
_modify_dither(config)
_modify_devices(config)
_modify_pipeline_filter_steps(config)


def _look_for_v1_volume(config):
if "filters" in config and isinstance(config["filters"], dict):
for name, params in list(config["filters"].items()):
if params["type"] == "Volume" and "fader" not in params["parameters"]:
return True
return False

def _look_for_v1_loudness(config):
if "filters" in config and isinstance(config["filters"], dict):
for name, params in config["filters"].items():
if params["type"] == "Loudness" and "ramp_time" in params["parameters"]:
return True
return False

def _look_for_v1_resampler(config):
return "devices" in config and "enable_resampling" in config["devices"]

def _look_for_v1_devices(config):
if "devices" in config:
for direction in ("capture", "playback"):
if direction in config["devices"] and "type" in config["devices"][direction]:
if config["devices"][direction]["type"] == "CoreAudio" and "change_format" in config["devices"][direction]:
return True
return False

def _look_for_v2_devices(config):
return "devices" in config and "capture" in config["devices"] and config["devices"]["capture"]["type"] == "File"

def _look_for_v1_dither(config):
if "filters" in config and isinstance(config["filters"], dict):
for _name, params in config["filters"].items():
if params["type"] == "Dither":
if params["parameters"]["type"] in ("Uniform", "Simple"):
return True
return False

def _look_for_v2_pipeline(config):
if "pipeline" in config and isinstance(config["pipeline"], list):
for step in config["pipeline"]:
if step["type"] == "Filter":
if "channel" in step:
return True
return False

def identify_version(config):
if _look_for_v1_volume(config):
return 1
if _look_for_v1_loudness(config):
return 1
if _look_for_v1_resampler(config):
return 1
if _look_for_v1_devices(config):
return 1
if _look_for_v1_dither(config):
return 1
if _look_for_v2_pipeline(config):
return 2
if _look_for_v2_devices(config):
return 2
return 3
6 changes: 5 additions & 1 deletion backend/views.py
Original file line number Diff line number Diff line change
Expand Up @@ -428,11 +428,14 @@ async def get_config_file(request):
"""
config_dir = request.app["config_dir"]
config_name = request.query["name"]
migrate = request.query.get("migrate", False)
config_file = path_of_configfile(request, config_name)
try:
config_object = make_config_filter_paths_relative(
read_yaml_from_path_to_object(request, config_file), config_dir
)
if migrate:
migrate_legacy_config(config_object)
except CamillaError as e:
raise web.HTTPInternalServerError(text=str(e))
return web.json_response(config_object, headers=HEADERS)
Expand Down Expand Up @@ -564,7 +567,8 @@ async def get_stored_configs(request):
Fetch a list of config files in config_dir.
"""
config_dir = request.app["config_dir"]
configs = list_of_files_in_directory(config_dir, title_and_desc=True)
validator = request.app["VALIDATOR"]
configs = list_of_files_in_directory(config_dir, title_and_desc=True, validator=validator)
return web.json_response(configs, headers=HEADERS)


Expand Down

0 comments on commit 4a4446c

Please sign in to comment.