xbmc.PlayList add/remove/shuffle bypass CPlayListPlayer, leaving the playback position stale
Split out of xbmc#18154. That upstream report has two parts; the JSON-RPC half is already correct on current code (jsonrpc-14), the Python half is not.
The bug
The legacy xbmc.PlayList API mutates the underlying CPlayList directly, bypassing CPlayListPlayer, which owns the current-song index (m_iCurrentSong). So adding, removing or shuffling around the currently playing song does not move the position pointer with it:
PlayList.remove() → pPlayList->Remove(filename) (interfaces/legacy/PlayList.cpp:105)
PlayList.add() → pPlayList->Insert(items, index) (:60)
PlayList.shuffle() → pPlayList->Shuffle() (:120)
The JSON-RPC equivalents route through CPlayListPlayer::Remove/Insert/Swap (via TMSG_PLAYLISTPLAYER_*), which adjust m_iCurrentSong, so they are unaffected.
Verified live (2026-08-19, jsonrpc-14 tip)
A script add-on playing a 5-track music playlist, skipped to index 3 (t04), then PlayList.remove(t01) (a song before the current):
before remove: getposition=3 playing=t04.mp3 size=5
after remove: getposition=3 playing=t04.mp3 size=4 <-- t04 is now at index 2; position should be 2
getposition() returns CPlayListPlayer::GetCurrentItemIdx() = m_iCurrentSong, so it reports the stale index, and when the current track ends the wrong item plays next (the reporter's "songs 0..n-1 skipped").
Fix sketch (undecided)
Route the legacy PlayList mutators through CPlayListPlayer so the position is maintained, as the JSON-RPC path does. Open questions: remove() takes a filename, not an index, so the matching index must be resolved (and duplicate-path ambiguity decided); and thread-safety — the Python API mutates in-process on the script thread, whereas the JSON-RPC path posts to the app thread.
Not on the jsonrpc-14 epic (this is the Python/legacy layer, not the JSON-RPC surface). Parked here to fix or promote upstream later.
xbmc.PlayListadd/remove/shuffle bypassCPlayListPlayer, leaving the playback position staleSplit out of xbmc#18154. That upstream report has two parts; the JSON-RPC half is already correct on current code (
jsonrpc-14), the Python half is not.The bug
The legacy
xbmc.PlayListAPI mutates the underlyingCPlayListdirectly, bypassingCPlayListPlayer, which owns the current-song index (m_iCurrentSong). So adding, removing or shuffling around the currently playing song does not move the position pointer with it:PlayList.remove()→pPlayList->Remove(filename)(interfaces/legacy/PlayList.cpp:105)PlayList.add()→pPlayList->Insert(items, index)(:60)PlayList.shuffle()→pPlayList->Shuffle()(:120)The JSON-RPC equivalents route through
CPlayListPlayer::Remove/Insert/Swap(viaTMSG_PLAYLISTPLAYER_*), which adjustm_iCurrentSong, so they are unaffected.Verified live (2026-08-19, jsonrpc-14 tip)
A script add-on playing a 5-track music playlist, skipped to index 3 (t04), then
PlayList.remove(t01)(a song before the current):getposition()returnsCPlayListPlayer::GetCurrentItemIdx()=m_iCurrentSong, so it reports the stale index, and when the current track ends the wrong item plays next (the reporter's "songs 0..n-1 skipped").Fix sketch (undecided)
Route the legacy
PlayListmutators throughCPlayListPlayerso the position is maintained, as the JSON-RPC path does. Open questions:remove()takes a filename, not an index, so the matching index must be resolved (and duplicate-path ambiguity decided); and thread-safety — the Python API mutates in-process on the script thread, whereas the JSON-RPC path posts to the app thread.Not on the
jsonrpc-14epic (this is the Python/legacy layer, not the JSON-RPC surface). Parked here to fix or promote upstream later.