File: chromecast_patterngenerator.py

package info (click to toggle)
displaycal-py3 3.9.16-1
  • links: PTS
  • area: main
  • in suites: forky, sid, trixie
  • size: 29,120 kB
  • sloc: python: 115,777; javascript: 11,540; xml: 598; sh: 257; makefile: 173
file content (167 lines) | stat: -rw-r--r-- 4,731 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
# -*- coding: utf-8 -*-

from time import sleep

# 0install: Make sure imported protobuf is from implementation to ensure
# correct version
import sys

if not getattr(sys, "frozen", False):
    import os
    import re

    for pth in sys.path:
        if os.path.basename(pth).startswith("protobuf-") and re.match(
            r"sha\d+(?:new)?", os.path.basename(os.path.dirname(pth))
        ):
            if "google" in sys.modules:
                del sys.modules["google"]
            try:
                import pkg_resources
            except ImportError:
                import pkgutil
            syspath = sys.path[:]
            sys.path[:] = [pth]
            import google.protobuf

            sys.path[:] = syspath
            break

if sys.version_info[:2] < (3,):
    # zeroconf 0.19.1 is the last version supporting Python 2.x
    # but zeroconf 0.20 lacks a check for Python version
    import zeroconf

    if zeroconf.__version__ > "0.19.1":
        raise ImportError(
            """
Python version > 3.3 required for python-zeroconf %s.
If you need support for Python 2 or Python 3.3 please use version 0.19.1
    """
            % zeroconf.__version__
        )

from pychromecast import get_chromecasts
from pychromecast.controllers import BaseController

from DisplayCAL import localization as lang


class ChromeCastPatternGeneratorController(BaseController):
    def __init__(self):
        super(ChromeCastPatternGeneratorController, self).__init__(
            "urn:x-cast:net.hoech.cast.patterngenerator", "B5C2CBFC"
        )
        self.request_id = 0

    def receive_message(self, message, data):
        return True  # Indicate we handled this message

    def send(
        self,
        rgb=(0, 0, 0),
        bgrgb=(0, 0, 0),
        offset_x=0.5,
        offset_y=0.5,
        h_scale=1,
        v_scale=1,
    ):
        fg = "#%02X%02X%02X" % tuple(round(v * 255) for v in rgb)
        bg = "#%02X%02X%02X" % tuple(round(v * 255) for v in bgrgb)
        self.request_id += 1
        self.send_message(
            {
                "requestId": self.request_id,
                "foreground": fg,
                "offset": [offset_x, offset_y],
                "scale": [h_scale, v_scale],
                "background": bg,
            }
        )


class ChromeCastPatternGenerator:
    def __init__(self, name, logfile=None):
        self._controller = ChromeCastPatternGeneratorController()
        self.name = name
        self.listening = False
        self.logfile = logfile

    def disconnect_client(self):
        self.listening = False
        if hasattr(self, "_cc"):
            if self._cc.app_id:
                self._cc.quit_app()
        if hasattr(self, "conn"):
            del self.conn

    def send(
        self,
        rgb=(0, 0, 0),
        bgrgb=(0, 0, 0),
        bits=None,
        use_video_levels=None,
        x=0,
        y=0,
        w=1,
        h=1,
    ):
        if w < 1:
            x /= 1.0 - w
        else:
            x = 0
        if h < 1:
            y /= 1.0 - h
        else:
            y = 0
        self._controller.send(rgb, bgrgb, x, y, w * 10, h * 10)

    def wait(self):
        self.listening = True
        if self.logfile:
            self.logfile.write(
                lang.getstr("connecting.to", ("Chromecast", " " + self.name)) + "\n"
            )
        if not hasattr(self, "_cc"):
            # Find our ChromeCast
            try:
                self._cc = next(
                    cc
                    for cc in get_chromecasts()
                    if str(cc.device.friendly_name) == self.name
                )
            except StopIteration:
                self.listening = False
                raise
            self._cc.register_handler(self._controller)
        # Wait for ChromeCast device to be ready
        while self.listening:
            self._cc.wait(0.05)
            if self._cc.status:
                break
        if self.listening:
            # Launch pattern generator app
            self._controller.launch()
            # Wait for it
            while (
                self.listening and self._cc.app_id != self._controller.supporting_app_id
            ):
                sleep(0.05)
            self.conn = True
            print(lang.getstr("connection.established"))


if __name__ == "__main__":
    from DisplayCAL import config

    config.initcfg()
    lang.init()

    pg = ChromeCastPatternGenerator("Smörebröd")

    # Find our ChromeCast and connect to it, then launch the pattern generator
    # app on the ChromeCast device
    pg.wait()

    # Display test color (yellow window on blue background)
    pg.send((1, 1, 0), (0, 0, 1), x=0.375, y=0.375, w=0.25, h=0.25)