diff --git a/terminalTv.py b/terminalTv.py index 3f8cbf6..6af99ab 100644 --- a/terminalTv.py +++ b/terminalTv.py @@ -3,6 +3,7 @@ import os import re import subprocess import sys +import json import xml.etree.ElementTree as ET from datetime import datetime, timedelta from urllib.request import urlopen, Request @@ -11,27 +12,53 @@ from urllib.error import URLError import threading import time -# Configuration -M3U_URL = "http://10.0.0.17:8409/iptv/channels.m3u" -XMLTV_URL = "http://10.0.0.17:8409/iptv/xmltv.xml" -MPV_COMMAND = ["mpv", "--really-quiet", "--no-terminal", "--force-window=immediate"] -USER_AGENT = "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/91.0.4472.124 Safari/537.36" -UPDATE_INTERVAL = 900 # 15 minutes in seconds +# Load configuration from JSON file +try: + with open('config.json') as config_file: + config = json.load(config_file) + M3U_URL = config.get('m3u_url', "http://10.0.0.17:8409/iptv/channels.m3u") + XMLTV_URL = config.get('xmltv_url', "http://10.0.0.17:8409/iptv/xmltv.xml") + USER_AGENT = config.get('user_agent', "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/91.0.4472.124 Safari/537.36") + UPDATE_INTERVAL = config.get('update_interval', 900) + MONITOR = config.get('monitor', None) + + # Base MPV command with monitor options if specified + MPV_BASE = ["mpv"] + if MONITOR is not None: + MPV_BASE.extend(["--fs", f"--fs-screen={MONITOR}"]) + MPV_BASE.extend(config.get('mpv_options', [ + "--really-quiet", + "--no-terminal", + "--force-window=immediate" + ])) +except FileNotFoundError: + print("Configuration file not found, using default settings") + M3U_URL = "http://10.0.0.17:8409/iptv/channels.m3u" + XMLTV_URL = "http://10.0.0.17:8409/iptv/xmltv.xml" + USER_AGENT = "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/91.0.4472.124 Safari/537.36" + UPDATE_INTERVAL = 900 + MONITOR = None + MPV_BASE = [ + "mpv", + "--really-quiet", + "--no-terminal", + "--force-window=immediate" + ] -# Color Palette +# Color Palette remains the same PALETTE = [ ('header', 'white', 'dark blue'), ('footer', 'white', 'dark blue'), - ('channel', 'black', 'light gray'), + ('channel', 'black', 'light cyan'), ('channel_focus', 'white', 'dark blue'), ('program_now', 'white', 'dark green'), ('program_next', 'black', 'light gray'), ('error', 'white', 'dark red'), - ('divider', 'light gray', ''), - ('program_desc', 'light cyan', ''), # New color for descriptions - ('time', 'yellow', ''), # New color for time displays - ('title', 'bold', ''), # New color for titles - ('update', 'light green', ''), # Color for update notifications + ('divider', 'dark green', ''), + ('program_desc', 'light cyan', ''), + ('time', 'yellow', ''), + ('title', 'bold', ''), + ('update', 'light blue', ''), ] # ASCII Art @@ -235,7 +262,8 @@ class IPTVPlayer: self.program_listbox = urwid.ListBox(self.program_walker) # Add update time to footer - self.footer_text = urwid.Text("Q: Quit | ↑↓: Navigate | Enter: Play Channel | L: Reload | Last update: Loading...", align='center') + monitor_info = f" | Monitor: {MONITOR}" if MONITOR is not None else "" + self.footer_text = urwid.Text(f"Q: Quit | ↑↓: Navigate | Enter: Play Channel | L: Reload | Last update: Loading...{monitor_info}", align='center') self.footer = urwid.AttrMap(self.footer_text, 'footer') program_frame = urwid.Frame( @@ -276,7 +304,8 @@ class IPTVPlayer: def update_footer(self): """Update footer with last update time""" time_str = self.last_update.strftime("%H:%M:%S") - self.footer_text.set_text(f"Q: Quit | ↑↓: Navigate | Enter: Play Channel | L: Reload | Last update: {time_str}") + monitor_info = f" | Monitor: {MONITOR}" if MONITOR is not None else "" + self.footer_text.set_text(f"Q: Quit | ↑↓: Navigate | Enter: Play Channel | L: Reload | Last update: {time_str}{monitor_info}") def start_update_thread(self): """Start background thread for periodic updates""" @@ -359,7 +388,7 @@ class IPTVPlayer: info = [] max_line_length = 60 # Define this at the top so it's available everywhere - info.append([("header", f"📺 Channel: {channel['name']}")]) + info.append([("header", f"--Channel: {channel['name']}")]) if channel.get('group'): info.append([("title", f"Group: {channel['group']}")]) @@ -372,7 +401,7 @@ class IPTVPlayer: # Current show section with colorful formatting info.append([]) # Empty line - info.append([("program_now", "⏺ NOW PLAYING")]) + info.append([("program_now", "--NOW PLAYING")]) info.append([("title", f"Title: {channel['current_show']['title']}")]) info.append([ ("time", f"Time: {start_time} - {end_time} "), @@ -381,7 +410,7 @@ class IPTVPlayer: if channel['current_show']['desc']: info.append([]) # Empty line - info.append([("program_desc", "📝 Description:")]) + info.append([("program_desc", "--Description:")]) # Split long description into multiple lines desc = channel['current_show']['desc'] for i in range(0, len(desc), max_line_length): @@ -395,13 +424,13 @@ class IPTVPlayer: info.append([]) # Empty line info.append([("divider", "─" * 50)]) info.append([]) # Empty line - info.append([("program_next", "⏭ UP NEXT")]) + info.append([("program_next", "--UP NEXT")]) info.append([("title", f"Title: {channel['next_show']['title']}")]) info.append([("time", f"Time: {next_start} - {next_end}")]) if channel['next_show']['desc']: info.append([]) # Empty line - info.append([("program_desc", "📝 Description:")]) + info.append([("program_desc", "--Description:")]) desc = channel['next_show']['desc'] # Limit description to 5 lines to prevent overflow max_lines = 5 @@ -419,13 +448,13 @@ class IPTVPlayer: next_end = channel['next_show']['stop'].strftime("%H:%M") info.append([]) # Empty line - info.append([("program_next", "⏭ UP NEXT")]) + info.append([("program_next", "--UP NEXT")]) info.append([("title", f"Title: {channel['next_show']['title']}")]) info.append([("time", f"Time: {next_start} - {next_end}")]) if channel['next_show']['desc']: info.append([]) # Empty line - info.append([("program_desc", "📝 Description:")]) + info.append([("program_desc", "--Description:")]) desc = channel['next_show']['desc'] # Limit description to 5 lines to prevent overflow max_lines = 5 @@ -447,7 +476,7 @@ class IPTVPlayer: self.mpv_process.wait() try: - self.mpv_process = subprocess.Popen(MPV_COMMAND + [url]) + self.mpv_process = subprocess.Popen(MPV_BASE + [url]) except Exception as e: # Create proper widget for error message self.program_walker[:] = [urwid.Text([("error", f"Failed to play stream: {str(e)}")])]