import os import sys import urllib.parse import requests import time from PyQt5.QtWidgets import (QApplication, QMainWindow, QWidget, QVBoxLayout, QHBoxLayout, QPushButton, QLabel, QListWidget, QSlider, QMessageBox, QTextEdit, QProgressBar) from PyQt5.QtCore import Qt, QTimer, QThread, pyqtSignal import vlc class VLCIPTVPlayer(QMainWindow): def __init__(self): super().__init__() self.setWindowTitle("VLC IPTV Player") self.resize(1024, 768) # Debug console self.debug_console = QTextEdit() self.debug_console.setReadOnly(True) # Setup UI first so we can show debug messages self.init_ui() self.log_message("Application started") # Initialize VLC self.init_vlc() # Setup PHP environment self.php_dir = os.path.dirname(__file__) # Use script directory self.required_files = { "myportal.php": "https://iptv.nywebforum.com/myportal.php?download=true", "mac_list.php": "https://iptv.nywebforum.com/mac_list.php?download=true", "playlist.m3u": "https://iptv.nywebforum.com/playlist.m3u" } # Check local files first self.load_default_playlist() def init_ui(self): """Initialize the user interface with debug console""" main_widget = QWidget(self) self.setCentralWidget(main_widget) layout = QVBoxLayout() main_widget.setLayout(layout) # Debug console at top layout.addWidget(self.debug_console, 1) # Video frame self.video_frame = QWidget() self.video_frame.setStyleSheet("background-color: black;") layout.addWidget(self.video_frame, 3) # Playlist self.playlist = QListWidget() self.playlist.itemDoubleClicked.connect(self.play_selected) layout.addWidget(self.playlist, 1) # Controls control_layout = QHBoxLayout() self.play_button = QPushButton("Play") self.play_button.clicked.connect(self.play_selected) self.stop_button = QPushButton("Stop") self.stop_button.clicked.connect(self.stop) self.reload_button = QPushButton("Update Files") self.reload_button.clicked.connect(self.update_files) self.volume_slider = QSlider(Qt.Horizontal) self.volume_slider.setRange(0, 100) self.volume_slider.setValue(50) self.volume_slider.valueChanged.connect(self.set_volume) control_layout.addWidget(self.play_button) control_layout.addWidget(self.stop_button) control_layout.addWidget(self.reload_button) control_layout.addWidget(QLabel("Volume:")) control_layout.addWidget(self.volume_slider) layout.addLayout(control_layout) def init_vlc(self): """Initialize VLC media player with error handling""" try: self.log_message("Initializing VLC...") self.instance = vlc.Instance() self.media_player = self.instance.media_player_new() if sys.platform == "win32": self.media_player.set_hwnd(self.video_frame.winId()) self.log_message("VLC Windows handle set") else: self.media_player.set_xwindow(self.video_frame.winId()) self.log_message("VLC XWindow set") self.log_message("VLC initialized successfully") return True except Exception as e: self.log_message(f"VLC initialization failed: {str(e)}", error=True) QMessageBox.critical(self, "VLC Error", "Failed to initialize VLC player.\n" "Please ensure VLC is installed from videolan.org") return False def log_message(self, message, error=False): """Add message to debug console""" timestamp = time.strftime("%H:%M:%S", time.localtime()) if error: self.debug_console.setTextColor(Qt.red) self.debug_console.append(f"[ERROR {timestamp}] {message}") else: self.debug_console.setTextColor(Qt.black) self.debug_console.append(f"[INFO {timestamp}] {message}") self.debug_console.setTextColor(Qt.black) self.debug_console.ensureCursorVisible() def update_files(self): """Update PHP and playlist files""" self.log_message("Starting file updates...") for filename, url in self.required_files.items(): filepath = os.path.join(self.php_dir, filename) try: # Special handling for PHP files - use download mode if filename.endswith('.php'): url = f"{url.split('?')[0]}?download=true" response = requests.get(url, timeout=10) response.raise_for_status() with open(filepath, 'wb') as f: f.write(response.content) self.log_message(f"Updated {filename}") except Exception as e: self.log_message(f"Failed to update {filename}: {str(e)}", error=True) self.load_default_playlist() def load_default_playlist(self): """Load and process the default playlist""" playlist_path = os.path.join(self.php_dir, "playlist.m3u") if os.path.exists(playlist_path): try: with open(playlist_path, "r", encoding="utf-8") as f: lines = f.readlines() self.playlist.clear() for line in lines: line = line.strip() if line and not line.startswith("#"): self.playlist.addItem(line) self.log_message(f"Loaded playlist with {self.playlist.count()} items") except Exception as e: self.log_message(f"Error loading playlist: {str(e)}", error=True) else: self.log_message("Playlist file not found", error=True) def play_selected(self): """Play the selected stream with error handling""" selected_items = self.playlist.selectedItems() if not selected_items: self.log_message("No stream selected", error=True) return original_url = selected_items[0].text() self.log_message(f"Attempting to play: {original_url}") try: # Process PHP URLs locally if we have the files if "myportal.php" in original_url: php_file = os.path.join(self.php_dir, "myportal.php") if os.path.exists(php_file): self.log_message("Processing with local PHP script...") parsed = urllib.parse.urlparse(original_url) params = urllib.parse.parse_qs(parsed.query) # Execute PHP locally stream_url = self.execute_php("myportal.php", params) else: stream_url = original_url self.log_message("Using original URL (no local PHP file)") if not stream_url.startswith(("http://", "https://")): raise Exception("Invalid stream URL returned by PHP script") else: stream_url = original_url self.log_message(f"Final stream URL: {stream_url}") # Play with VLC media = self.instance.media_new(stream_url) self.media_player.set_media(media) if self.media_player.play() == -1: raise Exception("VLC failed to start playback") self.log_message("Playback started successfully") except Exception as e: self.log_message(f"Playback error: {str(e)}", error=True) QMessageBox.critical(self, "Playback Error", f"Could not play stream:\n{str(e)}") def execute_php(self, script_name, params): """Execute PHP script locally""" script_path = os.path.join(self.php_dir, script_name) if not os.path.exists(script_path): raise Exception(f"PHP script not found: {script_name}") # Prepare command param_str = " ".join(f"{k}={v[0]}" for k, v in params.items()) # Try different execution methods try: import subprocess result = subprocess.run( ["php", script_path] + param_str.split(), capture_output=True, text=True, check=True ) return result.stdout.strip() except: try: cmd = f"php {script_path} {param_str}" with os.popen(cmd) as p: return p.read().strip() except: raise Exception("Failed to execute PHP script") def stop(self): """Stop playback""" self.media_player.stop() self.log_message("Playback stopped") def set_volume(self, value): """Set player volume""" self.media_player.audio_set_volume(value) self.log_message(f"Volume set to {value}%") def closeEvent(self, event): """Handle window close with cleanup""" self.stop() super().closeEvent(event) if __name__ == "__main__": # Verify dependencies app = QApplication(sys.argv) missing_deps = [] for dep in ["vlc", "requests"]: try: __import__(dep) except ImportError: missing_deps.append(dep) if missing_deps: msg = "Missing dependencies:\n" + "\n".join(f"- {dep}" for dep in missing_deps) msg += "\n\nPlease install with: pip install " + " ".join(missing_deps) QMessageBox.critical(None, "Missing Dependencies", msg) sys.exit(1) # Create and show player player = VLCIPTVPlayer() player.show() sys.exit(app.exec_())