~martijnbraam/pyatem

fb58f8d69f292775b3809214854fe374a26d7a70 — Martijn Braam 5 months ago 6a725f9 me_merge
WIP
A gtk_switcher/ui/preferences.ui~ => gtk_switcher/ui/preferences.ui~ +731 -0
@@ 0,0 1,731 @@
<?xml version="1.0" encoding="UTF-8"?>
<!-- Generated with glade 3.38.2 -->
<interface>
  <requires lib="gtk+" version="3.24"/>
  <requires lib="libhandy" version="0.0"/>
  <object class="HdyApplicationWindow" id="window">
    <property name="can-focus">False</property>
    <property name="title" translatable="yes">Preferences</property>
    <child>
      <object class="GtkBox">
        <property name="visible">True</property>
        <property name="can-focus">False</property>
        <property name="orientation">vertical</property>
        <child>
          <object class="HdyHeaderBar">
            <property name="visible">True</property>
            <property name="can-focus">False</property>
            <property name="title" translatable="yes">Preferences</property>
            <property name="show-close-button">True</property>
            <child type="title">
              <object class="HdyViewSwitcher">
                <property name="visible">True</property>
                <property name="can-focus">False</property>
                <property name="stack">mainstack</property>
              </object>
            </child>
            <child>
              <placeholder/>
            </child>
          </object>
          <packing>
            <property name="expand">False</property>
            <property name="fill">True</property>
            <property name="position">0</property>
          </packing>
        </child>
        <child>
          <object class="GtkStack" id="mainstack">
            <property name="visible">True</property>
            <property name="can-focus">False</property>
            <child>
              <object class="GtkBox" id="settings_switcher">
                <property name="visible">True</property>
                <property name="can-focus">False</property>
                <property name="orientation">vertical</property>
                <child>
                  <object class="GtkStackSwitcher">
                    <property name="visible">True</property>
                    <property name="can-focus">False</property>
                    <property name="margin-start">8</property>
                    <property name="margin-end">8</property>
                    <property name="margin-top">8</property>
                    <property name="margin-bottom">8</property>
                    <property name="stack">settingsstack</property>
                  </object>
                  <packing>
                    <property name="expand">False</property>
                    <property name="fill">True</property>
                    <property name="position">0</property>
                  </packing>
                </child>
                <child>
                  <object class="HdyClamp">
                    <property name="visible">True</property>
                    <property name="can-focus">False</property>
                    <child>
                      <object class="GtkStack" id="settingsstack">
                        <property name="visible">True</property>
                        <property name="can-focus">False</property>
                        <child>
                          <object class="GtkBox" id="page_general">
                            <property name="visible">True</property>
                            <property name="can-focus">False</property>
                            <property name="orientation">vertical</property>
                            <child>
                              <object class="GtkLabel">
                                <property name="visible">True</property>
                                <property name="can-focus">False</property>
                                <property name="halign">start</property>
                                <property name="margin-bottom">4</property>
                                <property name="label" translatable="yes">Video</property>
                                <style>
                                  <class name="heading"/>
                                </style>
                              </object>
                              <packing>
                                <property name="expand">False</property>
                                <property name="fill">True</property>
                                <property name="position">0</property>
                              </packing>
                            </child>
                            <child>
                              <object class="GtkFrame">
                                <property name="visible">True</property>
                                <property name="can-focus">False</property>
                                <property name="margin-bottom">16</property>
                                <property name="label-xalign">0</property>
                                <property name="shadow-type">in</property>
                                <child>
                                  <!-- n-columns=2 n-rows=4 -->
                                  <object class="GtkGrid">
                                    <property name="visible">True</property>
                                    <property name="can-focus">False</property>
                                    <property name="row-spacing">8</property>
                                    <property name="column-spacing">8</property>
                                    <child>
                                      <object class="GtkLabel">
                                        <property name="visible">True</property>
                                        <property name="can-focus">False</property>
                                        <property name="halign">end</property>
                                        <property name="label" translatable="yes">Video standard</property>
                                        <style>
                                          <class name="dim-label"/>
                                        </style>
                                      </object>
                                      <packing>
                                        <property name="left-attach">0</property>
                                        <property name="top-attach">0</property>
                                      </packing>
                                    </child>
                                    <child>
                                      <object class="GtkLabel">
                                        <property name="visible">True</property>
                                        <property name="can-focus">False</property>
                                        <property name="halign">end</property>
                                        <property name="label" translatable="yes">Multiview video standard</property>
                                        <style>
                                          <class name="dim-label"/>
                                        </style>
                                      </object>
                                      <packing>
                                        <property name="left-attach">0</property>
                                        <property name="top-attach">1</property>
                                      </packing>
                                    </child>
                                    <child>
                                      <object class="GtkLabel">
                                        <property name="visible">True</property>
                                        <property name="can-focus">False</property>
                                        <property name="halign">end</property>
                                        <property name="label" translatable="yes">Down convert as</property>
                                        <style>
                                          <class name="dim-label"/>
                                        </style>
                                      </object>
                                      <packing>
                                        <property name="left-attach">0</property>
                                        <property name="top-attach">2</property>
                                      </packing>
                                    </child>
                                    <child>
                                      <object class="GtkLabel">
                                        <property name="visible">True</property>
                                        <property name="can-focus">False</property>
                                        <property name="halign">end</property>
                                        <property name="label" translatable="yes">SDI output standard</property>
                                        <style>
                                          <class name="dim-label"/>
                                        </style>
                                      </object>
                                      <packing>
                                        <property name="left-attach">0</property>
                                        <property name="top-attach">3</property>
                                      </packing>
                                    </child>
                                    <child>
                                      <placeholder/>
                                    </child>
                                    <child>
                                      <placeholder/>
                                    </child>
                                    <child>
                                      <placeholder/>
                                    </child>
                                    <child>
                                      <placeholder/>
                                    </child>
                                  </object>
                                </child>
                                <child type="label_item">
                                  <placeholder/>
                                </child>
                                <style>
                                  <class name="view"/>
                                </style>
                              </object>
                              <packing>
                                <property name="expand">False</property>
                                <property name="fill">True</property>
                                <property name="position">1</property>
                              </packing>
                            </child>
                            <child>
                              <object class="GtkLabel">
                                <property name="visible">True</property>
                                <property name="can-focus">False</property>
                                <property name="halign">start</property>
                                <property name="margin-bottom">4</property>
                                <property name="label" translatable="yes">Media pool</property>
                                <style>
                                  <class name="heading"/>
                                </style>
                              </object>
                              <packing>
                                <property name="expand">False</property>
                                <property name="fill">True</property>
                                <property name="position">2</property>
                              </packing>
                            </child>
                            <child>
                              <object class="GtkFrame">
                                <property name="visible">True</property>
                                <property name="can-focus">False</property>
                                <property name="margin-bottom">16</property>
                                <property name="label-xalign">0</property>
                                <property name="shadow-type">in</property>
                                <child>
                                  <!-- n-columns=2 n-rows=2 -->
                                  <object class="GtkGrid">
                                    <property name="visible">True</property>
                                    <property name="can-focus">False</property>
                                    <property name="row-spacing">8</property>
                                    <property name="column-spacing">8</property>
                                    <child>
                                      <object class="GtkLabel">
                                        <property name="visible">True</property>
                                        <property name="can-focus">False</property>
                                        <property name="halign">end</property>
                                        <property name="label" translatable="yes">Clip 1 length</property>
                                        <style>
                                          <class name="dim-label"/>
                                        </style>
                                      </object>
                                      <packing>
                                        <property name="left-attach">0</property>
                                        <property name="top-attach">0</property>
                                      </packing>
                                    </child>
                                    <child>
                                      <object class="GtkLabel">
                                        <property name="visible">True</property>
                                        <property name="can-focus">False</property>
                                        <property name="halign">end</property>
                                        <property name="label" translatable="yes">Clip 2 length</property>
                                        <style>
                                          <class name="dim-label"/>
                                        </style>
                                      </object>
                                      <packing>
                                        <property name="left-attach">0</property>
                                        <property name="top-attach">1</property>
                                      </packing>
                                    </child>
                                    <child>
                                      <placeholder/>
                                    </child>
                                    <child>
                                      <placeholder/>
                                    </child>
                                  </object>
                                </child>
                                <child type="label_item">
                                  <placeholder/>
                                </child>
                                <style>
                                  <class name="view"/>
                                </style>
                              </object>
                              <packing>
                                <property name="expand">False</property>
                                <property name="fill">True</property>
                                <property name="position">3</property>
                              </packing>
                            </child>
                            <child>
                              <object class="GtkLabel">
                                <property name="visible">True</property>
                                <property name="can-focus">False</property>
                                <property name="halign">start</property>
                                <property name="margin-bottom">4</property>
                                <property name="label" translatable="yes">Camera Control</property>
                                <style>
                                  <class name="heading"/>
                                </style>
                              </object>
                              <packing>
                                <property name="expand">False</property>
                                <property name="fill">True</property>
                                <property name="position">4</property>
                              </packing>
                            </child>
                            <child>
                              <object class="GtkFrame">
                                <property name="visible">True</property>
                                <property name="can-focus">False</property>
                                <property name="margin-bottom">16</property>
                                <property name="label-xalign">0</property>
                                <property name="shadow-type">in</property>
                                <child>
                                  <!-- n-columns=2 n-rows=1 -->
                                  <object class="GtkGrid">
                                    <property name="visible">True</property>
                                    <property name="can-focus">False</property>
                                    <property name="row-spacing">8</property>
                                    <property name="column-spacing">8</property>
                                    <child>
                                      <object class="GtkLabel">
                                        <property name="visible">True</property>
                                        <property name="can-focus">False</property>
                                        <property name="halign">end</property>
                                        <property name="label" translatable="yes">Camera control monitoring output</property>
                                        <style>
                                          <class name="dim-label"/>
                                        </style>
                                      </object>
                                      <packing>
                                        <property name="left-attach">0</property>
                                        <property name="top-attach">0</property>
                                      </packing>
                                    </child>
                                    <child>
                                      <placeholder/>
                                    </child>
                                  </object>
                                </child>
                                <child type="label_item">
                                  <placeholder/>
                                </child>
                                <style>
                                  <class name="view"/>
                                </style>
                              </object>
                              <packing>
                                <property name="expand">False</property>
                                <property name="fill">True</property>
                                <property name="position">5</property>
                              </packing>
                            </child>
                          </object>
                          <packing>
                            <property name="name">general</property>
                            <property name="title" translatable="yes">General</property>
                          </packing>
                        </child>
                        <child>
                          <object class="GtkBox" id="page_audio">
                            <property name="visible">True</property>
                            <property name="can-focus">False</property>
                            <property name="orientation">vertical</property>
                            <child>
                              <placeholder/>
                            </child>
                            <child>
                              <placeholder/>
                            </child>
                            <child>
                              <placeholder/>
                            </child>
                          </object>
                          <packing>
                            <property name="name">audio</property>
                            <property name="title" translatable="yes">Audio</property>
                            <property name="position">1</property>
                          </packing>
                        </child>
                        <child>
                          <object class="GtkBox" id="page_multiview">
                            <property name="visible">True</property>
                            <property name="can-focus">False</property>
                            <property name="orientation">vertical</property>
                            <property name="spacing">16</property>
                            <child>
                              <!-- n-columns=6 n-rows=2 -->
                              <object class="GtkGrid">
                                <property name="visible">True</property>
                                <property name="can-focus">False</property>
                                <property name="row-spacing">4</property>
                                <property name="column-spacing">4</property>
                                <child>
                                  <object class="GtkLabel">
                                    <property name="visible">True</property>
                                    <property name="can-focus">False</property>
                                    <property name="halign">start</property>
                                    <property name="label" translatable="yes">Multiview layout</property>
                                    <style>
                                      <class name="heading"/>
                                    </style>
                                  </object>
                                  <packing>
                                    <property name="left-attach">0</property>
                                    <property name="top-attach">0</property>
                                    <property name="width">4</property>
                                  </packing>
                                </child>
                                <child>
                                  <object class="GtkLabel">
                                    <property name="visible">True</property>
                                    <property name="can-focus">False</property>
                                    <property name="halign">start</property>
                                    <property name="label" translatable="yes">Audio meters</property>
                                    <style>
                                      <class name="heading"/>
                                    </style>
                                  </object>
                                  <packing>
                                    <property name="left-attach">4</property>
                                    <property name="top-attach">0</property>
                                    <property name="width">2</property>
                                  </packing>
                                </child>
                                <child>
                                  <object class="GtkToggleButton">
                                    <property name="label" translatable="yes">1</property>
                                    <property name="visible">True</property>
                                    <property name="can-focus">True</property>
                                    <property name="receives-default">True</property>
                                  </object>
                                  <packing>
                                    <property name="left-attach">0</property>
                                    <property name="top-attach">1</property>
                                  </packing>
                                </child>
                                <child>
                                  <object class="GtkToggleButton">
                                    <property name="label" translatable="yes">2</property>
                                    <property name="visible">True</property>
                                    <property name="can-focus">True</property>
                                    <property name="receives-default">True</property>
                                  </object>
                                  <packing>
                                    <property name="left-attach">1</property>
                                    <property name="top-attach">1</property>
                                  </packing>
                                </child>
                                <child>
                                  <object class="GtkToggleButton">
                                    <property name="label" translatable="yes">3</property>
                                    <property name="visible">True</property>
                                    <property name="can-focus">True</property>
                                    <property name="receives-default">True</property>
                                  </object>
                                  <packing>
                                    <property name="left-attach">2</property>
                                    <property name="top-attach">1</property>
                                  </packing>
                                </child>
                                <child>
                                  <object class="GtkToggleButton">
                                    <property name="label" translatable="yes">4</property>
                                    <property name="visible">True</property>
                                    <property name="can-focus">True</property>
                                    <property name="receives-default">True</property>
                                  </object>
                                  <packing>
                                    <property name="left-attach">3</property>
                                    <property name="top-attach">1</property>
                                  </packing>
                                </child>
                                <child>
                                  <placeholder/>
                                </child>
                                <child>
                                  <placeholder/>
                                </child>
                              </object>
                              <packing>
                                <property name="expand">False</property>
                                <property name="fill">True</property>
                                <property name="position">0</property>
                              </packing>
                            </child>
                            <child>
                              <!-- n-columns=4 n-rows=4 -->
                              <object class="GtkGrid" id="multiview_layout">
                                <property name="visible">True</property>
                                <property name="can-focus">False</property>
                                <property name="row-spacing">4</property>
                                <property name="column-spacing">4</property>
                                <property name="row-homogeneous">True</property>
                                <property name="column-homogeneous">True</property>
                                <child>
                                  <placeholder/>
                                </child>
                                <child>
                                  <placeholder/>
                                </child>
                                <child>
                                  <placeholder/>
                                </child>
                                <child>
                                  <placeholder/>
                                </child>
                                <child>
                                  <placeholder/>
                                </child>
                                <child>
                                  <placeholder/>
                                </child>
                                <child>
                                  <placeholder/>
                                </child>
                                <child>
                                  <placeholder/>
                                </child>
                                <child>
                                  <placeholder/>
                                </child>
                                <child>
                                  <placeholder/>
                                </child>
                                <child>
                                  <placeholder/>
                                </child>
                                <child>
                                  <placeholder/>
                                </child>
                                <child>
                                  <placeholder/>
                                </child>
                                <child>
                                  <placeholder/>
                                </child>
                                <child>
                                  <placeholder/>
                                </child>
                                <child>
                                  <placeholder/>
                                </child>
                                <style>
                                  <class name="multiview"/>
                                </style>
                              </object>
                              <packing>
                                <property name="expand">False</property>
                                <property name="fill">True</property>
                                <property name="position">1</property>
                              </packing>
                            </child>
                            <child>
                              <placeholder/>
                            </child>
                          </object>
                          <packing>
                            <property name="name">multiview</property>
                            <property name="title" translatable="yes">Multiview</property>
                            <property name="position">2</property>
                          </packing>
                        </child>
                        <child>
                          <object class="GtkBox" id="page_labels">
                            <property name="visible">True</property>
                            <property name="can-focus">False</property>
                            <property name="orientation">vertical</property>
                            <child>
                              <placeholder/>
                            </child>
                            <child>
                              <placeholder/>
                            </child>
                            <child>
                              <placeholder/>
                            </child>
                          </object>
                          <packing>
                            <property name="name">labels</property>
                            <property name="title" translatable="yes">Labels</property>
                            <property name="position">3</property>
                          </packing>
                        </child>
                        <child>
                          <object class="GtkBox" id="page_hyperdeck">
                            <property name="visible">True</property>
                            <property name="can-focus">False</property>
                            <property name="orientation">vertical</property>
                            <child>
                              <placeholder/>
                            </child>
                            <child>
                              <placeholder/>
                            </child>
                            <child>
                              <placeholder/>
                            </child>
                          </object>
                          <packing>
                            <property name="name">hyperdeck</property>
                            <property name="title" translatable="yes">HyperDeck</property>
                            <property name="position">4</property>
                          </packing>
                        </child>
                        <child>
                          <object class="GtkBox" id="page_remote">
                            <property name="visible">True</property>
                            <property name="can-focus">False</property>
                            <property name="orientation">vertical</property>
                            <child>
                              <object class="GtkLabel">
                                <property name="visible">True</property>
                                <property name="can-focus">False</property>
                                <property name="halign">start</property>
                                <property name="margin-bottom">4</property>
                                <property name="label" translatable="yes">Remote</property>
                                <style>
                                  <class name="heading"/>
                                </style>
                              </object>
                              <packing>
                                <property name="expand">False</property>
                                <property name="fill">True</property>
                                <property name="position">0</property>
                              </packing>
                            </child>
                            <child>
                              <object class="GtkFrame">
                                <property name="visible">True</property>
                                <property name="can-focus">False</property>
                                <property name="margin-bottom">16</property>
                                <property name="label-xalign">0</property>
                                <property name="shadow-type">in</property>
                                <child>
                                  <!-- n-columns=2 n-rows=4 -->
                                  <object class="GtkGrid">
                                    <property name="visible">True</property>
                                    <property name="can-focus">False</property>
                                    <property name="row-spacing">8</property>
                                    <property name="column-spacing">8</property>
                                    <child>
                                      <object class="GtkLabel">
                                        <property name="visible">True</property>
                                        <property name="can-focus">False</property>
                                        <property name="halign">end</property>
                                        <property name="label" translatable="yes">Use RS-422 port for</property>
                                        <style>
                                          <class name="dim-label"/>
                                        </style>
                                      </object>
                                      <packing>
                                        <property name="left-attach">0</property>
                                        <property name="top-attach">0</property>
                                      </packing>
                                    </child>
                                    <child>
                                      <placeholder/>
                                    </child>
                                    <child>
                                      <placeholder/>
                                    </child>
                                    <child>
                                      <placeholder/>
                                    </child>
                                    <child>
                                      <placeholder/>
                                    </child>
                                    <child>
                                      <placeholder/>
                                    </child>
                                    <child>
                                      <placeholder/>
                                    </child>
                                    <child>
                                      <placeholder/>
                                    </child>
                                  </object>
                                </child>
                                <child type="label_item">
                                  <placeholder/>
                                </child>
                                <style>
                                  <class name="view"/>
                                </style>
                              </object>
                              <packing>
                                <property name="expand">False</property>
                                <property name="fill">True</property>
                                <property name="position">1</property>
                              </packing>
                            </child>
                          </object>
                          <packing>
                            <property name="name">remote</property>
                            <property name="title" translatable="yes">Remote</property>
                            <property name="position">5</property>
                          </packing>
                        </child>
                      </object>
                    </child>
                  </object>
                  <packing>
                    <property name="expand">False</property>
                    <property name="fill">True</property>
                    <property name="position">1</property>
                  </packing>
                </child>
              </object>
              <packing>
                <property name="name">switcher</property>
                <property name="title" translatable="yes">Switcher</property>
              </packing>
            </child>
            <child>
              <object class="GtkBox" id="settings_app">
                <property name="visible">True</property>
                <property name="can-focus">False</property>
                <property name="orientation">vertical</property>
                <child>
                  <placeholder/>
                </child>
                <child>
                  <placeholder/>
                </child>
                <child>
                  <placeholder/>
                </child>
              </object>
              <packing>
                <property name="name">app</property>
                <property name="title" translatable="yes">Control app</property>
                <property name="position">1</property>
              </packing>
            </child>
          </object>
          <packing>
            <property name="expand">True</property>
            <property name="fill">True</property>
            <property name="position">1</property>
          </packing>
        </child>
      </object>
    </child>
  </object>
