mirror of
https://github.com/AzuraCast/AzuraCast.git
synced 2024-06-26 19:07:05 +00:00
#1176 -- Refactor AutoDJ to "weight" playlists of all types.
This commit is contained in:
parent
50f4a1a394
commit
9a7d0f92db
|
@ -442,65 +442,6 @@ class StationPlaylist
|
|||
$this->schedule_days = implode(',', (array)$schedule_days);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns whether the playlist is scheduled to play according to schedule rules.
|
||||
*
|
||||
* @param Chronos|null $now
|
||||
* @return bool
|
||||
*/
|
||||
public function canPlayScheduled(Chronos $now = null): bool
|
||||
{
|
||||
if ($now === null) {
|
||||
$now = Chronos::now(new \DateTimeZone('UTC'));
|
||||
}
|
||||
|
||||
$day_to_check = (int)$now->format('N');
|
||||
$current_timecode = self::getCurrentTimeCode($now);
|
||||
|
||||
$schedule_start_time = $this->getScheduleStartTime();
|
||||
$schedule_end_time = $this->getScheduleEndTime();
|
||||
|
||||
// Handle all-day playlists.
|
||||
if ($schedule_start_time === $schedule_end_time) {
|
||||
return $this->canPlayScheduledOnDay($day_to_check);
|
||||
}
|
||||
|
||||
// Special handling for playlists ending at midnight (hour code "000").
|
||||
if (0 === $schedule_end_time) {
|
||||
$schedule_end_time = 2400;
|
||||
}
|
||||
|
||||
// Handle overnight playlists that stretch into the next day.
|
||||
if ($schedule_end_time < $schedule_start_time) {
|
||||
if ($current_timecode <= $schedule_end_time) {
|
||||
// Check the previous day, since it's before the end time.
|
||||
$day_to_check = (1 === $day_to_check) ? 7 : $day_to_check - 1;
|
||||
} else if ($current_timecode < $schedule_start_time) {
|
||||
// The playlist shouldn't be playing before the start time on the current date.
|
||||
return false;
|
||||
}
|
||||
|
||||
return $this->canPlayScheduledOnDay($day_to_check);
|
||||
}
|
||||
|
||||
// Non-overnight playlist check
|
||||
return $this->canPlayScheduledOnDay($day_to_check) &&
|
||||
($current_timecode >= $schedule_start_time && $current_timecode <= $schedule_end_time);
|
||||
}
|
||||
|
||||
/**
|
||||
* Given a day code (1-7) a-la date('N'), return if the playlist can be played on that day.
|
||||
*
|
||||
* @param int $day_to_check
|
||||
* @return bool
|
||||
*/
|
||||
public function canPlayScheduledOnDay($day_to_check): bool
|
||||
{
|
||||
$play_once_days = $this->getScheduleDays();
|
||||
return empty($play_once_days)
|
||||
|| in_array($day_to_check, $play_once_days);
|
||||
}
|
||||
|
||||
/**
|
||||
* @return int
|
||||
*/
|
||||
|
@ -541,26 +482,6 @@ class StationPlaylist
|
|||
$this->play_once_days = implode(',', (array)$play_once_days);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns whether the playlist is scheduled to play once.
|
||||
* @return bool
|
||||
*/
|
||||
public function canPlayOnce(): bool
|
||||
{
|
||||
$play_once_days = $this->getPlayOnceDays();
|
||||
|
||||
if (!empty($play_once_days) && !in_array(gmdate('N'), $play_once_days)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
$current_timecode = self::getCurrentTimeCode();
|
||||
|
||||
$playlist_play_time = $this->getPlayOnceTime();
|
||||
$playlist_diff = $current_timecode - $playlist_play_time;
|
||||
|
||||
return ($playlist_diff > 0 && $playlist_diff <= 15);
|
||||
}
|
||||
|
||||
/**
|
||||
* @return int
|
||||
*/
|
||||
|
@ -569,6 +490,25 @@ class StationPlaylist
|
|||
return $this->weight;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the "calculated" weight, factoring in the total number of songs in each playlist.
|
||||
*
|
||||
* @return int
|
||||
*/
|
||||
public function getCalculatedWeight(): int
|
||||
{
|
||||
$weight = $this->weight;
|
||||
if ($weight < 1) {
|
||||
$weight = 1;
|
||||
}
|
||||
|
||||
if (self::SOURCE_SONGS === $this->source) {
|
||||
$weight *= $this->media_items->count();
|
||||
}
|
||||
|
||||
return $weight;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param int $weight
|
||||
*/
|
||||
|
@ -627,6 +567,175 @@ class StationPlaylist
|
|||
return $this->media_items;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param array $recentSongHistory
|
||||
* @return bool
|
||||
*/
|
||||
public function canPlay(array $recentSongHistory = []): bool
|
||||
{
|
||||
switch($this->type) {
|
||||
case self::TYPE_ONCE_PER_DAY:
|
||||
return $this->canPlayOnce($recentSongHistory);
|
||||
break;
|
||||
|
||||
case self::TYPE_ONCE_PER_X_SONGS:
|
||||
return !$this->wasPlayedRecently($recentSongHistory, $this->getPlayPerSongs());
|
||||
break;
|
||||
|
||||
case self::TYPE_ONCE_PER_X_MINUTES:
|
||||
return $this->canPlayPerMinutes($recentSongHistory);
|
||||
break;
|
||||
|
||||
case self::TYPE_SCHEDULED:
|
||||
return $this->canPlayScheduled();
|
||||
break;
|
||||
|
||||
case self::TYPE_ADVANCED:
|
||||
return false;
|
||||
break;
|
||||
|
||||
case self::TYPE_DEFAULT:
|
||||
default:
|
||||
return true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns whether the playlist is scheduled to play according to schedule rules.
|
||||
*
|
||||
* @param Chronos|null $now
|
||||
* @return bool
|
||||
*/
|
||||
public function canPlayScheduled(Chronos $now = null): bool
|
||||
{
|
||||
if ($now === null) {
|
||||
$now = Chronos::now(new \DateTimeZone('UTC'));
|
||||
}
|
||||
|
||||
$day_to_check = (int)$now->format('N');
|
||||
$current_timecode = self::getCurrentTimeCode($now);
|
||||
|
||||
$schedule_start_time = $this->getScheduleStartTime();
|
||||
$schedule_end_time = $this->getScheduleEndTime();
|
||||
|
||||
// Handle all-day playlists.
|
||||
if ($schedule_start_time === $schedule_end_time) {
|
||||
return $this->canPlayScheduledOnDay($day_to_check);
|
||||
}
|
||||
|
||||
// Special handling for playlists ending at midnight (hour code "000").
|
||||
if (0 === $schedule_end_time) {
|
||||
$schedule_end_time = 2400;
|
||||
}
|
||||
|
||||
// Handle overnight playlists that stretch into the next day.
|
||||
if ($schedule_end_time < $schedule_start_time) {
|
||||
if ($current_timecode <= $schedule_end_time) {
|
||||
// Check the previous day, since it's before the end time.
|
||||
$day_to_check = (1 === $day_to_check) ? 7 : $day_to_check - 1;
|
||||
} else if ($current_timecode < $schedule_start_time) {
|
||||
// The playlist shouldn't be playing before the start time on the current date.
|
||||
return false;
|
||||
}
|
||||
|
||||
return $this->canPlayScheduledOnDay($day_to_check);
|
||||
}
|
||||
|
||||
// Non-overnight playlist check
|
||||
return $this->canPlayScheduledOnDay($day_to_check) &&
|
||||
($current_timecode >= $schedule_start_time && $current_timecode <= $schedule_end_time);
|
||||
}
|
||||
|
||||
/**
|
||||
* Given a day code (1-7) a-la date('N'), return if the playlist can be played on that day.
|
||||
*
|
||||
* @param int $day_to_check
|
||||
* @return bool
|
||||
*/
|
||||
protected function canPlayScheduledOnDay($day_to_check): bool
|
||||
{
|
||||
$play_once_days = $this->getScheduleDays();
|
||||
return empty($play_once_days)
|
||||
|| in_array($day_to_check, $play_once_days);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param array $songHistoryEntries
|
||||
* @return bool
|
||||
*/
|
||||
public function canPlayPerMinutes(array $songHistoryEntries = []): bool
|
||||
{
|
||||
$threshold = time() - ($this->getPlayPerMinutes() * 60);
|
||||
|
||||
$was_played = false;
|
||||
foreach($songHistoryEntries as $sh_row) {
|
||||
if ($sh_row['timestamp_cued'] < $threshold) {
|
||||
break;
|
||||
}
|
||||
|
||||
if ((int)$sh_row['playlist_id'] === $this->getId()) {
|
||||
$was_played = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
reset($songHistoryEntries);
|
||||
return !$was_played;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns whether the playlist is scheduled to play once.
|
||||
*
|
||||
* @param array $songHistoryEntries
|
||||
* @return bool
|
||||
*/
|
||||
public function canPlayOnce(array $songHistoryEntries = []): bool
|
||||
{
|
||||
$play_once_days = $this->getPlayOnceDays();
|
||||
|
||||
if (!empty($play_once_days) && !in_array(gmdate('N'), $play_once_days)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
$current_timecode = self::getCurrentTimeCode();
|
||||
|
||||
$playlist_play_time = $this->getPlayOnceTime();
|
||||
$playlist_diff = $current_timecode - $playlist_play_time;
|
||||
|
||||
if ($playlist_diff <= 0 || $playlist_diff > 15) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return !$this->wasPlayedRecently($songHistoryEntries);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param array $songHistoryEntries
|
||||
* @param int $length
|
||||
* @return bool
|
||||
*/
|
||||
public function wasPlayedRecently(array $songHistoryEntries = [], $length = 15): bool
|
||||
{
|
||||
if (empty($songHistoryEntries)) {
|
||||
return true;
|
||||
}
|
||||
|
||||
// Check if already played
|
||||
$relevant_song_history = array_slice($songHistoryEntries, 0, 15);
|
||||
|
||||
$was_played = false;
|
||||
foreach($relevant_song_history as $sh_row) {
|
||||
if ((int)$sh_row['playlist_id'] === $this->id) {
|
||||
$was_played = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
reset($songHistoryEntries);
|
||||
return $was_played;
|
||||
}
|
||||
|
||||
/**
|
||||
* Export the playlist into a reusable format.
|
||||
*
|
||||
|
|
|
@ -25,7 +25,8 @@ class RadioProvider implements ServiceProviderInterface
|
|||
$di[Radio\AutoDJ::class] = function($di) {
|
||||
return new Radio\AutoDJ(
|
||||
$di[\Doctrine\ORM\EntityManager::class],
|
||||
$di[\Azura\EventDispatcher::class]
|
||||
$di[\Azura\EventDispatcher::class],
|
||||
$di[\Monolog\Logger::class]
|
||||
);
|
||||
};
|
||||
|
||||
|
|
|
@ -6,6 +6,7 @@ use App\Event\Radio\GetNextSong;
|
|||
use App\Radio\Backend\Liquidsoap;
|
||||
use Azura\EventDispatcher;
|
||||
use Doctrine\ORM\EntityManager;
|
||||
use Monolog\Logger;
|
||||
use Symfony\Component\EventDispatcher\EventSubscriberInterface;
|
||||
|
||||
class AutoDJ implements EventSubscriberInterface
|
||||
|
@ -16,18 +17,29 @@ class AutoDJ implements EventSubscriberInterface
|
|||
/** @var EventDispatcher */
|
||||
protected $dispatcher;
|
||||
|
||||
/** @var Logger */
|
||||
protected $logger;
|
||||
|
||||
/**
|
||||
* @param EntityManager $em
|
||||
* @param EventDispatcher $dispatcher
|
||||
* @param Logger $logger
|
||||
*
|
||||
* @see \App\Provider\RadioProvider
|
||||
*/
|
||||
public function __construct(EntityManager $em, EventDispatcher $dispatcher)
|
||||
public function __construct(
|
||||
EntityManager $em,
|
||||
EventDispatcher $dispatcher,
|
||||
Logger $logger)
|
||||
{
|
||||
$this->em = $em;
|
||||
$this->dispatcher = $dispatcher;
|
||||
$this->logger = $logger;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return array
|
||||
*/
|
||||
public static function getSubscribedEvents()
|
||||
{
|
||||
return [
|
||||
|
@ -53,9 +65,19 @@ class AutoDJ implements EventSubscriberInterface
|
|||
return null;
|
||||
}
|
||||
|
||||
$this->logger->pushProcessor(function($record) use ($station) {
|
||||
$record['extra']['station'] = [
|
||||
'id' => $station->getId(),
|
||||
'name' => $station->getName(),
|
||||
];
|
||||
return $record;
|
||||
});
|
||||
|
||||
$event = new GetNextSong($station);
|
||||
$this->dispatcher->dispatch(GetNextSong::NAME, $event);
|
||||
|
||||
$this->logger->popProcessor();
|
||||
|
||||
$next_song = $event->getNextSong();
|
||||
|
||||
if ($next_song instanceof Entity\SongHistory && $is_autodj) {
|
||||
|
@ -72,10 +94,10 @@ class AutoDJ implements EventSubscriberInterface
|
|||
return $next_song;
|
||||
}
|
||||
|
||||
public function checkDatabaseForNextSong(GetNextSong $event)
|
||||
public function checkDatabaseForNextSong(GetNextSong $event): void
|
||||
{
|
||||
$next_song = $this->em->createQuery('SELECT sh, s, sp, sm
|
||||
FROM ' . Entity\SongHistory::class . ' sh
|
||||
$nextSongQuery = /** @lang DQL */ 'SELECT sh, s, sp, sm
|
||||
FROM App\Entity\SongHistory sh
|
||||
LEFT JOIN sh.song s
|
||||
LEFT JOIN sh.media sm
|
||||
LEFT JOIN sh.playlist sp
|
||||
|
@ -84,17 +106,23 @@ class AutoDJ implements EventSubscriberInterface
|
|||
AND sh.sent_to_autodj = 0
|
||||
AND sh.timestamp_start = 0
|
||||
AND sh.timestamp_end = 0
|
||||
ORDER BY sh.id DESC')
|
||||
ORDER BY sh.id DESC';
|
||||
|
||||
$next_song = $this->em->createQuery($nextSongQuery)
|
||||
->setParameter('station_id', $event->getStation()->getId())
|
||||
->setMaxResults(1)
|
||||
->getOneOrNullResult();
|
||||
|
||||
if ($next_song instanceof Entity\SongHistory) {
|
||||
$this->logger->debug('Database has a next song already registered.');
|
||||
$event->setNextSong($next_song);
|
||||
}
|
||||
}
|
||||
|
||||
public function getNextSongFromRequests(GetNextSong $event)
|
||||
/**
|
||||
* @param GetNextSong $event
|
||||
*/
|
||||
public function getNextSongFromRequests(GetNextSong $event): void
|
||||
{
|
||||
$station = $event->getStation();
|
||||
|
||||
|
@ -107,16 +135,22 @@ class AutoDJ implements EventSubscriberInterface
|
|||
$threshold = time() - ($threshold_minutes * 60);
|
||||
|
||||
// Look up all requests that have at least waited as long as the threshold.
|
||||
$request = $this->em->createQuery('SELECT sr, sm
|
||||
FROM '.Entity\StationRequest::class.' sr JOIN sr.track sm
|
||||
WHERE sr.played_at = 0 AND sr.station_id = :station_id AND sr.timestamp <= :threshold
|
||||
ORDER BY sr.id ASC')
|
||||
$requestQuery = /** @lang DQL */ 'SELECT sr, sm
|
||||
FROM App\Entity\StationRequest sr JOIN sr.track sm
|
||||
WHERE sr.played_at = 0
|
||||
AND sr.station_id = :station_id
|
||||
AND sr.timestamp <= :threshold
|
||||
ORDER BY sr.id ASC';
|
||||
|
||||
$request = $this->em->createQuery($requestQuery)
|
||||
->setParameter('station_id', $station->getId())
|
||||
->setParameter('threshold', $threshold)
|
||||
->setMaxResults(1)
|
||||
->getOneOrNullResult();
|
||||
|
||||
if ($request instanceof Entity\StationRequest) {
|
||||
$this->logger->debug(sprintf('Queueing next song from request ID %d.', $request->getId()));
|
||||
|
||||
$event->setNextSong($this->_playSongFromRequest($request));
|
||||
}
|
||||
}
|
||||
|
@ -127,10 +161,8 @@ class AutoDJ implements EventSubscriberInterface
|
|||
*
|
||||
* @param Entity\StationRequest $request
|
||||
* @return Entity\SongHistory
|
||||
* @throws \Doctrine\ORM\ORMException
|
||||
* @throws \Doctrine\ORM\OptimisticLockException
|
||||
*/
|
||||
protected function _playSongFromRequest(Entity\StationRequest $request)
|
||||
protected function _playSongFromRequest(Entity\StationRequest $request): Entity\SongHistory
|
||||
{
|
||||
// Log in history
|
||||
$sh = new Entity\SongHistory($request->getTrack()->getSong(), $request->getStation());
|
||||
|
@ -158,133 +190,74 @@ class AutoDJ implements EventSubscriberInterface
|
|||
{
|
||||
$station = $event->getStation();
|
||||
|
||||
$songHistoryCount = 15;
|
||||
|
||||
// Pull all active, non-empty playlists and sort by type.
|
||||
$playlists_by_type = [];
|
||||
foreach($station->getPlaylists() as $playlist) {
|
||||
/** @var Entity\StationPlaylist $playlist */
|
||||
if ($playlist->isPlayable()) {
|
||||
$playlists_by_type[$playlist->getType()][$playlist->getId()] = $playlist;
|
||||
$type = $playlist->getType();
|
||||
|
||||
if (Entity\StationPlaylist::TYPE_ONCE_PER_X_SONGS === $type) {
|
||||
$songHistoryCount = max($songHistoryCount, $playlist->getPlayPerSongs());
|
||||
}
|
||||
|
||||
$playlists_by_type[$type][$playlist->getId()] = $playlist;
|
||||
}
|
||||
}
|
||||
|
||||
// Pull all recent cued songs for easy referencing below.
|
||||
$cued_song_history = $this->em->createQuery('SELECT sh FROM '.Entity\SongHistory::class.' sh
|
||||
$cuedSongHistoryQuery = /** @lang DQL */ 'SELECT sh
|
||||
FROM App\Entity\SongHistory sh
|
||||
WHERE sh.station_id = :station_id
|
||||
AND (sh.timestamp_cued != 0 AND sh.timestamp_cued IS NOT NULL)
|
||||
AND sh.timestamp_cued >= :threshold
|
||||
ORDER BY sh.timestamp_cued DESC')
|
||||
ORDER BY sh.timestamp_cued DESC';
|
||||
|
||||
$cued_song_history = $this->em->createQuery($cuedSongHistoryQuery)
|
||||
->setParameter('station_id', $station->getId())
|
||||
->setParameter('threshold', time()-86399)
|
||||
->getArrayResult();
|
||||
|
||||
// Once per day playlists
|
||||
if (!empty($playlists_by_type['once_per_day'])) {
|
||||
foreach ($playlists_by_type['once_per_day'] as $playlist) {
|
||||
/** @var Entity\StationPlaylist $playlist */
|
||||
if ($playlist->canPlayOnce()) {
|
||||
// Check if already played
|
||||
$relevant_song_history = array_slice($cued_song_history, 0, 15);
|
||||
// Types of playlists that should play, sorted by priority.
|
||||
$typesToPlay = [
|
||||
Entity\StationPlaylist::TYPE_ONCE_PER_DAY,
|
||||
Entity\StationPlaylist::TYPE_ONCE_PER_X_SONGS,
|
||||
Entity\StationPlaylist::TYPE_ONCE_PER_X_MINUTES,
|
||||
Entity\StationPlaylist::TYPE_SCHEDULED,
|
||||
Entity\StationPlaylist::TYPE_DEFAULT,
|
||||
];
|
||||
|
||||
$was_played = false;
|
||||
foreach($relevant_song_history as $sh_row) {
|
||||
if ($sh_row['playlist_id'] == $playlist->getId()) {
|
||||
$was_played = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (!$was_played) {
|
||||
if ($event->setNextSong($this->_playSongFromPlaylist($playlist))) {
|
||||
return;
|
||||
};
|
||||
}
|
||||
|
||||
reset($cued_song_history);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Once per X songs playlists
|
||||
if (!empty($playlists_by_type['once_per_x_songs'])) {
|
||||
foreach($playlists_by_type['once_per_x_songs'] as $playlist) {
|
||||
/** @var Entity\StationPlaylist $playlist */
|
||||
|
||||
$relevant_song_history = array_slice($cued_song_history, 0, $playlist->getPlayPerSongs());
|
||||
|
||||
$was_played = false;
|
||||
foreach($relevant_song_history as $sh_row) {
|
||||
if ($sh_row['playlist_id'] == $playlist->getId()) {
|
||||
$was_played = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (!$was_played) {
|
||||
if ($event->setNextSong($this->_playSongFromPlaylist($playlist))) {
|
||||
return;
|
||||
};
|
||||
}
|
||||
|
||||
reset($cued_song_history);
|
||||
}
|
||||
}
|
||||
|
||||
// Once per X minutes playlists
|
||||
if (!empty($playlists_by_type['once_per_x_minutes'])) {
|
||||
foreach($playlists_by_type['once_per_x_minutes'] as $playlist) {
|
||||
/** @var Entity\StationPlaylist $playlist */
|
||||
|
||||
$threshold = time() - ($playlist->getPlayPerMinutes() * 60);
|
||||
|
||||
$was_played = false;
|
||||
foreach($cued_song_history as $sh_row) {
|
||||
if ($sh_row['timestamp_cued'] < $threshold) {
|
||||
break;
|
||||
} else if ($sh_row['playlist_id'] == $playlist->getId()) {
|
||||
$was_played = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (!$was_played) {
|
||||
if ($event->setNextSong($this->_playSongFromPlaylist($playlist))) {
|
||||
return;
|
||||
};
|
||||
}
|
||||
|
||||
reset($cued_song_history);
|
||||
}
|
||||
}
|
||||
|
||||
// Time-block scheduled playlists
|
||||
if (!empty($playlists_by_type['scheduled'])) {
|
||||
foreach ($playlists_by_type['scheduled'] as $playlist) {
|
||||
/** @var Entity\StationPlaylist $playlist */
|
||||
if ($playlist->canPlayScheduled()) {
|
||||
if ($event->setNextSong($this->_playSongFromPlaylist($playlist))) {
|
||||
return;
|
||||
};
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Default rotation playlists
|
||||
if (!empty($playlists_by_type['default'])) {
|
||||
$playlist_weights = [];
|
||||
foreach ($playlists_by_type['default'] as $playlist_id => $playlist) {
|
||||
/** @var Entity\StationPlaylist $playlist */
|
||||
$playlist_weights[$playlist_id] = $playlist->getWeight();
|
||||
foreach($typesToPlay as $type) {
|
||||
if (empty($playlists_by_type[$type])) {
|
||||
continue;
|
||||
}
|
||||
|
||||
$rand = random_int(1, (int)array_sum($playlist_weights));
|
||||
foreach ($playlist_weights as $playlist_id => $weight) {
|
||||
$eligible_playlists = [];
|
||||
foreach($playlists_by_type[$type] as $playlist_id => $playlist) {
|
||||
/** @var Entity\StationPlaylist $playlist */
|
||||
if ($playlist->canPlay($cued_song_history)) {
|
||||
$eligible_playlists[$playlist_id] = $playlist->getCalculatedWeight();
|
||||
}
|
||||
}
|
||||
|
||||
if (empty($eligible_playlists)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
$this->logger->debug(sprintf('Playable playlists of type "%s" found.', $type), $eligible_playlists);
|
||||
|
||||
// Shuffle playlists by weight.
|
||||
$rand = random_int(1, (int)array_sum($eligible_playlists));
|
||||
foreach ($eligible_playlists as $playlist_id => $weight) {
|
||||
$rand -= $weight;
|
||||
if ($rand <= 0) {
|
||||
$playlist = $playlists_by_type['default'][$playlist_id];
|
||||
$playlist = $playlists_by_type[$type][$playlist_id];
|
||||
|
||||
if ($event->setNextSong($this->_playSongFromPlaylist($playlist))) {
|
||||
return;
|
||||
};
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -326,7 +299,9 @@ class AutoDJ implements EventSubscriberInterface
|
|||
$this->em->flush();
|
||||
|
||||
return $sh;
|
||||
} else if (is_array($media_to_play)) {
|
||||
}
|
||||
|
||||
if (is_array($media_to_play)) {
|
||||
[$media_uri, $media_duration] = $media_to_play;
|
||||
|
||||
$sh = new Entity\SongHistory($song_repo->getOrCreate([
|
||||
|
|
Loading…
Reference in New Issue
Block a user