diff --git a/.DS_Store b/.DS_Store index 5bdf022..51e553f 100644 Binary files a/.DS_Store and b/.DS_Store differ diff --git a/app.py b/app.py index 1691273..1a61da7 100755 --- a/app.py +++ b/app.py @@ -23,7 +23,7 @@ BASE_DIR = os.path.dirname(os.path.abspath(__file__)) MEDIA_DIR = os.path.join(BASE_DIR, "media") CONFIG_FILE = os.path.join(BASE_DIR, "config.json") -APP_VERSION = "3.5.0" +APP_VERSION = "3.6.0" UPLOAD_EXTENSIONS = {".jpg", ".jpeg", ".png", ".mp4"} app = Flask(__name__) @@ -50,10 +50,21 @@ def save_config(cfg): def is_url(value): - return ( - isinstance(value, str) - and value.lower().startswith(("http://", "https://")) - ) + """Check if value is a URL (string or dict with 'url' key)""" + if isinstance(value, str): + return value.lower().startswith(("http://", "https://")) + if isinstance(value, dict) and "url" in value: + url = value.get("url", "") + return isinstance(url, str) and url.lower().startswith(("http://", "https://")) + return False + +def normalize_url(value): + """Convert URL string to dict with zoom factor, or return existing dict""" + if isinstance(value, dict) and "url" in value: + return value + if isinstance(value, str) and value.lower().startswith(("http://", "https://")): + return {"url": value, "zoom": 1.0} + return None # ------------------------------------------------- @@ -133,13 +144,15 @@ def player(screen): normal_files = [] # 1. Playlist-Reihenfolge - for name in playlist: - if is_url(name): - normal_files.append({"kind": "url", "url": name}) + for item in playlist: + if is_url(item): + url_data = normalize_url(item) + if url_data: + normal_files.append({"kind": "url", "url": url_data["url"], "zoom": url_data.get("zoom", 1.0)}) continue - if os.path.exists(os.path.join(folder, name)) and allowed_file(name): - normal_files.append({"kind": "file", "name": name}) + if os.path.exists(os.path.join(folder, item)) and allowed_file(item): + normal_files.append({"kind": "file", "name": item}) existing_file_names = { item["name"] for item in normal_files if item["kind"] == "file" @@ -160,14 +173,16 @@ def player(screen): if priority_cfg.get("enabled", False): prio_files = [] - for name in priority_cfg.get("playlist", []): - if is_url(name): - prio_files.append({"kind": "url", "url": name}) + for item in priority_cfg.get("playlist", []): + if is_url(item): + url_data = normalize_url(item) + if url_data: + prio_files.append({"kind": "url", "url": url_data["url"], "zoom": url_data.get("zoom", 1.0)}) continue - file_path = os.path.join(MEDIA_DIR, "priority", name) + file_path = os.path.join(MEDIA_DIR, "priority", item) if os.path.exists(file_path): - prio_files.append({"kind": "file", "name": name}) + prio_files.append({"kind": "file", "name": item}) else: prio_files = [] @@ -234,25 +249,28 @@ def admin(): screen_cfg["newsticker_enabled"] = screen_cfg.get("newsticker_enabled", False) # 1️⃣ Playlist-Reihenfolge - for name in playlist: - if is_url(name): - files.append({ - "name": name, - "type": "url", - "size": "URL" - }) + for item in playlist: + if is_url(item): + url_data = normalize_url(item) + if url_data: + files.append({ + "name": url_data["url"], + "type": "url", + "size": "URL", + "zoom": url_data.get("zoom", 1.0) + }) continue - file_path = os.path.join(path, name) + file_path = os.path.join(path, item) if not os.path.exists(file_path): continue - ext = os.path.splitext(name)[1].lower() + ext = os.path.splitext(item)[1].lower() ftype = "video" if ext == ".mp4" else "image" size = os.path.getsize(file_path) // 1024 files.append({ - "name": name, + "name": item, "type": ftype, "size": size }) @@ -286,25 +304,28 @@ def admin(): prio_playlist = cfg["priority"].get("playlist", []) # 1️⃣ Playlist-Reihenfolge - for name in prio_playlist: - if is_url(name): - priority_files.append({ - "name": name, - "type": "url", - "size": "URL" - }) + for item in prio_playlist: + if is_url(item): + url_data = normalize_url(item) + if url_data: + priority_files.append({ + "name": url_data["url"], + "type": "url", + "size": "URL", + "zoom": url_data.get("zoom", 1.0) + }) continue - file_path = os.path.join(prio_dir, name) + file_path = os.path.join(prio_dir, item) if not os.path.exists(file_path): continue - ext = os.path.splitext(name)[1].lower() + ext = os.path.splitext(item)[1].lower() ftype = "video" if ext == ".mp4" else "image" size = os.path.getsize(file_path) // 1024 priority_files.append({ - "name": name, + "name": item, "type": ftype, "size": size }) @@ -388,12 +409,24 @@ def upload(screen): @login_required def add_url(screen): url = request.form.get("url", "").strip() + zoom = request.form.get("zoom", "1.0").strip() + if not is_url(url): return redirect("/admin") + + try: + zoom_factor = float(zoom) + if zoom_factor <= 0: + zoom_factor = 1.0 + except (ValueError, TypeError): + zoom_factor = 1.0 + # Store as object with zoom factor + url_data = {"url": url, "zoom": zoom_factor} + config = load_config() if screen == "priority": - config.setdefault("priority", {}).setdefault("playlist", []).append(url) + config.setdefault("priority", {}).setdefault("playlist", []).append(url_data) else: screen_cfg = config.setdefault("screens", {}).setdefault(screen, { "interval": 10, @@ -401,7 +434,7 @@ def add_url(screen): "show_videos": True, "playlist": [] }) - screen_cfg.setdefault("playlist", []).append(url) + screen_cfg.setdefault("playlist", []).append(url_data) save_config(config) return redirect("/admin") @@ -424,12 +457,18 @@ def delete_file(screen, filename): # --- Playlist bereinigen --- if screen == "priority": playlist = cfg.get("priority", {}).get("playlist", []) - if filename in playlist: - playlist.remove(filename) + # Remove both string URLs and dict-based URLs + playlist[:] = [item for item in playlist if not ( + (isinstance(item, str) and item == filename) or + (isinstance(item, dict) and item.get("url") == filename) + )] else: playlist = cfg["screens"].get(screen, {}).get("playlist", []) - if filename in playlist: - playlist.remove(filename) + # Remove both string URLs and dict-based URLs + playlist[:] = [item for item in playlist if not ( + (isinstance(item, str) and item == filename) or + (isinstance(item, dict) and item.get("url") == filename) + )] save_config(cfg) return redirect("/admin") @@ -444,20 +483,36 @@ def delete_file(screen, filename): def save_playlist(screen): cfg = load_config() data = request.get_json() - + new_order = data["playlist"] # List of filenames/URLs as strings + + # Get the current playlist with all data (including zoom factors) if screen == "priority": - cfg.setdefault("priority", {}).setdefault("playlist", []) - cfg["priority"]["playlist"] = data["playlist"] + old_playlist = cfg.get("priority", {}).get("playlist", []) else: - screen_cfg = cfg.setdefault("screens", {}).setdefault(screen, { - "interval": 10, - "show_images": True, - "show_videos": True, - "playlist": [], - "newsticker_text": "", - "newsticker_enabled": False - }) - screen_cfg["playlist"] = data["playlist"] + old_playlist = cfg.get("screens", {}).get(screen, {}).get("playlist", []) + + # Create a mapping: filename/url -> full item (preserves zoom factor) + item_map = {} + for item in old_playlist: + if isinstance(item, dict) and "url" in item: + key = item["url"] # URL as key + else: + key = item # Filename as key + item_map[key] = item + + # Build new playlist: use the mapping to preserve zoom factors + new_playlist = [] + for key in new_order: + if key in item_map: + new_playlist.append(item_map[key]) + else: + # Item not found in mapping - add as is + new_playlist.append(key) + + if screen == "priority": + cfg.setdefault("priority", {})["playlist"] = new_playlist + else: + cfg.setdefault("screens", {}).setdefault(screen, {})["playlist"] = new_playlist save_config(cfg) return "", 204 diff --git a/config.json b/config.json index f4a5c2c..b4ff958 100755 --- a/config.json +++ b/config.json @@ -2,7 +2,10 @@ "priority": { "enabled": true, "playlist": [ - "https://www.meteoblue.com/en/meteotv/d7b0fd" + { + "url": "https://www.meteoblue.com/en/meteotv/d7b0fd", + "zoom": 1.0 + } ] }, "screens": { @@ -11,13 +14,16 @@ "show_images": true, "show_videos": false, "playlist": [ - "https://wbxroompresence.cancom.io/standort?find=Stuttgart", "Hilfe_KI.jpg", "e00a687f-d82a-446d-b8f3-07895fbc7309.png", - "Video_CANCOM_LIVE_2025_Stuttgart.MP4" + "Video_CANCOM_LIVE_2025_Stuttgart.MP4", + { + "url": "https://wbxroompresence.cancom.io/standort?find=Stuttgart", + "zoom": 0.8 + } ], - "newsticker_text": "Hallo dies ist der Newsticker", - "newsticker_enabled": false + "newsticker_text": "Herzlich willkommen bei der CANCOM - wir begr\u00fc\u00dfen unsere G\u00e4ste - wir w\u00fcnschen ihnen einen sch\u00f6nen Tag", + "newsticker_enabled": true }, "casino": { "interval": 10, diff --git a/templates/admin.html b/templates/admin.html index a8dfd21..e1857bc 100755 --- a/templates/admin.html +++ b/templates/admin.html @@ -177,11 +177,16 @@