Compare commits

...

2 Commits

@ -86,6 +86,7 @@ class Cast(wx.Frame):
self.m_chromecasts, self.m_browser = pychromecast.get_chromecasts() self.m_chromecasts, self.m_browser = pychromecast.get_chromecasts()
def get_player_controls(self, channel_index: int, uri: str) -> wx.BoxSizer: def get_player_controls(self, channel_index: int, uri: str) -> wx.BoxSizer:
outer_sizer = wx.BoxSizer(wx.VERTICAL)
inner_sizer = wx.BoxSizer(wx.HORIZONTAL) inner_sizer = wx.BoxSizer(wx.HORIZONTAL)
play_button = wx.Button(self.m_panel, play_button = wx.Button(self.m_panel,
-1, -1,
@ -104,8 +105,8 @@ class Cast(wx.Frame):
if self.m_mode == 'normal': if self.m_mode == 'normal':
back_button = wx.Button(self.m_panel, back_button = wx.Button(self.m_panel,
-1, -1,
"Back", "Go Back",
size=(WIDTH / 4, BTN_HEIGHT)) size=(WIDTH, BTN_HEIGHT))
back_button.Bind( back_button.Bind(
wx.EVT_BUTTON, wx.EVT_BUTTON,
lambda event, cindex=channel_index: self.show_video_list( lambda event, cindex=channel_index: self.show_video_list(
@ -115,12 +116,12 @@ class Cast(wx.Frame):
back_button = wx.Button(self.m_panel, back_button = wx.Button(self.m_panel,
-1, -1,
label="Close", label="Close",
size=(WIDTH / 4, BTN_HEIGHT)) size=(WIDTH, BTN_HEIGHT))
back_button.Bind(wx.EVT_BUTTON, lambda event: self.Destroy()) back_button.Bind(wx.EVT_BUTTON, lambda event: self.Destroy())
outer_sizer.Add(back_button, FLAGS)
inner_sizer.Add(play_button, FLAGS) inner_sizer.Add(play_button, FLAGS)
inner_sizer.Add(pause_button, FLAGS) inner_sizer.Add(pause_button, FLAGS)
inner_sizer.Add(stop_button, FLAGS) inner_sizer.Add(stop_button, FLAGS)
inner_sizer.Add(back_button, FLAGS)
if self.has_usable_chromecasts(): if self.has_usable_chromecasts():
btm = make_bitmap_from_file( btm = make_bitmap_from_file(
@ -151,10 +152,12 @@ class Cast(wx.Frame):
play_button.Bind(wx.EVT_BUTTON, self.play) play_button.Bind(wx.EVT_BUTTON, self.play)
pause_button.Bind(wx.EVT_BUTTON, self.pause) pause_button.Bind(wx.EVT_BUTTON, self.pause)
stop_button.Bind(wx.EVT_BUTTON, self.stop) stop_button.Bind(wx.EVT_BUTTON, self.stop)
outer_sizer.Add(inner_sizer, FLAGS)
inner_sizer.Fit(self) inner_sizer.Fit(self)
inner_sizer.Layout() outer_sizer.Fit(self)
outer_sizer.Layout()
return inner_sizer return outer_sizer
def get_providers(self) -> list[ChannelProvider]: def get_providers(self) -> list[ChannelProvider]:
@ -185,7 +188,8 @@ class Cast(wx.Frame):
channels = list() channels = list()
for id in chandict[provider]["channels"]: for id in chandict[provider]["channels"]:
channels.append(SVT.SVT(id)) channels.append(SVT.SVT(id))
svt = ChannelProvider(chandict[provider]["displayname"], channels=channels) svt = ChannelProvider(chandict[provider]["displayname"],
channels=channels)
providers.append(svt) providers.append(svt)
return providers return providers
@ -202,15 +206,13 @@ class Cast(wx.Frame):
break break
return result return result
def show_channel_list(self, _, provider_index) -> None: def show_channel_list(self, _, provider_index) -> None:
self.m_selected_provider_index = provider_index self.m_selected_provider_index = provider_index
self.m_selected_provider = self.m_providers[provider_index] self.m_selected_provider = self.m_providers[provider_index]
self.m_sizer.Clear(delete_windows=True) self.m_sizer.Clear(delete_windows=True)
self.m_sizer = wx.BoxSizer(wx.VERTICAL) self.m_sizer = wx.BoxSizer(wx.VERTICAL)
if len(self.m_providers) > 1: if len(self.m_providers) > 1:
back_callback = lambda event: self.show_provider_list( back_callback = lambda event: self.show_provider_list(event)
event)
self.add_back_button(back_callback) self.add_back_button(back_callback)
else: else:
closebtn = wx.Button(self.m_panel, closebtn = wx.Button(self.m_panel,
@ -387,7 +389,7 @@ class Cast(wx.Frame):
self.m_sizer.Add(cancel_btn) self.m_sizer.Add(cancel_btn)
for cast in self.m_chromecasts: for cast in self.m_chromecasts:
if cast.cast_type == 'audio': if cast.cast_type == 'audio':
continue continue
friendly_name = "Unknown Chromecast" friendly_name = "Unknown Chromecast"
try: try:
@ -395,9 +397,9 @@ class Cast(wx.Frame):
except AttributeError: except AttributeError:
friendly_name = cast.cast_info.friendly_name friendly_name = cast.cast_info.friendly_name
btn = wx.Button(self.m_panel, btn = wx.Button(self.m_panel,
id=-1, id=-1,
label=friendly_name, label=friendly_name,
size=(WIDTH, BTN_HEIGHT)) size=(WIDTH, BTN_HEIGHT))
btn.Bind( btn.Bind(
wx.EVT_BUTTON, wx.EVT_BUTTON,
lambda event, chromecast=cast, muri=uri, cindex=channel_index: lambda event, chromecast=cast, muri=uri, cindex=channel_index:

@ -22,7 +22,8 @@ BASEPATH = path.join(str(environ.get("HOME")), '.config/cast')
DB_FILE_NAME = 'cast.db' DB_FILE_NAME = 'cast.db'
SUB_TABLE = 'subscriptions' SUB_TABLE = 'subscriptions'
VIDEO_TABLE = 'videos' VIDEO_TABLE = 'videos'
USE_CACHED_CATEGORIES = False CAT_CACHE = None
CHAN_CACHE = None
def add_video(video_id: str, def add_video(video_id: str,
@ -77,27 +78,44 @@ def get_svt_thumb_from_id_changed(id: str,
size, id, changed) size, id, changed)
def get_all_svt_categories(basepath=BASEPATH) -> list: def get_all_svt_categories() -> list:
global USE_CACHED_CATEGORIES global CAT_CACHE
categoryfile = path.join(basepath,"categories.json") if CAT_CACHE:
if USE_CACHED_CATEGORIES: categories = CAT_CACHE
if path.isfile(categoryfile): else:
with open(categoryfile, 'r') as jfile: categories: list = list()
return(json.loads(jfile.read())) url = "https://www.svtplay.se/kategori"
data = get_svt_data(url)
for entry in data:
if 'genres' in entry.keys():
categories = entry['genres']
break
CAT_CACHE = categories
return categories
categories: list = list() def get_all_svt_channels() -> dict:
url = "https://www.svtplay.se/kategori" url = "https://www.svtplay.se/kanaler"
result: dict = dict()
data = get_svt_data(url) data = get_svt_data(url)
for entry in data: for entry in data:
if 'genres' in entry.keys(): if "channels" in entry:
categories = entry['genres'] for channel in entry["channels"]:
break if type(entry["channels"][channel]) == type(list()):
with open(categoryfile, 'w') as jfile: for item in entry["channels"][channel]:
jfile.write(json.dumps(categories)) if item["__typename"] == "Channel" and "running" in item:
USE_CACHED_CATEGORIES = True result[item["id"]] = {
return categories "thumbnail":
make_bitmap_from_url(
get_svt_thumb_from_id_changed(
item["running"]["image"]['id'],
item["running"]["image"]['changed'],
SCREEN_WIDTH),
wx.Size(width=SCREEN_WIDTH, height=480)),
"name":
item["name"]
}
return result
def get_svt_category(category: str) -> list: def get_svt_category(category: str) -> list:
@ -118,8 +136,8 @@ def get_svt_data(url: str) -> list:
result: list = list() result: list = list()
res = requests.get(url) res = requests.get(url)
soup = BeautifulSoup(res.text, features="lxml") soup = BeautifulSoup(res.text, features="lxml")
data = json.loads( data = json.loads(soup.find(
soup.find(id="__NEXT_DATA__").string)["props"]["urqlState"] id="__NEXT_DATA__").string)["props"]["urqlState"] # type: ignore
for key in data.keys(): for key in data.keys():
result.append(json.loads(data[key]["data"])) result.append(json.loads(data[key]["data"]))
return result return result
@ -232,9 +250,9 @@ def get_svt_thumbnail(link: str) -> str:
page = requests.get(link) page = requests.get(link)
soup = BeautifulSoup(page.text, 'html.parser') soup = BeautifulSoup(page.text, 'html.parser')
meta = soup.find(property="og:image") meta = soup.find(property="og:image")
image_link = meta["content"] image_link = meta["content"] #type: ignore
return image_link return image_link # type: ignore
def get_videos(channel_id: str, def get_videos(channel_id: str,
@ -308,7 +326,9 @@ def make_sized_button(parent_pnl: wx.Panel, bitmap_or_str: Union[wx.Bitmap,
return btn_sizer return btn_sizer
def make_bitmap_from_url(logo_url: str, size: wx.Size = SIZE, video_id: str = "") -> wx.Bitmap: def make_bitmap_from_url(logo_url: str,
size: wx.Size = SIZE,
video_id: str = "") -> wx.Bitmap:
if not video_id: if not video_id:
video_id = hash_string(logo_url) video_id = hash_string(logo_url)
thumbpath = path.join(BASEPATH, 'thumbnails') thumbpath = path.join(BASEPATH, 'thumbnails')
@ -344,57 +364,34 @@ def make_bitmap_from_file(path, size: wx.Size = SIZE) -> wx.Bitmap:
def resolve_svt_channel(svt_id: str, path: str = '/usr/share/cast') -> dict: def resolve_svt_channel(svt_id: str, path: str = '/usr/share/cast') -> dict:
global CHAN_CACHE
channels = { if CHAN_CACHE:
"ch-barnkanalen": { channels = CHAN_CACHE
"name": else:
"Barnkanalen", channels = get_all_svt_channels()
"thumbnail": channels["feed"] = {
make_bitmap_from_file('{}/assets/Barnkanalen.png'.format(path))
},
"ch-svt1": {
"name": "SVT 1",
"thumbnail":
make_bitmap_from_file('{}/assets/SVT1.png'.format(path))
},
"ch-svt2": {
"name": "SVT 2",
"thumbnail":
make_bitmap_from_file('{}/assets/SVT2.png'.format(path))
},
"ch-svt24": {
"name": "SVT 24",
"thumbnail":
make_bitmap_from_file('{}/assets/SVT24.png'.format(path))
},
"ch-kunskapskanalen": {
"name":
"Kunskapskanalen",
"thumbnail":
make_bitmap_from_file('{}/assets/Kunskapskanalen.png'.format(path))
},
"feed": {
"name": "Senaste program", "name": "Senaste program",
"thumbnail": "thumbnail":
make_bitmap_from_file('{}/assets/SVT.png'.format(path)) make_bitmap_from_file('{}/assets/SVT.png'.format(path))
}, }
"allprograms": { channels["allprograms"] = {
"name": "Alla program", "name": "Alla program",
"thumbnail": "thumbnail":
make_bitmap_from_file('{}/assets/SVT.png'.format(path)) make_bitmap_from_file('{}/assets/SVT.png'.format(path))
},
}
for category in get_all_svt_categories():
channels[category['id']] = {
"name":
category["name"],
"thumbnail":
make_bitmap_from_url(
get_svt_thumb_from_id_changed(category['image']['id'],
category['image']['changed']))
} }
for category in get_all_svt_categories():
channels[category['id']] = {
"name":
category["name"],
"thumbnail":
make_bitmap_from_url(
get_svt_thumb_from_id_changed(
category['image']['id'], category['image']['changed']))
}
CHAN_CACHE = channels
return channels[svt_id] return channels[svt_id]

Loading…
Cancel
Save