</interface>

M openswitcher_proxy/__main__.py => openswitcher_proxy/__main__.py +8 -1
@@ 8,6 8,7 @@ from openswitcher_proxy.frontend_httpapi import HttpApiFrontendThread
from openswitcher_proxy.frontend_status import StatusFrontendThread
from openswitcher_proxy.frontend_tcp import TcpFrontendThread
from openswitcher_proxy.hardware import HardwareThread
from openswitcher_proxy.hardware_merge_me import HardwareMergeMEThread

logging.basicConfig(
    format="%(asctime)s [%(levelname)-8s %(threadName)-15s] %(message)s",


@@ 26,7 27,13 @@ def run(config_path):
        nthreads['hardware'] = {}
        for hardware in config['hardware']:
            logging.info(f'  hardware: {hardware["id"]} ({hardware["label"]})')
            t = HardwareThread(hardware)
            htype = "atem"
            if 'type' in hardware:
                htype = hardware['type']
            if htype == "atem":
                t = HardwareThread(hardware)
            elif htype == "merge-me":
                t = HardwareMergeMEThread(hardware, nthreads)
            t.daemon = True
            threads.append(t)
            nthreads['hardware'][hardware['id']] = t

M openswitcher_proxy/frontend_status.py => openswitcher_proxy/frontend_status.py +2 -1
@@ 33,10 33,11 @@ class StatusRequestHandler(AuthRequestHandler):
                '<table border="1"><tr><th>id</th><th>label</th><th>address</th><th>status</th></tr>'.encode())
            for hwid in self.threadpool['hardware']:
                hardware = self.threadpool['hardware'][hwid]
                address = hardware.config['address'] if 'address' in hardware.config else ''
                self.wfile.write('<tr>'.encode())
                self.wfile.write(f'<td>{hwid}</td>'.encode())
                self.wfile.write(f'<td>{hardware.config["label"]}</td>'.encode())
                self.wfile.write(f'<td>{hardware.config["address"]}</td>'.encode())
                self.wfile.write(f'<td>{address}</td>'.encode())
                self.wfile.write(f'<td>{hardware.get_status()}</td>'.encode())
                self.wfile.write('</tr>'.encode())
            self.wfile.write('</table>'.encode())

