AzuraCast/src/Radio/AutoDJ/Annotations.php

130 lines
3.8 KiB
PHP

<?php
declare(strict_types=1);
namespace App\Radio\AutoDJ;
use App\Entity;
use App\Event\Radio\AnnotateNextSong;
use App\Radio\Adapters;
use Doctrine\ORM\EntityManagerInterface;
use Psr\EventDispatcher\EventDispatcherInterface;
use Psr\Log\LoggerInterface;
use RuntimeException;
use Symfony\Component\EventDispatcher\EventSubscriberInterface;
class Annotations implements EventSubscriberInterface
{
public function __construct(
protected EntityManagerInterface $em,
protected Entity\Repository\StationQueueRepository $queueRepo,
protected Entity\Repository\StationStreamerRepository $streamerRepo,
protected Adapters $adapters,
protected LoggerInterface $logger,
protected EventDispatcherInterface $eventDispatcher,
) {
}
/**
* @inheritDoc
*/
public static function getSubscribedEvents(): array
{
return [
AnnotateNextSong::class => [
['annotateSongPath', 15],
['annotatePlaylist', 10],
['annotateRequest', 5],
['postAnnotation', -10],
],
];
}
/**
* Pulls the next song from the AutoDJ, dispatches the AnnotateNextSong event and returns the built result.
*
* @param Entity\Station $station
* @param bool $asAutoDj
*/
public function annotateNextSong(
Entity\Station $station,
bool $asAutoDj = false,
): string {
$queueRow = $this->queueRepo->getNextToSendToAutoDj($station);
if (null === $queueRow) {
throw new RuntimeException('Queue is empty for station.');
}
$event = AnnotateNextSong::fromStationQueue($queueRow, $asAutoDj);
$this->eventDispatcher->dispatch($event);
return $event->buildAnnotations();
}
public function annotateSongPath(AnnotateNextSong $event): void
{
$media = $event->getMedia();
if ($media instanceof Entity\StationMedia) {
$event->setSongPath('media:' . ltrim($media->getPath(), '/'));
$backend = $this->adapters->getBackendAdapter($event->getStation());
$event->addAnnotations($backend->annotateMedia($media));
} else {
$queue = $event->getQueue();
if ($queue instanceof Entity\StationQueue) {
$customUri = $queue->getAutodjCustomUri();
if (!empty($customUri)) {
$event->setSongPath($customUri);
}
}
}
}
public function annotatePlaylist(AnnotateNextSong $event): void
{
$playlist = $event->getPlaylist();
if (null === $playlist) {
return;
}
if ($playlist->getIsJingle()) {
$event->addAnnotations([
'jingle_mode' => 'true',
]);
} else {
$event->addAnnotations([
'playlist_id' => $playlist->getId(),
]);
}
}
public function annotateRequest(AnnotateNextSong $event): void
{
$request = $event->getRequest();
if ($request instanceof Entity\StationRequest) {
$event->addAnnotations([
'request_id' => $request->getId(),
]);
}
}
public function postAnnotation(AnnotateNextSong $event): void
{
if (!$event->isAsAutoDj()) {
return;
}
$queueRow = $event->getQueue();
if ($queueRow instanceof Entity\StationQueue) {
$queueRow->setSentToAutodj();
$queueRow->setTimestampCued(time());
$this->em->persist($queueRow);
}
// The "get next song" function is only called when a streamer is not live.
$this->streamerRepo->onDisconnect($event->getStation());
$this->em->flush();
}
}