Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- import os
- import tkinter as tk
- from tkinter import ttk, filedialog, messagebox
- import vlc
- import subprocess
- import threading
- # Constants
- CHANNELS_FOLDER = 'CHANNELS'
- VLC_PATH = r"C:\Program Files\VideoLAN\VLC\vlc.exe"
- WGET_PATH = r"C:\CMDER\APP\wget.exe" # Update this with the correct path to wget.exe
- FFMPEG_PATH = r"C:\CMDER\APP\ffmpeg.exe" # Update this with the correct path to ffmpeg.exe
- # Initialize VLC
- instance = vlc.Instance('--verbose 2')
- player = instance.media_player_new()
- # Initialize variables
- is_dragging_slider = False
- is_muted = False
- class NajeebChannelPlayer(tk.Tk):
- def __init__(self):
- super().__init__()
- self.title("Najeeb IPTV Channel Player")
- self.geometry("1000x600")
- self.configure(bg='#2E2E2E')
- self.channels_info = {}
- self.process = None
- self.is_fullscreen = False
- self.create_widgets()
- self.load_channels_from_folder()
- self.update_video_slider()
- def create_widgets(self):
- self.control_frame = ttk.Frame(self, style="TFrame")
- self.control_frame.pack(side=tk.TOP, fill=tk.X, padx=10, pady=5)
- self.search_entry = ttk.Entry(self.control_frame, width=50)
- self.search_entry.pack(side=tk.LEFT, padx=5, pady=5)
- search_button = ttk.Button(self.control_frame, text="Search", command=self.search_channels)
- search_button.pack(side=tk.LEFT, padx=5, pady=5)
- filter_button = ttk.Button(self.control_frame, text="Filter", command=self.filter_channels)
- filter_button.pack(side=tk.LEFT, padx=5, pady=5)
- copy_button = ttk.Button(self.control_frame, text="Copy URL", command=self.copy_selected_url)
- copy_button.pack(side=tk.LEFT, padx=5, pady=5)
- preview_button = ttk.Button(self.control_frame, text="Preview", command=self.preview_selected_channel)
- preview_button.pack(side=tk.LEFT, padx=5, pady=5)
- stop_button = ttk.Button(self.control_frame, text="Stop Preview", command=self.stop_preview)
- stop_button.pack(side=tk.LEFT, padx=5, pady=5)
- # Volume and Mute Controls
- volume_frame = ttk.Frame(self.control_frame, style="TFrame")
- volume_frame.pack(side=tk.LEFT, padx=5, pady=5)
- volume_label = ttk.Label(volume_frame, text="Volume")
- volume_label.pack(side=tk.LEFT)
- volume_slider = ttk.Scale(volume_frame, from_=0, to=100, orient=tk.HORIZONTAL, command=self.set_volume)
- volume_slider.set(50) # Default volume
- volume_slider.pack(side=tk.LEFT, padx=5)
- self.mute_button = ttk.Button(volume_frame, text="Mute", command=self.mute_unmute)
- self.mute_button.pack(side=tk.LEFT, padx=5)
- # Additional Buttons
- self.additional_buttons_frame = ttk.Frame(self, style="TFrame")
- self.additional_buttons_frame.pack(side=tk.TOP, fill=tk.X, padx=10, pady=5)
- capture_video_button = ttk.Button(self.additional_buttons_frame, text="Capture Video", command=self.capture_video)
- capture_video_button.pack(side=tk.LEFT, padx=5, pady=5)
- record_audio_button = ttk.Button(self.additional_buttons_frame, text="Record Audio", command=self.record_audio)
- record_audio_button.pack(side=tk.LEFT, padx=5, pady=5)
- stop_record_button = ttk.Button(self.additional_buttons_frame, text="Stop Recording", command=self.stop_recording)
- stop_record_button.pack(side=tk.LEFT, padx=5, pady=5)
- screenshot_button = ttk.Button(self.additional_buttons_frame, text="Capture Screenshots", command=self.capture_screenshots)
- screenshot_button.pack(side=tk.LEFT, padx=5, pady=5)
- fullscreen_button = ttk.Button(self.additional_buttons_frame, text="Full Screen", command=self.toggle_fullscreen)
- fullscreen_button.pack(side=tk.LEFT, padx=5, pady=5)
- download_button = ttk.Button(self.additional_buttons_frame, text="Download with wget", command=self.download_video)
- download_button.pack(side=tk.LEFT, padx=5, pady=5)
- download_ffmpeg_button = ttk.Button(self.additional_buttons_frame, text="Download with ffmpeg", command=self.download_with_ffmpeg)
- download_ffmpeg_button.pack(side=tk.LEFT, padx=5, pady=5)
- # Video control slider
- self.video_slider = ttk.Scale(self, from_=0, to=1000, orient=tk.HORIZONTAL)
- self.video_slider.pack(side=tk.BOTTOM, fill=tk.X, padx=5, pady=5)
- self.video_slider.bind("<ButtonPress-1>", self.slider_pressed)
- self.video_slider.bind("<ButtonRelease-1>", self.slider_released)
- self.result_frame = ttk.Frame(self, style="TFrame")
- self.result_frame.pack(side=tk.LEFT, fill=tk.BOTH, expand=False, padx=1, pady=5)
- self.result_text = tk.Listbox(self.result_frame, width=30, height=25, selectmode=tk.SINGLE, bg='#FFFFFF', fg='#000000')
- self.result_text.pack(side=tk.LEFT, fill=tk.BOTH, expand=False)
- # Add scrollbars
- vsb = ttk.Scrollbar(self.result_frame, orient="vertical", command=self.result_text.yview)
- vsb.pack(side=tk.RIGHT, fill="y")
- self.result_text.configure(yscrollcommand=vsb.set)
- self.result_text.bind('<Double-1>', self.play_selected_channel)
- self.video_frame = tk.Frame(self, bg='#000000')
- self.video_frame.pack(side=tk.RIGHT, fill=tk.BOTH, expand=True, padx=10, pady=5)
- self.video_panel = tk.Frame(self.video_frame, bg='#000000')
- self.video_panel.pack(fill=tk.BOTH, expand=True)
- self.bind("<Motion>", self.show_controls_on_mouse_move)
- def load_channels_from_folder(self):
- try:
- files = [f for f in os.listdir(CHANNELS_FOLDER) if f.endswith('.txt')]
- all_channels = []
- for file in files:
- file_path = os.path.join(CHANNELS_FOLDER, file)
- with open(file_path, 'r', encoding='utf-8') as f:
- all_channels.extend(f.readlines())
- self.process_text_data(all_channels)
- except FileNotFoundError:
- messagebox.showerror("Error", f"The folder '{CHANNELS_FOLDER}' does not exist.")
- except PermissionError:
- messagebox.showerror("Error", f"Permission denied while accessing '{CHANNELS_FOLDER}'.")
- except Exception as e:
- self.result_text.insert(tk.END, f"Error loading channels from folder: {str(e)}\n")
- def process_text_data(self, text_data):
- self.result_text.delete(0, tk.END)
- self.channels_info = {}
- for line in text_data:
- line = line.strip()
- if line:
- if "http" in line:
- # Find the URL by splitting on space
- parts = line.split(' ', 1)
- if len(parts) == 2:
- channel_name = parts[0].strip()
- url = parts[1].strip()
- self.channels_info[channel_name] = url
- self.result_text.insert(tk.END, channel_name)
- def search_channels(self):
- search_term = self.search_entry.get().lower()
- self.result_text.delete(0, tk.END)
- for channel_name, url in self.channels_info.items():
- if search_term in channel_name.lower():
- self.result_text.insert(tk.END, channel_name)
- def filter_channels(self):
- search_term = self.search_entry.get().lower()
- self.result_text.delete(0, tk.END)
- for channel_name, url in self.channels_info.items():
- if search_term in channel_name.lower() or search_term in url.lower():
- self.result_text.insert(tk.END, channel_name)
- def play_selected_channel(self, event):
- try:
- selected_channel = self.result_text.get(tk.ACTIVE)
- if selected_channel in self.channels_info:
- url = self.channels_info[selected_channel]
- subprocess.Popen([VLC_PATH, url])
- except (tk.TclError, KeyError):
- pass
- def preview_selected_channel(self):
- try:
- selected_channel = self.result_text.get(tk.ACTIVE)
- if selected_channel in self.channels_info:
- url = self.channels_info[selected_channel]
- self.play_vlc_stream(url)
- except (tk.TclError, KeyError):
- pass
- def play_vlc_stream(self, stream_url):
- media = instance.media_new(stream_url)
- player.set_media(media)
- player.set_hwnd(self.video_panel.winfo_id())
- player.play()
- self.update_video_slider()
- def slider_pressed(self, event):
- global is_dragging_slider
- is_dragging_slider = True
- def slider_released(self, event):
- global is_dragging_slider
- is_dragging_slider = False
- player.set_time(int(self.video_slider.get()))
- def update_video_slider(self):
- if player and not is_dragging_slider:
- position = player.get_time() / 1000.0
- self.video_slider.set(position * 1000.0)
- self.after(1000, self.update_video_slider)
- def stop_preview(self):
- if player:
- player.stop()
- def copy_selected_url(self):
- selected_channel = self.result_text.get(tk.ACTIVE).strip()
- if selected_channel in self.channels_info:
- url = self.channels_info[selected_channel]
- self.clipboard_clear()
- self.clipboard_append(url)
- messagebox.showinfo("Copied", f"URL for '{selected_channel}' copied to clipboard.")
- else:
- messagebox.showerror("Error", "No valid channel selected to copy URL.")
- def mute_unmute(self):
- global is_muted
- is_muted = not is_muted
- player.audio_toggle_mute()
- self.mute_button.config(text="Unmute" if is_muted else "Mute")
- def set_volume(self, value):
- player.audio_set_volume(int(float(value)))
- def capture_video(self):
- try:
- selected_channel = self.result_text.get(tk.ACTIVE).strip()
- if selected_channel in self.channels_info:
- url = self.channels_info[selected_channel]
- filename = filedialog.asksaveasfilename(defaultextension=".mp4", filetypes=[("MP4 files", "*.mp4")])
- if filename:
- command = [FFMPEG_PATH, '-y', '-i', url, '-t', '03:55:00', '-c', 'copy', filename]
- threading.Thread(target=lambda: subprocess.run(command)).start()
- messagebox.showinfo("Capturing", f"Capturing 03:55 minutes of video to {filename}")
- else:
- messagebox.showerror("Error", "Selected text is not a valid URL.")
- except tk.TclError:
- messagebox.showerror("Error", "No text selected.")
- def record_audio(self):
- try:
- selected_channel = self.result_text.get(tk.ACTIVE).strip()
- if selected_channel in self.channels_info:
- url = self.channels_info[selected_channel]
- filename = filedialog.asksaveasfilename(defaultextension=".mp3", filetypes=[("MP3 files", "*.mp3")])
- if filename:
- command = [FFMPEG_PATH, '-y', '-i', url, '-f', 'mp3', '-c:a', 'libmp3lame', filename]
- self.process = subprocess.Popen(command)
- messagebox.showinfo("Recording", f"Recording audio to {filename}")
- else:
- messagebox.showerror("Error", "Selected text is not a valid URL.")
- except tk.TclError:
- messagebox.showerror("Error", "No text selected.")
- def stop_recording(self):
- if self.process:
- self.process.terminate()
- self.process = None
- messagebox.showinfo("Stopped", "Recording stopped")
- def capture_screenshots(self):
- selected_channel = self.result_text.get(tk.ACTIVE).strip()
- if selected_channel in self.channels_info:
- url = self.channels_info[selected_channel]
- filename_base = filedialog.asksaveasfilename(defaultextension=".png", filetypes=[("PNG files", "*.png")])
- if filename_base:
- self.capture_screenshots_recursively(url, filename_base, 10, 2, 0)
- else:
- messagebox.showerror("Error", "Selected text is not a valid URL.")
- def capture_screenshots_recursively(self, url, filename_base, total_screenshots, interval, count):
- if count < total_screenshots:
- filename = f"{filename_base}_{count + 1}.png"
- player.video_take_snapshot(0, filename, 0, 0)
- self.after(interval * 1000, self.capture_screenshots_recursively, url, filename_base, total_screenshots, interval, count + 1)
- else:
- messagebox.showinfo("Capturing Screenshots", f"Captured {total_screenshots} screenshots every {interval} seconds to {filename_base}")
- def toggle_fullscreen(self):
- self.is_fullscreen = not self.is_fullscreen
- self.attributes("-fullscreen", self.is_fullscreen)
- self.control_frame.pack_forget() if self.is_fullscreen else self.control_frame.pack(side=tk.TOP, fill=tk.X, padx=10, pady=5)
- self.additional_buttons_frame.pack_forget() if self.is_fullscreen else self.additional_buttons_frame.pack(side=tk.TOP, fill=tk.X, padx=10, pady=5)
- self.result_frame.pack_forget() if self.is_fullscreen else self.result_frame.pack(side=tk.LEFT, fill=tk.BOTH, expand=False, padx=1, pady=5)
- def show_controls_on_mouse_move(self, event):
- if self.is_fullscreen:
- self.control_frame.pack(side=tk.TOP, fill=tk.X, padx=10, pady=5)
- self.additional_buttons_frame.pack(side=tk.TOP, fill=tk.X, padx=10, pady=5)
- self.result_frame.pack(side=tk.LEFT, fill=tk.BOTH, expand=False, padx=1, pady=5)
- self.after(2000, self.hide_controls)
- def hide_controls(self):
- if self.is_fullscreen:
- self.control_frame.pack_forget()
- self.additional_buttons_frame.pack_forget()
- self.result_frame.pack_forget()
- def download_video(self):
- selected_channel = self.result_text.get(tk.ACTIVE).strip()
- if selected_channel in self.channels_info:
- url = self.channels_info[selected_channel]
- filename = filedialog.asksaveasfilename(defaultextension=".mp4", filetypes=[("MP4 files", "*.mp4")])
- if filename:
- command = [WGET_PATH, url, "-O", filename]
- threading.Thread(target=lambda: subprocess.run(command)).start()
- messagebox.showinfo("Downloading", f"Downloading video to {filename}")
- else:
- messagebox.showerror("Error", "Selected text is not a valid URL.")
- def download_with_ffmpeg(self):
- selected_channel = self.result_text.get(tk.ACTIVE).strip()
- if selected_channel in self.channels_info:
- url = self.channels_info[selected_channel]
- filename = filedialog.asksaveasfilename(defaultextension=".mp4", filetypes=[("MP4 files", "*.mp4")])
- if filename:
- command = [FFMPEG_PATH, '-y', '-i', url, '-c', 'copy', filename]
- print(f"Running command: {' '.join(command)}") # Print the command for debugging
- try:
- threading.Thread(target=lambda: subprocess.run(command)).start()
- messagebox.showinfo("Downloading", f"Downloading video with ffmpeg to {filename}")
- except Exception as e:
- messagebox.showerror("Error", f"Failed to start download: {str(e)}")
- else:
- messagebox.showerror("Error", "Selected text is not a valid URL.")
- if __name__ == "__main__":
- app = NajeebChannelPlayer()
- app.mainloop()
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement