diff --git a/usr/lib/hypnotix/common.py b/usr/lib/hypnotix/common.py index 0e60b5f..c4e1293 100755 --- a/usr/lib/hypnotix/common.py +++ b/usr/lib/hypnotix/common.py @@ -98,11 +98,14 @@ def __init__(self, provider, info): self.group_title = None self.title = None self.url = None + self.lcn = None match = EXTINF.fullmatch(info) if match is not None: res = match.groupdict() if 'params' in res: params = dict(PARAMS.findall(res['params'])) + if "tvg-lcn" in params and params['tvg-lcn'].strip() != "": + self.lcn = params['tvg-lcn'].strip() if "tvg-name" in params and params['tvg-name'].strip() != "": self.name = params['tvg-name'].strip() if "tvg-logo" in params and params['tvg-logo'].strip() != "": diff --git a/usr/lib/hypnotix/hypnotix.py b/usr/lib/hypnotix/hypnotix.py index 4885ac5..a07776b 100755 --- a/usr/lib/hypnotix/hypnotix.py +++ b/usr/lib/hypnotix/hypnotix.py @@ -542,6 +542,15 @@ def show_channels(self, channels, favorites=False): self.download_channel_logos(logos_to_refresh) else: self.sidebar.hide() + + self.update_hchannels() + self.chan_lcn_buf = 0 + self.timeoutID = 0 + try: + self.active_channel = self.hchannels[0].channel + except: + pass + self.prev_channel = None def show_vod(self, items): logos_to_refresh = [] @@ -713,6 +722,9 @@ def on_search_bar(self, widget): self.latest_search_bar_text = search_bar_text self.search_bar.set_sensitive(False) GLib.timeout_add_seconds(0.1, self.on_search) + + def update_hchannels(self): + self.hchannels = [c for c in self.channels_listbox.get_children() if unidecode(self.search_bar.get_text()).lower() in c.channel.name.lower()] def on_search(self): self.visible_search_results = 0 @@ -728,6 +740,7 @@ def on_search(self): self.search_bar.set_sensitive(True) self.search_bar.grab_focus_without_selecting() self.navigate_to("channels_page") + self.update_hchannels() def init_channels_listbox(self): self.latest_search_bar_text = None @@ -859,18 +872,29 @@ def on_favorite_button_toggled(self, widget): self.manager.save_favorites(self.favorite_data) def on_channel_activated(self, box, widget): + self.prev_channel = self.active_channel self.active_channel = widget.channel self.play_async(self.active_channel) def on_prev_channel(self): if self.stack.get_visible_child_name() == "channels_page": - self.channels_listbox.do_move_cursor(self.channels_listbox, Gtk.MovementStep.DISPLAY_LINES, -1) - self.channels_listbox.do_activate_cursor_row(self.channels_listbox) + idx = self.channels_listbox_selected_index() + step = -1 if idx != 0 else (len(self.hchannels) - 1) + self.channels_listbox_activate_row(step) def on_next_channel(self): if self.stack.get_visible_child_name() == "channels_page": - self.channels_listbox.do_move_cursor(self.channels_listbox, Gtk.MovementStep.DISPLAY_LINES, 1) - self.channels_listbox.do_activate_cursor_row(self.channels_listbox) + idx = self.channels_listbox_selected_index() + step = 1 if idx != (len(self.hchannels) - 1) else (1 - len(self.hchannels)) + self.channels_listbox_activate_row(step) + + def channels_listbox_selected_index(self): + channel = [c for c in self.hchannels if c.channel.name == self.active_channel.name][0] + return self.hchannels.index(channel) + + def channels_listbox_activate_row(self, step): + self.channels_listbox.do_move_cursor(self.channels_listbox, Gtk.MovementStep.DISPLAY_LINES, step) + self.channels_listbox.do_activate_cursor_row(self.channels_listbox) @async_function def play_async(self, channel): @@ -1449,6 +1473,11 @@ def on_menu_quit(self, widget): self.application.quit() def on_key_press_event(self, widget, event): + try: + widgetType = widget.get_focus().get_name() + except: # we can pretend the channel widget is focused + widgetType = "ChannelWidget" + channel_focused = self.fullscreen or "ChannelWidget" in widgetType # Get any active, but not pressed modifiers, like CapsLock and NumLock persistant_modifiers = Gtk.accelerator_get_default_mod_mask() @@ -1457,6 +1486,11 @@ def on_key_press_event(self, widget, event): # Bool of Control or Shift modifier states ctrl = modifier == Gdk.ModifierType.CONTROL_MASK shift = modifier == Gdk.ModifierType.SHIFT_MASK + + def activate_hchannel(chan): + idx = self.channels_listbox_selected_index() + step = self.hchannels.index(chan) - idx + self.channels_listbox_activate_row(step) if ctrl and event.keyval == Gdk.KEY_r: self.reload(page=None, refresh=True) @@ -1481,6 +1515,53 @@ def on_key_press_event(self, widget, event): self.on_prev_channel() elif event.keyval == Gdk.KEY_Right: self.on_next_channel() + return True + elif event.keyval == Gdk.KEY_Home: + if channel_focused: + chan = [c for c in self.hchannels if c.channel == self.prev_channel][0] + activate_hchannel(chan) + return True + elif event.keyval == Gdk.KEY_Return: + if channel_focused: + try: + chan = [c for c in self.hchannels if c.channel.lcn == str(self.chan_lcn_buf)] + + """ + + If this branch will be merged with "epg", it's very easy to jump across channels using + their EPG numbers (without needing a lcn tag) just by adding the lines here below: + + + if (len(chan) == 0 and self.epg is not None): + epg_channel = [p.attrib["id"] for p in self.epg.findall("channel") if p.attrib["id"].split()[-1] == str(self.chan_lcn_buf)][0] + chan = [c for c in self.hchannels if chan_match(c.channel.name, epg_channel)] + + """ + + activate_hchannel(chan[0]) + finally: + self.chan_lcn_buf = 0 + return True + else: + self.chan_lcn_buf = 0 + else: + if channel_focused: + try: + self.chan_lcn_buf = self.chan_lcn_buf * 10 + int(chr(event.keyval)) + timeout = 1500 + self.mpv.command("show-text", str(self.chan_lcn_buf) + "-", timeout) + + def reset_chan_lcn_buf(): + self.chan_lcn_buf = 0 + return False + + if (self.timeoutID != 0): + GLib.source_remove(self.timeoutID) + self.timeoutID = 0 + + self.timeoutID = GLib.timeout_add(timeout, reset_chan_lcn_buf) + except: + self.chan_lcn_buf = 0 # elif event.keyval == Gdk.KEY_Up: # # Up of in the list # pass