A openswitcher_proxy/hardware_merge_me.py => openswitcher_proxy/hardware_merge_me.py +113 -0
@@ 0,0 1,113 @@
import threading
import logging
import time
from functools import partial

from pyatem.protocol import AtemProtocol


class SwitcherDummy:
    def __init__(self):
        self.mixerstate = {}
        self.me_map = []


class HardwareMergeMEThread(threading.Thread):
    def __init__(self, config, namedthreads):
        self.namedthreads = namedthreads
        threading.Thread.__init__(self)
        self.name = 'hw.' + str(config['id'])
        self.switcher = SwitcherDummy()
        self.config = config
        self.stop = False
        self.status = 'init'
        self.downstreams = config['hardware'].split(',')
        self.state = {}

    def run(self):
        self.status = 'waiting for downstream device sync...'
        logging.info('Waiting for downstream device sync')
        for ds in self.downstreams:
            self.state[ds] = False
            self.namedthreads['hardware'][ds].switcher.on('connected', partial(self.on_connected, ds))
            self.namedthreads['hardware'][ds].switcher.on('change', partial(self.on_change, ds))
            self.namedthreads['hardware'][ds].switcher.on('disconnected', partial(self.on_disconnected, ds))

        while not self.stop:
            time.sleep(1)

    def get_status(self):
        return self.status

    def on_connected(self, subdev):
        self.state[subdev] = True
        connected = 0
        for ds in self.state:
            if self.state[ds]:
                connected += 1
        if connected != len(self.state):
            self.status = 'connecting [{}/{}]'.format(connected, len(self.state))
        else:
            self.status = 'connected'
            logging.info("connected to all downstreams, building initial state")
            self.build_initial_state()

    def on_disconnected(self, subdev):
        self.state[subdev] = False
        self.status = 'lost connection'
        logging.error('Lost connection with subdevice ' + subdev)

    def on_change(self, subdev, key, value):
        if key == 'mixer-effect-config':
            self.switcher.me_map

    def build_initial_state(self):
        count_mediaplayers = 0
        count_aux = 0
        count_multiviewers = 0
        count_hyperdecks = 0
        count_dve = 0
        count_stingers = 0
        count_supersources = 0
        count_rs485 = 0

        for ds in self.downstreams:
            topology = self.namedthreads['hardware'][ds].switcher.mixerstate['topology']
            me_count = topology.me_units
            for i in range(0, me_count):
                self.switcher.me_map.append((ds, i))
            count_mediaplayers += topology.mediaplayers
            count_multiviewers += topology.multiviewers
            count_hyperdecks += topology.hyperdecks
            count_dve += topology.dve
            count_stingers += topology.stingers
            count_supersources += topology.supersources
            count_rs485 += topology.rs485
            count_aux += topology.aux_outputs

        self.switcher.mixerstate['topology'] = self.namedthreads['hardware'][self.downstreams[0]].switcher.mixerstate[
            'topology']
        self.switcher.mixerstate['topology'].me_units = len(self.switcher.me_map)
        self.switcher.mixerstate['topology'].aux_outputs = count_aux
        self.switcher.mixerstate['topology'].mediaplayers = count_mediaplayers
        self.switcher.mixerstate['topology'].multiviewers = count_multiviewers
        self.switcher.mixerstate['topology'].rs485 = count_rs485
        self.switcher.mixerstate['topology'].hyperdecks = count_hyperdecks
        self.switcher.mixerstate['topology'].dve = count_dve
        self.switcher.mixerstate['topology'].stingers = count_stingers
        self.switcher.mixerstate['topology'].supersources = count_supersources
        self.switcher.mixerstate['topology'].update()

        for ds in self.downstreams:
            ds_mixerstate = self.namedthreads['hardware'][ds].switcher.mixerstate
            for key in ds_mixerstate:
                if key in ['topology']:
                    continue
                if isinstance(ds_mixerstate[key], dict):
                    for field in self.ds_mixerstate[key]:
                        if isinstance(ds_mixerstate[key][field], dict):
                            self.switcher.mixerstate[key][field] = ds_mixerstate[key][field]
                        elif hasattr(ds_mixerstate[key][field].__class__, 'ME'):

                    if key not in self.switcher.mixerstate:
                        self.switcher.mixerstate[key] = {}

