Skip to content

Commit

Permalink
#2739 -- Fix duplicate prevention and weighted scheduling.
Browse files Browse the repository at this point in the history
  • Loading branch information
BusterNeece committed Apr 26, 2020
1 parent 835968d commit b608b2f
Showing 1 changed file with 23 additions and 19 deletions.
42 changes: 23 additions & 19 deletions src/Radio/AutoDJ.php
Original file line number Diff line number Diff line change
Expand Up @@ -314,16 +314,16 @@ public function calculateNextSong(BuildQueue $event): void
});

// Loop through the playlists and attempt to play them with no duplicates first,
// then loop through them again with "preferred mode" turned off.
foreach ([true, false] as $preferredMode) {
// then loop through them again while allowing duplicates.
foreach ([false, true] as $allowDuplicates) {
foreach ($eligible_playlists as $playlist_id => $weight) {
$playlist = $playlists_by_type[$type][$playlist_id];

if ($event->setNextSong($this->playSongFromPlaylist(
$playlist,
$cued_song_history,
$now,
$preferredMode
$allowDuplicates
))) {
$this->logger->info('Playable track found and registered.', [
'next_song' => (string)$event,
Expand All @@ -343,17 +343,17 @@ public function calculateNextSong(BuildQueue $event): void
* @param Entity\StationPlaylist $playlist
* @param array $recentSongHistory
* @param Chronos $now
* @param bool $preferredMode Whether to return a media ID even if duplicates can't be prevented.
* @param bool $allowDuplicates Whether to return a media ID even if duplicates can't be prevented.
*
* @return Entity\SongHistory|null
*/
protected function playSongFromPlaylist(
Entity\StationPlaylist $playlist,
array $recentSongHistory,
Chronos $now,
bool $preferredMode = true
bool $allowDuplicates = false
): ?Entity\SongHistory {
$media_to_play = $this->getQueuedSong($playlist, $recentSongHistory, $preferredMode);
$media_to_play = $this->getQueuedSong($playlist, $recentSongHistory, $allowDuplicates);

if ($media_to_play instanceof Entity\StationMedia) {
$playlist->setPlayedAt($now->getTimestamp());
Expand Down Expand Up @@ -403,14 +403,14 @@ protected function playSongFromPlaylist(
/**
* @param Entity\StationPlaylist $playlist
* @param array $recentSongHistory
* @param bool $preferredMode Whether to return a media ID even if duplicates can't be prevented.
* @param bool $allowDuplicates Whether to return a media ID even if duplicates can't be prevented.
*
* @return Entity\StationMedia|array|null
*/
protected function getQueuedSong(
Entity\StationPlaylist $playlist,
array $recentSongHistory,
bool $preferredMode = true
bool $allowDuplicates = false
) {
if (Entity\StationPlaylist::SOURCE_REMOTE_URL === $playlist->getSource()) {
return $this->playRemoteUrl($playlist);
Expand All @@ -419,7 +419,7 @@ protected function getQueuedSong(
switch ($playlist->getOrder()) {
case Entity\StationPlaylist::ORDER_RANDOM:
$mediaQueue = $this->spmRepo->getPlayableMedia($playlist);
$mediaId = $this->preventDuplicates($mediaQueue, $recentSongHistory, $preferredMode);
$mediaId = $this->preventDuplicates($mediaQueue, $recentSongHistory, $allowDuplicates);
break;

case Entity\StationPlaylist::ORDER_SEQUENTIAL:
Expand Down Expand Up @@ -450,14 +450,18 @@ protected function getQueuedSong(
}
}

$mediaId = $this->preventDuplicates($mediaQueue, $recentSongHistory, false);
if ($allowDuplicates) {
$mediaId = $this->preventDuplicates($mediaQueue, $recentSongHistory, false);

if (null === $mediaId) {
$this->logger->warning('Duplicate prevention yielded no playable song; resetting song queue.');
if (null === $mediaId) {
$this->logger->warning('Duplicate prevention yielded no playable song; resetting song queue.');

// Pull the entire shuffled playlist if a duplicate title can't be avoided.
$mediaQueue = $this->spmRepo->getPlayableMedia($playlist);
$mediaId = $this->preventDuplicates($mediaQueue, $recentSongHistory, true);
// Pull the entire shuffled playlist if a duplicate title can't be avoided.
$mediaQueue = $this->spmRepo->getPlayableMedia($playlist);
$mediaId = $this->preventDuplicates($mediaQueue, $recentSongHistory, true);
}
} else {
$mediaId = $this->preventDuplicates($mediaQueue, $recentSongHistory, false);
}

if (null !== $mediaId) {
Expand All @@ -476,7 +480,7 @@ protected function getQueuedSong(
$this->logger->error(sprintf('Playlist "%s" did not return a playable track.', $playlist->getName()), [
'playlist_id' => $playlist->getId(),
'playlist_order' => $playlist->getOrder(),
'preferred_mode' => $preferredMode,
'allow_duplicates' => $allowDuplicates,
]);
return null;
}
Expand Down Expand Up @@ -522,14 +526,14 @@ protected function playRemoteUrl(Entity\StationPlaylist $playlist): ?array
/**
* @param array $eligibleMedia
* @param array $playedMedia
* @param bool $preferredMode Whether to return a media ID even if duplicates can't be prevented.
* @param bool $allowDuplicates Whether to return a media ID even if duplicates can't be prevented.
*
* @return int|null
*/
protected function preventDuplicates(
array $eligibleMedia = [],
array $playedMedia = [],
bool $preferredMode = true
bool $allowDuplicates = false
): ?int {
if (empty($eligibleMedia)) {
$this->logger->debug('Eligible song queue is empty!');
Expand Down Expand Up @@ -575,7 +579,7 @@ protected function preventDuplicates(
return $mediaId;
}

if ($preferredMode) {
if ($allowDuplicates) {

// If we reach this point, there's no way to avoid a duplicate title.
$mediaIdsByTimePlayed = [];
Expand Down

0 comments on commit b608b2f

Please sign in to comment.