import gradio as gr
import time
import json
from typing import Dict, List, Tuple
import random
class ChromecastController:
def __init__(self):
self.tv_states = {
1: {"name": "TV - Sala Principal", "device": "Chromecast Ultra", "connected": True, "playing": False, "volume": 50, "content": "Esperando..."},
2: {"name": "TV - Barra", "device": "Chromecast 4K", "connected": True, "playing": False, "volume": 50, "content": "Esperando..."},
3: {"name": "TV - Terraza", "device": "Chromecast with Google TV", "connected": True, "playing": False, "volume": 50, "content": "Esperando..."}
}
self.current_video = None
self.is_playing = False
self.progress = 0
self.playlist = [
{"title": "Video Promocional", "source": "YouTube", "url": "https://www.youtube.com/watch?v=dQw4w9WgXcQ", "duration": "3:45"},
{"title": "Video Corporativo", "source": "Vimeo", "url": "https://vimeo.com/123456789", "duration": "2:30"},
{"title": "Video Evento", "source": "Directo", "url": "https://example.com/video.mp4", "duration": "5:15"}
]
def get_tv_status(self, tv_id: int) -> Dict:
"""Get status of a specific TV"""
return self.tv_states.get(tv_id, {})
def get_all_tvs_status(self) -> List[Dict]:
"""Get status of all TVs"""
return [self.tv_states[i] for i in range(1, 4)]
def load_video(self, url: str) -> Tuple[str, str, str]:
"""Load a video URL to all TVs"""
if not url:
return "❌ Error", "Por favor, introduce una URL válida", "error"
self.current_video = url
video_name = self._extract_video_name(url)
for i in range(1, 4):
self.tv_states[i]["content"] = video_name
self.progress = 0
return "✅ Éxito", f"Video '{video_name}' cargado en todas las TVs", "success"
def _extract_video_name(self, url: str) -> str:
"""Extract video name from URL"""
if "youtube" in url.lower():
return "Video de YouTube"
elif "vimeo" in url.lower():
return "Video de Vimeo"
elif ".mp4" in url.lower():
return "Video Directo"
else:
return "Video Online"
def control_tv(self, tv_id: int, action: str) -> Tuple[str, str, str]:
"""Control individual TV"""
if tv_id not in self.tv_states:
return "❌ Error", f"TV {tv_id} no encontrada", "error"
tv = self.tv_states[tv_id]
if action == "play":
if not self.current_video:
return "❌ Error", "No hay video cargado", "error"
tv["playing"] = True
self.is_playing = True
return "✅ Reproduciendo", f"TV {tv_id} está reproduciendo", "success"
elif action == "pause":
tv["playing"] = False
return "⏸️ Pausado", f"TV {tv_id} pausado", "info"
elif action == "stop":
tv["playing"] = False
tv["content"] = "Esperando..."
return "⏹️ Detenido", f"TV {tv_id} detenido", "info"
elif action == "mute":
tv["volume"] = 0 if tv["volume"] > 0 else 50
status = "silenciado" if tv["volume"] == 0 else "activado"
return "🔇 Volumen", f"TV {tv_id} {status}", "info"
return "❌ Error", "Acción no reconocida", "error"
def control_all_tvs(self, action: str) -> Tuple[str, str, str]:
"""Control all TVs simultaneously"""
if action == "play":
if not self.current_video:
return "❌ Error", "Por favor, carga un video primero", "error"
for i in range(1, 4):
self.tv_states[i]["playing"] = True
self.is_playing = True
return "✅ Reproduciendo", "Reproduciendo en todas las TVs", "success"
elif action == "pause":
for i in range(1, 4):
self.tv_states[i]["playing"] = False
self.is_playing = False
return "⏸️ Pausado", "Pausado en todas las TVs", "info"
elif action == "stop":
for i in range(1, 4):
self.tv_states[i]["playing"] = False
self.tv_states[i]["content"] = "Esperando..."
self.is_playing = False
self.current_video = None
self.progress = 0
return "⏹️ Detenido", "Transmisión detenida", "info"
elif action == "mute":
for i in range(1, 4):
self.tv_states[i]["volume"] = 0 if self.tv_states[i]["volume"] > 0 else 50
return "🔇 Volumen", "Silencio toggled en todas las TVs", "info"
return "❌ Error", "Acción no reconocida", "error"
def change_volume(self, volume: int) -> Tuple[str, str, str]:
"""Change volume for all TVs"""
volume = max(0, min(100, volume))
for i in range(1, 4):
self.tv_states[i]["volume"] = volume
return "🔊 Volumen", f"Volumen ajustado a {volume}%", "info"
def update_progress(self) -> Tuple[float, str, str]:
"""Update playback progress"""
if self.is_playing and self.progress < 100:
self.progress += 0.5
current_seconds = int(self.progress * 2.25)
current_time = f"{current_seconds // 60:02d}:{current_seconds % 60:02d}"
duration = "03:45"
return self.progress, current_time, duration
def get_playlist(self) -> List[Dict]:
"""Get current playlist"""
return self.playlist
def add_to_playlist(self, url: str, title: str = "") -> Tuple[str, str, str]:
"""Add video to playlist"""
if not url:
return "❌ Error", "Introduce una URL primero", "error"
if not title:
title = self._extract_video_name(url)
self.playlist.append({
"title": title,
"source": "Custom",
"url": url,
"duration": "--:--"
})
return "✅ Éxito", "Video agregado a la playlist", "success"
def play_from_playlist(self, index: int) -> Tuple[str, str, str]:
"""Play video from playlist"""
if 0 <= index < len(self.playlist):
video = self.playlist[index]
return self.load_video(video["url"])
return "❌ Error", "Video no encontrado en playlist", "error"
# Initialize controller
controller = ChromecastController()
def update_tvs_display():
"""Update the TVs status display"""
statuses = controller.get_all_tvs_status()
html = ""
for i, tv in enumerate(statuses, 1):
status_class = "connected" if tv["connected"] else "disconnected"
if tv["playing"]:
status_class = "playing"
status_text = "Conectado" if status_class == "connected" else "Desconectado"
if status_class == "playing":
status_text = "Reproduciendo"
status_color = {
"connected": "#16a34a",
"playing": "#d97706",
"disconnected": "#dc2626"
}[status_class]
html += f"""
📺 {tv['name']}
{status_text}
Dispositivo:{tv['device']}
Reproduciendo:{tv['content']}
Volumen:{tv['volume']}%
"""
return html
def update_playlist_display():
"""Update the playlist display"""
playlist = controller.get_playlist()
html = ""
for i, video in enumerate(playlist):
html += f"""
{video['title']}
{video['source']} • {video['duration']}
"""
return html
def load_video_url(url):
"""Load video from URL"""
title, message, status = controller.load_video(url)
return title, message, update_tvs_display(), url
def control_individual_tv(tv_id, action):
"""Control individual TV"""
title, message, status = controller.control_tv(tv_id, action)
return title, message, update_tvs_display()
def control_all_tvs_action(action):
"""Control all TVs"""
title, message, status = controller.control_all_tvs(action)
return title, message, update_tvs_display(), "" if action == "stop" else gr.update()
def change_volume_all(volume):
"""Change volume for all TVs"""
title, message, status = controller.change_volume(volume)
return title, message, update_tvs_display(), f"{volume}%"
def update_playback_progress():
"""Update playback progress"""
progress, current_time, duration = controller.update_progress()
return progress, current_time, duration
def add_video_to_playlist(url, title):
"""Add video to playlist"""
result_title, message, status = controller.add_to_playlist(url, title)
return result_title, message, update_playlist_display()
def play_playlist_item(index):
"""Play item from playlist"""
title, message, status = controller.play_from_playlist(index)
return title, message, update_tvs_display()
def load_sample_video(sample_type):
"""Load sample video"""
samples = {
"youtube": "https://www.youtube.com/watch?v=dQw4w9WgXcQ",
"vimeo": "https://vimeo.com/123456789",
"direct": "https://commondatastorage.googleapis.com/gtv-videos-bucket/sample/BigBuckBunny.mp4"
}
url = samples.get(sample_type, "")
return load_video_url(url)
# Create Gradio interface
with gr.Blocks(title="Control Multimedia Chromecast", theme=gr.themes.Soft()) as demo:
gr.HTML("""
📺 Control Multimedia Chromecast - Hostelería
Sistema de control para múltiples dispositivos Chromecast
""")
with gr.Row():
with gr.Column(scale=2):
# Quick Actions
gr.HTML("