M proxy.toml => proxy.toml +15 -3
@@ 3,11 3,23 @@ id = "mini"
label = "Atem Mini"
address = "192.168.2.84"

[[hardware]]
id = "mini2"
label = "Testdevice"
address = "192.168.2.17"

[[hardware]]
id = "merged"
label = "Mini 2M/E"
hardware = "mini,mini2"
type = "merge-me"
me-input = 4

[[frontend]]
type = "http-api"
bind = ":8080"
auth = false
hardware = "mini"
hardware = "mini,mini2,merged"

[[frontend]]
type = "websocket"


@@ 15,7 27,7 @@ bind = ":8081"
auth = true
username = "admin"
password = "admin"
hardware = "mini"
hardware = "mini,mini2"
static-files = "/var/www/mywebapp"

[[frontend]]


@@ 29,4 41,4 @@ bind = ":8083"
auth = true
username = "admin"
password = "password"
hardware = "mini"
\ No newline at end of file
hardware = "mini,mini2"
\ No newline at end of file

M pyatem/field.py => pyatem/field.py +27 -0
@@ 88,6 88,7 @@ class MixerEffectConfigField(FieldBase):
    """

    CODE = "_MeC"
    ME = "index"

    def __init__(self, raw):
        self.raw = raw


@@ 348,6 349,7 @@ class ProgramBusInputField(FieldBase):
    """

    CODE = "PrgI"
    ME = "index"

    def __init__(self, raw):
        self.raw = raw


