summaryrefslogtreecommitdiff
path: root/gui.py
blob: 33c8d6da74fec1601212bf24fa8840789376dbfd (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
136
137
138
139
140
141
142
143
144
145
146
import gi

gi.require_version('Gtk', '3.0')
import logging

from gi.repository import GObject, Gtk, Gdk

BUTTON_SPACING = 10


class PyATEMSwitcherGui():
    def __init__(self, config, switcher):
        self.log = logging.getLogger('GUI')
        self.config = config

        cssProvider = Gtk.CssProvider()
        cssProvider.load_from_path('style.css')
        screen = Gdk.Screen.get_default()
        styleContext = Gtk.StyleContext()
        styleContext.add_provider_for_screen(
            screen,
            cssProvider,
            Gtk.STYLE_PROVIDER_PRIORITY_USER,
        )

        self.window = Gtk.Window()
        self.window.connect("destroy", self._exit)

        self.window.set_wmclass('pygtk-atem-switcher', 'PyGTK-ATEM-Switcher')

        self.switcher = switcher
        self.switcher.on_connect(self._switcher_connected)
        self.switcher.on_connect_attempt(self._switcher_connect_attempt)
        self.switcher.on_disconnect(self._switcher_disconnected)

        self.switcher.on_connect(self._switcher_state_changed)
        self.switcher.on_receive(self._switcher_state_changed)

        self.window.set_border_width(BUTTON_SPACING)

        self.header = Gtk.HeaderBar()
        self.header.props.title = 'PyATEMSwitcherGui: Idle'
        self.window.set_titlebar(self.header)

        self.box = None
        self.buttons = {}

    def _exit(self, *args, **kwargs):
        self.switcher.disconnect()
        Gtk.main_quit(*args, **kwargs)

    def _button_clicked(self, button, name):
        self.log.info(f'Button {name} was pressed')
        for btn in self.buttons:
            ctx = self.buttons[btn][0].get_style_context()
            if btn == name:
                self.log.debug(f'{btn}.add_class("selected")')
                ctx.add_class('selected')
                self.switcher.trans(self.buttons[btn][1])
            else:
                self.log.debug(f'{btn}.remove_class("selected")')
                ctx.remove_class('selected')

    def _switcher_connected(self, params):
        switcher = params['switcher']
        log = logging.getLogger('GUI connected')

        log.debug(f'_switcher_connected({params})')
        log.info(f'Connected to "{switcher.atemModel}" @ {switcher.ip}')
        self.header.props.title = f'{switcher.atemModel} @ {switcher.ip}'

        inputs = {}
        for idx,i in enumerate(switcher.inputProperties):
            if not i.shortName:
                break
            if i.shortName.lower() in ('-', 'empty', 'x'):
                continue
            if f'in_{i.shortName}' in self.buttons:
                log.warning(f'ignoring duplicate button {i.shortName)')
                continue
            log.debug(f'Creating Button for {i.shortName} of type {i.externalPortType}: {i.longName}')
            btn = Gtk.Button.new_with_label(
                i.longName
            )
            btn.connect(
                'clicked',
                self._button_clicked,
                f'in_{i.shortName}',
            )
            log.debug(f'Adding {i.shortName} to FlowBox')
            self.buttons[f'in_{i.shortName}'] = (btn, idx)
            inputs.setdefault(str(i.externalPortType), []).append(btn)

        log.debug('Creating vertically stacked box as container')
        self.box = Gtk.VBox(spacing=BUTTON_SPACING)

        for input_type in ('hdmi', 'sdi', 'internal'):
            if input_type not in inputs:
                continue

            for btn in inputs[input_type]:
                self.box.pack_start(btn, True, True, 0)

        log.debug('All buttons added, adding box to window')
        self.window.add(self.box)
        self.window.show_all()
        self.log.debug('done')

    def _switcher_connect_attempt(self, params):
        self.header.props.title = 'PyATEMSwitcherGui: Connecting ...'

    def _switcher_disconnected(self, params):
        if self.box is not None:
            self.window.remove(self.box)
        self.box = None
        self.buttons = {}
        self.header.props.title = 'PyATEMSwitcherGui: Not connected'

    def _switcher_state_changed(self, params):
        cmd = params.get('cmd', 'PrgI')

        if cmd in ('PrgI', 'PrvI'):
            pgm = params['switcher'].programInput[0].videoSource
            prv = params['switcher'].previewInput[0].videoSource
            pgm_n = params['switcher'].inputProperties[pgm].shortName
            prv_n = params['switcher'].inputProperties[prv].shortName
            for btn in self.buttons:
                ctx = self.buttons[btn][0].get_style_context()
                if btn == f'in_{pgm_n}':
                    ctx.add_class('program')
                else:
                    ctx.remove_class('program')
                if btn == f'in_{prv_n}' and pgm != prv:
                    ctx.add_class('preview')
                else:
                    ctx.remove_class('preview')
                ctx.remove_class('selected')
        elif cmd == 'TrPs' and params['switcher'].transition[0].position == 0:
            for btn in self.buttons:
                ctx = self.buttons[btn][0].get_style_context()
                ctx.remove_class('preview')

    def main_loop(self):
        self.switcher.connect()
        self.window.show_all()
        Gtk.main()