---
feature: "Přehrávání a notifikační systém"
description: "Info notifikace při startu přehrávání, autoplay další epizody s countdownem, monitoring přehrávače a cross-process koordinace"
files:
  - wcs/playback/PlayerMonitor.py
  - wcs/playback/PlaylistCountdownMonitor.py
  - wcs/playback/dialog_scheduler.py
  - wcs/playback/metadata.py
  - wcs/playback/DialogMediaInfoWithGame.py
  - wcs/playback/dialogs/__init__.py
  - wcs/playback/dialogs/base_game_dialog.py
  - wcs/playback/dialogs/countdown.py
  - wcs/playback/dialogs/managers.py
  - wcs/playback/dialogs/media_info.py
parent: true
children:
  - "Notifikační systém (Info dialogy)"
  - "Autoplay systém (Countdown + další epizoda)"
  - "PlayerMonitor"
  - "PlaylistCountdownMonitor"
  - "Dialog Scheduler"
  - "MediaMetadata"
  - "Playback Dialogy"
  - "Managers"
created: "2026-04-04"
updated: "2026-04-06"
status: "complete"
---

# Přehrávání a notifikační systém

Kompletní systém pro obohacení přehrávání v Kodi. Dva hlavní subsystémy:

1. **Notifikační systém** – info dialog (poster, rating, plot, hra) zobrazený po startu přehrávání. Funguje ze VŠECH zdrojů: menu doplňku (TMDb), Kodi knihovna, MyTV kanály.
2. **Autoplay systém** – countdown dialog před koncem epizody + automatické přehrání další. Funguje POUZE z Kodi knihovny a MyTV kanálů (NE z TMDb menu doplňku).

## Soubory

| Soubor | Velikost | Řádků | Účel |
|--------|----------|-------|------|
| `wcs/playback/PlayerMonitor.py` | 23 KB | 481 | Player monitoring, autoplay, file-based locky |
| `wcs/playback/PlaylistCountdownMonitor.py` | 23 KB | 555 | Countdown pro MyTV kanály |
| `wcs/playback/dialog_scheduler.py` | 7 KB | 197 | Plánování info dialogů (threading, timing) |
| `wcs/playback/metadata.py` | 6 KB | 183 | MediaMetadata – jednotný datový model |
| `wcs/playback/DialogMediaInfoWithGame.py` | 1 KB | 21 | Re-export wrapper (zpětná kompatibilita) |
| `wcs/playback/dialogs/base_game_dialog.py` | 6 KB | 162 | GameDialogMixin – sdílený herní kód |
| `wcs/playback/dialogs/countdown.py` | 8 KB | 179 | AutoplayCountdownDialog UI |
| `wcs/playback/dialogs/managers.py` | 11 KB | 267 | Manager třídy + singleton factory |
| `wcs/playback/dialogs/media_info.py` | 27 KB | 636 | MediaInfoDialog – info dialog UI |

## Architektura – vstupní body

```
┌─────────────────────────────────────────────────────────────────┐
│                      VSTUPNÍ BODY                               │
├───────────────┬───────────────┬──────────────┬──────────────────┤
│ Film z menu   │ Epizoda z     │ Epizoda z    │ Epizoda z Kodi   │
│ doplňku       │ menu doplňku  │ MyTV kanálu  │ knihovny          │
│               │ (2 flow)      │              │                  │
└──────┬────────┴──────┬────────┴──────┬───────┴────────┬─────────┘
       │               │               │                │
  INFO DIALOG ✅   INFO DIALOG ✅  INFO DIALOG ✅   INFO DIALOG ✅
  AUTOPLAY ❌      AUTOPLAY ❌    AUTOPLAY ✅      AUTOPLAY ✅
```

### Flow 1: Film z menu doplňku
```
router.py: action='play_movie_from_addon'
  → utils.play_movie_from_addon(meta)
    → search_and_select_movie_file()
    → PlayMedia(play_url)
    → MediaMetadata.from_tmdb_movie(meta)
    → schedule_info_dialog(metadata, source='addon_movie')
      → Thread: wait → 3s delay → MovieInfoManager.show_movie_info()
```

### Flow 2a: Epizoda z menu doplňku (play_episode_from_addon)
```
router.py: action='play_episode_from_addon'
  → utils.search_and_play_episode()
    → search_and_select_episode_file()
    → _on_episode_playback_start()
      → schedule_episode_info_dialog()
        → MediaMetadata.from_tmdb_episode()
        → schedule_info_dialog(metadata, source='addon_episode')
    → PlayMedia(play_url)
```

### Flow 2b: Epizoda z menu doplňku (tmdb_episode_search)
```
router.py: action='tmdb_episode_search'
  → SeriesSearch.search_and_handle_episode()
    → _internal_search_and_select_series_file()
    → schedule_episode_info_dialog()    ← PŘIDÁNO v2.0.2
      → MediaMetadata.from_tmdb_episode()
      → schedule_info_dialog(metadata, source='addon_episode')
    → setResolvedUrl()   (NE PlayMedia!)
```
> [!NOTE]
> Flow 2b se liší od 2a tím, že používá `setResolvedUrl` (Kodi samo přehraje) místo `PlayMedia()`. Notifikace byly přidány v2.0.2 – dříve tento flow notifikace neměl.

