Browse Source

08/21/2025

master
melancholytron 4 months ago
parent
commit
655107a566
  1. 69
      terminalTv.py

69
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
# 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"
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
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)}")])]

Loading…
Cancel
Save