Architecture
System Overview
M2 is an offline music player focused on local-file playback with a single-process runtime.
Most implementation lives in Objective-C, with app services in M2Services.*,
view composition in M2MusicModule.*, and app shell in ViewController.*.
Targets
| Target | Role | Languages |
|---|---|---|
M2 |
Main app: playback, library, playlists, favorites, desktop shell. | Objective-C + Swift bridge |
M2LiveActivityExtension |
Sleep timer Live Activity UI. | Swift |
Startup Sequence
AppDelegate
-> configure AVAudioSession
-> initialize Core Data container
SceneDelegate
-> create UIWindow
-> preload library/playlists/favorites/analytics/cache
-> initialize playback manager singleton
-> show root shell (ViewController)
ViewController
-> build tabs (Music / Playlists / Favorites)
-> build desktop sidebar + mini-player for Catalyst
-> sync shell with playback notifications
Module Boundaries
| File | Responsibility |
|---|---|
M2Services.* |
Library scanning, metadata caches, playlist/favorites stores, playback core, analytics, sleep timer. |
M2MusicModule.* |
Feature view controllers, list/grid presentation, desktop-specific feature pages. |
ViewController.* |
Application shell, desktop sidebar, mini-player, keyboard shortcuts, tab coordination. |
M2Cells.* |
Reusable track/playlist cells for table and collection contexts. |
M2Models.* |
Runtime domain models (M2Track, M2Playlist). |
Notification Contracts
M2PlaybackStateDidChangeNotification: transport state changed.M2PlaybackProgressDidChangeNotification: current playback time update.M2PlaylistsDidChangeNotification: playlist storage mutation.M2FavoritesDidChangeNotification: favorites mutation.M2SleepTimerDidChangeNotification: sleep timer state update.
Desktop Shell Behavior
- Catalyst shell enforces dark visual style and a fixed left sidebar.
- Mini-player is always present in desktop layout.
- Tab transitions and navigation pushes are configured without animation on desktop feature flows.
- Pinned playlists are managed in sidebar and open directly into playlist details.
Runtime Sequence: Track Tap
User tap on track
-> controller resolves queue + index
-> opens player screen (if needed)
-> playback manager receives playTracks:startIndex:
-> AVAudioPlayer starts
-> playback state notification sent
-> mini-player and active lists refresh