diff --git a/app/connections.py b/app/connections.py index 91cebd9e..6aca109c 100644 --- a/app/connections.py +++ b/app/connections.py @@ -51,6 +51,7 @@ class HttpRequestType(Enum): PLAYER_PREV = "mediaplayercmd?command=previous" PLAYER_STOP = "mediaplayercmd?command=stop" PLAYER_REMOVE = "mediaplayerremove?file=" + GRUB = "grab?format=jpg&mode=" class TestException(Exception): @@ -334,6 +335,7 @@ class HttpAPI: self._settings = settings self._shutdown = False self._session_id = 0 + self._main_url = None self._base_url = None self._data = None self.init() @@ -351,6 +353,8 @@ class HttpAPI: url += urllib.parse.quote(ref) elif req_type is HttpRequestType.PLAY or req_type is HttpRequestType.PLAYER_REMOVE: url += "{}{}".format(ref_prefix, urllib.parse.quote(ref).replace("%3A", "%253A")) + elif req_type is HttpRequestType.GRUB: + url = "{}/{}{}".format(self._main_url, req_type.value, ref) def done_callback(f): callback(f.result()) @@ -362,10 +366,10 @@ class HttpAPI: def init(self): user, password = self._settings.http_user, self._settings.http_password use_ssl = self._settings.http_use_ssl - url = "http{}://{}:{}".format("s" if use_ssl else "", self._settings.host, self._settings.http_port) - self._base_url = "{}/web/".format(url) - init_auth(user, password, url, use_ssl) - url = "{}/web/{}".format(url, HttpRequestType.TOKEN.value) + self._main_url = "http{}://{}:{}".format("s" if use_ssl else "", self._settings.host, self._settings.http_port) + self._base_url = "{}/web/".format(self._main_url) + init_auth(user, password, self._main_url, use_ssl) + url = "{}/web/{}".format(self._main_url, HttpRequestType.TOKEN.value) s_id = get_session_id(user, password, url) if s_id != "0": self._data = urllib.parse.urlencode({"user": user, "password": password, "sessionid": s_id}).encode("utf-8") @@ -381,6 +385,8 @@ def get_response(req_type, url, data=None): with urlopen(Request(url, data=data), timeout=10) as f: if req_type is HttpRequestType.STREAM or req_type is HttpRequestType.STREAM_CURRENT: return {"m3u": f.read().decode("utf-8")} + elif req_type is HttpRequestType.GRUB: + return {"img_data": f.read()} elif req_type is HttpRequestType.CURRENT: for el in ETree.fromstring(f.read().decode("utf-8")).iter("e2event"): return {el.tag: el.text for el in el.iter()} # return first[current] event from the list diff --git a/app/ui/main_app_window.py b/app/ui/main_app_window.py index 5b99ba51..5e0a6e8b 100644 --- a/app/ui/main_app_window.py +++ b/app/ui/main_app_window.py @@ -238,6 +238,9 @@ class Application(Gtk.Application): self._signal_level_bar.bind_property("visible", builder.get_object("record_button"), "visible") self._receiver_info_box.bind_property("visible", self._http_status_image, "visible", 4) self._receiver_info_box.bind_property("visible", self._signal_box, "visible") + # Screenshots + self._screenshots_button = builder.get_object("screenshots_button") + self._receiver_info_box.bind_property("visible", self._screenshots_button, "visible") # Force ctrl press event for view. Multiple selections in lists only with Space key(as in file managers)!!! self._services_view.connect("key-press-event", self.force_ctrl) self._fav_view.connect("key-press-event", self.force_ctrl) @@ -347,6 +350,10 @@ class Application(Gtk.Application): set_action("upload_bouquets", lambda a, v: self.on_upload_data(DownloadType.BOUQUETS)) # Edit set_action("on_edit", self.on_edit) + # Screenshots + set_action("on_screenshot_all", self.on_screenshot_all) + set_action("on_screenshot_video", self.on_screenshot_video) + set_action("on_screenshot_osd", self.on_screenshot_osd) def set_accels(self): """ Setting accelerators for the actions. """ @@ -2213,6 +2220,37 @@ class Application(Gtk.Application): self._service_epg_label.set_text(dsc) self._service_epg_label.set_tooltip_text(evn.get("e2eventdescription", "")) + # ******************** Screenshots ************************# + + def on_screenshot_all(self, action, value=None): + self._http_api.send(HttpRequestType.GRUB, "all", self.on_screenshot) + + def on_screenshot_video(self, action, value=None): + self._http_api.send(HttpRequestType.GRUB, "video", self.on_screenshot) + + def on_screenshot_osd(self, action, value=None): + self._http_api.send(HttpRequestType.GRUB, "osd", self.on_screenshot) + + def on_screenshot(self, data): + if "error_code" in data: + return + + img = data.get("img_data", None) + if img: + self._screenshots_button.set_sensitive(False) + try: + import tempfile + import subprocess + + with tempfile.NamedTemporaryFile(mode="wb", suffix=".jpg") as tf: + tf.write(img) + p = subprocess.Popen(["open" if self._settings.is_darwin else "xdg-open", tf.name], + stdout=subprocess.PIPE, + stderr=subprocess.PIPE) + p.communicate() + finally: + self._screenshots_button.set_sensitive(True) + # ***************** Filter and search *********************# def on_filter_toggled(self, action, value): diff --git a/app/ui/main_window.glade b/app/ui/main_window.glade index 5b5c22fa..9132da41 100644 --- a/app/ui/main_window.glade +++ b/app/ui/main_window.glade @@ -653,6 +653,70 @@ Author: Dmitriy Yefremov False gtk-save-as + + False + + + True + False + 10 + 10 + 5 + 5 + vertical + 2 + + + True + True + True + app.on_screenshot_all + All + True + + + False + True + 0 + + + + + True + True + True + app.on_screenshot_video + Video + True + + + False + True + 1 + + + + + True + True + True + app.on_screenshot_osd + OSD + True + + + False + True + 2 + + + + + main + 1 + + + True False @@ -2864,6 +2928,8 @@ Author: Dmitriy Yefremov True False + center + center gtk-info @@ -2910,10 +2976,35 @@ Author: Dmitriy Yefremov 0 + + + status-bar-button + False + True + Screenshot + center + center + screenshots_menu + + + True + False + zoom-best-fit + + + + + False + True + 3 + + False No connection to the receiver! + center + center 10 10 network-offline @@ -2953,6 +3044,8 @@ Author: Dmitriy Yefremov False True Record + center + center