GroupListeningPlugin
GroupListeningPlugin is where NoMercy Connect watch-party parity lands for the music player.
The idea is server-coordinated lockstep transport: every client in a session plays the same track at the same position, drift gets corrected automatically, and one client holds the DJ role to issue control actions.
This plugin is roadmapped for v2.1. The class is exported now so consumers can register it, hold the import path stable, and react to the failure event before the implementation ships.
When the player initializes, use() throws NotImplementedError internally.
The core catches that error inside _registerPlugin, logs it, calls dispose(), and emits plugin:failed and plugin:group-listening:failed.
The error never surfaces to your code.
Do not register this plugin in production code yet.
import { GroupListeningPlugin } from '@nomercy-entertainment/nomercy-music-player/plugins';
import type { GroupListeningOptions, GroupListeningEvents } from '@nomercy-entertainment/nomercy-music-player/plugins';
Plugin id: 'group-listening'
Options
The GroupListeningOptions interface is defined in source and will drive the v2.1 implementation.
The fields below reflect the real interface, not speculative design.
| Option | Type | Default | Description |
|---|---|---|---|
wsUrl | string | required | WebSocket endpoint for room and session sync. |
sessionId | string | undefined | Room or session id this client joins. Omit to create a new session. |
driftThresholdMs | number | 80 | Acceptable playback drift in milliseconds before a correction is applied. |
maxRateAdjust | number | 0.05 | Maximum playback-rate adjustment factor used during drift correction, equivalent to plus or minus 5 percent. |
canControl | boolean | true | Whether this client may issue control actions (that is, hold the DJ role). |
Events
The GroupListeningEvents interface exists in source and reserves the event names for v2.1.
No events fire in v2.0 because use() throws before any wiring takes place.
The table below is a reference for what the interface declares; do not subscribe to these events until the implementation ships.
| Event | Payload | Description |
|---|---|---|
session:joined | { sessionId: string; participants: number } | Reserved: this client successfully joined a session. |
session:left | void | Reserved: this client left the session. |
sync:applied | { source: 'remote'; action: 'play' | 'pause' | 'seek' | 'next' | 'previous'; from: string } | Reserved: a remote sync action was applied to this client. |
sync:broadcast | { action: string; payload: unknown } | Reserved: a control action was broadcast to the session by this client. |
sync:drift | { deltaMs: number } | Reserved: clock drift was detected and a correction is being applied. |
sync:participants | { count: number } | Reserved: the participant count in the session changed. |
role:dj-acquired | { id: string } | Reserved: this client acquired the DJ role. |
role:dj-lost | void | Reserved: this client lost the DJ role. |
unsupported | { reason: string } | Reserved: the server protocol or environment is unsupported. |
Methods
use()
use(): void
Stub implementation.
Always throws NotImplementedError with message 'GroupListeningPlugin: roadmapped for v2.1. Not available in v2.0.'
The core catches this internally; the exception does not reach your code.
dispose()
dispose(): void
No-op in the stub — there is nothing to tear down.
Registration
Register the plugin and listen to plugin:failed to react when the core disables it.
Do not wrap addPlugin or setup in a try/catch expecting NotImplementedError — the core swallows that error internally and it never reaches your code.
import nmMPlayer from '@nomercy-entertainment/nomercy-music-player';
import { GroupListeningPlugin } from '@nomercy-entertainment/nomercy-music-player/plugins';
const player = nmMPlayer('main')
.addPlugin(GroupListeningPlugin, {
wsUrl: 'wss://your-server.example.com/sync',
sessionId: 'room-abc',
driftThresholdMs: 80,
canControl: true,
})
.setup({
baseUrl: 'https://raw.githubusercontent.com/NoMercy-Entertainment/nomercy-media/master/Music',
playlist: [
{
id: 'kjc-01',
name: 'Thaw You Out',
url: '/D/Derek%20Clegg/%5B2010%5D%20KJC/01%20Thaw%20You%20Out.mp3',
artist: 'Derek Clegg',
},
],
});
// The core emits plugin:failed when use() throws internally.
// Use this event to detect that GroupListeningPlugin is not yet active.
player.on('plugin:group-listening:failed', ({ id, error }) => {
console.warn(`${id} is not available in v2.0:`, error.message);
});