Media Playback
Relevant source files
The following files were used as context for generating this wiki page:
- Putio/Features/MediaPlayers/MediaPlaybackManager.swift
- Putio/Features/MediaPlayers/VideoPlayerViewController.swift
- Putio/Features/MediaPlayers/AudioPlayerViewController.swift
- Putio/Features/MediaPlayers/NextMediaFinder.swift
- Putio/Features/MediaPlayers/MediaPlayerItemModel.swift
- Putio/Features/Chromecast/ChromecastManager.swift
- Putio/Common/API/PutioSDK.swift
The Media Playback system in the put.io iOS application provides a unified interface for streaming and playing back video and audio content. It supports both online streaming directly from the put.io API and offline playback of downloaded files. The system handles session management, playback position tracking (resuming), and integration with external devices via Google Cast (Chromecast).
The architecture is built around a central MediaPlaybackManager that routes playback requests to specialized controllers based on the media type. It leverages AVFoundation for local/online playback and the Google Cast SDK for remote display.
Core Components and Architecture
The playback system uses a coordinator-like pattern where the MediaPlaybackManager acts as the entry point for all playback actions.
The diagram above illustrates the routing of media items to their respective specialized players.
MediaPlaybackManager
The MediaPlaybackManager is a singleton responsible for instantiating the correct view controller based on the FileType of the MediaPlayerItem.
- Video Playback: Instantiates
VideoPlayerViewController, which inherits fromAVPlayerViewController. - Audio Playback: Instantiates a
UINavigationControllercontaining anAudioPlayerViewController.
Sources: Putio/Features/MediaPlayers/MediaPlaybackManager.swift:7-35
MediaPlayerItem
The MediaPlayerItem struct serves as the universal data model for the playback system. It abstracts the source of the media, whether it originates from a PutioFile (online), a Download (offline), or a PutioNextFile (auto-play next).
| Field | Type | Description |
|---|---|---|
id | Int | Unique identifier for the file. |
url | URL | The streaming or local file URL. |
fileType | FileType | Enum: .audio or .video. |
consumptionType | ConsumptionType | Enum: .online or .offline. |
startFrom | Int | The timestamp (in seconds) to resume playback from. |
Sources: Putio/Features/MediaPlayers/MediaPlayerItemModel.swift:6-48
Video Playback and Position Tracking
Video playback is managed by VideoPlayerViewController. A critical feature is the synchronization of "Start From" (resume) positions between the local device and the put.io servers.
Playback Position Synchronization
The system uses VideoPlaybackPositionStore to cache positions locally and the PutioSDK to fetch and update positions on the server.
Sequence of events for resolving and persisting video playback positions.
- Initial Setup: Upon loading, the controller checks for local cached positions before falling back to the API. If a "Start From" point exists, it presents a dialog asking the user to "Continue watching" or "Start from the beginning".
- Background Persistence: Playback positions are forcefully persisted during app lifecycle events such as
didEnterBackgroundorwillTerminateusingUIBackgroundTaskIdentifierto ensure the API call completes. - IFTTT Integration: The player sends events (
playback_started,playback_stopped) to the put.io API for IFTTT automation.
Sources: Putio/Features/MediaPlayers/VideoPlayerViewController.swift:55-101, Putio/Features/MediaPlayers/VideoPlayerViewController.swift:233-272, Putio/Features/MediaPlayers/MediaPlayerItemModel.swift:58-114
Audio Playback and Queue Management
Audio playback is handled by AudioPlayerViewController, which uses AVQueuePlayer to support playlists and continuous playback.
Next Item Discovery
The NextMediaFinder component is used to automatically discover and queue the next logical track. It searches in two locations:
- Local Database: If the current item is
.offline, it looks for the next completed download in Realm. - API: If
.online, it callsapi.findNextFileto retrieve the next item in the folder.
Sources: Putio/Features/MediaPlayers/NextMediaFinder.swift:15-35, Putio/Features/MediaPlayers/AudioPlayerViewController.swift:125-140
Remote Command Center
The audio player integrates with MPNowPlayingInfoCenter and MPRemoteCommandCenter, allowing users to control playback via the iOS Lock Screen or Control Center. It supports:
- Play/Pause toggling.
- Skipping forward/backward (15-second intervals).
- Seeking via the playback position command.
Sources: Putio/Features/MediaPlayers/AudioPlayerViewController.swift:168-208
Chromecast Integration
The ChromecastManager handles remote playback on Google Cast-enabled devices. It translates PutioFile objects into GCKMediaInformation for the Cast SDK.
Media Preparation
Before casting, the manager verifies if the file requires conversion (e.g., non-h264 codecs) and fetches available subtitles via api.getSubtitles.
The logic flow for initiating a Chromecast session.
Metadata and Subtitles
- Metadata: Includes the title and a screenshot URL formatted for the receiver.
- Subtitles: Subtitles are fetched from the API and converted into
GCKMediaTrackobjects. If the user settings allow, the first track is automatically activated. - Playback Type: Supports both
HLS(m3u) andMP4streaming, configurable via the application settings.
Sources: Putio/Features/Chromecast/ChromecastManager.swift:105-168, Putio/Features/Chromecast/ChromecastManager.swift:170-209
Summary
The Media Playback system provides a robust implementation for consuming content stored on put.io. By combining AVFoundation for local performance with the PutioSDK for cloud synchronization, it ensures that users can seamlessly switch between devices and media types while maintaining their playback progress. The inclusion of NextMediaFinder and ChromecastManager extends the experience beyond simple file viewing into a comprehensive media consumption suite.