mirror of
https://github.com/DYefremov/DemonEditor.git
synced 2025-12-21 16:09:41 +01:00
basic implementation of the play mode
This commit is contained in:
@@ -1,12 +1,17 @@
|
|||||||
import os
|
import os
|
||||||
|
import subprocess
|
||||||
import sys
|
import sys
|
||||||
from datetime import datetime
|
from datetime import datetime
|
||||||
|
from enum import Enum
|
||||||
|
from urllib.request import urlopen
|
||||||
|
|
||||||
from app.commons import run_task, log, _DATE_FORMAT
|
from app.commons import run_task, log, _DATE_FORMAT
|
||||||
|
from app.settings import PlayStreamsMode
|
||||||
|
|
||||||
|
|
||||||
class Player:
|
class Player:
|
||||||
__VLC_INSTANCE = None
|
__VLC_INSTANCE = None
|
||||||
|
__PLAY_STREAMS_MODE = PlayStreamsMode.BUILT_IN
|
||||||
|
|
||||||
def __init__(self, rewind_callback, position_callback, error_callback, playing_callback):
|
def __init__(self, rewind_callback, position_callback, error_callback, playing_callback):
|
||||||
try:
|
try:
|
||||||
@@ -46,6 +51,10 @@ class Player:
|
|||||||
cls.__VLC_INSTANCE = Player(rewind_callback, position_callback, error_callback, playing_callback)
|
cls.__VLC_INSTANCE = Player(rewind_callback, position_callback, error_callback, playing_callback)
|
||||||
return cls.__VLC_INSTANCE
|
return cls.__VLC_INSTANCE
|
||||||
|
|
||||||
|
@staticmethod
|
||||||
|
def get_play_mode():
|
||||||
|
return Player.__PLAY_STREAMS_MODE
|
||||||
|
|
||||||
@run_task
|
@run_task
|
||||||
def play(self, mrl=None):
|
def play(self, mrl=None):
|
||||||
if mrl:
|
if mrl:
|
||||||
@@ -105,6 +114,90 @@ class Player:
|
|||||||
self._player.set_fullscreen(full)
|
self._player.set_fullscreen(full)
|
||||||
|
|
||||||
|
|
||||||
|
class HttpPlayer:
|
||||||
|
""" Simple wrapper for VLC media player to interact over http. """
|
||||||
|
|
||||||
|
__VLC_INSTANCE = None
|
||||||
|
__PLAY_STREAMS_MODE = PlayStreamsMode.VLC
|
||||||
|
|
||||||
|
class Commands(Enum):
|
||||||
|
STATUS = "http://127.0.0.1:{}/requests/status.xml"
|
||||||
|
PLAY = "http://127.0.0.1:{}/requests/status.xml?command=in_play&input={}"
|
||||||
|
STOP = "http://127.0.0.1:{}/requests/status.xml?command=pl_stop"
|
||||||
|
CLEAR = "http://127.0.0.1:{}/requests/status.xml?command=pl_empty"
|
||||||
|
|
||||||
|
def __init__(self, exe, port):
|
||||||
|
from concurrent.futures import ThreadPoolExecutor as PoolExecutor
|
||||||
|
|
||||||
|
self._executor = PoolExecutor(max_workers=1)
|
||||||
|
self._cmd = [exe, "--no-stats", "--verbose=-1", "--extraintf", "http", "--http-port", port,
|
||||||
|
"--no-playlist-skip-ads", "--one-instance", "--quiet"]
|
||||||
|
self._p = None
|
||||||
|
self._state = None
|
||||||
|
self._port = port
|
||||||
|
|
||||||
|
@classmethod
|
||||||
|
def get_instance(cls, settings):
|
||||||
|
if not cls.__VLC_INSTANCE:
|
||||||
|
import shutil
|
||||||
|
|
||||||
|
is_darwin = settings.is_darwin
|
||||||
|
# TODO Add options[vlc_exe and port] to the settings!
|
||||||
|
exe = "/Applications/VLC.app/Contents/MacOS/VLC" if is_darwin else "/usr/bin/vlc"
|
||||||
|
if shutil.which(exe) is None:
|
||||||
|
raise ImportError
|
||||||
|
cls.__VLC_INSTANCE = HttpPlayer(exe=exe, port=str(9090))
|
||||||
|
return cls.__VLC_INSTANCE
|
||||||
|
|
||||||
|
@staticmethod
|
||||||
|
def get_play_mode():
|
||||||
|
return HttpPlayer.__PLAY_STREAMS_MODE
|
||||||
|
|
||||||
|
@run_task
|
||||||
|
def play(self, mrl=None):
|
||||||
|
if not self._p or self._p and self._p.poll() is not None:
|
||||||
|
self._p = subprocess.Popen(self._cmd + [mrl], preexec_fn=os.setsid)
|
||||||
|
self._p.communicate()
|
||||||
|
else:
|
||||||
|
self._executor.submit(self.open_command, self.Commands.CLEAR)
|
||||||
|
self._executor.submit(self.open_command, self.Commands.PLAY, mrl)
|
||||||
|
|
||||||
|
def open_command(self, command, url=None):
|
||||||
|
if command is self.Commands.PLAY:
|
||||||
|
url = self.Commands.PLAY.value.format(self._port, url)
|
||||||
|
else:
|
||||||
|
url = command.value.format(self._port)
|
||||||
|
|
||||||
|
try:
|
||||||
|
with urlopen(url, timeout=5) as f:
|
||||||
|
self._state = command
|
||||||
|
except Exception as e:
|
||||||
|
log("{}[open_command, {}] error: {}".format(__class__.__name__, command, e))
|
||||||
|
|
||||||
|
def stop(self):
|
||||||
|
if self._state is self.Commands.PLAY:
|
||||||
|
self._executor.submit(self.open_command, self.Commands.STOP)
|
||||||
|
|
||||||
|
def pause(self):
|
||||||
|
pass
|
||||||
|
|
||||||
|
def set_time(self, time):
|
||||||
|
pass
|
||||||
|
|
||||||
|
@run_task
|
||||||
|
def release(self):
|
||||||
|
if self._p and self._p.poll() is None:
|
||||||
|
import signal
|
||||||
|
# Good explanation here: https://stackoverflow.com/a/4791612
|
||||||
|
os.killpg(os.getpgid(self._p.pid), signal.SIGTERM)
|
||||||
|
|
||||||
|
def is_playing(self):
|
||||||
|
return self._state is self.Commands.PLAY
|
||||||
|
|
||||||
|
def set_full_screen(self, full):
|
||||||
|
pass
|
||||||
|
|
||||||
|
|
||||||
class Recorder:
|
class Recorder:
|
||||||
__VLC_REC_INSTANCE = None
|
__VLC_REC_INSTANCE = None
|
||||||
|
|
||||||
|
|||||||
@@ -8,16 +8,16 @@ from itertools import chain
|
|||||||
from gi.repository import GLib, Gio
|
from gi.repository import GLib, Gio
|
||||||
|
|
||||||
from app.commons import run_idle, log, run_task, run_with_delay, init_logger
|
from app.commons import run_idle, log, run_task, run_with_delay, init_logger
|
||||||
from app.connections import HttpAPI, HttpRequestType, download_data, DownloadType, upload_data, test_http, \
|
from app.connections import (HttpAPI, HttpRequestType, download_data, DownloadType, upload_data, test_http,
|
||||||
TestException, HttpApiException
|
TestException, HttpApiException)
|
||||||
from app.eparser import get_blacklist, write_blacklist, parse_m3u
|
from app.eparser import get_blacklist, write_blacklist, parse_m3u
|
||||||
from app.eparser import get_services, get_bouquets, write_bouquets, write_services, Bouquets, Bouquet, Service
|
from app.eparser import get_services, get_bouquets, write_bouquets, write_services, Bouquets, Bouquet, Service
|
||||||
from app.eparser.ecommons import CAS, Flag, BouquetService
|
from app.eparser.ecommons import CAS, Flag, BouquetService
|
||||||
from app.eparser.enigma.bouquets import BqServiceType
|
from app.eparser.enigma.bouquets import BqServiceType
|
||||||
from app.eparser.iptv import export_to_m3u
|
from app.eparser.iptv import export_to_m3u
|
||||||
from app.eparser.neutrino.bouquets import BqType
|
from app.eparser.neutrino.bouquets import BqType
|
||||||
from app.settings import SettingsType, Settings, SettingsException
|
from app.settings import SettingsType, Settings, SettingsException, PlayStreamsMode
|
||||||
from app.tools.media import Player, Recorder
|
from app.tools.media import Player, Recorder, HttpPlayer
|
||||||
from app.ui.epg_dialog import EpgDialog
|
from app.ui.epg_dialog import EpgDialog
|
||||||
from app.ui.transmitter import LinksTransmitter
|
from app.ui.transmitter import LinksTransmitter
|
||||||
from .backup import BackupDialog, backup_data, clear_data_path
|
from .backup import BackupDialog, backup_data, clear_data_path
|
||||||
@@ -25,17 +25,17 @@ from .dialogs import show_dialog, DialogType, get_chooser_dialog, WaitDialog, ge
|
|||||||
from .download_dialog import DownloadDialog
|
from .download_dialog import DownloadDialog
|
||||||
from .imports import ImportDialog, import_bouquet
|
from .imports import ImportDialog, import_bouquet
|
||||||
from .iptv import IptvDialog, SearchUnavailableDialog, IptvListConfigurationDialog, YtListImportDialog
|
from .iptv import IptvDialog, SearchUnavailableDialog, IptvListConfigurationDialog, YtListImportDialog
|
||||||
from .main_helper import insert_marker, move_items, rename, ViewTarget, set_flags, locate_in_services, \
|
from .main_helper import (insert_marker, move_items, rename, ViewTarget, set_flags, locate_in_services,
|
||||||
scroll_to, get_base_model, update_picons_data, copy_picon_reference, assign_picon, remove_picon, \
|
scroll_to, get_base_model, update_picons_data, copy_picon_reference, assign_picon,
|
||||||
is_only_one_item_selected, gen_bouquets, BqGenType, get_iptv_url, append_picons, get_selection, get_model_data, \
|
remove_picon, is_only_one_item_selected, gen_bouquets, BqGenType, get_iptv_url, append_picons,
|
||||||
remove_all_unused_picons
|
get_selection, get_model_data, remove_all_unused_picons)
|
||||||
from .picons_downloader import PiconsDialog
|
from .picons_downloader import PiconsDialog
|
||||||
from .satellites_dialog import show_satellites_dialog
|
from .satellites_dialog import show_satellites_dialog
|
||||||
from .search import SearchProvider
|
from .search import SearchProvider
|
||||||
from .service_details_dialog import ServiceDetailsDialog, Action
|
from .service_details_dialog import ServiceDetailsDialog, Action
|
||||||
from .settings_dialog import show_settings_dialog
|
from .settings_dialog import show_settings_dialog
|
||||||
from .uicommons import Gtk, Gdk, UI_RESOURCES_PATH, LOCKED_ICON, HIDE_ICON, IPTV_ICON, MOVE_KEYS, KeyboardKey, Column, \
|
from .uicommons import (Gtk, Gdk, UI_RESOURCES_PATH, LOCKED_ICON, HIDE_ICON, IPTV_ICON, MOVE_KEYS, KeyboardKey, Column,
|
||||||
FavClickMode
|
FavClickMode)
|
||||||
|
|
||||||
|
|
||||||
class Application(Gtk.Application):
|
class Application(Gtk.Application):
|
||||||
@@ -172,7 +172,7 @@ class Application(Gtk.Application):
|
|||||||
# Player
|
# Player
|
||||||
self._player = None
|
self._player = None
|
||||||
self._full_screen = False
|
self._full_screen = False
|
||||||
self._drawing_area_xid = None
|
self._current_mrl = None
|
||||||
# Record
|
# Record
|
||||||
self._recorder = None
|
self._recorder = None
|
||||||
# http api
|
# http api
|
||||||
@@ -1000,7 +1000,8 @@ class Application(Gtk.Application):
|
|||||||
self.show_error_dialog(str(e))
|
self.show_error_dialog(str(e))
|
||||||
return
|
return
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
log("Append services error: " + str(e))
|
from traceback import format_exc
|
||||||
|
log("Reading data error: {}".format(format_exc()))
|
||||||
self.show_error_dialog(get_message("Reading data error!") + "\n" + str(e))
|
self.show_error_dialog(get_message("Reading data error!") + "\n" + str(e))
|
||||||
return
|
return
|
||||||
else:
|
else:
|
||||||
@@ -1525,7 +1526,10 @@ class Application(Gtk.Application):
|
|||||||
if event.get_event_type() == Gdk.EventType.DOUBLE_BUTTON_PRESS:
|
if event.get_event_type() == Gdk.EventType.DOUBLE_BUTTON_PRESS:
|
||||||
if self._fav_click_mode is FavClickMode.DISABLED:
|
if self._fav_click_mode is FavClickMode.DISABLED:
|
||||||
return
|
return
|
||||||
elif self._fav_click_mode is FavClickMode.STREAM:
|
|
||||||
|
self._fav_view.set_sensitive(False)
|
||||||
|
|
||||||
|
if self._fav_click_mode is FavClickMode.STREAM:
|
||||||
self.on_play_stream()
|
self.on_play_stream()
|
||||||
elif self._fav_click_mode is FavClickMode.ZAP_PLAY:
|
elif self._fav_click_mode is FavClickMode.ZAP_PLAY:
|
||||||
self.on_zap(self.on_watch)
|
self.on_zap(self.on_watch)
|
||||||
@@ -1700,6 +1704,7 @@ class Application(Gtk.Application):
|
|||||||
row = self._fav_model[path][:]
|
row = self._fav_model[path][:]
|
||||||
if row[Column.FAV_TYPE] != BqServiceType.IPTV.name:
|
if row[Column.FAV_TYPE] != BqServiceType.IPTV.name:
|
||||||
self.show_error_dialog("Not allowed in this context!")
|
self.show_error_dialog("Not allowed in this context!")
|
||||||
|
self.set_playback_elms_active()
|
||||||
return
|
return
|
||||||
|
|
||||||
url = get_iptv_url(row, self._s_type)
|
url = get_iptv_url(row, self._s_type)
|
||||||
@@ -1709,24 +1714,36 @@ class Application(Gtk.Application):
|
|||||||
self.play(url)
|
self.play(url)
|
||||||
|
|
||||||
def play(self, url):
|
def play(self, url):
|
||||||
if not self._player:
|
mode = self._settings.play_streams_mode
|
||||||
try:
|
if mode is PlayStreamsMode.M3U:
|
||||||
self._player = Player.get_instance(rewind_callback=self.on_player_duration_changed,
|
self.save_stream_to_m3u(url)
|
||||||
position_callback=self.on_player_time_changed,
|
|
||||||
error_callback=self.on_player_error,
|
|
||||||
playing_callback=self.set_playback_elms_active)
|
|
||||||
except (ImportError, NameError, AttributeError):
|
|
||||||
self.show_error_dialog("No VLC is found. Check that it is installed!")
|
|
||||||
return
|
return
|
||||||
|
|
||||||
|
if mode is PlayStreamsMode.VLC:
|
||||||
|
try:
|
||||||
|
if self._player and self._player.get_play_mode() is not mode:
|
||||||
|
self._player.release()
|
||||||
|
self._player = None
|
||||||
|
if not self._player:
|
||||||
|
self._player = HttpPlayer.get_instance(self._settings)
|
||||||
|
except ImportError:
|
||||||
|
self.show_error_dialog("No VLC is found. Check that it is installed!")
|
||||||
else:
|
else:
|
||||||
if self._drawing_area_xid:
|
self._player.play(url)
|
||||||
self._player.set_xwindow(self._drawing_area_xid)
|
finally:
|
||||||
|
self.set_playback_elms_active()
|
||||||
|
else:
|
||||||
|
if not self._player_box.get_visible():
|
||||||
w, h = self._main_window.get_size()
|
w, h = self._main_window.get_size()
|
||||||
self._player_box.set_size_request(w * 0.6, -1)
|
self._player_box.set_size_request(w * 0.6, -1)
|
||||||
|
self._current_mrl = url
|
||||||
self._player_box.set_visible(True)
|
self._player_box.set_visible(True)
|
||||||
self._fav_view.set_sensitive(False)
|
|
||||||
|
if self._player and self._player.get_play_mode() is PlayStreamsMode.BUILT_IN:
|
||||||
GLib.idle_add(self._player.play, url, priority=GLib.PRIORITY_LOW)
|
GLib.idle_add(self._player.play, url, priority=GLib.PRIORITY_LOW)
|
||||||
|
elif self._player:
|
||||||
|
self.show_error_dialog("Play mode has been changed!\nRestart the program to apply the settings.")
|
||||||
|
self.set_playback_elms_active()
|
||||||
|
|
||||||
def on_player_stop(self, item=None):
|
def on_player_stop(self, item=None):
|
||||||
if self._player:
|
if self._player:
|
||||||
@@ -1794,11 +1811,26 @@ class Application(Gtk.Application):
|
|||||||
return "{}{:02d}:{:02d}".format(str(h) + ":" if h else "", m, s)
|
return "{}{:02d}:{:02d}".format(str(h) + ":" if h else "", m, s)
|
||||||
|
|
||||||
def on_drawing_area_realize(self, widget):
|
def on_drawing_area_realize(self, widget):
|
||||||
if sys.platform == "darwin":
|
w, h = self._main_window.get_size()
|
||||||
|
widget.set_size_request(w * 0.6, -1)
|
||||||
|
|
||||||
|
if not self._player:
|
||||||
|
try:
|
||||||
|
self._player = Player.get_instance(rewind_callback=self.on_player_duration_changed,
|
||||||
|
position_callback=self.on_player_time_changed,
|
||||||
|
error_callback=self.on_player_error,
|
||||||
|
playing_callback=self.set_playback_elms_active)
|
||||||
|
except (ImportError, NameError, AttributeError):
|
||||||
|
self.show_error_dialog("No VLC is found. Check that it is installed!")
|
||||||
|
return True
|
||||||
|
else:
|
||||||
|
if self._settings.is_darwin:
|
||||||
self._player.set_nso(widget)
|
self._player.set_nso(widget)
|
||||||
else:
|
else:
|
||||||
self._drawing_area_xid = widget.get_window().get_xid()
|
self._player.set_xwindow(widget.get_window().get_xid())
|
||||||
self._player.set_xwindow(self._drawing_area_xid)
|
self._player.play(self._current_mrl)
|
||||||
|
finally:
|
||||||
|
self.set_playback_elms_active()
|
||||||
|
|
||||||
def on_player_drawing_area_draw(self, widget, cr):
|
def on_player_drawing_area_draw(self, widget, cr):
|
||||||
""" Used for black background drawing in the player drawing area.
|
""" Used for black background drawing in the player drawing area.
|
||||||
@@ -1932,17 +1964,37 @@ class Application(Gtk.Application):
|
|||||||
error_code = data.get("error_code", 0)
|
error_code = data.get("error_code", 0)
|
||||||
if error_code or self._http_status_image.get_visible():
|
if error_code or self._http_status_image.get_visible():
|
||||||
self.show_error_dialog("No connection to the receiver!")
|
self.show_error_dialog("No connection to the receiver!")
|
||||||
|
self.set_playback_elms_active()
|
||||||
return
|
return
|
||||||
|
|
||||||
m3u = data.get("m3u", None)
|
m3u = data.get("m3u", None)
|
||||||
if m3u:
|
if m3u:
|
||||||
return [s for s in m3u.split("\n") if not s.startswith("#")][0]
|
return [s for s in m3u.split("\n") if not s.startswith("#")][0]
|
||||||
|
|
||||||
|
def save_stream_to_m3u(self, url):
|
||||||
|
path, column = self._fav_view.get_cursor()
|
||||||
|
s_name = self._fav_model.get_value(self._fav_model.get_iter(path), Column.FAV_SERVICE) if path else "stream"
|
||||||
|
|
||||||
|
try:
|
||||||
|
response = show_dialog(DialogType.CHOOSER, self._main_window, settings=self._settings)
|
||||||
|
if response in (Gtk.ResponseType.CANCEL, Gtk.ResponseType.DELETE_EVENT):
|
||||||
|
return
|
||||||
|
|
||||||
|
with open("{}{}.m3u".format(response, s_name), "w", encoding="utf-8") as file:
|
||||||
|
file.writelines("#EXTM3U\n#EXTVLCOPT--http-reconnect=true\n#EXTINF:-1,{}\n{}\n".format(s_name, url))
|
||||||
|
except IOError as e:
|
||||||
|
self.show_error_dialog(str(e))
|
||||||
|
else:
|
||||||
|
show_dialog(DialogType.INFO, self._main_window, "Done!")
|
||||||
|
finally:
|
||||||
|
GLib.idle_add(self._fav_view.set_sensitive, True)
|
||||||
|
|
||||||
@run_idle
|
@run_idle
|
||||||
def on_zap(self, callback=None):
|
def on_zap(self, callback=None):
|
||||||
""" Switch(zap) the channel """
|
""" Switch(zap) the channel """
|
||||||
path, column = self._fav_view.get_cursor()
|
path, column = self._fav_view.get_cursor()
|
||||||
if not path or not self._http_api:
|
if not path or not self._http_api:
|
||||||
|
self.set_playback_elms_active()
|
||||||
return
|
return
|
||||||
|
|
||||||
ref = self.get_service_ref(path)
|
ref = self.get_service_ref(path)
|
||||||
@@ -1957,6 +2009,9 @@ class Application(Gtk.Application):
|
|||||||
GLib.idle_add(scroll_to, path, self._fav_view)
|
GLib.idle_add(scroll_to, path, self._fav_view)
|
||||||
if callback:
|
if callback:
|
||||||
callback()
|
callback()
|
||||||
|
else:
|
||||||
|
self.show_error_dialog("No connection to the receiver!")
|
||||||
|
self.set_playback_elms_active()
|
||||||
|
|
||||||
self._http_api.send(HttpRequestType.ZAP, ref, zap)
|
self._http_api.send(HttpRequestType.ZAP, ref, zap)
|
||||||
|
|
||||||
@@ -1966,6 +2021,7 @@ class Application(Gtk.Application):
|
|||||||
|
|
||||||
if srv_type == BqServiceType.IPTV.name or srv_type == BqServiceType.MARKER.name:
|
if srv_type == BqServiceType.IPTV.name or srv_type == BqServiceType.MARKER.name:
|
||||||
self.show_error_dialog("Not allowed in this context!")
|
self.show_error_dialog("Not allowed in this context!")
|
||||||
|
self.set_playback_elms_active()
|
||||||
return
|
return
|
||||||
|
|
||||||
srv = self._services.get(fav_id, None)
|
srv = self._services.get(fav_id, None)
|
||||||
|
|||||||
@@ -1953,6 +1953,7 @@ Author: Dmitriy Yefremov
|
|||||||
<property name="active">True</property>
|
<property name="active">True</property>
|
||||||
<property name="draw_indicator">True</property>
|
<property name="draw_indicator">True</property>
|
||||||
<property name="group">get_m3u_radio_button</property>
|
<property name="group">get_m3u_radio_button</property>
|
||||||
|
<signal name="toggled" handler="on_play_mode_changed" swapped="no"/>
|
||||||
</object>
|
</object>
|
||||||
<packing>
|
<packing>
|
||||||
<property name="expand">False</property>
|
<property name="expand">False</property>
|
||||||
@@ -1984,7 +1985,6 @@ Author: Dmitriy Yefremov
|
|||||||
<property name="receives_default">False</property>
|
<property name="receives_default">False</property>
|
||||||
<property name="active">True</property>
|
<property name="active">True</property>
|
||||||
<property name="draw_indicator">True</property>
|
<property name="draw_indicator">True</property>
|
||||||
<property name="group">play_in_built_radio_button</property>
|
|
||||||
</object>
|
</object>
|
||||||
<packing>
|
<packing>
|
||||||
<property name="expand">False</property>
|
<property name="expand">False</property>
|
||||||
@@ -1998,7 +1998,7 @@ Author: Dmitriy Yefremov
|
|||||||
<object class="GtkLabel" id="play_streams_label">
|
<object class="GtkLabel" id="play_streams_label">
|
||||||
<property name="visible">True</property>
|
<property name="visible">True</property>
|
||||||
<property name="can_focus">False</property>
|
<property name="can_focus">False</property>
|
||||||
<property name="label" translatable="yes">Play streams in:</property>
|
<property name="label" translatable="yes">Play streams mode:</property>
|
||||||
</object>
|
</object>
|
||||||
</child>
|
</child>
|
||||||
</object>
|
</object>
|
||||||
|
|||||||
@@ -5,7 +5,7 @@ from enum import Enum
|
|||||||
from app.commons import run_task, run_idle
|
from app.commons import run_task, run_idle
|
||||||
from app.connections import test_telnet, test_ftp, TestException, test_http, HttpApiException
|
from app.connections import test_telnet, test_ftp, TestException, test_http, HttpApiException
|
||||||
from app.settings import SettingsType, Settings, PlayStreamsMode
|
from app.settings import SettingsType, Settings, PlayStreamsMode
|
||||||
from app.ui.dialogs import show_dialog, DialogType
|
from app.ui.dialogs import show_dialog, DialogType, get_message
|
||||||
from .main_helper import update_entry_data, scroll_to
|
from .main_helper import update_entry_data, scroll_to
|
||||||
from .uicommons import Gtk, Gdk, UI_RESOURCES_PATH, FavClickMode, DEFAULT_ICON
|
from .uicommons import Gtk, Gdk, UI_RESOURCES_PATH, FavClickMode, DEFAULT_ICON
|
||||||
|
|
||||||
@@ -51,6 +51,7 @@ class SettingsDialog:
|
|||||||
"on_network_settings_visible": self.on_network_settings_visible,
|
"on_network_settings_visible": self.on_network_settings_visible,
|
||||||
"on_http_use_ssl_toggled": self.on_http_use_ssl_toggled,
|
"on_http_use_ssl_toggled": self.on_http_use_ssl_toggled,
|
||||||
"on_click_mode_togged": self.on_click_mode_togged,
|
"on_click_mode_togged": self.on_click_mode_togged,
|
||||||
|
"on_play_mode_changed": self.on_play_mode_changed,
|
||||||
"on_transcoding_preset_changed": self.on_transcoding_preset_changed,
|
"on_transcoding_preset_changed": self.on_transcoding_preset_changed,
|
||||||
"on_apply_presets": self.on_apply_presets,
|
"on_apply_presets": self.on_apply_presets,
|
||||||
"on_digit_entry_changed": self.on_digit_entry_changed,
|
"on_digit_entry_changed": self.on_digit_entry_changed,
|
||||||
@@ -381,7 +382,7 @@ class SettingsDialog:
|
|||||||
def show_info_message(self, text, message_type):
|
def show_info_message(self, text, message_type):
|
||||||
self._info_bar.set_visible(True)
|
self._info_bar.set_visible(True)
|
||||||
self._info_bar.set_message_type(message_type)
|
self._info_bar.set_message_type(message_type)
|
||||||
self._message_label.set_text(text)
|
self._message_label.set_text(get_message(text))
|
||||||
|
|
||||||
@run_idle
|
@run_idle
|
||||||
def show_spinner(self, show):
|
def show_spinner(self, show):
|
||||||
@@ -547,6 +548,13 @@ class SettingsDialog:
|
|||||||
|
|
||||||
return FavClickMode.DISABLED
|
return FavClickMode.DISABLED
|
||||||
|
|
||||||
|
def on_play_mode_changed(self, button):
|
||||||
|
if self._main_stack.get_visible_child_name() != "streaming":
|
||||||
|
return
|
||||||
|
|
||||||
|
if button.get_active():
|
||||||
|
self.show_info_message("Save and restart the program to apply the settings.", Gtk.MessageType.WARNING)
|
||||||
|
|
||||||
@run_idle
|
@run_idle
|
||||||
def set_play_stream_mode(self, mode):
|
def set_play_stream_mode(self, mode):
|
||||||
self._play_in_built_radio_button.set_sensitive(not self._settings.is_darwin)
|
self._play_in_built_radio_button.set_sensitive(not self._settings.is_darwin)
|
||||||
|
|||||||
Reference in New Issue
Block a user