For reference, the source code is in `~/src/rithik-b/PlaylistManager`.
Here is how “add this map to a playlist” is wired in this repo.
### 1. User clicks Add (opens the picker)
The Add button on the level detail screen calls `AddPlaylistModalController.ShowModal()`:
```64:70:PlaylistManager/UI/ViewControllers/LevelDetailButtonsViewController.cs
[UIAction("add-button-click")]
private void OpenAddModal()
{
addPlaylistController.ShowModal();
}
```
`ShowModal` parses the BSML if needed, opens the modal, and lists playlists from the default lib manager:
```97:103:PlaylistManager/UI/ViewControllers/AddPlaylistModalController.cs
internal void ShowModal()
{
Parse();
parserParams.EmitEvent("close-modal");
parserParams.EmitEvent("open-modal");
ShowPlaylistsForManager(PlaylistLibUtils.playlistManager);
}
```
### 2. User picks a playlist row — that is where the map is actually added
The real work is in `AddPlaylistModalController.OnCellSelect`: after navigating folders, choosing a playlist calls **`IPlaylist.Add(...)`** from **BeatSaberPlaylistsLib**, then persists and notifies:
```165:204:PlaylistManager/UI/ViewControllers/AddPlaylistModalController.cs
[UIAction("select-cell")]
private void OnCellSelect(TableView tableView, int index)
{
playlistTableData.TableView.ClearSelection();
// Folder Selected
if (index < childManagers.Count)
{
ShowPlaylistsForManager(childManagers[index]);
}
else
{
index -= childManagers.Count;
var selectedPlaylist = childPlaylists[index];
IPlaylistSong playlistSong;
if (HighlightDifficulty)
{
playlistSong = selectedPlaylist.Add(standardLevelDetailViewController.beatmapLevel, standardLevelDetailViewController.beatmapKey);
}
else
{
playlistSong = selectedPlaylist.Add(standardLevelDetailViewController.beatmapLevel);
}
try
{
selectedPlaylist.RaisePlaylistChanged();
parentManager.StorePlaylist(selectedPlaylist);
popupModalsController.ShowOkModal(modalTransform, string.Format("Song successfully added to {0}", selectedPlaylist.Title), null, animateParentCanvas: false);
// TODO: Doesn't refresh the sprite.
Events.RaisePlaylistSongAdded(playlistSong, selectedPlaylist);
}
catch (Exception e)
{
popupModalsController.ShowOkModal(modalTransform, "An error occured while adding song to playlist.", null, animateParentCanvas: false);
Plugin.Log.Critical(string.Format("An exception was thrown while adding a song to a playlist.\nException Message: {0}", e.Message));
}
finally
{
ShowPlaylistsForManager(parentManager);
}
}
}
```
So:
- **PlaylistManager code**: `AddPlaylistModalController.OnCellSelect` (orchestration, UI, `StorePlaylist`, `Events.RaisePlaylistSongAdded`).
- **Library code**: `selectedPlaylist.Add(...)` — implementation of how the entry is stored lives in **BeatSaberPlaylistsLib** (`IPlaylist`), not in this repository.
There is no other `.Add(` on a playlist for this flow in the grep results; removing a song is the parallel path in `LevelDetailButtonsViewController.RemoveSong()`.
## hooking into the process
### 1. Subscribe to PlaylistManager’s public event (simplest)
After a successful add from the **Add to playlist** UI, PlaylistManager raises a **public static** event:
```16:18:PlaylistManager/Utilities/Events.cs
///
/// Raised when an is added to an
///
public static event Action playlistSongAdded;
```
It is invoked **after** `RaisePlaylistChanged()` and `StorePlaylist()` succeed:
```187:194:PlaylistManager/UI/ViewControllers/AddPlaylistModalController.cs
try
{
selectedPlaylist.RaisePlaylistChanged();
parentManager.StorePlaylist(selectedPlaylist);
popupModalsController.ShowOkModal(modalTransform, string.Format("Song successfully added to {0}", selectedPlaylist.Title), null, animateParentCanvas: false);
// TODO: Doesn't refresh the sprite.
Events.RaisePlaylistSongAdded(playlistSong, selectedPlaylist);
}
```
In your plugin: add a **reference to `PlaylistManager.dll`**, a **manifest dependency** on PlaylistManager, then subscribe in `OnEnable` (or menu init) and unsubscribe in `OnDisable`:
- Namespace: `PlaylistManager.Utilities`
- Type: `Events`
- Event: `playlistSongAdded`
- Handler signature: `(IPlaylistSong song, IPlaylist playlist)` from `BeatSaberPlaylistsLib.Types`
**Caveat:** This is only raised for adds that go through **this** code path. It is the **only** `RaisePlaylistSongAdded` call site in the repo, so adds done only via BeatSaberPlaylistsLib (or another mod) will **not** fire this event.