File: patchichi_export.py

package info (click to toggle)
raysession 0.17.2-1
  • links: PTS, VCS
  • area: main
  • in suites: forky, sid
  • size: 19,168 kB
  • sloc: python: 44,371; sh: 1,538; makefile: 208; xml: 86
file content (185 lines) | stat: -rw-r--r-- 6,755 bytes parent folder | download
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
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
import logging
import operator
from pathlib import Path

from typing import TYPE_CHECKING, Any
from .bases.port import Port
from .bases.elements import JackPortFlag
from patshared import PortType, PortMode, from_json_to_str

if TYPE_CHECKING:
    from .patchbay_manager import PatchbayManager

_logger = logging.getLogger(__name__)


def _export_port_list_to_patchichi(mng: 'PatchbayManager') -> str:
    def slcol(input_str: str) -> str:
        return input_str.replace(':', '\\:')
    
    contents = ''

    gps_and_ports = list[tuple[str, list[Port]]]()
    for group in mng.groups:
        for port in group.ports:
            if port.type is PortType.MIDI_ALSA:
                group_name = port.full_name.split(':')[4]
            else:
                group_name = port.full_name.partition(':')[0]

            for gp_name, gp_port_list in gps_and_ports:
                if gp_name == group_name:
                    gp_port_list.append(port)
                    break
            else:
                gps_and_ports.append((group_name, [port]))

    for group_name, port_list in gps_and_ports:
        port_list.sort(key=operator.attrgetter('port_id'))
            
    for group_name, port_list in gps_and_ports:
        gp_written = False              
        last_type_and_mode = (PortType.NULL, PortMode.NULL)
        physical = False
        terminal = False
        monitor = False
        pg_name = ''
        signal_type = ''

        for port in port_list:
            if not gp_written:
                contents += f'\n::{group_name}\n'
                gp_written = True

                group = mng.get_group_from_name(group_name)
                if group is not None:
                    group_attrs = list[str]()
                    if group.client_icon:
                        group_attrs.append(
                            f'CLIENT_ICON={slcol(group.client_icon)}')
                        
                    if group.mdata_icon:
                        group_attrs.append(
                            f'ICON_NAME={slcol(group.mdata_icon)}')

                    if group.has_gui:
                        if group.gui_visible:
                            group_attrs.append('GUI_VISIBLE')
                        else:
                            group_attrs.append('GUI_HIDDEN')
                    if group_attrs:
                        contents += ':'
                        contents += '\n:'.join(group_attrs)
                        contents += '\n'

            if port.flags & JackPortFlag.IS_PHYSICAL:
                if not physical:
                    contents += ':PHYSICAL\n'
                    physical = True
            elif physical:
                contents += ':~PHYSICAL\n'
                physical = False

            if last_type_and_mode != (port.type, port.mode):
                if port.type is PortType.AUDIO_JACK:
                    if port.flags & JackPortFlag.IS_CONTROL_VOLTAGE:
                        contents += ':CV'
                    else:
                        contents += ':AUDIO'
                elif port.type is PortType.MIDI_JACK:
                    contents += ':MIDI'
                elif port.type is PortType.MIDI_ALSA:
                    contents += ':ALSA'

                contents += f':{port.mode.name}\n'
                last_type_and_mode = (port.type, port.mode)
            
            if port.mdata_signal_type != signal_type:
                if port.mdata_signal_type:
                    contents += \
                        f':SIGNAL_TYPE={slcol(port.mdata_signal_type)}\n'
                else:
                    contents += ':~SIGNAL_TYPE\n'
            
            if port.mdata_portgroup != pg_name:
                if port.mdata_portgroup:
                    contents += \
                        f':PORTGROUP={slcol(port.mdata_portgroup)}\n'
                else:
                    contents += ':~PORTGROUP\n'
                pg_name = port.mdata_portgroup

            if port.type is PortType.MIDI_ALSA:
                port_short_name = ':'.join(port.full_name.split(':')[5:])
            else:
                port_short_name = port.full_name.partition(':')[2]

            contents += f'{port_short_name}\n'
            
            if port.mdata_pretty_name or port.order:
                port_attrs = list[str]()
                if port.mdata_pretty_name:
                    port_attrs.append(f'PRETTY_NAME={slcol(port.mdata_pretty_name)}')
                if port.order:
                    port_attrs.append(f'ORDER={port.order}')
                contents += ':'
                contents += '\n:'.join(port_attrs)
                contents += '\n'

    return contents

def export_to_patchichi_json(
        mng: 'PatchbayManager', path: Path, editor_text='') -> bool:
    if not editor_text:
        editor_text = _export_port_list_to_patchichi(mng)

    file_dict = dict[str, Any]()
    file_dict['VERSION'] = (0, 3)       
    file_dict['editor_text'] = editor_text
    file_dict['connections'] = [
        (c.port_out.full_name, c.port_in.full_name)
        for c in mng.connections]

    file_dict['views'] = mng.views.to_json_list()

    # save specific portgroups json dict
    # because we save only portgroups with present ports
    portgroups_dict = dict[str, dict[str, dict[str, dict]]]()

    for port_type, ptype_dict in mng.portgroups_memory.items():
        if port_type.name is None:
            continue

        portgroups_dict[port_type.name] = js_ptype_dict = {}
        for gp_name, group_dict in ptype_dict.items():
            js_ptype_dict[gp_name] = {}
            group = mng.get_group_from_name(gp_name)
            if group is None:
                continue

            for port_mode, pmode_list in group_dict.items():
                pg_list = js_ptype_dict[gp_name][port_mode.name] = []
                for pg_mem in pmode_list:
                    one_port_found = False

                    for port_str in pg_mem.port_names:
                        for port in group.ports:
                            if (port.type is port_type
                                    and port.mode is port_mode
                                    and port.short_name == port_str):
                                pg_list.append(pg_mem.as_new_dict())
                                one_port_found = True
                                break
                        
                        if one_port_found:
                            break

    file_dict['portgroups'] = portgroups_dict

    try:
        with open(path, 'w') as f:
            f.write(from_json_to_str(file_dict))
        return True
    except Exception as e:
        _logger.error(f'Failed to save patchichi file: {str(e)}')
        return False