### Flow 3: Epizoda z MyTV kanálu
```
utils.search_and_play_episode(mytv_channel_id=...)
  → _on_episode_playback_start()
    → schedule_episode_info_dialog()
  → PlayMedia(play_url)
  → PlaylistCountdownMonitor.activate(meta)
    → Countdown + autoplay další epizody
```

### Flow 4: Epizoda z Kodi knihovny
```
LibraryManager.resolve_episode_from_library()
  → setResolvedUrl()
  → schedule_library_info_dialog(fetcher, fallback)
    → Thread: wait → 3s → fetcher() → MediaMetadata.from_kodi_library_episode()
  → _activate_singleton_monitoring()
    → PlayerMonitor: info dialog + countdown + autoplay
```

### Flow 5: Autoplay (knihovna) – konec epizody
```
PlayerMonitor._monitor_worker()
  → Detekce blížícího se konce
  → _show_countdown_dialog()
    → AutoplayManager.show_countdown_dialog(remaining_time)
      → timeout_callback → _handle_next_episode()
      → NEBO: user_action → _handle_next_episode()
```

## Child funkce

### Notifikační systém (Info dialogy)

- **Co dělá**: Po startu přehrávání zobrazí fullscreen info dialog s posterem/stillem, názvem, hodnocením, popiskem a herním panelem. Funguje ze VŠECH zdrojů – menu doplňku (TMDb data), Kodi knihovna (JSON-RPC data), MyTV kanály.
- **Mechanismus**: `DialogScheduler` spustí daemon thread → čeká na start přehrávání (max 10s) → 3s delay → zkontroluje settings → zobrazí dialog.
- **Data flow**: Vstupní data → `MediaMetadata` normalizace → `EpisodeInfoManager`/`MovieInfoManager` → `MediaInfoDialog.doModal()`.
- **Závislosti**: `dialog_scheduler.py`, `metadata.py`, `managers.py`, `media_info.py`
- **Settings**: `show_episode_info` – zapíná/vypíná info dialogy

### Autoplay systém (Countdown + další epizoda)

- **Co dělá**: Před koncem epizody zobrazí countdown dialog s informacemi o další epizodě. Po timeoutu nebo kliknutí „Přehrát" automaticky spustí další epizodu. Funguje POUZE z Kodi knihovny a MyTV kanálů.
- **Dva nezávislé subsystémy**:
  - **PlayerMonitor** – pro Kodi knihovnu. Monitoring thread sleduje čas, countdown dialog, timeout_callback.
  - **PlaylistCountdownMonitor** – pro MyTV kanály. Samostatný monitor s channel historií.
- **timeout_callback**: Po uplynutí countdownu spustí `_handle_next_episode()` v novém threadu (0.5s delay pro stabilitu).
- **Cross-process ochrana**: File-based locky (`_acquire_lock('info_dialog')`, `_acquire_lock('next_episode')`) brání duplicitním notifikacím a spuštěním při paralelních CPythonInvokerech (viz issue 001).
- **Settings**: `autoplay_countdown_seconds` (countdown délka), `autoplay_trigger_seconds` (kdy spustit countdown)

### PlayerMonitor

- **Co dělá**: Singleton `xbmc.Player` monitor pro autoplay z Kodi knihovny. Detekuje start přehrávání přes `temp_autoplay_active` setting. Po detekci zobrazí info dialog, spustí monitoring thread pro countdown, a při timeout/akci uživatele přehraje další epizodu.
- **Klíčové metody**:
  - `onPlayBackStarted()` – detekuje přehrávání, spustí `_handle_test_playback_start` v threadu
  - `_handle_test_playback_start()` – file-based lock `info_dialog`, zobrazí info, spustí monitoring
  - `_show_episode_info()` – používá `MediaMetadata` (z knihovny nebo fallback)
  - `_monitor_worker()` – sleduje čas, spustí countdown dialog
  - `_show_countdown_dialog()` – zobrazí countdown, zpracuje výsledek (play/cancel/timeout)
  - `_handle_next_episode()` – file-based lock `next_episode`, sestaví URL, PlayMedia
  - `get_player_monitor()` – singleton factory
- **Cross-process koordinace (issue 001)**:
  - File-based locky v `addon_data/_autoplay_locks/` (info_dialog.lock, next_episode.lock)
  - TTL 30s pro případ crashe
  - `xbmc.sleep()` místo `time.sleep()` (neblokuje Kodi event loop)
  - `xbmcvfs.translatePath()` místo deprecated `xbmc.translatePath()`
- **Vstupy**: Kodi player events, `autoplay_manager.current_series_info/current_episode_info`
- **Výstupy**: Info dialog, countdown dialog, PlayMedia pro další epizodu
- **Závislosti**: `managers.py` (AutoplayManager, EpisodeInfoManager), `metadata.py` (MediaMetadata), `wcs/library/LibraryManager.py`
- **Settings**: `temp_autoplay_active`, `show_episode_info`

