summaryrefslogtreecommitdiff
path: root/tools/audio/extraction/extraction_xml.py
blob: 4cdc816f4e4be49a56a939849c9e6be6e835979b (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
# SPDX-FileCopyrightText: © 2024 ZeldaRET
# SPDX-License-Identifier: CC0-1.0
#
#
#

from xml.etree import ElementTree
from xml.etree.ElementTree import Element

from .util import error

class ExtractionDescription:

    def __init__(self, file_path : str, file_name : str, version_name : str) -> None:
        self.type_name = type(self).__name__.replace("ExtractionDescription", "")
        self.file_name = file_name.replace(".xml", "")
        self.file_path = file_path

        xml_root = ElementTree.parse(file_path).getroot()
        if xml_root.tag != self.type_name or "Name" not in xml_root.attrib or "Index" not in xml_root.attrib:
            error(f"Malformed {self.type_name} extraction xml: \"{file_path}\"")

        self.name = xml_root.attrib["Name"]
        self.index = int(xml_root.attrib["Index"])

        self.post_init(xml_root, version_name)

    def post_init(self, xml_root : Element, version_name : str):
        raise NotImplementedError() # Implement in subclass

    def in_version(self, version_include, version_exclude, version_name : str):
        if version_include == "":
            version_include = "All"
        if version_exclude == "":
            version_exclude = "None"

        # Determine if this layout is the one we need
        if version_include != "All":
            version_include = version_include.split(",")
        if version_exclude != "None":
            version_exclude = version_exclude.split(",")

        included = version_include == "All" or version_name in version_include
        excluded = version_exclude != "None" and version_name in version_exclude

        return included and not excluded

class SampleBankExtractionDescription(ExtractionDescription):

    def post_init(self, xml_root : Element, version_name : str):
        self.included_version = None
        self.sample_info = []
        self.sample_info_versions = []
        self.blob_info = []

        for item in xml_root:
            if item.tag == "Sample":
                version_include = item.attrib.get("VersionInclude", "")
                version_exclude = item.attrib.get("VersionExclude", "")
                in_version = self.in_version(version_include, version_exclude, version_name)
                if in_version:
                    self.sample_info.append(item.attrib)
                self.sample_info_versions.append((item.tag, item.attrib, in_version))
            elif item.tag == "Blob":
                version_include = item.attrib.get("VersionInclude", "")
                version_exclude = item.attrib.get("VersionExclude", "")
                in_version = self.in_version(version_include, version_exclude, version_name)
                if in_version:
                    self.blob_info.append(item.attrib)
                self.sample_info_versions.append((item.tag, item.attrib, in_version))
            else:
                print(xml_root.attrib)
                assert False, item.tag

class SoundFontExtractionDescription(ExtractionDescription):

    def post_init(self, xml_root : Element, version_name : str):
        self.envelopes_info = []
        self.instruments_info = {}
        self.drums_info = []
        self.effects_info = []
        self.envelopes_info_versions = []
        self.instruments_info_versions = []
        self.drums_info_versions = []
        self.effects_info_versions = []
        
        for item in xml_root:
            if item.tag == "Envelopes":
                for env in item:
                    assert env.tag == "Envelope"

                    version_include = env.attrib.get("VersionInclude", "")
                    version_exclude = env.attrib.get("VersionExclude", "")
                    in_version = self.in_version(version_include, version_exclude, version_name)
                    if in_version:
                        self.envelopes_info.append(env.attrib["Name"])
                    self.envelopes_info_versions.append((env.attrib, in_version))
            elif item.tag == "Instruments":
                for instr in item:
                    assert instr.tag == "Instrument"
                    prg_num = int(instr.attrib["ProgramNumber"])

                    version_include = instr.attrib.get("VersionInclude", "")
                    version_exclude = instr.attrib.get("VersionExclude", "")
                    in_version = self.in_version(version_include, version_exclude, version_name)
                    if in_version:
                        self.instruments_info[prg_num] = instr.attrib["Name"]
                    self.instruments_info_versions.append((instr.attrib, in_version))
            elif item.tag == "Drums":
                for drum in item:
                    assert drum.tag == "Drum"

                    version_include = drum.attrib.get("VersionInclude", "")
                    version_exclude = drum.attrib.get("VersionExclude", "")
                    in_version = self.in_version(version_include, version_exclude, version_name)
                    if in_version:
                        self.drums_info.append(drum.attrib["Name"])
                    self.drums_info_versions.append((drum.attrib, in_version))
            elif item.tag == "Effects":
                for effect in item:
                    assert effect.tag == "Effect"

                    version_include = effect.attrib.get("VersionInclude", "")
                    version_exclude = effect.attrib.get("VersionExclude", "")
                    in_version = self.in_version(version_include, version_exclude, version_name)
                    if in_version:
                        self.effects_info.append(effect.attrib["Name"])
                    self.effects_info_versions.append((effect.attrib, in_version))
            else:
                assert False, item.tag

class SequenceExtractionDescription(ExtractionDescription):

    def post_init(self, xml_root : Element, version_name : str):
        pass