@@ 381,6 383,7 @@ class PreviewBusInputField(FieldBase):
    """

    CODE = "PrvI"
    ME = "index"

    def __init__(self, raw):
        self.raw = raw


@@ 852,6 855,22 @@ class TopologyField(FieldBase):
        self.stingers = field[10]
        self.supersources = field[11]

    def update(self):
        field = list(struct.unpack('>28B', self.raw))
        field[0] = self.me_units
        field[1] = self.sources
        field[2] = self.downstream_keyers
        field[3] = self.aux_outputs
        field[4] = self.mixminus_outputs
        field[5] = self.mediaplayers
        field[6] = self.multiviewers
        field[7] = self.rs485
        field[8] = self.hyperdecks
        field[9] = self.dve
        field[10] = self.stingers
        field[11] = self.supersources
        self.raw = struct.pack('>28B', *field)

    def __repr__(self):
        return '<topology, me={} sources={} aux={}>'.format(self.me_units, self.sources, self.aux_outputs)



@@ 1002,6 1021,7 @@ class TransitionMixField(FieldBase):
    """

    CODE = "TMxP"
    ME = "index"

    def __init__(self, raw):
        self.raw = raw


@@ 1030,6 1050,7 @@ class FadeToBlackField(FieldBase):
    """

    CODE = "FtbP"
    ME = "index"

    def __init__(self, raw):
        self.raw = raw


@@ 1059,6 1080,7 @@ class TransitionDipField(FieldBase):
    """

    CODE = "TDpP"
    ME = "index"

    def __init__(self, raw):
        self.raw = raw


@@ 1097,6 1119,7 @@ class TransitionWipeField(FieldBase):
    """

    CODE = "TWpP"
    ME = "index"

    def __init__(self, raw):
        self.raw = raw


@@ 1156,6 1179,7 @@ class TransitionDveField(FieldBase):
    """

    CODE = "TDvP"
    ME = "index"

    def __init__(self, raw):
        self.raw = raw


@@ 1534,6 1558,7 @@ class KeyPropertiesBaseField(FieldBase):
    """

    CODE = "KeBP"
    ME = "index"

    def __init__(self, raw):
        self.raw = raw


@@ 1562,6 1587,7 @@ class KeyPropertiesDveField(FieldBase):
    """

    CODE = "KeDV"
    ME = "index"

    def __init__(self, raw):
        self.raw = raw


@@ 1614,6 1640,7 @@ class KeyPropertiesLumaField(FieldBase):
    """

    CODE = "KeLm"
    ME = "index"

    def __init__(self, raw):
        self.raw = raw