### PlaylistCountdownMonitor

- **Co dělá**: Sleduje přehrávání epizody z MyTV kanálu a zobrazuje countdown dialog pro další epizodu. Aktivuje se přes `activate(meta)` s channel_id. Ukládá progress do `ChannelHistory`.
- **Klíčové metody**: `activate(meta)`, `deactivate()`, `_check_countdown()`, `get_playlist_monitor()` (singleton)
- **Vstupy**: Meta data kanálu (channel_id, tmdb_id, season, episode)
- **Výstupy**: Countdown dialog, spuštění další epizody
- **Závislosti**: [004-mytv.md](004-mytv.md) (ChannelHistory), [006-metadata.md](006-metadata.md) (TMDb)
- **Settings**: `autoplay_countdown_seconds`, `autoplay_trigger_seconds`

### Dialog Scheduler

- **Co dělá**: Sjednocený plánovač pro zobrazení info dialogů. Nahrazuje 4 dříve duplicitní threading patterny. Dvě hlavní funkce:
  - `schedule_info_dialog(metadata, source)` – addon přehrávání (metadata předem známá)
  - `schedule_library_info_dialog(fetcher, fallback, source)` – knihovna (metadata se načtou po startu přehrávání)
- **Konstanty**: `PLAYBACK_WAIT_ATTEMPTS=100` (~10s), `PLAYBACK_WAIT_INTERVAL=0.1`, `DIALOG_DELAY=3`
- **Workflow**: Spustí daemon thread → čeká na `isPlaying()` → 3s delay → zkontroluje `show_episode_info` setting → zobrazí dialog
- **Závislosti**: `metadata.py`, `managers.py`
- **Settings**: `show_episode_info`

### MediaMetadata

- **Co dělá**: Jednotný datový model pro metadata přehrávaného obsahu. Normalizuje data z různých zdrojů (TMDb, Kodi knihovna) do konzistentního formátu.
- **Factory metody**:
  - `from_tmdb_movie(data)` – film z TMDb, `poster` → `thumb`
  - `from_tmdb_episode(data)` – epizoda z TMDb, `episode_thumb` → `thumb` (fallback `poster`)
  - `from_kodi_library_movie(data)` – film z knihovny, dekóduje `image://` URL
  - `from_kodi_library_episode(data)` – epizoda z knihovny
- **Normalizace**: `_clean_url()` (dekóduje Kodi image:// URL), `_clean_rating()` (formátuje rating na čistý string)
- **Atributy**: `media_type`, `title`, `thumb`, `fanart`, `rating`, `plot`, `year`, `tmdb_id`, `genre`, `director`, `runtime`, `series_name`, `episode_title`, `season_number`, `episode_number`
- **Závislosti**: žádné
- **Settings**: žádné

### Playback Dialogy

- **Co dělá**: Sada Kodi WindowXML dialogů pro obohacení přehrávání:
  - **MediaInfoDialog** (`media_info.py`) – fullscreen info dialog (poster, rating, plot, herní panel), 5s auto-close, pill-shaped tlačítka
  - **AutoplayCountdownDialog** (`countdown.py`) – countdown dialog s vizuálním odpočtem, tlačítka Přehrát/Zrušit
  - **GameDialogMixin** (`base_game_dialog.py`) – sdílený herní kód (Milionář integrace)
- **XML skiny**: `resources/skins/Default/1080i/notifications/` (classic/modern styly)
- **Závislosti**: [003-games.md](003-games.md) (GameController)
- **Settings**: `dialog_style`

### Managers

- **Co dělá**: Wrapper třídy a singleton factory pro vytváření dialogů.
- **Třídy**:
  - `MovieInfoManager` – vytvoří a zobrazí `MediaInfoDialog` s `media_type='movie'`
  - `EpisodeInfoManager` – vytvoří a zobrazí `MediaInfoDialog` s `media_type='series'`
  - `AutoplayManager` – řídí autoplay logiku:
    - `set_current_episode()` – nastaví aktuální epizodu
    - `get_next_episode_info()` – zjistí další epizodu z knihovny (`LibraryManager.get_next_episode_metadata_from_library()`)
    - `show_countdown_dialog()` – zobrazí countdown, **timeout_callback** spustí `_handle_next_episode()` po uplynutí
- **Singleton factory**: `get_movie_info_manager()`, `get_episode_info_manager()`, `get_autoplay_manager()`
- **Závislosti**: `media_info.py`, `countdown.py`, [014-library.md](014-library.md) (LibraryManager)

## Známé opravené problémy

### Issue 001: Duplicitní notifikace při autoplay (resolved)
- **Příčina**: Kodi spouští každé `PlayMedia()` v novém CPythonInvokeru – in-memory singletony a `threading.Lock` NEFUNGUJÍ pro cross-process koordinaci
- **Řešení**: File-based locky v `addon_data/_autoplay_locks/`, `xbmc.sleep()` místo `time.sleep()`, `xbmcvfs.translatePath()`
- **Detail**: viz `docs/issues/001-autoplay-duplicate-notifications.md`
